📄 kstart.asm
字号:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 32-bit kernel startup code;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%include "asm.inc"SECTION .text;SEGMENT _TEXT USE32 CLASS=CODE;BITS 32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; entry point;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GLOBAL entryentry:; check if data segment linked, located, and loaded properly mov eax,[ds_magic] cmp eax,DS_MAGIC je ds_ok; display a blinking white-on-blue 'D' and freeze mov word [0B8000h],9F44h jmp short $ds_ok:; stop using bootloader GDT, and load new GDT lgdt [gdt_ptr] mov ax,LINEAR_DATA_SEL mov ds,ax mov es,ax mov ss,ax mov fs,ax mov gs,ax jmp LINEAR_CODE_SEL:sbatsbat:; zero the C language BSS; 'bss' and 'end' are defined in the linker script fileEXTERN bss, end mov edi,bss mov ecx,end sub ecx,edi xor eax,eax rep stosb mov esp,stack; set up interrupt handlers, then load IDT register mov ecx,(idt_end - idt) >> 3 ; number of exception handlers mov edi,idt mov esi,isr0do_idt: mov eax,esi ; EAX=offset of entry point mov [edi],ax ; set low 16 bits of gate offset shr eax,16 mov [edi + 6],ax ; set high 16 bits of gate offset add edi,8 ; 8 bytes/interrupt gate add esi,(isr1 - isr0) ; bytes/stub loop do_idt lidt [idt_ptr]; GRUB 0.90 leaves the NT bit set in EFLAGS. The first IRET we attempt; will cause a TSS-based task-switch, which will cause Exception 10.; Let's prevent that: push dword 2 popfIMP main call main ; call C code jmp $ ; freeze;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Multiboot header for GRUB bootloader. This must be in the first 8K; of the kernel file. We use the aout kludge so it works with ELF,; DJGPP COFF, Win32 PE, or other formats.;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; these are in the linker script fileEXTERN code, bss, endALIGN 4mboot: dd MULTIBOOT_HEADER_MAGIC dd MULTIBOOT_HEADER_FLAGS dd MULTIBOOT_CHECKSUM; aout kludge. These must be PHYSICAL addresses dd mboot dd code dd bss dd end dd entry;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; interrupt/exception handlers;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IMP fault; I shouldn't have to do this!%macro PUSHB 1 db 6Ah db %1%endmacro%macro INTR 1 ; (byte offset from start of stub)isr%1: push byte 0 ; ( 0) fake error code PUSHB %1 ; ( 2) exception number push gs ; ( 4) push segment registers push fs ; ( 6) push es ; ( 8) push ds ; ( 9) pusha ; (10) push GP registers mov ax,LINEAR_DATA_SEL ; (11) put known-good values... mov ds,eax ; (15) ...in segment registers mov es,eax ; (17) mov fs,eax ; (19) mov gs,eax ; (21) mov eax,esp ; (23) push eax ; (25) push pointer to regs_t.1:; setvect() changes the operand of the CALL instruction at run-time,; so we need its location = 27 bytes from start of stub. We also want; the CALL to use absolute addressing instead of EIP-relative, so: mov eax,fault ; (26) call eax ; (31) jmp all_ints ; (33)%endmacro ; (38)%macro INTR_EC 1isr%1: nop ; error code already pushed nop ; nop+nop=same length as push byte PUSHB %1 ; ( 2) exception number push gs ; ( 4) push segment registers push fs ; ( 6) push es ; ( 8) push ds ; ( 9) pusha ; (10) push GP registers mov ax,LINEAR_DATA_SEL ; (11) put known-good values... mov ds,eax ; (15) ...in segment registers mov es,eax ; (17) mov fs,eax ; (19) mov gs,eax ; (21) mov eax,esp ; (23) push eax ; (25) push pointer to regs_t.1:; setvect() changes the operand of the CALL instruction at run-time,; so we need its location = 27 bytes from start of stub. We also want; the CALL to use absolute addressing instead of EIP-relative, so: mov eax,fault ; (26) call eax ; (31) jmp all_ints ; (33)%endmacro ; (38); the vector within the stub (operand of the CALL instruction); is at (isr0.1 - isr0 + 1)all_ints: pop eax popa ; pop GP registers pop ds ; pop segment registers pop es pop fs pop gs add esp,8 ; drop exception number and error code iret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; name: getvect; action: reads interrupt vector; in: [EBP + 12] = vector number; out: vector stored at address given by [EBP + 8]; modifies: EAX, EDX; minimum CPU: '386+; notes: C prototype:; typedef struct; { unsigned access_byte, eip; } vector_t;; getvect(vector_t *v, unsigned vect_num);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EXP getvect push ebp mov ebp,esp push esi push ebx mov esi,[ebp + 8]; get access byte from IDT[i] xor ebx,ebx mov bl,[ebp + 12] shl ebx,3 mov al,[idt + ebx + 5] mov [esi + 0],eax; get handler address from stub mov eax,isr1 sub eax,isr0 ; assume stub size < 256 bytes mul byte [ebp + 12] mov ebx,eax add ebx,isr0 mov eax,[ebx + (isr0.1 - isr0 + 1)] mov [esi + 4],eax pop ebx pop esi pop ebp ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; name: setvect; action: writes interrupt vector; in: [EBP + 12] = vector number,; vector stored at address given by [EBP + 8]; out: (nothing); modifies: EAX, EDX; minimum CPU: '386+; notes: C prototype:; typedef struct; { unsigned access_byte, eip; } vector_t;; getvect(vector_t *v, unsigned vect_num);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EXP setvect push ebp mov ebp,esp push esi push ebx mov esi,[ebp + 8]; store access byte in IDT[i] mov eax,[esi + 0] xor ebx,ebx mov bl,[ebp + 12] shl ebx,3 mov [idt + ebx + 5],al; store handler address in stub mov eax,isr1 sub eax,isr0 ; assume stub size < 256 bytes mul byte [ebp + 12] mov ebx,eax add ebx,isr0 mov eax,[esi + 4] mov [ebx + (isr0.1 - isr0 + 1)],eax pop ebx pop esi pop ebp ret;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; interrupt/exception stubs; *** CAUTION: these must be consecutive, and must all be the same size.;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INTR 0 ; zero divide (fault) INTR 1 ; debug/single step INTR 2 ; non-maskable interrupt (trap) INTR 3 ; INT3 (trap) INTR 4 ; INTO (trap) INTR 5 ; BOUND (fault) INTR 6 ; invalid opcode (fault) INTR 7 ; coprocessor not available (fault) INTR_EC 8 ; double fault (abort w/ error code) INTR 9 ; coproc segment overrun (abort; 386/486SX only) INTR_EC 0Ah ; bad TSS (fault w/ error code) INTR_EC 0Bh ; segment not present (fault w/ error code) INTR_EC 0Ch ; stack fault (fault w/ error code) INTR_EC 0Dh ; GPF (fault w/ error code) INTR_EC 0Eh ; page fault INTR 0Fh ; reserved INTR 10h ; FP exception/coprocessor error (trap) INTR 11h ; alignment check (trap; 486+ only) INTR 12h ; machine check (Pentium+ only) INTR 13h INTR 14h INTR 15h INTR 16h INTR 17h INTR 18h INTR 19h INTR 1Ah INTR 1Bh INTR 1Ch INTR 1Dh INTR 1Eh INTR 1Fh; isr20 through isr2F are hardware interrupts. The 8259 programmable; interrupt controller (PIC) chips must be reprogrammed to make these work. INTR 20h ; IRQ 0/timer interrupt INTR 21h ; IRQ 1/keyboard interrupt INTR 22h INTR 23h INTR 24h INTR 25h INTR 26h ; IRQ 6/floppy interrupt INTR 27h INTR 28h ; IRQ 8/real-time clock interrupt INTR 29h INTR 2Ah INTR 2Bh INTR 2Ch INTR 2Dh ; IRQ 13/math coprocessor interrupt INTR 2Eh ; IRQ 14/primary ATA ("IDE") drive interrupt INTR 2Fh ; IRQ 15/secondary ATA drive interrupt; syscall software interrupt INTR 30h; the other 207 vectors are undefined%assign i 31h%rep (0FFh - 30h) INTR i%assign i (i + 1)%endrep;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SECTION .data;SEGMENT _DATA USE32 CLASS=DATAds_magic: dd DS_MAGICgdt:; NULL descriptor dw 0 ; limit 15:0 dw 0 ; base 15:0 db 0 ; base 23:16 db 0 ; type db 0 ; limit 19:16, flags db 0 ; base 31:24; unused descriptor dw 0 dw 0 db 0 db 0 db 0 db 0LINEAR_DATA_SEL equ $-gdt dw 0FFFFh dw 0 db 0 db 92h ; present, ring 0, data, expand-up, writable db 0CFh ; page-granular (4 gig limit), 32-bit db 0LINEAR_CODE_SEL equ $-gdt dw 0FFFFh dw 0 db 0 db 9Ah ; present,ring 0,code,non-conforming,readable db 0CFh ; page-granular (4 gig limit), 32-bit db 0gdt_end:gdt_ptr: dw gdt_end - gdt - 1 dd gdt; 256 ring 0 interrupt gatesidt:%rep 256 dw 0 ; offset 15:0 dw LINEAR_CODE_SEL ; selector db 0 ; (always 0 for interrupt gates) db 8Eh ; present,ring 0,'386 interrupt gate dw 0 ; offset 31:16%endrepidt_end:idt_ptr: dw idt_end - idt - 1 ; IDT limit dd idt ; linear adr of IDT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SECTION .bss;SEGMENT _BSS USE32 CLASS=BSS resd 1024stack:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -