红联Linux门户
Linux帮助

用nasm重写linux0.00

发布时间:2015-12-27 10:09:12来源:linux网站作者:tobacco

linux0.00由两个文件组成:boot.s(引导代码),head.s(运行代码)。程序最终在屏幕上不断打印A(任务1)和B(任务2)以及C(系统中断处理)。


boot.s代码:

bootseg equ 0x07c0 
sysseg equ 0x1000 
syslen equ 17 
start: 
jmp bootseg:go 
go: 
mov ax,cs 
mov ds,ax 
mov ss,ax 
mov sp,0x0400 

load_syetem: 
mov dx,0x0000 
mov cx,0x0002 
mov ax,sysseg 
mov es,ax 
xor bx,bx 
mov ax,0x200+syslen 
int 0x13 
jnc ok_load 
die: 
jmp die 

ok_load: 
cli 
mov ax,sysseg 
mov ds,ax 
xor ax,ax 
mov es,ax 
mov cx,0x2000 
sub si,si 
sub di,di 
rep movsb 

mov ax,bootseg 
mov ds,ax 
lidt [idt_48] 
lgdt [gdt_48] 
mov ax,0x0001 
lmsw ax 
jmp 8:0 

gdt: 
dw 0,0,0,0 
dw 0x07ff 
dw 0x0000 
dw 0x9a00 
dw 0x00c0 

dw 0x07ff 
dw 0x0000 
dw 0x9200 
dw 0x00c0 

idt_48: 
dw 0,0,0 
gdt_48: 
dw 0x7ff 
dw 0x7c00+gdt,0 
times 510-($-$$) db 0 
dw 0xaa55 


head.s代码:

LATCH equ 11930 
SCRN_SEL equ 0x18 
TSS0_SEL equ 0x20 
LDT0_SEL equ 0x28 
TSS1_SEL equ 0x30 
LDT1_SEL equ 0x38 
bits 32;设置处理器模式位模式为32位 
startup_32: 
mov eax,0x10 
mov ds,ax 
lss esp,[init_stack] 

call setup_idt 
call setup_gdt 
mov eax,dword 0x10 
mov ds,ax 
mov es,ax 
mov fs,ax 
mov gs,ax 
lss esp,[init_stack] 

mov al,0x36 
mov edx,0x43 
out dx,al 
mov eax,LATCH 
mov edx,0x40 
out dx,al 
mov al,ah 
out dx,al 

mov eax,0x00080000 
mov ax,timer_interrupt 
mov dx,0x8e00 
mov ecx,0x08 
lea esi,[idt+ecx*8] 
mov [esi],eax 
mov [esi+4],edx 
mov ax,system_interrupt 
mov dx,0xef00 
mov ecx,0x80 
lea esi,[idt+ecx*8] 
mov [esi],eax 
mov [esi+4],edx 

pushf 
and dword[esp],0xffffbfff 
popf 
mov eax,TSS0_SEL 
ltr ax 
mov eax,LDT0_SEL 
lldt ax 
mov dword[current],0 
sti 
push long 0x17 
push long init_stack 
pushf 
push long 0x0f 
push long task0 
iret 

setup_gdt: 
lgdt [lgdt_opcode] 
ret 
setup_idt: 
mov edx,ignore_int-$$;lea edx,[ignore_int] 
mov eax,0x00080000 
mov ax,dx 
mov dx,0x8e00 
mov edx,ignore_int-$$;lea edi,[idt] 
mov ecx,256 
rp_idt: 
mov [edi],eax 
mov [edi+4],edx 
add edi,8 
dec ecx 
jne rp_idt 
lidt [lidt_opcode] 
ret 

write_char: 
push gs 
push ebx 
mov ebx,SCRN_SEL 
mov gs,bx 
mov bx,[scr_loc] 
shl ebx,1 
mov [gs:ebx],al 
shr ebx,1 
inc ebx 
cmp ebx,2000 
jb .l1 
mov ebx,0 
.l1: 
mov [scr_loc],ebx 
pop ebx 
pop gs 
ret 

align 4 
ignore_int: 
push ds 
push eax 
mov eax,0x10 
mov ds,ax 
mov eax,67 
call write_char 
pop eax 
pop ds 
iret 

align 4 
timer_interrupt: 
push ds 
push eax 
mov eax,0x10 
mov ds,ax 
mov al,0x20 
out 0x20,al 
mov eax,1 
cmp [current],eax 
je .l1 
mov [current],eax 
jmp TSS1_SEL:0 
jmp .l2 
.l1: 
mov dword[current],0 
jmp TSS0_SEL:0 
.l2: 
pop eax 
pop ds 
iret 

align 4 
system_interrupt: 
push ds 
push edx 
push ecx 
push ebx 
push eax 
mov edx,0x10 
mov ds,dx 
call write_char 
pop eax 
pop ebx 
pop ecx 
pop edx 
pop ds 
iret 

current: dd 0 
scr_loc: dd 0 

align 4 
lidt_opcode: 
dw 256*8-1 
dd idt 
lgdt_opcode: 
dw (end_gdt-gdt)-1 
dd gdt 

align 8 
idt: 
times 256*8 db 0 
gdt: 
dq 0x0000000000000000 
dq 0x00c09a00000007ff 
dq 0x00c09200000007ff 
dq 0x00c0920b80000002 
dw 0x68,tss0,0xe900,0x0 
dw 0x40,ldt0,0xe200,0x0 
dw 0x68,tss1,0xe900,0x0 
dw 0x40,ldt1,0xe200,0x0 
end_gdt: 
times 128*4 db 0 
init_stack: 
dd init_stack 
dw 0x10 

align 8 
ldt0: 
dq 0x0000000000000000 
dq 0x00c0fa00000003ff 
dq 0x00c0f200000003ff 
tss0: 
dd 0 
dd krn_stk0,0x10 
dd 0,0,0,0,0 
dd 0,0,0,0,0 
dd 0,0,0,0,0 
dd 0,0,0,0,0,0 
dd LDT0_SEL,0x8000000 

times 128*4 db 0 

krn_stk0: 

align 8 
ldt1: 
dq 0x0000000000000000 
dq 0x00c0fa00000003ff 
dq 0x00c0f200000003ff 

tss1: 
dd 0 
dd krn_stk1,0x10 
dd 0,0,0,0,0 
dd task1,0x200 
dd 0,0,0,0 
dd usr_stk1,0,0,0 
dd 0x17,0x0f,0x17,0x17,0x17,0x17 
dd LDT1_SEL,0x8000000 
times 128*4 db 0 
krn_stk1: 
task0: 
mov eax,0x17 
mov ds,ax 
mov al,65 
int 0x80 
mov ecx,0xfff 
.l1: 
loop .l1 
jmp task0 

task1: 
mov al,66 
int 0x80 
mov ecx,0xfff 
.l2: 
loop .l2 
jmp task1 

times 128*4 db 0 
usr_stk1: 


将两个文件各自汇编为二进制文件格式,再将boot二进制代码写入映像文件的第一个扇区(前512字节),将head二进制代码紧接着boot代码写入映像文件。


NASM在Ubuntu上的安装与简单使用:http://www.linuxdiyf.com/linux/15191.html

linux下的汇编环境搭建(nasm):http://www.linuxdiyf.com/linux/13778.html