%macro push_regs 0 pusha push gs push fs push es push ds %endmacro %macro pop_regs 0 pop ds pop es pop fs pop gs popa %endmacro SECTION .text extern idt_p global load_idt load_idt: lidt [idt_p] ret %macro kernel_stack 0 mov eax, [cur_cx] mov [eax], esp mov esp, [kernel_cx] %endmacro %macro proc_stack 0 mov [kernel_cx], esp mov eax, [cur_cx] mov esp, [eax] %endmacro %macro begin_isr 1 extern interrupt_%1 global isr%1 isr%1: cli push_regs mov eax, [cur_cx] mov [eax], esp mov esp, [kernel_cx] %endmacro extern cur_cx extern kernel_cx %macro end_isr 0 mov [kernel_cx], esp mov eax, [cur_cx] mov esp, [eax] pop_regs sti iretd %endmacro %macro define_basic_isr 1 begin_isr %1 call interrupt_%1 end_isr %endmacro ; ISR DEFINITIONS define_basic_isr 0 ; division by zero ;define_basic_isr 1 ;define_basic_isr 2 ;define_basic_isr 3 ;define_basic_isr 4 ;define_basic_isr 5 ;define_basic_isr 6 ;define_basic_isr 7 ;define_basic_isr 8 ;define_basic_isr 9 ;define_basic_isr 10 ;define_basic_isr 11 ;define_basic_isr 12 define_basic_isr 13 ; general protection fault begin_isr 14 ; page fault mov eax, cr2 ; page fault addr push eax call interrupt_14 add esp, 4 end_isr define_basic_isr 32 ; system timer define_basic_isr 33 ; keyboard controller define_basic_isr 38 ; floppy controller ; interrupt st00f x3 ;%macro push_regs 0 ; pusha ; EAX, ECX, EDX, EBX, ESP, EBP, ESI and EDI ; push gs ; push fs ; push es ; push ds ;endmacro ; [proc_esp + 15 *4] ; 15*4 = 60 extern syscall_table begin_isr 128 ; system call mov ebx, [cur_cx] ; get the current context's stack pointer mov eax, [ebx] mov long ebx, [eax + 60] ; syscall number push long [eax + 76] ; param 4 push long [eax + 72] push long [eax + 68] push long [eax + 64] ; param 1 mov eax, [syscall_table + ebx * 4] ; syscall address or eax, eax ; does the syscall exist? jz no_syscall ; nope call eax ; call the syscall ; push eax ; push mojmsg ;extern printf ; call printf ; cli ; hlt add esp, 16 ; pop params off kernel stack mov [kernel_cx], esp ; restore current context's stack mov ebx, [cur_cx] mov esp, [ebx] ; pop regs by hand; we want to return a value in eax pop ds pop es pop fs pop gs pop edi pop esi pop ebp add esp, 4 ; esp pop ebx pop edx pop ecx add esp, 4 ; eax sti iret no_syscall: ; stack is kinda dirty here >_> push ebx push syscallnummsg extern printf call printf add esp, 8 push nosyscall extern panic call panic ; Don't use ; Is this incredibly stupid? o_O global lowlevel_yield lowlevel_yield: mov [kernel_cx], esp mov eax, [cur_cx] mov esp, [eax] ; reverse of iretd pushfd push cs ; push .return ; push long 0x12 push .return push_regs mov eax, [cur_cx] mov [eax], esp mov esp, [kernel_cx] ; TODO: schedule next process here extern next_process call next_process mov [kernel_cx], esp mov eax, [cur_cx] mov esp, [eax] pop_regs ; if all processes are currently yielding, we need to sti ; for a while to let interrupts come through push ecx extern num_processes extern num_yielding mov ecx, [num_processes] cmp ecx, [num_yielding] ; push waste ; extern printf ; call printf jnz .nowait sti ; hlt ; wait for an interrupt mov ecx, 10 ; waste some cycles .loop nop loop .loop .nowait pop ecx sti iretd ;global lowlevel_yield .return ; begin_isr ; push ork ; extern printf ; call printf cli kernel_stack ret ;%macro end_isr 0 ; mov [kernel_cx], esp ; mov eax, [cur_cx] ; mov esp, [eax] ; pop_regs ; sti ; iret ;%endmacro SECTION .data waste db "%d %d\n", 10, 0 ork db "Oerk 0x%x", 10, 0 mojmsg db "Moi: 0x%x", 10, 0 nosyscall db "Missing syscall", 10, 0 syscallnummsg db "Syscall number is %d", 10, 0