在这里插入图片描述

一、准备工作

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的空间是按如下进行分配的:

起始结束大小作用
FFFF0FFFFF16BBIOS的入口地址,此地址也属于BIOS代码,同样属于顶部的640K字节。此处16字节的内容是跳转指令jmp f0000:e05b
F0000FFFEF64K-16B系统BIOS范围是F0000~FFFFF共640K
C8000EFFFF160K映射硬件适配器的ROM或内存映射式I/O
C0000C7FFF32K显示适配器BIOS
B8000BFFFF32K用于文本模式显示适配器
B0000B7FFFF32K用于黑白显示适配器
A0000AFFFF64K用于彩色显示适配器
9FC009FFFF1KEBDA扩展BIOS数据区
7E009FBFF622080B 约608K可用区域
7C007DFF512BMBR被BIOS加载到此处
5007BFF30464B约30K可用区域
4004FF256BBIOS 数据区
0003FF1K中断向量表

高于 1M的是高位内存区和扩展内存。80386,80486,奔腾等最高寻址4G空间。

三、8086的启动流程

  1. 计算机上电后,CPU跳到0xFFFF0位置
  2. 跳转F000:E05B运行BIOS
  3. BIOS 运行完,最后一步检查0盘0道1扇区,如果这个扇区最后两字节是0x55,0xaa,bios就把这个扇区的内容加载到0x7c00,使用语句 jmp 0:7c00
  4. 系统进入 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结束。

本文学习资源来自《自己动手写操作系统》于渊 电子工业出版社。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐