Autor Thema: IDT/ISR Assembler Problem  (Gelesen 10626 mal)

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« am: 14. July 2012, 14:45 »
Hallo,
ich wollte heute eigentlich einfach IDTs und ISRs in Assembler implementieren, habe aber ein seltsames Problem.
Hier erstmal der Code:
IDT_Zeiger:
dw 256*8-1
dd IDT

IDT:
times 256*8 db 0 ; Platzhalter für 256 IDTs mit jeweils 8 Bytes

_IDT_setzen:
; ebp+8  -> Typ und Attribute
; ebp+12 -> Selektor
; ebp+16 -> Adresse der Bahandlungsfunktion
; ebp+20 -> Nummer der IDT
push ebp
mov ebp, esp
push eax
push ebx
push ecx
mov ebx, IDT ; die Adresse der IDTs in ebx speichern
mov eax, [ebp+20] ; die Nummer der IDT in eax speichern
mov cx, 8
mul cx
add ebx, eax ; ebx ist jetzt die Startadresse der IDT
mov eax, [ebp+16]
and eax, 0xFFFF
mov [ebx], word ax ; den ersten Teil der Adresse speichern
mov ax, [ebp+12]
mov [ebx+2], word ax
mov [ebx+4], byte 0
mov al, [ebp+8]
mov [ebx+5], byte al
mov eax, [ebp+16]
rol eax, 8
and eax, 0xFFFF
mov [ebx+6], word ax
pop ecx
pop eax
pop ebx
mov esp, ebp
pop ebp
ret 16

IDT_installieren:
IDT_setzen 0, ISR0, 0x08, 0x8E
lidt [IDT_Zeiger]
ret

ISR0:
Text_schreiben "Funktioniert! :)", 0, 1, 0xF
ret

und in der main.asm
mov ax, 1
mov dx, 0
div dx

Es passiert nur leider nichts, also habe ich mir mal die Bochslogs angeschaut. Es gibt tatsächlich die exception 0, aber der Rest sieht nicht gut aus:
03471086138d[CPU0 ] protected mode activated
03471086157d[MEM0 ] allocate_block: used_blocks=0x3 of 0x20
03471152232d[CPU0 ] exception(0x00): error_code=0000
03471152232d[CPU0 ] interrupt(): vector = 00, TYPE = 3, EXT = 1
03471152232d[CPU0 ] interrupt(): INTERRUPT TO SAME PRIVILEGE
03471152235d[CPU0 ] BxError: Encountered an unknown instruction b1=0xff (signalling #UD)
03471152235d[CPU0 ] modrm was 0xff, nnn was 7, rm was 7
03471152235i[CPU0 ] 0x00000000d20009d2>> (invalid)  : FFFF
03471152235d[CPU0 ] exception(0x06): error_code=0000
03471152235d[CPU0 ] interrupt(): vector = 06, TYPE = 3, EXT = 1
03471152235e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x06)
03471152235d[CPU0 ] exception(0x0d): error_code=0032
03471152235d[CPU0 ] interrupt(): vector = 0d, TYPE = 3, EXT = 1
03471152235e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
03471152235d[CPU0 ] exception(0x0d): error_code=006a
03471152235d[CPU0 ] exception(0x08): error_code=0000
03471152235d[CPU0 ] interrupt(): vector = 08, TYPE = 3, EXT = 1
03471152235e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
03471152235d[CPU0 ] exception(0x0d): error_code=0042
03471152235i[CPU0 ] CPU is in protected mode (active)
03471152235i[CPU0 ] CS.mode = 32 bit
03471152235i[CPU0 ] SS.mode = 32 bit
03471152235i[CPU0 ] | EAX=00000001  EBX=00000000  ECX=00090002  EDX=000f0000
03471152235i[CPU0 ] | ESP=001fffef  EBP=00000000  ESI=000e93f2  EDI=0000ffac
03471152235i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
03471152235i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
03471152235i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 ffffffff 1 1
03471152235i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
03471152235i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
03471152235i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 ffffffff 1 1
03471152235i[CPU0 ] |  FS:0000( 0000| 0|  0) 00000000 00000000 0 0
03471152235i[CPU0 ] |  GS:0000( 0000| 0|  0) 00000000 00000000 0 0
03471152235i[CPU0 ] | EIP=d20009d2 (d20009d2)
03471152235i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
03471152235i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
03471152235i[CPU0 ] 0x00000000d20009d2>> (invalid)  : FFFF
03471152235d[CTRL ] searching for component 'cpu' in list 'bochs'
03471152235d[CTRL ] searching for component 'reset_on_triple_fault' in list 'cpu'
03471152235p[CPU0 ] >>PANIC<< exception(): 3rd (13) exception with no resolution
03471152235e[CPU0 ] WARNING: Any simulation after this point is completely bogus !
03471152235p[CPU0 ] >>PANIC<< Entering to shutdown state still not implemented

Dann habe ich den Code in QEMU debugged und die Funktion IDT_installieren besteht nur aus Nullen. Ich weiß nicht, was am Code falsch sein sollte und kann mir auch nicht erklären, dass alles ab der Funktion IDT_installieren leer ist.
Auch kann ich mir die seltsame Position im Code nicht erklären, an der Bochs abbricht.
Danke schon mal für jede Hilfe. :)

EDIT:
Das Makro IDT_setzen:
%macro IDT_setzen 4
push dword %1
push dword %2
push dword %3
push dword %4
call _IDT_setzen
%endmacro

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 14. July 2012, 16:54 »
Dann habe ich den Code in QEMU debugged und die Funktion IDT_installieren besteht nur aus Nullen.
Du benutzt nicht zufällig einen selbstgeschriebenen Bootloader?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 14. July 2012, 16:59 »
Doch. Aber dieses Problem habe ich soeben gelöst.
IDT_setzen 0, ISR0, 0x08, 0x8E
Damit gibt es Probleme. Wenn ich eine eins statt 0 einsetze, gibt es keine Probleme, ich weiß aber nicht, wie ich eine "Debug Exception" hinbekommen soll...

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 14. July 2012, 20:04 »
Ah, Problem gelöst. :)
rol eax, 8
in der Funktion _IDT_setzen ist natürlich Blödsinn.
shr eax, 16
Damit funktioniert's
« Letzte Änderung: 14. July 2012, 22:42 von üäpöol »

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 16. July 2012, 17:10 »
Leider hören die Probleme nicht auf ...
Ich bekomme ständig exceptions ohne offensichtlichen Grund. Ich vermute, dass ich irgendetwas vergessen habe.
Grundsätzlich funktioniert schon alles, ich kann sogar einen funktionierenden Timer programmieren, aber wenn ich z.B. eine Taste drücke, wird sofort die Fehlermeldung "Coprocessor Fault Exception" ausgegeben. Außerdem muss ich nach jedem IRQ wieder die Interrupts frei geben (sti), da es ansonsten keine neuen Interrupts gibt. Hier der gesamte Code:

IDT_Zeiger:
dw 256*8-1
dd IDT

IDT:
times 256*8 db 0 ; Platzhalter für 256 IDTs mit jeweils 8 Bytes

_IDT_setzen:
; ebp+8  -> Typ und Attribute
; ebp+12 -> Selektor
; ebp+16 -> Adresse der Bahandlungsfunktion
; ebp+20 -> Nummer der IDT
push ebp
mov ebp, esp
push eax ; die Register sichern
push ebx
push ecx
mov ebx, IDT ; die Adresse der IDTs in ebx speichern
mov ax, [ebp+20] ; die Nummer der IDT in eax speichern
mov ecx, 8
mul ecx
add ebx, eax ; ebx ist jetzt die Startadresse der IDT
mov eax, [ebp+16]
and eax, 0xFFFF
mov [ebx], word ax ; den ersten Teil der Adresse speichern
mov ax, [ebp+12]
mov [ebx+2], word ax ; den Selektor speichern
mov [ebx+4], byte 0 ; den reservierten Speicher auf 0 setzen
mov eax, [ebp+8]
mov [ebx+5], byte al ; Typ und Attribute speichern
mov eax, [ebp+16]
shr eax, 16
and eax, 0xFFFF
mov [ebx+6], eax ; den zweiten Teil der Adresse speichern
pop ecx ; die Register zurücksetzen
pop eax
pop ebx
mov esp, ebp
pop ebp
ret 16

Interrupts_installieren:
IDT_setzen 0, ISR0, 0x08, 0x8E
IDT_setzen 1, ISR1, 0x08, 0x8E
IDT_setzen 2, ISR2, 0x08, 0x8E
IDT_setzen 3, ISR3, 0x08, 0x8E
IDT_setzen 4, ISR4, 0x08, 0x8E
IDT_setzen 5, ISR5, 0x08, 0x8E
IDT_setzen 6, ISR6, 0x08, 0x8E
IDT_setzen 7, ISR7, 0x08, 0x8E
IDT_setzen 8, ISR8, 0x08, 0x8E
IDT_setzen 9, ISR9, 0x08, 0x8E
IDT_setzen 10, ISR10, 0x08, 0x8E
IDT_setzen 11, ISR11, 0x08, 0x8E
IDT_setzen 12, ISR12, 0x08, 0x8E
IDT_setzen 13, ISR13, 0x08, 0x8E
IDT_setzen 14, ISR14, 0x08, 0x8E
IDT_setzen 15, ISR15, 0x08, 0x8E
IDT_setzen 16, ISR16, 0x08, 0x8E
IDT_setzen 17, ISR17, 0x08, 0x8E
IDT_setzen 18, ISR18, 0x08, 0x8E
IDT_setzen 19, ISR19, 0x08, 0x8E

push ax

mov al, 17
out 0x20, al
out 0xA0, al

mov al, 0x20
out 0x21, al
mov al, 0x28
out 0xA1, al

mov al, 4
out 0x21, al
mov al, 2
out 0xA1, al

mov al, 1
out 0x21, al
out 0xA1, al

mov al, 0
out 0x21, al
out 0xA1, al

pop ax

IRQ_setzen 0, IRQ_allgeimer_Handler
IRQ_setzen 1, IRQ_allgeimer_Handler
IRQ_setzen 2, IRQ_allgeimer_Handler
IRQ_setzen 3, IRQ_allgeimer_Handler
IRQ_setzen 4, IRQ_allgeimer_Handler
IRQ_setzen 5, IRQ_allgeimer_Handler
IRQ_setzen 6, IRQ_allgeimer_Handler
IRQ_setzen 7, IRQ_allgeimer_Handler
IRQ_setzen 8, IRQ_allgeimer_Handler
IRQ_setzen 9, IRQ_allgeimer_Handler
IRQ_setzen 10, IRQ_allgeimer_Handler
IRQ_setzen 11, IRQ_allgeimer_Handler
IRQ_setzen 12, IRQ_allgeimer_Handler
IRQ_setzen 13, IRQ_allgeimer_Handler
IRQ_setzen 14, IRQ_allgeimer_Handler
IRQ_setzen 15, IRQ_allgeimer_Handler

lidt [IDT_Zeiger]

sti
ret

IRQ_allgeimer_Handler:
push ax
mov al, 0x20
out 0x20, al
pop ax
sti
ret

_IRQ_setzen:
; ebp+8 -> Zeiger auf Funktion
; ebp+12 -> IRQ Nummer
push ebp
mov ebp, esp
push eax
push ebx
mov eax, [ebp+12]
add eax, 32
mov ebx, [ebp+8]
IDT_setzen eax, ebx, 0x08, 0x8E
pop ebx
pop eax
mov esp, ebp
pop ebp
ret 8

ISR0:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Division By Zero Exception.", 0, 0, 0xF
hlt

ISR1:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Debug Exception.", 0, 0, 0xF
hlt

ISR2:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Non Maskable Interrupt Exception.", 0, 0, 0xF
hlt

ISR3:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Breakpoint Exception.", 0, 0, 0xF
hlt

ISR4:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Into Detected Overflow Exception.", 0, 0, 0xF
hlt

ISR5:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Out of Bounds Exception.", 0, 0, 0xF
hlt

ISR6:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Invalid Opcode Exception.", 0, 0, 0xF
hlt

ISR7:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: No Coprocessor Exception.", 0, 0, 0xF
hlt

ISR8:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Double Fault Exception.", 0, 0, 0xF
hlt

ISR9:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Coprocessor Segment Overrun Exception.", 0, 0, 0xF
hlt

ISR10:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Bad TSS Exception.", 0, 0, 0xF
hlt

ISR11:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Segment Not Present Exception.", 0, 0, 0xF
hlt

ISR12:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Stack Fault Exception.", 0, 0, 0xF
hlt

ISR13:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: General Protection Fault Exception.", 0, 0, 0xF
hlt

ISR14:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Page Fault Exception.", 0, 0, 0xF
hlt

ISR15:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Unknown Interrupt Exception.", 0, 0, 0xF
hlt

ISR16:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Coprocessor Fault Exception.", 0, 0, 0xF
hlt

ISR17:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Alignment Check Exception.", 0, 0, 0xF
hlt

ISR18:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: Machine Check Exception.", 0, 0, 0xF
hlt

ISR19:
call Bildschirm_leeren
Text_schreiben "Folgender schwerer Kernelfehler ist aufgetreten: SIMD Floating Point.", 0, 0, 0xF
hlt

Ich finde einfach den/die Fehler nicht, kenne mich mit dem Thema aber auch nicht so gut aus.
Die andere Möglichkeit ist, dass es am Bootloader liegt, was ich aber eher nicht vermute.

Danke für jede Hilfe. :)

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 16. July 2012, 18:01 »
Das klingt danach als hättest du die IRQs nicht umgemappt. Im Real Mode sind die IRQs 0-7 auf die Interrupts 8-15 gemappt. Also ist der Keyboard IRQ auf Interrupt 9 gemappt. Das ist genau die Coprocessor Exception. Du solltest nochmal prüfen, ob der Code der den PIC initialisiert, auch tatsächlich aufgerufen wird.

Zu der Sache mit dem Interrupts wieder freigeben: Aus Interrupthandlern musst du mit IRET zurückkehren, nicht mit RET. Wenn du RET verwendest, hast du einmal das Problem mit den Flags, das du ja schon festgestellt hast, aber zusätzlich kommt noch, dass immer etwas auf dem Stack vergessen wird.
Dieser Text wird unter jedem Beitrag angezeigt.

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 16. July 2012, 18:15 »
Ah, OK. Danke. Der Code wird aufgerufen, aber ich bin mir nicht sicher, er auch funktioniert, denn im Bochs Log steht nichts davon. Wie kann ich das denn herausfinden?

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 16. July 2012, 18:42 »
Du könntest nach dem Initialisieren einen Breakpoint setzen und dann im Bochs Debugger info pic eingeben. In der Console von Qemu existiert dieser Befehl übrigens ebenfalls.
« Letzte Änderung: 16. July 2012, 18:43 von Jidder »
Dieser Text wird unter jedem Beitrag angezeigt.

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 16. July 2012, 22:11 »
Folgendes gibt der Bochs Debugger aus:
s.master_pic.imr = 00
s.master_pic.isr = 00
s.master_pic.irr = 00
s.master_pic.irq = 06
s.slave_pic.imr = 00
s.slave_pic.isr = 00
s.slave_pic.irr = 00
s.slave_pic.irq = 00

Stimmt das so? Ich fürchte nicht ...

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 16. July 2012, 23:07 »
Hm, ich glaube Bochs stellt die Information doch nicht zur Verfügung. Versuchs mal in Qemu. Das zeigt auch die Interruptzuordnung an.
Dieser Text wird unter jedem Beitrag angezeigt.

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 17. July 2012, 15:40 »
Bei QEMU wird mir nur "Undefined info command: "pic".  Try "help info"." ausgegeben.

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 17. July 2012, 16:52 »
Ach, hab's hinbekommen.
Folgendes wird ausgegeben:
pic0: irr=03 imr=00 isr=00 hprio=0 irq_base=20 rr_sel=0 elcr=0 fnm=0
pic1: irr=00 imr=00 isr=00 hprio=0 irq_base=28 rr_sel=0 elcr=0 fnm=0

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 17. July 2012, 17:45 »
Dann scheint das Umprogrammieren vom PIC wohl zu klappen, und du musst den Fehler wo anders suchen. Du könntest zum Beispiel mal ins Log von Qemu gucken, ob da tatsächlich der Interrupt 9 verzeichnis ist. Dazu musst du Qemu mit den Parametern -d int aufrufen. Es wird dann eine Datei qemu.log erstellt (unter linux /tmp/qemu.log). Die entsprechenden Zeilen sehen dann so aus
0: v=09 e=..., wobei das hinter dem v die Interruptnummer ist.
« Letzte Änderung: 17. July 2012, 17:47 von Jidder »
Dieser Text wird unter jedem Beitrag angezeigt.

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 17. July 2012, 18:32 »
In QEMU wird nachdem der Timer abgelaufen ist "Invalid Opcode Exception" ausgegeben und es wird auch tatsächlich Interrupt 6 ausgeführt. Seltsam ist dabei aber auch die EIP: EIP=0009f6e4.
Die höchste EIP sollte aber 11484 sein.
Es scheint, etwas gewaltig schief zu gehen.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 17. July 2012, 19:37 »
Wenn ich sowas sehe, ist meine erste Vermutung immer, dass irgendwas auf dem Stack schief geht. Meistens heißt das fehlerhafte Modifikationen am Stack Pointer. Insbesondere im Fall von Assemblerprogrammierung: nicht zueinander passende Paare von push/pop, call/ret oder int/iret. Zweite Möglichkeit wäre eine defekte IDT.
Dieser Text wird unter jedem Beitrag angezeigt.

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 17. July 2012, 20:08 »
Ich habe jetzt keine Fehler gefunden, habe jetzt aber auch nicht so viel Zeit. Ich poste hier jetzt mal einen der letzen CPU Status.
EAX=00000000 EBX=00000000 ECX=00000002 EDX=00000000
ESI=00000000 EDI=00000000 EBP=00000000 ESP=001ffff3
EIP=00011423 EFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0000 00000000 00000000 00000000
GS =0000 00000000 00000000 00000000
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     0001005d 00000017
IDT=     00010159 000007ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000000 CCD=00000001 CCO=EFLAGS 
EFER=0000000000000000
Ist das noch OK?

EDIT:
Ach, hab ich ganz vergessen.
Die "schlafen" Funktion. An der kann es natürlich auch liegen:
_schlafen:
push ebp
mov ebp, esp
push eax
mov al, [_schlafen_ausgeschlafen]
cmp al, 1
jne _schlafen_Zaehler_setzen
jmp _schlafen_Ueberpruefung
_schlafen_Zaehler_setzen:
IRQ_setzen 0, _schlafen_return
mov al, 0x36
out 0x43, al
mov al, 169
out 0x40, al
mov al, 4
out 0x40, al
_schlafen_Ueberpruefung:
mov ax, [_schlafen_geschlafen]
cmp ax, [ebp+8]
jl _schlafen_Ueberpruefung
mov byte [_schlafen_ausgeschlafen], 0
mov dword [_schlafen_geschlafen], 0
_schlafen_Ende:
pop eax
mov esp, ebp
pop ebp
ret 4

_schlafen_return:
mov byte [_schlafen_ausgeschlafen], 0
inc dword [_schlafen_geschlafen]
push ax
mov al, 0x20
out 0x20, al
pop ax
iret
« Letzte Änderung: 17. July 2012, 20:14 von üäpöol »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 17. July 2012, 22:48 »
An dem Registerdump ist auffällig, dass fast alle Register 0 sind und der Wert in ESP nicht durch 4 teilbar ist. Die Adressen von GDT und IDT sind ebenfalls krumm. Beides tut der Performance nicht unbedingt gut. Aber was fehlerhaftes ist da ohne weiteren Kontext nicht zu erkennen. (Zum Beispiel zu welchem Zeitpunkt ist der Stackframe aufgenommen, und was ist da interessantes passiert.)

Zu der Schlafen-Funktion: Die einzige Abstraktion, die du wohl akzeptierst, ist der klassische Stack Frame von Hochsprachen ... Meinste die Funktion kannst du wiederverwenden, wenn du mehr willst, als CPU-Zyklen verheizen beim Warten auf die Uhr? (Zum Beispiel Multitasking.) Das rumgefummel in der IDT gefällt mir überhaupt nicht, aber wenn es funktioniert, dann kann ich da auch nicht mehr zu sagen.
Dieser Text wird unter jedem Beitrag angezeigt.

üäpöol

  • Beiträge: 110
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 17. July 2012, 22:52 »
Was genau meinst du mit "rumgefummel"? Es funktioniert ja offensichtlich nicht ...

EDIT:
Zu IDT und GDT, was wären denn gerade Adressen?
« Letzte Änderung: 17. July 2012, 22:54 von üäpöol »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 17. July 2012, 23:14 »
Mit Rumgefummel meine ich das Verändern der IDT nach der Initialisierung. Das bezieht sich auf meine Anmerkung mit den Abstraktionen. Deine bisherige Verwendung von Timern unterstützt zum Beispiel kein Multitasking. Wenn du irgendwann mal Multitasking machen willst, kannst du deine komplette _schlafen-Funktion wegwerfen, weil der Scheduler erwartet die Hoheit über den Timer zu haben. Eine Abstraktion wäre also Prozesse/Threads einzuführen, die sich schlafen legen können. Eine andere Herangehensweise an Abstraktionen wäre Interrupts als Ereignisse aufzufassen. Prozesse (oder der Kernel) können dann Callbacks für Ereignisse (Timer-IRQs, Keyboard-IRQs) registrieren, die dann aufgerufen werden. Der Vorteil wäre, dass du dann ein Producer-Consumer-Modell aufbauen könntest und nicht mehr an Hardwaredetails wie zum Beispiel das Layout der IDT oder die Frequenz des Timers gebunden bist, und vor allem dass pro IRQ nur ein Handler installiert werden kann. Verändern der IDT und des PIC sind außerdem kritische Operationen, bei denen du eigentlich Interrupts deaktivieren müsstest, solange du Änderungen vornimmst.

Aber eine Abstraktion ist alles nicht notwendig und dein Ansatz ist nicht zwingend falsch (außer vielleicht das mit den Interrupts), deswegen mein Kommentar, dass ich da nichts gegen sagen kann, wenn es funktioniert.

Mit geraden Adressen meine ich Adressen, die auf Wortbreite ausgerichtet sind. Das heißt für x86, welche die Vielfaches von 4 sind. Der Hauptgrund für sowas ist Performance, weil die CPU sonst manchmal zwei Cachelines füllen muss, nur um ein Wort zu lesen.
Dieser Text wird unter jedem Beitrag angezeigt.

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 18. July 2012, 00:17 »
Sowohl GDT als auch IDT müssen ausgerichtet sein.
Wenn ich mich recht entsinne, auf eine 8-Byte-Grenze.

Gruß,
Svenska

 

Einloggen