对已早期的 linux内核,由于gcc不支持16位的汇编代码,故而 boot.s 是采用 intel的汇编形式如下:
! boot.s ! ! It then loads the system at 0x10000, using BIOS interrupts. Thereafter ! it disables all interrupts, changes to protected mode, and calls the BOOTSEG = 0x07c0 SYSSEG = 0x1000 ! system loaded at 0x10000 (65536). SYSLEN = 17 ! sectors occupied. entry start start: jmpi go,#BOOTSEG go: mov ax,cs mov ds,ax mov ss,ax mov sp,#0x400 ! arbitrary value >>512 ! ok, we've written the message, now load_system: 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 ! now we want to move to protected mode ... ok_load: cli ! no interrupts allowed ! mov ax, #SYSSEG mov ds, ax xor ax, ax mov es, ax mov cx, #0x2000 sub si,si sub di,di rep movw mov ax, #BOOTSEG mov ds, ax lidt idt_48 ! load idt with 0,0 lgdt gdt_48 ! load gdt with whatever appropriate ! absolute address 0x00000, in 32-bit protected mode. mov ax,#0x0001 ! protected mode (PE) bit lmsw ax ! This is it! jmpi 0,8 ! jmp offset 0 of segment 8 (cs) gdt: .word 0,0,0,0 ! dummy .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) .word 0x0000 ! base address=0x00000 .word 0x9A00 ! code read/exec .word 0x00C0 ! granularity=4096, 386 .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) .word 0x0000 ! base address=0x00000 .word 0x9200 ! data read/write .word 0x00C0 ! granularity=4096, 386 idt_48: .word 0 ! idt limit=0 .word 0,0 ! idt base=0L gdt_48: .word 0x7ff ! gdt limit=2048, 256 GDT entries .word 0x7c00+gdt,0 ! gdt base = 07xxx .org 510 .word 0xAA55现在gnu的 as 和汇编都已经支持16位的汇编 ,为了统一 方便以后学习,现在将其改为at&t的语法格式:
#boot.s rewrite with at&t assemble (c) Aleishus 2013 #注意在16位汇编下 逻辑地址的段地址*16+逻辑地址的偏移量=物理地址,bois将程序加载到物理地址0x7c00 , 因此 逻辑段的地址就是BOOTSEG= 0x07c0 BOOTSEG = 0x07c0 SYSSEG = 0x1000 SYSLEN = 17 .code16 .global start .text start: ljmp $BOOTSEG,$go go: movw %cs ,%ax movw %ax ,%ds movw %ax ,%ss movw $0x500 ,%sp #ok loading system ... load_system: xorw %dx ,%dx movw $0x0002 ,%cx movw $SYSSEG ,%ax movw %ax ,%es xorw %bx ,%bx movw $0x200+SYSLEN,%ax int $0x13 jnc ok_load die:jmp die #ok we move to protected mode ok_load: cli movw $SYSSEG ,%ax movw %ax ,%ds xorw %ax ,%ax movw %ax ,%es movw $0x2000 ,%cx xorw %si ,%si xorw %di ,%di rep movsw movw $BOOTSEG ,%ax movw %ax ,%ds lidt idt_48-BOOTSEG lgdt gdt_48-BOOTSEG movw $0x0001 ,%ax lmsw %ax ljmp $8 ,$0 gdt: .quad 0x0000000000000000 .quad 0x00c09a00000007ff .quad 0x00c09200000007ff idt_48: .word 0 .long 0 gdt_48: .word 0x03f .long 0x7c00+gdt #org表示重 地510个字节开始 基地之 偏移地址0x1fe开始 填充引导标志共bois识别,刚好占一个扇区 512bit .org 510 .word 0xaa55下面是Makefile 文件
# Makefile for the simple example kernel. #AS86 =as86 -0 -a #LD86 =ld86 -0 AS =as LD =ld #LDFLAGS0 =-m elf_i386 -Ttext 0 -e startup_32 -s -x -M LDFLAGS0 =--oformat binary -e startup_32 -Ttext 0 LDFALGS1 =--oformat binary -e start -Ttext 0 all: Image #Image: boot system # dd bs=512 if=boot of=Image # objcopy -O binary system head # cat head >> Image Image: boot head dd bs=512 if=boot of=Image cat head >> Image disk: Image dd bs=8192 if=Image of=/dev/fd0 sync;sync;sync head.o: head.s $(AS) -o head.o head.s #system: head.o # $(LD) $(LDFLAGS0) head.o -o system > System.map head: head.o $(LD) $(LDFLAGS0) head.o -o head boot.o: boot.s $(AS) -o boot.o boot.s boot:boot.o $(LD) $(LDFALGS1) -o boot boot.o clean: rm -f Image boot head *.o