http://blog.csdn.net/ltbylc/article/details/8309257
0. 自己试着在win7下用NASM和minGW改写汇编和C混合编程,结果受挫了。还是先使用作者提供的工具构建吧。
1. 通过前2天的工作已经能使用NASM制作一个映像了,并且编写的汇编代码可以成为引导扇区代码。
2. 引导扇区代码中可以调用BIOS中断,读取软盘上其它扇区到内存中,根据FAT12文件系统格式得知,保存到软盘内的第一个文件的文件名一定从19逻辑扇区开始,且该文件的内容从逻辑扇区33开始。
3. 引导扇区可以将第一个保存的文件(kernel.sys=自己改的名字,功能是跳入保护模式并调用C语言编写的函数代码)读入内存并使之执行,找这个文件用到了一个技巧,不然通过文件系统结构分析出文件位置,并加载码就太复杂了。
4. 引导扇区代码如下ipl10.asm
- ; haribote-ipl
- ; TAB=4
- CYLS EQU 10
- ORG 0x7c00
- JMP entry
- DB 0x90
- DB "HARIBOTE"
- DW 512
- DB 1
- DW 1
- DB 2
- DW 224
- DW 2880
- DB 0xf0
- DW 9
- DW 18
- DW 2
- DD 0
- DD 2880
- DB 0,0,0x29
- DD 0xffffffff
- DB "HARIBOTEOS "
- DB "FAT12 "
- RESB 18
- entry:
- MOV AX,0
- MOV SS,AX
- MOV SP,0x7c00
- MOV DS,AX
- MOV AX,0x0820
- MOV ES,AX
- MOV CH,0
- MOV DH,0
- MOV CL,2
- readloop:
- MOV SI,0
- retry:
- MOV AH,0x02
- MOV AL,1
- MOV BX,0
- MOV DL,0x00
- INT 0x13
- JNC 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
- MOV CL,1
- ADD DH,1
- CMP DH,2
- JB readloop
- MOV DH,0
- ADD CH,1
- CMP CH,CYLS
- JB readloop
- MOV [0x0ff0],CH
- JMP 0xc200
- error:
- 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
- JMP fin
- msg:
- DB 0x0a, 0x0a
- DB "load error"
- DB 0x0a
- DB 0
- ;RESB 0x7dfe-$
- times 510-($-$$) db 0
- DB 0x55, 0xaa
5. 跳入保护模式代码如下asmhead.nas
(1)准备GDT
(2)用LGDT加载gdtr
(3)打开A20
(4)设置CR0的PE位
(5)跳转进入保护模式
- ; haribote-os boot asm
- ; TAB=4
- BOTPAK EQU 0x00280000
- DSKCAC EQU 0x00100000
- DSKCAC0 EQU 0x00008000
- CYLS EQU 0x0ff0
- LEDS EQU 0x0ff1
- VMODE EQU 0x0ff2
- SCRNX EQU 0x0ff4
- SCRNY EQU 0x0ff6
- VRAM EQU 0x0ff8
- ORG 0xc200 ;让引导扇区加载后从这里开始运行
- MOV AL,0x13 ;保存信息
- MOV AH,0x00
- INT 0x10
- MOV BYTE [VMODE],8
- MOV WORD [SCRNX],320
- MOV WORD [SCRNY],200
- MOV DWORD [VRAM],0x000a0000
- MOV AH,0x02
- INT 0x16 ; keyboard BIOS
- MOV [LEDS],AL
- MOV AL,0xff
- OUT 0x21,AL
- NOP
- OUT 0xa1,AL
- CLI
- CALL waitkbdout
- MOV AL,0xd1
- OUT 0x64,AL
- CALL waitkbdout
- MOV AL,0xdf ; enable A20
- OUT 0x60,AL
- CALL waitkbdout
- [INSTRSET "i486p"]
- LGDT [GDTR0]
- MOV EAX,CR0
- AND EAX,0x7fffffff
- OR EAX,0x00000001
- MOV CR0,EAX
- JMP pipelineflush
- pipelineflush:
- MOV AX,1*8
- MOV DS,AX
- MOV ES,AX
- MOV FS,AX
- MOV GS,AX
- MOV SS,AX
- MOV ESI,bootpack
- MOV EDI,BOTPAK
- MOV ECX,512*1024/4
- CALL memcpy
- MOV ESI,0x7c00
- MOV EDI,DSKCAC
- MOV ECX,512/4
- CALL memcpy
- MOV ESI,DSKCAC0+512
- MOV EDI,DSKCAC+512
- MOV ECX,0
- MOV CL,BYTE [CYLS]
- IMUL ECX,512*18*2/4
- SUB ECX,512/4
- CALL memcpy
- MOV EBX,BOTPAK
- MOV ECX,[EBX+16]
- ADD ECX,3
- SHR ECX,2
- JZ skip
- MOV ESI,[EBX+20]
- ADD ESI,EBX
- MOV EDI,[EBX+12]
- CALL memcpy
- skip:
- MOV ESP,[EBX+12]
- JMP DWORD 2*8:0x0000001b
- waitkbdout:
- IN AL,0x64
- AND AL,0x02
- JNZ waitkbdout
- RET
- memcpy:
- MOV EAX,[ESI]
- ADD ESI,4
- MOV [EDI],EAX
- ADD EDI,4
- SUB ECX,1
- JNZ memcpy
- RET
- ALIGNB 16
- GDT0:
- RESB 8
- DW 0xffff,0x0000,0x9200,0x00cf
- DW 0xffff,0x0000,0x9a28,0x0047
- DW 0
- GDTR0:
- DW 8*3-1
- DD GDT0
- ALIGNB 16
- bootpack:
6. C语言代码如下bootpack.c
- void io_hlt(void);
- void write_mem8(int addr,int data);
- void HariMain(void)
- {
- int i;
- for(i=0xa0000;i<=0xaffff;i++)
- {
- write_mem8(i,15);
- }
- for(;;)
- {
- io_hlt();
- }
- }
7. C语言中调用的io_hlt和write_mem8函数放到了如下代码中func.asm
- [FORMAT "WCOFF"]
- [INSTRSET "i486p"]
- [BITS 32]
- [FILE "naskfunc.nas"]
- global _io_hlt,_write_mem8
- [section .text]
- ;void io_hlt(void);
- _io_hlt:
- HLT
- RET
- ;void write_mem8(int addr,int data);
- _write_mem8:
- MOV ECX,[ESP+4]
- MOV AL,[ESP+8]
- MOV [ECX],AL
- RET
8. 在toolset文件夹内建立一个新文件夹,将上面所有的文件放在里边,编译链接接上面的文件,写个bat文件如下
- nasm -o ipl10.bin ipl10.asm
- nasm -o img.img img.asm
- ..\z_tools\nask.exe asmhead.nas asmhead.bin
- ..\z_tools\cc1.exe -I..\z_tools\haribote\ -Os -Wall -quiet -o bootpack.gas bootpack.c
- ..\z_tools\gas2nask.exe -a bootpack.gas bootpack.nas
- ..\z_tools\nask.exe bootpack.nas bootpack.obj
- ..\z_tools\nask.exe func.asm func.obj
- ..\z_tools\obj2bim.exe @..\z_tools\haribote\haribote.rul out:bootpack.bim stack:3136k map:bootpack.map bootpack.obj func.obj
- ..\z_tools\bim2hrb.exe bootpack.bim bootpack.hrb 0
- copy /B asmhead.bin+bootpack.hrb kernel.sys
9.这样除了中间文件外,生成img.img文件和kernel.sys文件。使用winImage打开img.img文件将kernel.sys文件加入到该img文件中。
10. 启动Bochs,呵呵看见屏幕白了,这可是从C代码里控制的啊!
11. asmhead中跳入保护模式的代码慢慢在深入掌握,不然会掉入细节里不能自拔了。
12. asmhead和C代码是通过copy /B进行链接的其中asmhead代码最后留了个标号bootpack,在这个标号后面C的目标代码被砍去文件头直接将代码链接到了这里,所以能实现从汇编跳转到C语言的目的。