Here is my asm handler for ISRs:
Code: Select all
; This macro creates a 'stub' for an ISR that does not
; push its own error code, a dummy error code (0) is used instead.
; NOTE: The general handler expects the interrupt number
; and error code on the stack.
%macro ISR_STUB_NOERRORCODE 1
[GLOBAL isr%1]
isr%1:
cli ; disable interrupts
push 0 ; push a dummy error code
push dword %1 ; push the interrupt number
jmp common_stub_isr ; use the common ISR handler to handle this ISR
%endmacro
; This macro creates a 'stub' for an ISR that pushes its own error code.
; NOTE: The general handler expects the interrupt number
; and error code on the stack.
%macro ISR_STUB 1
[GLOBAL isr%1]
isr%1:
cli ; disable interrupts
push dword %1 ; push the interrupt number
jmp common_stub_isr ; use the common ISR handler to handle this ISR
%endmacro
...
; set up the ISR/IRQ stubs
ISR_STUB_NOERRORCODE 0
ISR_STUB_NOERRORCODE 1
...
; a C function that writes a string to the console
[EXTERN debugconsole_writeline]
fmt: db 'AD', 0 ; Acronym for 'Assembly-Done', I print this out for debugging...
; Common ISR stub that saves all needed information to the stack then calls
; the C handler.
common_stub_isr:
pusha ; pushes edi, esi, ebp, esp, ebx, edx, ecx, eax
xor eax, eax
mov ax, ds ; save the data segment descriptor
push eax ; ...
; The kernel data segment is the 3rd gdt entry (index 2),
; each of which is 8 bytes. Thus its offfset is (2 * 8) = 16
; which is 0x10 in hex.
;
; We need to update all of the segment registers to reflect this.
;
; For now, these registers are always 0x10 (this is setup when
; the GDT is created, and hasn't been touched since; which
; technically makes this code redundant).
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
call IsrHandler ; call C code
; print a notification to the screen saying we got this far
; NOTE: This does result in 'AD' being printed to the screen.
push fmt
call debugconsole_writeline
add esp, 4
pop eax ; reload the original segment descriptors
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; print a notification to the screen saying we got this far
; Starting here, AD is no longer printed (which is why
; I have come to believe the code above is the culprit)
push fmt
call debugconsole_writeline
add esp, 4
popa ; pops edi, esi, ebp, esp, eb, edx, ec, eax
add esp, 8 ; cleans up the pushed error code and ISR number
; print a notification to the screen saying we got this far
push fmt
call debugconsole_writeline
add esp, 4
sti ; enable interrupts
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
So my guess is that my problem lies in:
Code: Select all
pop eax ; reload the original data segment descriptor
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
I would greatly appreciate it if someone could send me in the right direction as far as where to hunt some bugs!
Thanks!