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