Interrupt-Vector?



  • Hi!

    Ich hab mir gedacht, die Interrupt-Vektoren liegen bei adresse 0. Jeder Interrupt hat 4 bytes, also liegt der Tastaturint (9) bei 4*9=24h. Dort muss man wohl Segment/Offset eintragen.
    Aber das klappt leider nicht. 😞
    Wahrscheinlich habe ich die falsche adresse genommen. (24h hab ich mehr oder weniger geraten). An welche adresse muss ich Seg/Off eintragen, damit ich jeden Tastendruck bekomme? Gut wäre auch noch der Timerbaustein.
    Das ist übrigens für ein eigenes (sehr sehr kleines) OS, ich kann also im ganzen Speicher rumschreiben und keine DOS-ints aufrufen.

    [ Dieser Beitrag wurde am 01.06.2002 um 13:40 Uhr von cd9000 editiert. ]



  • wenn ich dich richtig verstanden habe möchtest du den interrupt umbiegen.
    dazu gibt es die funktion 35h des interrupt 21h.
    zunächst lädst du die adresse deiner eigenen prozedur nach dx
    mov dx, label
    mov ah, 25h
    mov al, 09h ;oder deinen interrupt
    int 21h
    über dir funktion 25h des interruot 21h bekommst du die adresse einer interrupt service routine. die solltest du dir vorher speichern, damit du sie später aufrufen kannst.



  • Mit deiner Formel landest Du schon an der richtigen Addresse der Interrupt Tabelle... (0000h:0024h)
    Vielleicht stimmt aber der Eintrag nicht ganz 😕
    Dort musst Du zuerst das Offset des Handlers und dann das Segment angeben. (LowOffs,HighOffs,LowSeg,HighSeg - jeweils ein Byte)

    hth



  • @Anubis: Ich habe doch extra dazugeschrieben, dass ich KEINEN dos-int aufrufen kann. Damit meinte ich vorrangig den int 21h.

    @Nobuo:
    Ich habe es genauso gemacht wie du gesagt hast. Warum funktioniert folgender Code trotzdem nicht?

    .model tiny
    .386
    .code
      org 0h
    
    Entry:
      jmp SkipData
    
      Message db "Kernel geladen!", 13, 10, 0
    
    SkipData:
      assume cs:@code, ds:@code, es:@code
      mov ax, cs
      mov ds, ax
      mov es, ax
    
      assume ds:0
      mov ax, seg    TastaturHandler
      mov dx, offset TastaturHandler
      mov bx, 24h
    
      mov cx, 0h
      mov ds, cx
    
      mov ds:[bx], dx   ; Erst das Offset
      mov ds:[bx+2], ax ; Dann das Segment des Handlers
    
    hang:
      jmp hang
    
    TastaturHandler proc far
      mov al, '!'
      mov ah, 0Eh
      mov bx, 7
      int 10h
      iret
    TastaturHandler endp
    
    end Entry ; Der Einsprungpunkt ist nur gegeben, damit tasm nicht meckert
    

    edit: Code tags richtiggemacht 🙂

    [ Dieser Beitrag wurde am 01.06.2002 um 17:18 Uhr von cd9000 editiert. ]



  • Mein TASM compiler wollte den Code irgendwie nicht compilieren (war iergendein Fehler mit den zugewiesenen Segmentregistern 😕 )
    Wie dem auch sei. ich habe mir mal erlaubt deinen Code ein bisschen umzuschreiben:

    IDEAL ;Ich find den MASM-Syntax einfach nur Schroecklich 🙄
    model tiny
    P386
    codeseg
    org 100h ;Ich hab das ganze als .com compiliert -> Start bei 100h

    Entry:
    jmp short @@SkipData

    Message db "Kernel geladen!", 13, 10, 0

    @@SkipData:
    mov ax, cs
    mov es, ax

    xor ax, ax
    mov ds, ax

    mov [word ptr ds:0024h],offset TastaturHandler + 7B00h ; Erst das Offset + 7B00h, da Code an addresse 7C00h liegt und TASM sowieso schon 0100h zur Addresse addiert (siehe org 100h)
    mov [word ptr ds:0026h],cs ; Dann das Segment des Handlers - ist imho gleich dem codesegment

    hang:
    jmp hang

    Proc TastaturHandler
    mov al, '!'
    mov ah, 0Eh
    mov bx, 7
    int 10h
    iret
    Endp TastaturHandler

    end Entry ; Der Einsprungpunkt ist nur gegeben, damit tasm nicht meckert

    Ich habe das jetzt nicht getestet, sollte aber eigentlich laufen 😉



  • Hmmmm...
    Kernel.asm wird von meinem Bootsektor geladen, es liegt an der adresse 1000h:0000h = 10000h.

    mov [word ptr ds:0024h], offset TastaturHandler + 7B00h
    

    Aber schau mal: Nehmen wir mal an offset TastaturHandler ergibt 31h. Jetzt noch 7B00 dazu ergibt 7B31. Segment gleich cs, also 7C0 (bei meinem bootsektor). 07C0:7B31 ergibt aber F731h. Da liegt sicher nicht der Handler.

    Der Code wird übrigens ganz sicher ausgeführt, die Message wird ausgegeben (den print code hab ich nur weggelassen).

    Nochmal der überarbeitete Code:

    IDEAL
    model tiny
    P386
    codeseg
      org 0h
    
      jmp 1000h:@@Entry ; Um sicherzugehen, dass das Segment 1000h ist
    @@Entry:
      assume cs:@code, ds:@code, es:@code
      mov ax, cs
      mov ds, ax
      mov es, ax
    
      ; Printcode der Message
    
      xor cx, cx
      mov ds, cx
    
      mov [word ptr ds:24h], offset TastaturHandler
      mov [word ptr ds:26h], seg    TastaturHandler
    
    @@hang:
      jmp @@hang
    
    proc TastaturHandler
      mov al, '!'
      mov ah, 0Eh
      mov bx, 7
      int 10h
      iret
    endp TastaturHandler
    
    end @@Entry
    

    Was ist eigentlich der Unterschied des IDEAL-Modes gegenüber des "normalen" modes? Kennst du eine Seite auf der das beschrieben ist?



  • btw:
    es funktioniert immer noch nicht. 😞
    Kam glaub ich im letzten Posting nicht rüber. 🙄



  • Es kam sehr wohl rueber (fuer mich zumindest) aber als Mod geht man lieber auf Nummer sicher...
    Ich habe nun also erstmal einen Code geschrieben, der dir die Werte der Segmentregister bim Bootup ausgibt, wartet, bis eine Taste gedrueckt wird und neu bootet. (den hab ich auch getestet)
    Code folgt:
    IDEAL
    model tiny
    P386
    codeseg
    org 100h

    Entry:
    jmp short @@SkipData

    HexData0 db "0123456789ABCDEF"
    Msgs0 db "CS:ES:DS:"

    @@SkipData:
    cli
    mov ax, cs
    mov ss, ax
    mov sp,0FFFEh
    sti

    push ds
    push es
    mov ax, cs
    mov ds, ax

    mov ax,0B800h
    mov es,ax

    xor di, di
    mov si,offset Msgs0 + 7B00h
    mov cx,0003h
    mov ah,0Ah
    @@WriteL0:
    lodsb
    stosw
    loop @@WriteL0

    mov bx, cs
    call HexWord0
    add di, 0008h

    mov si,offset Msgs0 + 7B03h
    mov cx,0003h
    mov ah,0Ah
    @@WriteL1:
    lodsb
    stosw
    loop @@WriteL1

    pop bx
    call HexWord0

    add di, 0008h

    mov si,offset Msgs0 + 7B06h
    mov cx,0003h
    mov ah,0Ah
    @@WriteL2:
    lodsb
    stosw
    loop @@WriteL2

    pop bx
    call HexWord0

    xor ax,ax
    int 16h
    int 19h

    Proc HexWord0 NEAR

    mov cx,0004h
    @@ConvertLoop0:
    mov si,offset HexData0 + 7B00h
    rol bx,04h
    mov dx,bx
    and dx,0004h
    add si,dx
    lodsb
    stosw
    loop @@ConvertLoop0
    ret

    ENDP HexWord0

    end Entry ; Der Einsprungpunkt ist nur gegeben, damit tasm nicht meckert

    Wenn du das laufen laesst steht da folgendes auf dem Bildschirm:
    cs:0000 ds:0000 es:0000
    ->nix mit code liegt bei 1000:0000
    Vielleicht ist das aus meinem letzten Post so nicht hervor gegangen, aber der Code vom Bootsektor wird vom Bios nach 0000:7C00 kopiert. 😉

    Aber schau mal: Nehmen wir mal an offset TastaturHandler ergibt 31h. Jetzt noch 7B00 dazu ergibt 7B31. Segment gleich cs, also 7C0 (bei meinem bootsektor). 07C0:7B31 ergibt aber F731h. Da liegt sicher nicht der Handler.

    Falsch! es werden eben NICHT nur 7B00 dazugerechnet. Du musst auch noch org 100h beruecksichtigen. Org 100h addiert zu allen Addressen 100h dazu. => Addresse + 7C00 (da faengt der Code an) - 100h = 7B00h
    Hoffe das war verstaendlich.

    Dann fehlt in deinem Code noch was wichtiges:
    Die Stack initialisation. (Hab ich zuerst uebersehen, sry)

    Als naechstes poste ich dann eine getestete Version deines codes.



  • Du hast mich doch nicht richtig verstanden. Ich habe bereits einen funktionierenden Bootsektor. Dieser lädt meinen Kernel an die adresse 1000h:0h. (ganz sicher!). Der Bootloader liegt bei 0:7c00 das ist klar, aber mein kernel wird ja manuell an 1000:0 geladen.

    Den interrupt kann ich immer noch nicht korrekt auf meinen Code umleiten 😞
    Den Stack initialisiere ich jetzt wie du gesagt hast.



  • Dann sag das doch 😮 Kann schliesslich keine Gedanken lesen 😃
    Egal. Es kann eigentlich nur noch an der Art und Weise liegen, in der du die Addresse deines Handlers bestimmst. Ich habe nun naemlich genau den Code, den ich oben gepostet hatte auf den Bootsektor gespiel und es hat funktioniert 🕶

    Ich denke, dass am "seg TastaturHandler" liegt. Probier doch einfach mal cs oder gleich 1000h in den Interruptvector zu schreiben.



  • 😞 😞 😞
    es will einfach nicht klappen!

    IDEAL
    model tiny
    P386
    codeseg
      org 0h
    
      jmp 1000h:@@Entry
    @@Entry:
      mov [word ptr 0:24h], offset TastaturHandler
      mov [word ptr 0:26h], 1000h ; seg TastaturHandler
    
      sti ; Interrupts zulassen
    @@hang:
      jmp @@hang
    
    proc TastaturHandler
      int 19h ; neustart
      iret
    endp TastaturHandler
    
    end @@Entry
    

    Sogar dieser kleine Code funktioniert einfach nicht 😞
    Aber woran kann das liegen?



  • Was passiert denn wenn man eine Taste drückt? Gar nichts?
    Wilde Vermutung: Ich hab mal gehört es soll nicht so gut sein Interrupts innerhalb von Interrupts aufzurufen. Versuch doch mal deinen INT Aufruf zu simulieren (pushf, und dann ein FAR CALL).



  • Es passiert gar nix, das ist es ja 😞

    Das mit den Interrupts in Interrupts klingt für mich plausibel. Ich werds gleich mal testen. (Ich bin gerad an nem anderen Rechner).



  • Ok ich hab mal folgenden test-Code geschrieben:

    IDEAL
    model tiny
    P386
    codeseg
      org 0h
    
    @@Entry:
      jmp @@SkipData
      Message db "Kernel geladen!", 13, 10, 0
    
    @@SkipData:
      assume cs:@code, ds:@code, es:@code
      mov ax, cs
      mov ds, ax
      mov es, ax
    
      mov eax, [0:19h*4h]
      ;mov [dword ptr Int19], eax
      mov [Int19], ax
      shr eax, 16
      mov [Int19+2], ax
      pushf
      db 0FFh
      Int19 dw ?, ?
    
    end @@Entry
    

    Da müsste doch eigentlich int 19h (neustart) aufgerufen werden? Aber es tut sich einfach nix 😞



  • hm. der Opcode fuer den far call stimmt ja wohl auch net.
    Ich wurde folgendes vorschlagen:

    IDEAL
    model tiny
    P386
    codeseg
    org 0h

    @@Entry:
    jmp @@SkipData
    Message db "Kernel geladen!", 13, 10, 0

    @@SkipData:
    assume cs:@code, ds:@code, es:@code
    mov ax, cs
    mov ds, ax
    mov es, ax

    mov eax, [0:19h*4h]
    mov [Int19], eax
    pushf
    call [dword ptr Int19]

    Int19 dd ?

    end @@Entry



  • Ich habs hingekriegt! Nach einigen Stunden Ausprobierens.

    IDEAL
    model tiny
    P386
    
    macro NewLine
      mov al, 13
      mov ah, 0Eh
      mov bx, 7
      int 10h
      mov al, 10
      mov ah, 0Eh
      mov bx, 7
      int 10h
    endm NewLine
    
    codeseg
      org 0h
    
    @@Entry:
      jmp @@SkipData
      StartMsg db "Kernel geladen, cs = ", 0
    
    @@SkipData:
      assume cs:@code, ds:@code, es:@code
      mov ax, cs
      mov ds, ax
      mov es, ax
    
      mov si, offset StartMsg
      call Print
    
      mov ax, 0
      mov ds, ax
    
      mov ax, cs
      mov es, ax
      mov ax, [word ptr 24h]
      mov [es:OldInt9], ax
      mov ax, [word ptr 26h]
      mov [es:OldInt9+2], ax
    
      cli
      mov [word ptr 24h], offset Int21Handler
      mov [word ptr 26h], 1000h
      sti
    
    @@hang:
      jmp @@hang
    
    ; Erwartet die Adresse des auszugebenden nullterminierten Puffers in DS:SI
    proc Print far
    @@PrintLoop:
      lodsb
      cmp al, 0
      je @@PrintEnde
      mov ah, 0Eh
      mov bx, 7
      int 10h
      jmp @@PrintLoop
    @@PrintEnde:
      retf
    endp Print
    
    TasteGedrueckt db "Taste gedrueckt!", 0
    proc Int9Handler far
    
      ; Den Original-Handler des BIOS aufrufen
      pushf
      db 09Ah         ; far call
      OldInt9 dw ?, ?
    
      mov si, offset TasteGedrueckt
    
      iret
    endp Int9Handler
    
    end @@Entry
    

    Ich weiß nicht so ganz wo der Fehler jetzt eigentlich lag. Vielleicht daran, dass ich nicht den alten int9 handler des BIOS aufgerufen habe.
    Ist ja auch egal, hauptsache es klappt 🙂 🙂



  • Aja jetzt fällts mir wieder ein, der Fehler ist folgender:
    [0:24h]
    Das wird vom TASM seltsamerweise zu [ds:24h] ausgewertet. Und da ds natürlich nicht 0 war hat es nicht geklappt.



  • Das wuerde nicht nur TASM so interpretieren. Ein Speicherzugriff wird immer aus einem Segmentregister und dem Offset errechnet.
    Ist mir gar nicht aufgefallen... In den ersten Codeausschnitten, die du gepostet hast, wars schliesslich auch noch richtig 😕



  • Naja ich versteh ja auch nicht so ganz warum es nicht geklappt hat, aber das ist doch jetzt eh egal 🙂

    Eine sache noch:
    Wenn ich den alten Handler des BIOS nicht aufrufe, reagiert er auf einen einzigen Tastendruck und dann hängt er sich (anscheinend) auf und macht nix mehr. Was macht denn der Handler des BIOS so wichtiges?



  • Dann poste doch bitte nochmal den richtigen code bzw. berichtige den im letzten Post...
    Da wird schliesslich irgendwie ein Offset von einem "Int21Handler" den ich da nirgends sehe in den Int9-Vector geschrieben und im int9Handler wird nur der alte int9 aufgerufen und dann si gesetzt. Also sollte eigentlich sowieso gar nichts passieren, wenn eine Taste gedrueckt wird. 😕


Anmelden zum Antworten