操作系统学习4 自己动手写一段x86架构引导程序
学习x86汇编语言3 自己动手写一段程序引导计算机一、本章准备工具一、8086的内存分布二、8086的启动流程三、编译引导程序四、制作虚拟软盘1. 把 TINIX.IMG 也放到nasm目录 ,改名 MYOS.IMG2. 打开FloppyWrite.exe五、建立一个虚拟机1. 随便新建一个虚拟机2. 添加软盘控制器3. 启动虚拟机六、调试引导程序的方法七、使用vscode查看镜像内容一、本章准备
操作系统学习4 自己动手写一段x86架构引导程序
一、准备工作
1. 本章使用的工具
- FloppyWriter.exe 软盘绝对扇区读写工具,各大下载网站能下载到
- nasm :https://www.nasm.us/pub/nasm/releasebuilds/2.15.04rc5/win64/nasm-2.15.04rc5-win64.zip
- 一个1.44M的磁盘镜像 可以从网上下载一个 TINIX.IMG
- Virtual Box虚拟机
- DOS Box
- vscode安装HexDump插件
2. 关于nasm一些语法说明
nasm使用的是AT&T汇编的语法 , 其中:
- 关键字要求使用小写(作为对比Intel汇编语言要求使用大写)
- 赋值方向:第一个是源操作数,第二个是目的操作数,赋值方向从左向右(作为对比Intel正好相反)
- 使用寄存器前加%,使用立即数前加 $
- 远跳转指令和远调用指令要加前缀l(Intel使用FAR关键字)
- 内存间接寻址使用
()
(Inten使用[]
) - 指令后缀,b字节,w字,l双字,q四字;f前跳转,b后跳转。
$
表示当前行被编译后的地址$$
表示一个section开始的位置[]
如果不加[]
引用变量,NASM认为在引用该变量的地址。如果要访问里面的值,就要加[]
一段代码示例:
二、8086的内存分布
8086 地址位长度是20,1M的寻址空间。这1M的空间是按如下进行分配的:
起始 | 结束 | 大小 | 作用 |
---|---|---|---|
FFFF0 | FFFFF | 16B | BIOS的入口地址,此地址也属于BIOS代码,同样属于顶部的640K字节。此处16字节的内容是跳转指令jmp f0000:e05b |
F0000 | FFFEF | 64K-16B | 系统BIOS范围是F0000~FFFFF共640K |
C8000 | EFFFF | 160K | 映射硬件适配器的ROM或内存映射式I/O |
C0000 | C7FFF | 32K | 显示适配器BIOS |
B8000 | BFFFF | 32K | 用于文本模式显示适配器 |
B0000 | B7FFFF | 32K | 用于黑白显示适配器 |
A0000 | AFFFF | 64K | 用于彩色显示适配器 |
9FC00 | 9FFFF | 1K | EBDA扩展BIOS数据区 |
7E00 | 9FBFF | 622080B 约608K | 可用区域 |
7C00 | 7DFF | 512B | MBR被BIOS加载到此处 |
500 | 7BFF | 30464B约30K | 可用区域 |
400 | 4FF | 256B | BIOS 数据区 |
000 | 3FF | 1K | 中断向量表 |
高于 1M的是高位内存区和扩展内存。80386,80486,奔腾等最高寻址4G空间。
三、8086的启动流程
- 计算机上电后,CPU跳到0xFFFF0位置
- 跳转F000:E05B运行BIOS
- BIOS 运行完,最后一步检查0盘0道1扇区,如果这个扇区最后两字节是0x55,0xaa,bios就把这个扇区的内容加载到0x7c00,使用语句
jmp 0:7c00
。 - 系统进入 MBR,即运行0x7c00处程序。
下面就写一段程序加载到7c00,让计算机来引导看是否能启动。
四、编译引导程序
org 07c00h ; 告诉编译器程序加载到7c00处
mov ax, cs ; 将代码段地址加载到ax中
mov ds, ax ; 将ds寄存器设置为代码段地址,以便访问数据
mov es, ax ; 将es寄存器也设置为代码段地址,方便后续操作
call DispStr ; 调用显示字符串的例程
jmp $ ; 无限循环,$代表当前汇编行的地址
DispStr: ; 显示字符串的例程
mov ax, BootMessage ; 将字符串的首地址加载到ax中
mov bp, ax ; 将ax中的地址传递给bp,设置ES:BP为字符串地址
mov cx, 16 ; 字符串长度为16个字符
mov ax, 01301h ; AH = 13h(函数号),AL = 01h(显示模式)
mov bx, 000ch ; 页面号为0,黑底红字
mov dl, 0 ; dl = 0,表示在当前显示页中显示
int 10h ; 调用BIOS的INT 10h中断,进行显示操作
ret ; 返回
BootMessage: db "Hello, MY OS!" ; 想要在屏幕上显示的字符串
times 510-($-$$) db 0 ; 用0填充剩余的空间,使得生成的二进制代码恰好为512字节
dw 0xaa55 ; 引导扇区结束标志
把代码保存到nasm的目录,编译:
nasm boot.asm -o boot.bin
五、制作虚拟软盘
1. 把 TINIX.IMG 也放到nasm目录 ,改名 MYOS.IMG
2. 打开FloppyWrite.exe
选择Write File to Image
提示选择文件先选择Boot.bin,第二次弹窗选择MYOS.IMG
六、建立一个虚拟机
1. 随便新建一个虚拟机
2. 添加软盘控制器
添加后的效果:
3. 启动虚拟机
要退出的话需要强制退出。
七、调试引导程序的方法
修改上面代码,把org 07c00h
改成 org 0100h
, 即将程序的起始地址从引导扇区的标准地址0x7c00
修改为 0x0100
。这个改变将使得编译后的程序不再是一个完整的引导扇区,而是一个简单的 .com
文件。
在 DOS 系统中,.com
文件是一种不含有分段信息的简单可执行文件格式。它们被设计成加载到内存的某个地址并直接执行。由于.com
文件不包含任何标准的头部信息或分段信息,它们的加载地址是固定的,即始终加载到内存的 0x0100
地址处。
在 DOSBox 或类似的环境中,可以直接运行这个 .com
文件,因为它们是合法的可执行文件,并且在 DOS 中以 .com
文件格式执行。
下面使用nasm的预编译宏切换org语句加载的地址:
;%define _BOOT_DEBUG_ ; 做Boot Sector时把这行注释掉
; 启用这行就用nasm Boot.asm -o Boot.com生成.com文件用于调试
%ifdef _BOOT_DEBUG_
org 0100h
%else
org 07c00h
%endif
mov ax, cs
mov ds, ax
mov es, ax
call DispStr ; 调用显示字符串例程
jmp $ ; 无限循环
DispStr:
mov ax, BootMessage
mov bp, ax ; ES:BP = 串地址
mov cx, 16 ; CX = 串长度
mov ax, 01301h ; AH = 13, AL = 01h
mov bx, 000ch ; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
mov dl, 0
int 10h ; 10h 号中断
ret
BootMessage: db "Hello, MY OS!" ; 想要开机后在屏幕上显示的字符串
times 510-($-$$) db 0 ; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 0xaa55 ; 结束标志
八、使用vscode查看镜像内容
VsCode安装 HexDump插件后,在要查看的文件点击键,选择ShowHexdump就可以来查看磁盘镜像的内容:
这里可以看到前512字节就是自己写的汇编程序,以55AA结束。
本文学习资源来自《自己动手写操作系统》于渊 电子工业出版社。
更多推荐
所有评论(0)