03day 进入32位模式并导入C语言
来源:互联网 发布:手游刷金币的软件 编辑:程序博客网 时间:2024/05/31 06:24
从启动区执行操作系统
ipl:
; haribote-ipl; TAB=4CYLS EQU 10 ; ORG 0x7c00 ; 我们将磁盘映像的启示512字节加载到Boot Sector Entry中; 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 ; init MOV SS,AX MOV SP,0x7c00 MOV DS,AX; MOV AX,0x0820 MOV ES,AX MOV CH,0 ; 柱面 0 MOV DH,0 ; 磁头 0 MOV CL,2 ; 扇区 2(扇区从1开始到18)readloop: MOV SI,0 ; retry: MOV AH,0x02 ; AH=0x02 : MOV AL,1 ; MOV BX,0 MOV DL,0x00 ; INT 0x13 ; JNC next ; ADD SI,1 ; CMP SI,5 ; JAE error ; SI >= 5 MOV AH,0x00 MOV DL,0x00 ; INT 0x13 ; JMP retrynext: MOV AX,ES ; ADD AX,0x0020 MOV ES,AX ; ADD ES,0x020 写入位置向后移动512字节 ADD CL,1 ; 写入扇区+1 CMP CL,18 ; CL大于18 ? JBE readloop ; CL <= 18 MOV CL,1 ADD DH,1 CMP DH,2 ;CL=1 磁头+=1 磁头>=2 ? JB readloop ; DH < 2 MOV DH,0 ADD CH,1 CMP CH,CYLS ;CYLS=10 我们要读取10个柱面 JB readloop ; CH < CYLS ; 执行到这里说明我们读取完成; 10*2*18*512/1024=180KB 我们将磁盘中180KB读取到0x08200~0x34fff ; 那0x08000~0x081fff 呢 这部分是留给启动区的 要将这512字节留给启动区; 通过我们的观察 操作系统的代码的启示位置位于文件偏移的0x4200处,加载后的内存位置应该是; 0x8000+0x4200=0xc200; 所以这里我们要跳转到操作系统的代码起始处 c200 MOV [0x0ff0],CH ; CH=10 JMP 0xc200 ;到这里 error: MOV SI,msgputloop: MOV AL,[SI] ADD SI,1 ; CMP AL,0 JE fin MOV AH,0x0e ; MOV BX,15 ; INT 0x10 ; JMP putloopfin: HLT ; JMP fin ; msg: DB 0x0a, 0x0a ; DB "load error" DB 0x0a ; DB 0 RESB 0x7dfe-$ ; DB 0x55, 0xaa
启动区的制作大体就是这样 读取我们的操作系统 然后跳转到操作系统代码的入口处。
这里示例的代码很简单。
haribote.nas
; haribote-os; TAB=4 ORG 0xc200 ; 写入内存位置 MOV AL,0x13 ; al=13 调用显卡设置模式 ; al=0x13 VGA图形模式 320*200*8 彩色模式 调色板模式 MOV AH,0x00 INT 0x10fin: HLT JMP fin
32位模式前期准备
一旦使用32位模式就不能调用BIOS功能了,因为BIOS是用16位机器语言写的,在进入BIOS前 我们要获取我们想获取的信息。
; haribote-os; TAB=4; BOOT_INFOCYLS EQU 0x0ff0 ; 把我们需要的信息保存在0X0FF* 的区域LEDS EQU 0x0ff1VMODE EQU 0x0ff2 ; SCRNX EQU 0x0ff4 ; SCRNY EQU 0x0ff6 ; VRAM EQU 0x0ff8 ; ORG 0xc200 ; MOV AL,0x13 ; MOV AH,0x00 INT 0x10 ;VGA显卡 320*200*8 MOV BYTE [VMODE],8 ; MOV WORD [SCRNX],320 MOV WORD [SCRNY],200 MOV DWORD [VRAM],0x000a0000; 用BIOS取得键盘上各种LED指示灯的状态 MOV AH,0x02 INT 0x16 ; keyboard BIOS MOV [LEDS],ALfin: HLT JMP fin
BIOS内存分布图
接下来我们直接切换到32位模式 然后运行C语言写的程序。
所以haribote.sys 前半部分是由汇编写的 后面是用c语言写的。汇编的后半部分使我们切换到32位模式的代码,暂时不作讲解。
接下来是c语言部分。
比如:
void HariMain(void){fin: /* */ goto fin;}
程序一直在死循环中。
那么bootpack.c是怎么样变成机器语言呢?
- ccl.exe c编译器 bootpack.c –> bootpack.gas
- gas2nask.exe 汇编格式转换 bootpack.gas –> bootpack.nas
- nask.exe 汇编编译为目标文件 bootpack.nas –> bootpack.obj
- obj2bim.exe 链接生成二进制映像文件替代品 bootpack.obj –> bootpack.bim
- bim2hrb.exe bootpack.bim –> bootpack.hrb
此时c语言就变成了机器语言 使用copy指令将asmhead.bin 与bootpack.hrb 结合起来,成为haribote.sys
程序是从以HariMain命名的函数开始运行的。
为了不要我们程序进入死循环中,我们想办法让程序进入HLT状态
; naskfunc; TAB=4[FORMAT "WCOFF"] ; [BITS 32] ; ; [FILE "naskfunc.nas"] ; GLOBAL _io_hlt ; ; [SECTION .text] ; _io_hlt: ; void io_hlt(void); HLT RET
显而易见,我们添加了io_hlt函数的实现 它的行为很简单,使计算机处于HLT状态。
同时看一下c文件
void io_hlt(void);void HariMain(void){fin: io_hlt(); goto fin;}
可以同时看一下我们的编译规则
bootpack.bim : bootpack.obj naskfunc.obj Makefile $(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \ bootpack.obj naskfunc.obj
把汇编文件和c文件链接到一起即可。
make run 运行,大功告成。
最后附上asmhead.nas, (切换到32位模式)
; haribote-os boot asm; TAB=4BOTPAK EQU 0x00280000 ; DSKCAC EQU 0x00100000 ; DSKCAC0 EQU 0x00008000 ; ; BOOT_INFO娭學CYLS EQU 0x0ff0 ; LEDS EQU 0x0ff1VMODE 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 pipelineflushpipelineflush: MOV AX,1*8 ; MOV DS,AX MOV ES,AX MOV FS,AX MOV GS,AX MOV SS,AX; bootpack偺揮憲 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 ; ECX += 3; SHR ECX,2 ; ECX /= 4; JZ skip ; MOV ESI,[EBX+20] ; ADD ESI,EBX MOV EDI,[EBX+12] ; CALL memcpyskip: MOV ESP,[EBX+12] ; JMP DWORD 2*8:0x0000001bwaitkbdout: IN AL,0x64 AND AL,0x02 JNZ waitkbdout ; RETmemcpy: MOV EAX,[ESI] ADD ESI,4 MOV [EDI],EAX ADD EDI,4 SUB ECX,1 JNZ memcpy ; RET; ALIGNB 16GDT0: RESB 8 ; DW 0xffff,0x0000,0x9200,0x00cf ; DW 0xffff,0x0000,0x9a28,0x0047 ; DW 0GDTR0: DW 8*3-1 DD GDT0 ALIGNB 16bootpack:
0 0
- 03day 进入32位模式并导入C语言
- 三、进入32位模式并导入C语言
- 3、进入32位模式并导入C语言
- 进入32位模式并导入C语言
- 第3天 进入32位模式并导入C语言
- 30天自制操作系统(第03天)–进入32位模式并引入C语言
- [读书笔记]30 天自制操作系统 day3 进入32bit模式并导入C语言
- [Rx86OS-IV] 导入32位C语言
- 08day 鼠标显示控制 与32位模式切换
- 进入C语言世界
- 操作系统开发系列—2.进入32位保护模式
- C语言——确定某数比特位中1的个数并打印其32位比特数值
- Day-1:C语言基本知识:
- java开发操作系统内核:由实模式进入保护模式之32位寻址
- 32位的C语言编程环境
- 《32位单片机c语言编程》笔记
- c语言编程32位,二进制。
- C语言数据类型32位和64位不同
- Mysql limit 优化,百万至千万级快速分页 复合索引
- 编译运行HTS
- IOS 快捷键
- java特种兵读书笔记(3-3)——java程序员的OS之虚拟机回收算法
- Netty权威指南读书笔记(二)
- 03day 进入32位模式并导入C语言
- 蓝桥杯 历届试题 数字游戏
- 几种深度学习工具的比较
- Netty权威指南读书笔记(三)
- 【iOS开发】iOS知识点总结
- iOS开发之Objective-C与JavaScript的交互
- Oracle维护常用SQL语句(查询系统表和视图)
- LockCount
- NumPy学习 -- 002_常用函数