Keresés

Aktív témák

  • kisfurko

    senior tag

    Ne ijesszétek már el...
    Én írtam egy DOS extendert segítség nélkül (van beépített debuggere is, de az nem lesz kész már soha :D), szóval csak kitartás kell.

    Először is le kell tiltani minden megszakítást. Utána létre kell hozni a GDT-t, IDT-t, egy TSS-t (ha nem csak 0-ás privilégium szinten akarsz szüttyögni), ezeket betölteni a megfelelő regiszterekbe. A GDT-ben minimum kell egy kód és egy adat szegmens leírója, ha nem csak 0-ás p. szint van, akkor kell még egy-egy ezekből megfelelő jogosultságokkal. Az IDT-ben kell a megszakításoknak (mind a 16-nak) és az exception-öknek bejegyzés. Ha BIOS-t is akarsz használni, akkor nem árt egy int vagy call gate, amivel hívhatod virtual 86 módban a valós kódokat. Ha kultúrált vagy, akkor csinálsz LDT-t is (ez egy bejegyzés a GDT-ben) és betöltöd azt is a megfelelő regiszterbe. Ajánlatos még átprogramozni a PIC-eket, hogy ne olyan kretén helyeken jöjjenek az interruptok (ne ütközzön például a GP Fault-tal a HDD). A GDT, IDT, TSS (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).
    Kérdezz nyugodtan, sajnos forrást most nem tudok bemásolni, mert nincs bekötve az első, szeretett, kicsi HDD-m, de ha kell, akkor szívesen megteszem, remélem még működik.
    Sokat szoptam a témával, jelentősen lerövidítheti a fejlesztési idődet a segítség (mert okos intelék nem írnak le ám mindent...:(). Még az a szerencséd is megvan, hogy teljesen dokumentáltam, hogy később is megértsem.

    Szerk: úgyis kihagytam valamit, ha kell még a segítség, szólj!

    [Szerkesztve]

  • kisfurko

    senior tag

    válasz WN31RD #17 üzenetére

    Baromira attól függ a bonyolultság, hogy mire akarja használni. Sima memóriakezelés nem nagy ügy, a processzkezelés sem (ha egyáltalán multitaszk kell neki), de ez nem is lényeg. Gondolj egy C64-re például, abban nem volt se memóriakezelés (jó, a BASIC interpreter kezelte a sajátját), se processzkezelés, se IPC, mégis jól lehetett használni.
    Én is akartam saját operációs rendszert írni, de letettem róla, mert nem adnak ki elég információt a hardware-ekről. Meg azért is hagytam abba, mert a PC-vel ilyen szinten nem érdemes foglalkozni, diliházban végeztem volna az apró idiótaságok miatt. :DD
    De ameddig irogattam az extendert (az első lépés a védett módhoz), addig baromira élveztem, nagyon sokat tanultam, szinte kívülről fújom az x86 architektúrát.
    Egyszerűen csodálatos volt, amikor működött a V86 mód :))

  • kisfurko

    senior tag

    válasz RedAnt #20 üzenetére

    ''Emiatt szerintem pmodeban is eleg lesz 1 privilegiumszint''
    Azért ajánlanám a két szintet, mert ha stack hiba van (ami igen gyakori), akkor triple fault miatt reset a vége, és ekkor nem tudod, hol a hiba. Úgy célszerű csinálni, hogy először legyen meg a megfelelő IDT az exception-ök lekezeléséhez. Ezt úgy érdemes csinálni, hogy mondjuk:

    exception1:
    push 1
    jmp exceptionhandler
    exception2:
    push 2
    ...

    exceptionhandler:
    kiírni a CS:EIP-t, a regisztereket, meg egyéb dolgokat, amik jólesnek...:))

    Az IDT-be meg szépen beírkálod a címeket.
    Meg tanulásnak sem rossz a több privilégiumszint. Mert ahhoz kell a TSS (ami a V86-hoz is kell).
    Különben protected mode-ba lépni gyerekjáték, de hogy interaktív programot csináljál... Persze könnyen írhatsz egy billentyűkezelő interruptot pufferrel, meg egy karakterkiíró rutint, ami 0b8000h-tól rakja be a karaktereket (ilyet is csináltam, hogy a debugger csak maga fusson, minden segédrutin nélkül, így BIOS-t is lehet vele lépésről lépésre futtatni). Én inkább csináltam V86-os futtatást, hogy simán használhassam a BIOS rutinokat (meg esetleg a DOS-t).

    A NASM pedig tényleg jó, én megszokásból használtam tasm-ot.
    Igazából assemblert is akartam írni, meg linkert, talán egyszer még előveszem a ''project''-et :) Csak mostanság a 3D grafikával foglalkozom.
    Szóval, ha kell segítség, akkor nyugodtan szólj!

    [Szerkesztve]

  • kisfurko

    senior tag

    válasz OddMan #22 üzenetére

    Floppynál nincs MBR, az csak HDD-n van. Az MBR-ben a partíciók leírásai, és a boot szektor betöltője van. Igazából mindegy, mert fogja, betölti az első szektort, majd futtatja. Semmi másra nincs szükség, a FAT az a DOS része. Oda rakod a kerneled, ahová jólesik, neked kell betöltened a boot szektorbeli kóddal.
    Azért nem látja a lemez tartalmát, mert számára ismeretlen a formátum.
    Megszokásból csak a második sávon kezdik az adatokat, az első sávon csak a boot szektor van (HDD esetén MBR).

  • kisfurko

    senior tag

    válasz OddMan #23 üzenetére

    Úgy van megcsinálva az MBR, hogy a 0:7c00 címre tölti a boot szektort. Ezért ugrik a 07c0:start címre.
    Legegyszerűbb, ha olyan kódot írsz, ami relokálható (csak relativ címzések vannak benne), s akkor le van tojva, hova töltötték be a kódodat.

  • kisfurko

    senior tag

    válasz OddMan #27 üzenetére

    Hát....
    Ne tedd 0f0000h-ra a programod, mert ott a BIOS van...:D
    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.

  • kisfurko

    senior tag

    válasz OddMan #28 üzenetére

    Én úgy tudom, hogy az első 32 int vektor van lefoglalva. Itt [L]http://www.intel.com/design/Pentium4/documentation.htm?iid=ipp_dlc_procp4f+tech_doc

  • kisfurko

    senior tag

    válasz OddMan #31 üzenetére

    ''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ég nem nasm-oztam, mert mindent meg tudtam oldani tasm alatt, és át kellett volna szoknom. Egyszer olvastam végig a doksiját, és nem sokra emlékszem...

    Na, megnéztem amit küldtél, de szerintem semmi probléma. Hogyan futtatod? Ugye nem debuggerben? Mivel nem használod a GDT-t (mert nincs szegmens betöltés), ezért azzal még nem kell foglalkozni. Van valami memory manager (qemm, emm386 stb.) bent a memóriában? És honnan tudod, hogy pontosan hol szállt el? Valami emulátorból próbálkozol?

    [Szerkesztve]

  • kisfurko

    senior tag

    válasz OddMan #34 üzenetére

    ''Létezik egyáltalán olyan debugger, amit lehetne használni?''
    A probléma ott van, hogy védett módba csak valós módból lehet átkapcsolni, így csak olyan debuggert használhatsz, ami valós módú. De mivel átkapcsolsz, a szegmens regiszterek új értelmet nyernek, azokhoz kellene a megfelelő GDT stb. Ráadásul az interruptokat is engedélyezi (hiába volt cli, az csak virtuálisan, a programod szempontjából érvényes). A turbo debugger meg amúgy is elég béna (kicsi, valós módú programokhoz jó).
    Én úgy csináltam, hogy stack-re mentettem az engem érdeklő regiszetereket, majd vissza valós módba, ott pedig szépen, kényelmesen kibányásztam a védett módú stack helyéről a számokat.
    Az IDT az egy nagy tömb, felépítését tekintve olyan, mint a GDT. Ugyanúgy kell beállítani, mint a GDT-t (lidt). A bejegyzések szintén 8 byte-osak. Egy bejegyzés így néz ki:

    dw offszet also 16 bitje
    dw szelektor
    db 0 ; ez igazabol csak 5 bites, ez azt mondja meg, hogy call gate eseten hany dwordot (wordot) kell a ket kulonbozo szint verme kozott masolni (mert minden szintnek sajat verme van)
    db 0 ; a tipust es a priv. szintet adja meg, ugyanugy mint egy deszkriptornal. A tipus ertekei a kovetkezok lehetnek:
    ; 4 286 call gate
    ; 5 386 task gate
    ; 6 286 interrupt gate
    ; 7 286 trap gate
    ; 12 386 call gate
    ; 14 386 int gate
    ; 15 386 trap gate
    dw 0 ; offszet felso 16 bitje

    Szóval, baromira hasonló, de itt nem bázis és határ van, hanem szelektor és offszet. Ez a címe a kiszolgáló rutinnak, ide ugrik, a valós módban csak szelektor és offszet van pl. A típust állítsd interrupt gate-re (14)!

    A kivételek listája:

    0 osztás hiba
    1 debug trap
    2 NMI
    3 int3 utasítás
    4 into utasítás
    5 bound hiba
    6 érvénytelen utasítás
    7 device not available (taszkváltásnál kell, vagy koprocesszor emulációnál)
    8 double fault (hiba amikor éppen hibát szolgálsz ki)
    10 érvénytelen TSS
    11 szegmens nem aktív (a P bitje 0)
    12 stack hiba
    13 általános hiba (ez kell nagyon :DD)
    14 lapozási hiba
    16 FPU hiba
    Meg még van egy pár, de ezek a legfontosabbak. A 9-es és 15-ös nem maradt ki, az nincs. A legegyszerűbb, ha csinálsz egy 32 elemű IDT-t, az lefedi az összes (akár jövőbeni) kivételt. Ahogy ajánlottam feljebb, az összes rutin csak annyi, hogy beteszed a számát a kivételnek a verembe, majd ugrasz a közös rutinra. Érdemes a verembe piszmogni, mert amikor a kiszolgálóra jut a vezérlés, akkor csak az ''áll készen'', hiszen a szegmens regiszterek ismeretlen értéket tartalmaznak (és a CS nem írható). Vagy benyomatod a verembe a DS-t, majd szabad a pálya. Mindenképpen 0-ás priv. szint kell a kiszolgáláshoz (természetesen a cél CS-nek is 0-ás szintűnek kell lennie)! Persze az int3, into lehet alacsonyabb szinten, ott azt jelenti, hogy melyik a legalacsonyabb szint, ahol végrehajtható az utasítás.

    Van még egy lényeges dolog. Lehet, hogy tudsz róla, lehet, hogy nem. Amikor átváltasz másik módba, akkor a szegmensek megőrzik a régi tartalmukat. De itt ne csak a számra gondolj, amit betöltöttél, hanem azokra az értékekre, amit a deszkriptorban állítani tudsz (valós módban is ugyanúgy működik a határ ellenőrzés pl.). Hogy ez ne okozzon gondot, átváltás után szükség van egy szegmensközi ugrásra (far jmp pl.). Ha vissza is akarsz váltani, akkor szükséged lesz egy olyan deszkriptorra, ami egy valós módú szegmenst ír le. 64k-s határral, 16 bites móddal, 0-ás priv. szinttel. Lehet, hogy a fajtáját is be kell állítani, már nem emlékszem, hogy én hogyan csináltam.
    Kiváncsian várom a fejleményeket!

  • kisfurko

    senior tag

    válasz OddMan #38 üzenetére

    Nincs különbség, csak egyes nyomorék assemblerek kettősponttal viszik csak.
    Majd válaszolok a többire is, de egyelőre nincs időm, ne haragudj.

  • kisfurko

    senior tag

    válasz OddMan #37 üzenetére

    ''Most egy TSS-t szeretnék létrehozni, ami nem a 0-ás privilégium szinten futna.''
    Ezt nem értem...:)
    A TSS ahhoz kell, hogy mindenféle járulékos információt a taszkkal kapcsolatban tárolni tudjon a proci (Task State Segment). Itt tárolódik például az összes stack címe, vagy taszkváltáskor a regiszterek tartalma, de az I/O permission bitmap is (a V86 módnak). Tehát, ha akarsz 0-ás priv. szinten kívül más szintet, akkor kell egy TSS. A szükséges priv. szint stack mutatóit be kell állítani benne, majd a deszkriptor táblában létre kell hozni egy TSS bejegyzést, és ezt a címet (mint akár egy szegmens címét) be kell tölteni, csak nem egy szegmens regiszterbe, hanem a Task Register-be (pl. mov ax,TSS_SEG ltr ax). Ha nincs szükség az I/O permission bitmap-re, akkor állítsd a kezdetét a TSS határán túlra.
    A C-s dologhoz sajnos nem tudok semmit tanácsolni, én csak full assemblyben csináltam mindent. Ezt a GRUB-os dolgot említették sokan, biztos jó. :DD

Aktív témák