qq:992591601 欢迎交流
2016-03-31作
2016-06-01、2016-06-27改
我总结了些基本原理:
1.软盘的第一个扇区为启动区
2.计算机读软盘是以512字节为单位来读写,所以第一个扇区为512字节
3.一张软盘1440KB,2880个扇区
4.第一扇区为启动区,加载操作系统用
5.启动区结束标志位55AA
一个简单的开机引导程序(这个算是很基本的了):
; hello-os ; TAB=4 ORG 0x7c00 ; bios 将程序加载到0x7c00 + 偏移地址执行 ;以下,FAT12格式引导程序专用代码 JMP entry DB 0x90 DB "HELLOIPL" ; name DW 512 ; size of a sector(must be 512byte) DB 1 ; size of a cluster(must be a sector) DW 1 ; FAT begin from 1st sector DB 2 ; FAT num DW 224 ; size of root directory DW 2880 ; size of disk(2880 sectors) DB 0xf0 ; type of disk DW 9 ; length of FAT(must be 9 sectors) DW 18 ; how many sectors with a track DW 2 ; head num DD 0 ; 不使用分区 DD 2880 ; size of disk(2880 sectors) DB 0,0,0x29 DD 0xffffffff DB "HELLO-OS " DB "FAT12 " RESB 18 ; 先空出18字节 ; the main part of the program entry: MOV AX,0 MOV SS,AX MOV SP,0x7c00 MOV DS,AX MOV ES,AX MOV SI,msg putloop: MOV AL,[SI] ADD SI,1 CMP AL,0 JE fin MOV AH,0x0e MOV BX,15 INT 0x10 JMP putloop fin: HLT ; 让CPU停止,等待指令 JMP fin ; 无限循环 msg: DB 0x0a, 0x0a DB "hello, world" DB 0x0a DB 0 RESB 0x7dfe-$ ; 填写0x00直到0x7dfe,0x7dfe – 0x7c00 = 510 DB 0x55, 0xaa ;bootsector end mark
解析:
org 0x7c00;
告诉nask,在开始执行的时候,将这些机器语言指令装载到内存哪一部分。
org是伪指令,是给编译器来读的,而不是给计算机执行的,
另外,操作系统的引导区域,是被固定分配在0x00007c00 - 0x00007dff
mov si,msg;
msg是标号,本质是一个数字。而标号的计算是依靠之前的org指令。
mov al,[si];
将si所指向地址存储单元中的数据送给al。
虽然我们可以用寄存器来指定内存地址,但可以用作此用途的寄存器只有bx,bx,di,si。
cmp al,0; je fin;
if(al == 0)
{
goto fin;
}
int指令中断显示字符。不多说。
hlt指令,让cpu停止动作。
makefile的用法:
2016.06.01
我加入自己的思想写下这样代码
sonnos.asm
org 07c00h CYLS EQU 10 ;以下,FAT12格式引导程序专用代码 JMP entry DB 0x90 DB "HELLOIPL" ; name DW 512 ; size of a sector(must be 512byte) DB 1 ; size of a cluster(must be a sector) DW 1 ; FAT begin from 1st sector DB 2 ; FAT num DW 224 ; size of root directory DW 2880 ; size of disk(2880 sectors) DB 0xf0 ; type of disk DW 9 ; length of FAT(must be 9 sectors) DW 18 ; how many sectors with a track DW 2 ; head num DD 0 ; 不使用分区 DD 2880 ; size of disk(2880 sectors) DB 0,0,0x29 DD 0xffffffff DB "HELLO-OS " DB "FAT12 " RESB 18 ; 先空出18字节 entry: mov ax,0 mov ss,ax mov sp,0x7c00 mov ds,ax ;read disk mov ax,0x0820 mov es,ax mov ch,0 ;柱面0 mov dh,0 ;磁头0 mov cl,2 ;扇区2 readloop: mov si,0 ;记录失败次数 retry: mov ah,0x02 ;ah=0x02:读入磁盘 mov al,1 ;a sector mov bx,0 mov dl,0x00 ;A驱动器 int 0x13 ;调用磁盘bios jnc next ;没出错跳转next add si,1 cmp si,5 ;大于则跳转 jae error mov ah,0x00 mov dl,0x00 int 0x13 ;重置驱动器 jmp retry next: mov ax,es add ax,0x0020 mov es,ax add cl,1 cmp cl,18 jbe readloop ; if cl <= 18 readloopへ mov cl,1 add dh,1 cmp dh,2 jb readloop ; if dh < 2 readloopへ mov dh,0 add ch,1 cmp ch,CYLS jb readloop ; if ch < CYLS readloopへ mov ax,cs ; print poem mov ds,ax mov es,ax call PrintStr ;jmp $ ; 读完软盘后从C language开始执行 mov [0x0ff0],ch jmp 0xc200 error: mov si,msg PrintStr: mov ax,BootPoem mov bp,ax mov cx,300 mov ax,01301h mov bx,00009h mov dh,10 mov dl,0 int 10h ret msg: db 0x0a, 0x0a db "load error" db 0x0a db 0 BootPoem: db "Hold fast to dreams" db 0x0a db "For if dreams die" db 0x0a db "Life is a broken-winged bird " db 0x0a db "That can never fly" db 0x0a db "Hold fast to dreams" db 0x0a db "For when dreams go" db 0x0a db "Life is a barren field" db 0x0a db "Frozen only with snow" db 0x0a times 510-($-$$) db 0 ; 接下来510字节写0 dw 0xaa55 ; 最后一个字0xaa55是引导程序结束标志
1,实现开机引导后,屏幕蓝色字体打印一首英文诗歌
2,使用nasm编译器,不像书中使用自制的nask
default : ../z_tools/make.exe img sonnos.bin : sonnos.asm Makefile ../z_tools/nasm.exe sonnos.asm -o sonnos.bin helloos.img : sonnos.bin Makefile ../z_tools/edimg.exe imgin:../z_tools/fdimg0at.tek wbinimg src:sonnos.bin len:512 from:0 to:0 imgout:helloos.img asm : ../z_tools/make.exe -r sonnos.bin img : ../z_tools/make.exe -r helloos.img run : ../z_tools/make.exe img copy helloos.img ..z_toolsqemufdimage0.bin ../z_tools/make.exe -C ../z_tools/qemu install : ../z_tools/make.exe img ../z_tools/imgtol.com w a: helloos.img clean : -del sonnos.bin src_only : ../z_tools/make.exe clean -del helloos.img