Keresés

Aktív témák

  • OddMan

    őstag

    Egy aprócska asm kérdés:

    Van különbség a kettő között?

    azonosito dd 1000h
    azonosito: dd 1000h

    A kettőspontot '':'' valahol kiteszik valahol pedig nem.
    Mit jelent a kettőspont pontosan? :F

  • OddMan

    őstag

    válasz kisfurko #35 üzenetére

    Na sikerült a kivételkezelés is. :DD Most egy TSS-t szeretnék létrehozni, ami nem a 0-ás privilégium szinten futna. A másik dolog, amin most gondolkodom, hogy szeretném az egész progit átírni C-be. Szal az is tele lenne asm betétekkel, de lennének függvények meg struktúrák, használhatnék ciklusokat feltételeket stb.
    A kérdésem, hogy szerinted ezt, mibe lehetne megcsinálni? Eddig a Mingw-t és a DJGPP fejlesztő környezeteket nézegettem. Ezekkel lehetne a.out, COFF, ELF formátumú fájlokat készíteni, amiket a GRUB loader képes betölteni. Ennek az lenne az előnye, hogy a GRUB már maga védett módba kapcsolja gépet, és egy csomó információt átadhat az induló kernelnek. Egyébként azt néztem, hogy a GRUB az 1MB fölé teszi a kernelt, tehát fixen be lehetne írni a GDT-be a báziscímeket is. Nem kell számolgatni, hogy éppen hol van a kernel. Aztán C-ben már könnyedén lehetne írni saját függvényeket, amelyek kezelnék a képernyőt, billentyűt, időzítőt stb. :U Nem akarok C könyvtári függvényeket használni, csak magát a C-t, és így egy tényleg szép strukturált kódot lehetne írni, ami tele van assembly-vel, de mégis strukturált ás átlátható. :t

  • OddMan

    őstag

    válasz kisfurko #33 üzenetére

    ''Hogyan futtatod? Ugye nem debuggerben?'' :B De, azért nem ment!
    A Turbo debugger-ben akartam futtatni azért fagyott le az egész.
    Találtam a neten egy teljesen ingyenes dos emulátort a neve DOSBox-0.61 és abban teljesen tökéletesen működik. Egyébként rendes MS-DOS alatt is működik. Létezik egyáltalán olyan debugger, amit lehetne használni? :F

    Írtam védett módban egy olyan kiíró rutint, amivel az összes regiszter értékét hexában ki tudom írni a képernyőre. A kérdésem, hogy hogyan kell beállítani az IDT, hogy ha kivétel történik, akkor fusson le ez a kis rutin, hogy lássam hol száll el a program, ha már debuggolni nem tudok. :U

  • OddMan

    őstag

    válasz OddMan #31 üzenetére

    Huh most esett le a hogyan kell fizikai címet csinálni kérdésem.

    mov eax, ds
    shl eax, 4 ;ezt nem értem, hogyha 4-el balra léptetem a biteket, akkor mitől lesz az a fizikai címe a DS-nek?

    Tehát azért, mert a DS csak 16bit-es és mindig utána kell képzelni még 4db 0-ás bitet. Így ha balra léptetem 4-el, akkor az eax-be már a 20 bites fizikai cím lesz. Aztán azt meg csak hozzá kell adni a GDT_addr relatív címéhez és így már tényleg a GDT_addr változóban az igazi fizikai cím szerepel, ugye? :DD

  • OddMan

    őstag

    válasz kisfurko #30 üzenetére

    Nagyon köszi, hogy segítesz.

    ''Ne tedd 0f0000h-ra a programod, mert ott a BIOS van...''
    Szereztem egy valós modú memória térképet, és most már tudom, hogy hova lehet töltögetni.

    ''A jmp far-t heggeszteni kell:
    db 0eah ;ez a jmp far abszolut címre kódja
    dw uj_ip,uj_cs
    Értelemszerűen, az IP legyen 32 bites, ha 32 bites kód fut.''
    Na a nasm-ban a ''jmp dword cs:ip'' 32bit-es és ''jmp word cs:ip'' 16bit-es far ugrás.
    Megnéztem az exe-t hexa editorral és úgy néz ki, hogy a nasm jól fordítja le ezeket az utasításokat. Te próbáltad már a nasm-ot? Mert ha mégsem fordítja jól, akkor az álltalad írt gépikód formát fogom használni. Meg gondolom bizonyos esetekben kell a 66h prefix, amikor a szegmens 16bit-es az utasítás meg 32bit-es.

    Más:
    Azt értem, hogy az lgdt utasításnak fizikai cím kell, de azt már nem, hogyan kell azt megkapni.

    mov eax, ds
    shl eax, 4 ;ezt nem értem, hogyha 4-el balra léptetem a biteket, akkor mitől lesz az a fizikai címe a DS-nek? :F
    add [GDT_ptr+2], eax
    lgdt [GDT_ptr] ;Load the GDT


    GDT_addr:
    ;;0. descriptor
    NULL_SEL equ $-GDT_addr
    dw 0
    dw 0
    db 0
    db 0
    db 0
    db 0

    ;;1. descriptor (code segment 1MB 0-nál kezdődik)
    CODE16_SEL equ $-GDT_addr
    dw 0FFFFh ;a szegmens hosszának alsó wordja (határ)
    dw 0 ;a báziscím alsó wordje
    db 0 ;a báziscím felső wordjének alsó bájtja
    db 10011010b ;P=1, DPL=00, S=1, C/D=1, C/E=0, R/W=1, A=0
    db 00001111b ;G=0, D/B=0, AVL=0, reserved=0, határ=1111
    db 0 ;a báziscím felső wordjének felső bájtja

    ;;2. descriptor (data segment 1MB 0-nál kezdődik)
    DATA16_SEL equ $-GDT_addr
    dw 0FFFFh ;a szegmens hosszának alsó wordja (határ)
    dw 0 ;a báziscím alsó wordje
    db 0 ;a báziscím felső wordjének alsó bájtja
    db 10010010b ;P=1, DPL=00, S=1, C/D=0, C/E=0, R/W=1, A=0
    db 00001111b ;G=0, D/B=1, AVL=0, reserved=0, határ=1111
    db 0 ;a báziscím felső wordjének felső bájtja

    ;;3. descriptor (code segment 1MB 0-nál kezdődik)
    CODE32_SEL equ $-GDT_addr
    dw 0FFFFh ;a szegmens hosszának alsó wordja (határ)
    dw 0 ;a báziscím alsó wordje
    db 0 ;a báziscím felső wordjének alsó bájtja
    db 10011010b ;P=1, DPL=00, S=1, C/D=1, C/E=0, R/W=1, A=0
    db 01001111b ;G=0, D/B=1, AVL=0, reserved=0, határ=1111
    db 0 ;a báziscím felső wordjének felső bájtja

    ;;4. descriptor (data segment 1MB 0-nál kezdődik)
    DATA32_SEL equ $-GDT_addr
    dw 0FFFFh ;a szegmens hosszának alsó wordja (határ)
    dw 0 ;a báziscím alsó wordje
    db 0 ;a báziscím felső wordjének alsó bájtja
    db 10010010b ;P=1, DPL=00, S=1, C/D=0, C/E=0, R/W=1, A=0
    db 01001111b ;G=0, D/B=1, AVL=0, reserved=0, határ=1111
    db 0 ;a báziscím felső wordjének felső bájtja

    ;;5. deszkriptor (stack segment 8Kb 200000h-nál kezdődik)
    STACK_SEL equ $-GDT_addr
    dw 02000h ;a szegmens hosszának alsó wordja (határ)
    dw 0 ;a báziscím alsó wordje
    db 20h ;a báziscím felső wordjének alsó bájtja
    db 10010010b ;P=1, DPL=00, S=1, C/D=0, C/E=0, R/W=1, A=0
    db 01000000b ;G=0, D/B=1, AVL=0, reserved=0, határ=0000
    db 0 ;a báziscím felső wordjének felső bájtja

    ;;6. deszkriptor (screen segment 16Kb 0B8000h-nál kezdődik)
    SCREEN_SEL equ $-GDT_addr
    dw 04000h ;a szegmens hosszának alsó wordja (határ)
    dw 08000h ;a báziscím alsó wordje
    db 0Bh ;a báziscím felső wordjének alsó bájtja
    db 10010010b ;P=1, DPL=00, S=1, C/D=0, C/E=0, R/W=1, A=0
    db 01000000b ;G=0, D/B=1, AVL=0, reserved=0, határ=0000
    db 0 ;a báziscím felső wordjének felső bájtja
    GDT_end:

    GDT_ptr:
    dw GDT_end-GDT_addr ;GDT mérete
    dd GDT_addr ;GDT címe

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    A segmenseim határai csak 1MB, mert úgysem kell egyelőre több.
    Egyébként én most kezdetnek egy olyan progit írok, amely dos alatt átkapcsol védett módba majd vissza. Amíg ez nem megy, addig nem megyek tovább.
    Előre is köszi a válaszokat. :U

  • OddMan

    őstag

    válasz OddMan #27 üzenetére

    Még van egy-két kérdésem, ezeket ti már biztosan tudjátok.
    Elkezdtem tanulmányozni a védett módot. Sajnos a megszakítások és kivételek kezelése rész eléggé homályos számomra. Kivételkezelés valós módban nem volt. Nos akkor amit nem tudok, hogy mi az a minimum 16 kivétel amit az IDT-be fell kell vennem? Tudtok valami doksit, ahol van erről leírás? A köv. kérdésem, hogy, védett módban az int xxh parancsot már nem lehet használni ugye? Tehát a bios-t el lehet felejteni?

    A GDT-vel kapcsolatban még annyit szeretnék kérdezni, hogy idézet:
    ''szóval ezek a táblák nyugodtan lehetnek data sorokban, csak a bázisukat kell számítani, kivéve, ha mindig ugyanoda rakod).''
    Hogyan kell a bázist számolni és miért kell? Ez még valós módban történik ugye?

    Érdekelne a sorrend is, hogyan kezdjek egy védett modú asm progit:
    -Na először is én ellenőrzöm a proc típusát.
    -Utána a GDT fizikai címmé alakítása aztán a GDT beállítása az lgdt src paranccsal. A GDT struktúráját is elkészítettem.
    -A CR0 PE bitjének 1-be állításával védett módba kapcsolok.
    -A szegmens regiszterekbe betöltöm a kívánt szelektorokat.

    Ha egyenlőre nem akarok taszkokat és egyéb nyalánkságot, akkor érdemes egy 4GB-os code és egy data szegmens deszkriptor-t használni?

    Talán egyelőre ennyi. :DD
    Előre is nagyon köszi a segítséget! :U
    Ha valaki tud olyan helyet, ahol még lehet kapni a Dr. Kovács Magda 80386 I. és 80386/80486 II. című könyvét, az legyen szíves írja ide a bolt címét. :F

  • OddMan

    őstag

    Köszi mindenkinek a segítséget. Sikerült bootolnom és elindítani egy nagyon egyszerű saját kernel kezdeményt.
    Lenne még egy kis problémám. Valós módban hogyan kell használni a jmp far parancsot? Szal arra gondoltam, hogy a progimat az 1MB-on belül a F0000h címre szeretném betölteni és aztán ráadni a vezérlét a jmp far 0F0000h:0 paranccsal, de a nasm valamiért állandóan hibát ír ki. Távoli ugrást még sosem használtam ezért nem ismerem a parancs működését.

    A neten láttam egy példát, de nekem az sem működik jól.
    Iderakom egy részletét egy kicsit átírva, ahogy nekem kéne.

    section .text

    jmp far [OS32ADDR]

    section .data

    OS32ADDR: dw 0 ;IP
    dw 0F000 ;CS

    ;CS:IP = 0F000:0

  • OddMan

    őstag

    válasz OddMan #22 üzenetére

    Közben rájöttem, hogy miért nem látom a floppy tartalmát.

    000h 446 Machine Code and Associated Data.
    1BEh 16 Partition 1 Information. //ezek a byte-ok nálam végig nullák. Ez volt a baj szerintem.
    1CEh 16 Partition 2 Information.
    1DEh 16 Partition 3 Information.
    1EEh 16 Partition 4 Information.
    1FEh 2 Boot Signature AA55h.

    Szal az első 446 byte a boot code és a következő 4x16 byte pedig a particíós táblák elhelyezkedése mérete és a boot flag állapota van itt tárolva.
    Aztán jön a lezáró AA55h .

    Láttam egy kódot a nasm-hoz a neten, de valamit nem értek benne.
    iderakom:

    ; 3.ASM
    ; Load a program off the disk and jump to it

    ; Tell the compiler that this is offset 0.
    ; It isn't offset 0, but it will be after the jump.
    [ORG 0]

    jmp 07C0h:start ; Goto segment 07C0 ;Ezt az első ugrást nem értem. ha elugrik a 07C00h:start címre, akkor ott nincsen semmi. A következő code sorok már nem tudnak lefutni, mivel azok a 00000:0000 címre lettek betöltve vagy nem? Szal szerintem ez így nem múködik. Valki segítsen!

    start:
    .|. the segment registers
    mov ax, cs
    mov ds, ax
    mov es, ax


    reset: ; Reset the floppy drive
    mov ax, 0 ;
    mov dl, 0 ; Drive=0 (=A)
    int 16h ;
    jc reset ; ERROR => reset again


    read:
    mov ax, 1000h ; ES:BX = 1000:0000
    mov es, ax ;
    mov bx, 0 ;

    mov ah, 2 ; Load disk data to ES:BX
    mov al, 5 ; Load 5 sectors
    mov ch, 0 ; Cylinder=0
    mov cl, 2 ; Sector=2
    mov dh, 0 ; Head=0
    mov dl, 0 ; Drive=0
    int 13h ; Read!

    jc read ; ERROR => Try again


    jmp 1000h:0000 ; Jump to the program


    times 510-($-$$) db 0
    dw 0AA55h

  • OddMan

    őstag

    Éppen egy boot progit csinálok, amivel egy nagyon egyszerű kernelt szeretnék majd elindítani floppy lemezről, de nem tudom, hogy a floppy lemez melyik szektorára mit kell írni.
    Az első 512 byte az MBR ide kerül a boot progim, amit sikerült is elhelyeznem a <B>debug boot.exe 100 0 0 1</B> paranccsal. Viszont azt nem tudom, hogy a köv szektorok hogyan vannak. Szal gondolom ez után kell lenni valahol a 12bit-es fat táblának és utána kéne lennie valahol a mini kernelemnek ugye? Az egész kernel kezdeményt meg boot progit egyelőre csak 16bit-es és valós módban írtam meg.
    A másik dolog amit észrevettem, hogy a lemezre amire kiírom a debug-al a boot sectort, többet nem tudom megnézni a tartalmát. Ez mitől lehet? :F

    Tegnap linux-ban a dd parancsal megnéztem egy NTFS filerendszerű driveot, aminél az első 512 byte volt a boot sector és utána majdnem 32Kb-os területen keresztül csak 00 byte-ok voltak, utána jött az első partició boot sectora. Ebből arra következtetek, hogy minden filerendszernél máshogyan kell majd betölteni a boot filet ugye? ?F

Aktív témák