一、启动区
ORG 0x7C00JMP entryDB 0x90DB "HELLOIPL"DW 512DB 1DW 1DB 2DW 224DW 2880DB 0xf0DW 9DW 18DW 2DD 0DD 2880DB 0,0,0x29DD 0xffffffffDB "HELLO-OS "DB "FAT12 "RESB 18entry:MOV AX, 0MOV SS, AXMOV SP, 0x7c00MOV DS, AXMOV AX, 0x0820MOV ES, AXMOV CH, 0 ;柱面0MOV DH, 0 ;磁头0MOV CL, 2 ;扇区2readloop:MOV AL, 1 ;扇区数量MOV BX, 0MOV DL, 0 ;A驱动器MOV AH, 0x02 ;读扇区INT 0x13JNC nexterror:MOV AH, 0x0eMOV AL, 'e'INT 0x10MOV AL, 'r'INT 0x10MOV AL, 'r'INT 0x10MOV AL, 'o'INT 0x10MOV AL, 'r'INT 0x10JMP finnext:MOV AX, ES ADD AX, 0x20 ;下一扇区MOV ES, AXADD CL, 1CMP CL, 18JBE readloopMOV CL, 1ADD DH, 1CMP DH, 2JB readloop ;读反面的磁头1MOV DH, 0ADD CH, 1CMP CH, 10 ;读10个柱面JB readloopJMP 0xc200fin:HLTJMP finRESB 0x7dfe-$DB 0x55, 0xaa
前面的一部分内容(entry之前)是img镜像文件的固定格式,后面是启动区的正式内容
使用循环的方式读磁盘,按扇区——磁头——柱面的顺序,一个磁头18个扇区,一个柱面两个磁头。
程序的最后跳转到0xc200,因为磁盘内容装载在0x8000,文件内容存在0x4200,所以kernal.com就在0x8000+0x4200=0xc200的位置
(二)操作系统本身
;kernal.nas[BITS 16]ORG 0xc200MOV AH, 0x0eMOV AL, 'A'INT 0x10fin:HLTJMP fin
输出一个A字符。
使用nasm kernal.nas -o kernal.com
的方式编译,装载到img文件中即可。程序的开始要指定ORG 0xc200, 这样汇编器才能正确把标签名对照到正确的地址。
(三)图形模式切换
切换到图形模式:
MOV AL, 0x13MOV AH, 0x00INT 0x10
分辨率320*200的VGA图形模式,VRAM的地址在0xa0000~0xaffff。
注意十六位下,用SI/DI寻址只能寻址到0x0000~0xffff的地址,所以要用寄存器寻址。
描画条纹图案:
MOV AX,0xA000MOV DS,AXMOV AL, 0x13MOV AH, 0x00INT 0x10MOV SI, 0x0000
L1:MOV BX, SIAND BL, 0x0fMOV BYTE[DS:SI], BLADD SI, 1CMP SI, 0xFFFFJBE L1
fin:HLTJMP fin
参考书中第四天的内容写的,不过暂时还未切换32位模式所以只能用汇编写。用[DS:SI]的方式寻址,16位下段号相当于[DS*16+SI],DS代入0xA000,SI代入0x0000,那么[DS:SI]就是[0xA0000]。
上一节是在80*25的字符模式下描画了一个文字A,这次我们尝试着在图形模式下描画文字A,参考第五天中文字显示的代码。
用汇编语言写比较复杂的循环可能是比较麻烦...(
实现如下:
其实主体的结构不难,最难的其实是内存段的处理,访问font_A的时候指定的是代码段寄存器CS,而访问显存需要指定数据段DS,还不能混用,如果给CS赋0xA0000就会出大问题。
[BITS 16]ORG 0xc200MOV AL, 0x13MOV AH, 0x00INT 0x10;font_AMOV CX, 0MOV AX, 0xa000MOV DS, AXMOV SI, 0x0000ADD SI, 8*320ADD SI, 8loop:CMP CX, 16JE finMOV BX, CXMOV BH, BYTE[CS:font_A+BX]AND BH, 0x80CMP BH, 0JE L1MOV BYTE[DS:SI+0], 15
L1:MOV BX, CXMOV BH, BYTE[CS:font_A+BX]AND BH, 0x40CMP BH, 0JE L2MOV BYTE[DS:SI+1], 15
L2:MOV BX, CXMOV BH, BYTE[CS:font_A+BX]AND BH, 0x20CMP BH, 0JE L3MOV BYTE[DS:SI+2], 15
L3:MOV BX, CXMOV BH, BYTE[CS:font_A+BX]AND BH, 0x10CMP BH, 0JE L4MOV BYTE[DS:SI+3], 15
L4:MOV BX, CXMOV BH, BYTE[CS:font_A+BX]AND BH, 0x08CMP BH, 0JE L5MOV BYTE[DS:SI+4], 15
L5:MOV BX, CXMOV BH, BYTE[CS:font_A+BX]AND BH, 0x04CMP BH, 0JE L6MOV BYTE[DS:SI+5], 15
L6:MOV BX, CXMOV BH, BYTE[CS:font_A+BX]AND BH, 0x02CMP BH, 0JE L7MOV BYTE[DS:SI+6], 15
L7:MOV BX, CXMOV BH, BYTE[CS:font_A+BX]AND BH, 0x01CMP BH, 0JE L8MOV BYTE[DS:SI+7], 15
L8:ADD CX, 1ADD SI, 320JMP loopfin:HLTJMP finfont_A:DB 0x00,0x18,0x18,0x18,0x18,0x24,0x24,0x24DB 0x24,0x7e,0x42,0x42,0x42,0xe7,0x00,0x00
话说在320*200的分辨率下,8*16的字符看上去确实很大==