操作系统真象还原——1&2.初见MBR
第1章 部署工作环境CPU所能理解的指令格式是其在硬件上已经规定的,原则上只要按照IA-32 指令格式往二进制文件中写指令,就能够直接同CPU 对话了虚拟机只是一个普通的进程,该进程模拟了硬件资源,在虚拟机中运行的程序其所做出的任何行为都先被虚拟机检查,由虚拟机分析后,代为向操作系统申请。实验环境:virualBox + Ubuntu21.04(前提安装gcc、gdb、make、libgtk2.0
第1章 部署工作环境
-
CPU所能理解的指令格式是其在硬件上已经规定的,原则上只要按照IA-32 指令格式往二进制文件中写指令,就能够直接同CPU 对话了
-
虚拟机只是一个普通的进程,该进程模拟了硬件资源,在虚拟机中运行的程序其所做出的任何行为都先被虚拟机检查,由虚拟机分析后,代为向操作系统申请。
-
实验环境:virualBox + Ubuntu21.04(前提安装gcc、gdb、make、libgtk2.0-dev、xorg-dev、g++、build-essential) + bochs
- 推荐文章:
[1]https://blog.csdn.net/weixin_30751947/article/details/94875872?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.pc_relevant_paycolumn_v2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.pc_relevant_paycolumn_v2&utm_relevant_index=2
[2]https://blog.csdn.net/aurorayqz/article/details/80310954 - 真相还原中的配置自己的bochs安装路径要注意,不要写错了
- 使用
keyboard: keymap=BOCHSPATH/share/bochs/kemaps/x11-pc-us.map
,可能版本问题,如果未报此行错误可以不用管 - 报错dLopen failed for module ‘x’ (libbx_ x.so): file not found(https://blog.csdn.net/weixin_30363981/article/details/97344363)
- 推荐文章:
-
安装bochs其中最后一个命令是x11不是xll,\是换行符不用写在命令行
第2章 编写MBR主引导记录
-
程序载入内存
- 程序被加载器加载到内存的某个区域
- CPU的cs : ip 寄存器被指向这个程序的起始地址
-
实模式下的内存布局
-
基本输入输出系统BIOS建立的中断向量表可以使用“int中断号”来实现相关的硬件调用
-
地址映射:CPU提交要访问的地址给MMU(内存管理单元),MMU将虚拟地址转化为物理地址去访问ROM、显存或内存(32位系统指的地址总线是32位,这32位的地址不完全是用来访问内存的)
-
计算机从加电启动到运行
- 在计算机POST加电的一瞬间, 计算机主板和其他设备供电,BIOS的控制芯片组会向CPU发出并保持一个RESET(重置)信号,重置CPU内部状态,直到芯片组检测到电源已经开始稳定供电后,便撤去RESET信号
- CPU 的cs : ip 寄存器被强制初始化为0xF00 : 0xFFF0 。由于开机的时候处于实模式,段基址要左移4 位,于是0xF00 : 0xFFF0 转换地址为BIOS 的入口地址0xFFFF0 (Shadow技术:由于ROM的执行速度远比RAM要低,所以加电后在ROM中的BIOS会被装载到Shadow RAM中的指定区域里。由于Shadow RAM的物理编址与对应的ROM相同,所以当需要访问BIOS时,只需访问Shadow RAM而不必再访问ROM,这就能大大加快计算机系统的运算时间)
- CPU到地址0xFFFF0处取出跳转指令
jmp far f000:e05b
,即再跳向0xfe05b处执行BIOS代码,检测外设并进行初始化,完成后在内存中0x000 ~0x3FF 处建立中断向量表并填写中断例程 - BIOS最后会校验启动盘的0 盘0 道1 扇区(CHS 方式中扇区的编号是从1 开始的,LBA从0开始的),如果此扇区末尾的两个字节分别是魔数0x55 和0xaa, BIOS 便认为此扇区中确实存在可执行的主引导记录MBR ,便加载到物理地址0x7c00 ,随后跳转到此地址继续执行,此时,CPU控制权由BIOS交给MBR。这里有个小细节, BIOS 跳转到0x7c00 是用
jmp 0: 0x7c00
实现的,这是jmp 指令的直接绝对远转移用法,段寄存器cs 会被替换,这里的段基址 由之前的0xf00 变成了0
-
0x7c00的由来
512字节大小的MBR 被BIOS加载到0x7C00到0x7DFF 处,MBR 是一段程序,程序的运行需要栈的支持,栈也是在内存中的,大约1KB。结合以上三点,选择32KB 中的最后1KB 最为合适,那此地址是多少呢? 32KB 换算为十六进制为0x8000,减去1kb(0x400)的话,即为0x7c00
-
.bin
文件是纯二进制文件,不含伪指令 -
当显示器工作在80*25的文本模式(80行25列共2000字符),一个字符用两个字节表示,低位字节是字符的ASCII码,高位字节是字符属性,所以显示一屏字符需要4KB
; 主引导程序MBR
; SECTION是伪指令,cpu不运行,只是方便程序员规划程序分段使用
; `vstart=0x7c00`表示在程序编译时将起始地址编译为0x7c00
; SS存放栈顶的段地址,SP存放栈顶的偏移地址。在任何时刻 ,SS:SP都是指向栈顶元素
; CS存放内存中代码段入口的段基址,CS:IP表示下一条要运行的指令内存地址
; 初始化部分
SECTION MBR vstart=0x7c00 ; =前后不能有空格
mov ax,cs ; 由于BIOS是通过`jmp 0:Ox7c00`转到MBR的,故cs此时为0
mov ds,ax ; 段寄存器不能使用立即数进行赋值,可以使用通用寄存器ax
mov es,ax
mov ss,ax
mov fs,ax
mov sp,0x7c00
; 使用10号中断的0x06功能号,进行窗口上卷清屏,避免BIOS检测信息影响显示
mov ax,0x600 ; ah存放将要调用的中断子功能号
mov bx,0x700
mov cx,0 ; (CL,CH)=窗口左上角的(X,Y)位置
mov dx,0x184f ; (DL,DH)=窗口右下角的(X,Y)位置(80,25)
int 0x10 ; 调用中断
; 使用10号中断的0x03功能号,获取光标位置
mov ah,3 ; 将中断子功能号存入ah寄存器等待被调用
mov bh,0 ; 存放待获取光标的页号
int 0x10
; 调用中断后,ch=光标开始行,cl=光标结束行,dh=光标所在行号,dl=光标所在列号
; 打印字符串
mov ax,message
mov bp,ax ; es:bp为串首地址
mov cx,5 ; cx存放串长度,不包括结束符0的字符个数
mov ax,0x1301 ; ah表示调用13号子功能,al表示写字符方式01(光标跟随显示)
mov bx,0x2 ; bh存储要显示的页号,bl是字符属性(02h表示黑底绿字)
int 0x10
; $表示本行指令所在的地址,$$表示本section的起始地址,$-$$表示执行代码行到段首的偏移量
jmp $ ; 在本行代码死循环
message db "ws MBR"
times 510-($-$$) db 0 ; 将剩余字节用0进行填充
db 0x55,0xaa ; 最后两个字节填充MBR的标识
-
安装nasm命令
sudo apt-get install nasm
-
dd命令是linux自带的,不需要安装
-
将mbr汇编文件放到bochs文件夹下的运行脚本
#!/bin/bash
rm -rf ./hd.img
bin/bximage -hd -mode=“flat” -size=60 -q hd.img
echo “disk creat success!!”
nasm mbr.s -o mbr.bin
dd if=mbr.bin of=hd.img bs=512 count=1 conv=notrunc
echo “disk write success!!”
bin/bochs -f bochsrc
更多推荐
所有评论(0)