nach langwiriges debuggen habe ich einen fehler gefunden.
pusha hat nur 16bit-register gepusht, richtig wäre pushad gewesen.
einige assembler ignorieren das, einige anscheinend nicht.
nun stimmt auch die "regs" struktur wieder
in den protected mode komme ich via
mov eax, cr0 ; switch-over to Protected Mode
or eax, 1 ; set bit 0 of CR0 register
mov cr0, eax ;
jmp 0x8:ProtectedMode
[Bits 32]
ProtectedMode:
mov ax, 0x10
mov ds, ax ; data descriptor --> data, stack and extra segment
mov ss, ax
mov es, ax
xor eax, eax ; null desriptor --> FS and GS
mov fs, ax
mov gs, ax
mov esp, 0x1FFF00 ; set stack below 2 MB limit
da bochs seine address-anzeige auf 32 Bit erweitert, sieht man dass
er sich im protected-mode befindet. außerdem ist dieser teil
des codes nicht von dem compilerwechsel betroffen
(vor dem wechsel funktionierte das ganze komischerweise).
da sollte der fehler also nicht liegen.
vor dem cli (am anfang vom IRQ0 handler)
hat CS den wert 0x08 (DS, SS und ES sind 0x10). diese werte
stimmen mit der GDT überein.
Legst Du für die Nicht-Exception-Interrupts einen Pseudo-Error-Code auf den Stack? Viele machen das um im generischen Interrupthandler immer einen identischen Stack-Aufbau zu haben.
ja, im falle des IRQ0 lege ich zuerst 0 (fehlercode, DWORD), und dann
0x20 (nummer des interrupt, DWORD) auf den stack.
vor dem ersten push am anfang des stubs, also direkt am anfang des
interrupts zeigt esp auf 0x1ffe70. nachdem die struktur vollständig
auf dem stack liegt, und bevor sie an den C-handler übergeben wird,
enhält sie folgende werte:
gs : 00000000
fs : 00000000
es : 00000010
ds : 00000010
edi: 00008200 // basisaddresse des C-kernels, vllt hat edi solange überlebt
esi: 0000c800
ebp: 001ffe84
esp: 001ffe68
ebx: 00000000
edx: 00000013
ecx: 0000c40b
eax: 00000be4
int_nummer: 00000020 // stimmt
err_code: 00000000 // stimmt auch
eip: 0000b7af
cs : 00000008 // stimmt
flags: 00000206
useresp: 000b8000
ss : 00000be4
dieses gebilde liegt bei 0x1ffe38, d.h. der esp ist seit begin des interrupts
14 DWords gewandert. diese zahl entspricht der register (struct regs),
die manuell auf den stack gelegt werden.
bevor "IRET" ausgeführt wird, zeigt esp wieder auf 0x1ffe70.
danach fliegt sofort die exception, d.h. ich lande mit dem debugger wieder
beim "CLI" eines interrupt-stubs, (0xD -> GPF)
nach dem IRET und vor dem CLI haben die segmentregister jedoch
korrekte werte (CS = 0x8, DS, SS, ES = 0x10) ??
wenn ich im C-handler die regs-struktur dumpe, erhalte ich auch die
selben werte. verändern tue ich sie nicht...
padding ist auf 1 byte, und die größe der struktur stimmt auch
(19 DWORDs).
da ich im kernelmode bin, haben USERESP und SS keine werte vom
int bekommen...