下面给出head部分的nasm源代码。其中的stack_start,main,printk都只是用于测试,,并不是linux中的,因为现在main等函数还没有。
head.asm
bits 32
[section .text]
global _idt,_gdt,_pg_dir,_tmp_floppy_area
_pg_dir:
startup_32:
mov eax,0x10 ;设置段寄存器
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
lss esp,[stack_start];此处的stack_start为测试用的,不是linux中的
call setup_idt ;建立idt,gdt表
call setup_gdt
mov eax,0x10 ;重新设置段寄存器
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
lss esp,[stack_start];此处的stack_start为测试用的,不是linux中的
xor eax,eax ;测试A20地址线是否打开
s1:
inc eax
mov [0x000000],eax
cmp eax,[0x100000]
je s1
mov eax,cr0 ;检测是否有数学协处理器
and eax,0x80000011
or eax,2
mov cr0,eax
call check_87
jmp after_page_table
check_87:
fninit
fstsw ax
cmp al,0
je s2
mov eax,cr0
xor eax,6
mov cr0,eax
ret
align 32
s2: db 0xDB,0xE4
ret
setup_idt: ;建立idt表,并加载
lea edx,[ignore_int]
mov eax,0x00080000
mov ax,dx
mov dx,0x8E00
lea edi,[_idt]
mov ecx,256
rp_sidt:
mov [edi],eax
mov [4+edi],edx
add edi,8
dec ecx
jne rp_sidt
lidt [idt_descr]
ret
setup_gdt: ;加载gdt
lgdt [gdt_descr]
ret
times 0x1000-($-$$) db 0
pg0:
times 0x2000-($-$$) db 0
pg1:
times 0x3000-($-$$) db 0
pg2:
times 0x4000-($-$$) db 0
pg3:
times 0x5000-($-$$) db 0
_tmp_floppy_area:
times 1024 db 0
after_page_table:
push 0
push 0
push 0
push L6
push main ;此处的main为测试用的,不是linux中的
jmp setup_paging
L6:
jmp L6
int_msg:
db "Unknown interrupt\n\r"
align 32
ignore_int: ;中断处理程序
push eax
push ecx
push edx
push ds
push ds
push fs
mov eax,0x10
mov ds,ax
mov es,ax
mov fs,ax
push int_msg
;call printk
pop eax
pop fs
pop es
pop ds
pop edx
pop ecx
pop eax
iret
align 32
setup_paging:
mov ecx,1024*5 ;把页目录表和4个页表清零
xor eax,eax
xor edi,edi
cld
rep
stosd
;初始化页目录表
mov dword [_pg_dir],pg0+7
mov dword [_pg_dir+4],pg1+7
mov dword [_pg_dir+8],pg2+7
mov dword [_pg_dir+12],pg3+7
;初始化页表
mov edi,pg3+4092
mov eax,0xfff007
std
s3:
stosd
sub eax,0x1000
jge s3
xor eax,eax
mov cr3,eax
mov eax,cr0
or eax,0x80000000
mov cr0,eax
ret
align 32
dw 0
idt_descr:
dw 256*8-1
dd _idt
align 32
dw 0
gdt_descr:
dw 256*8-1
dd _gdt
align 64
_idt: times 256 dq 0
_gdt:
dq 0x0000000000000000
dq 0x00c09a0000000fff
dq 0x00c0920000000fff
dq 0x0000000000000000
times 252 dq 0
main:
mov edi,(80 * 11 + 0)*2 +0xb8000
mov ah,0Ch
mov al,'f'
mov [gs:edi],ax
jmp $
times 512 db 0
stack_start:
dd stack_start
dd 0x10
将head.asm编译为.bin文件。然后,把head.bin写到软盘的第6个扇区开始的位置(即前面文章所提到的system.bin,在这里不把system.bin写到软盘。这里只是测试一下head,真正的应该是把head连接到system的最开始部分).
结果图: