01 从计算机结构到汇编程序入门
00. 准备
01 .二进制编辑器
在Bz - c.mos (vcraft.jp)下载,解压使用Bz1621.lzh,双击Bz.exe打开二进制编辑器
输入:0到168000行
1 | +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F |
显示:0到168000行
1 | 0123456789ABCDEF |
中途或者写完后,可以另存为helloos.img,该文件占用 1474560(1440*1024) 字节.
打开 tolset 文件夹,在里面新建 helloos0 文件夹,将 helloos.img 放入并新建两个文件: install.bat 和 run.bat
run.bat
1 | copy helloos.img ..\z_tools\qemu\fdimage0.bin |
解释:
- 第一行 copy:cmd命令 该行将 helloos.img 复制到 qemu 并重命名为 fdimage0.bin
- 第二行 运行PC模拟器QEMU,让代码在上面跑,模拟器在光盘里 ./tolset/z_tools 目录下
install.bat
1 | ..\z_tools\imgtol.com w a: helloos.img |
解释:
- 将 helloos.img 刻录到软盘 a w :写 a:软盘盘符
双击 run.bat 运行显示:
1 | hello, world |
02 .仅使用DB和RESB的汇编
汇编代码需要编译,这里采用作者自制的编译器 nask
超长源代码
1 | DB 0xeb, 0x4e, 0x90, 0x48, 0x45, 0x4c, 0x4c, 0x4f |
asm.bat
1 | ..\z_tools\nask.exe helloos.nas helloos.img |
运行上面命令,可以得到 helloos.img
使用DB和RESB简化
1 | DB 0xeb, 0x4e, 0x90, 0x48, 0x45, 0x4c, 0x4c, 0x4f |
- DB:往文件里面输入一个字节
- RESB:”reserve byte”的缩写,RESB XX 从现在的地址开始空出 XX 个字节,nask编译时把空出的填充为 0x00
03 .多指令汇编
1 | ; hello-os |
- DB:可以直接写字符串
- DW:”define word” ,写2个字节
- DD:”define double word”,写4个字节
- 第41行,RESB 0x1fe-$ 美元符号 $ 是个变量,在该程序中,我们已经在前面输出了132个字节,所以这里的 $ 就是132,因此 0x1fe - $ 就是378 连续输出378个0x00。用它是因为要保证第510字节开始地址是55AA,如果显示信息如 “hello, world” 的有长度变化,不用这个 $ 自动计算,就会出错。
问题:DB 0xeb, 0x4e, 0x90 是什么意思?
可写为
1
2DB 0xeb, 0x4e
DB 0x90根据day2的代码 上面第一行代码 DB 0xeb, 0x4e 被改为了 JMP entry ,为什么?
0xeb 是 x86 汇编指令 JMP SHORT,而 NASK 汇编把 JMP SHORT 简写为 JMP,0x90是x86汇编里的 NOP(空指令),也就是说 0xeb 0x4e 0x90 和汇编代码 JMP 0x4e; NOP; 是等价的
0x4e 从哪里来?
0x4e 是转移的位移量,把书翻到第24页数一下从 0x90 开始到第25页的 resb 18 一共占的字节数,正好是 0x4e($78_o$)个
从开头到主体有 80 个字节(0x50)为什么 JMP 0x4e?
0x4e 是 0x50-2。减2是因为 pc 指针已经指向了下一句 NOP 指令前面,所以偏移量要减去 JMP 和 entry 的机器码 (0xeb 和 0x4e) 所占的内存空间
为什么要 0x55 0xAA ?
见书P26末-P27始,计算机读软盘以512字节为单位,软盘512字节为一个扇区,并且读到的第一个扇区为启动扇区,检查第一个扇区最后两个字节是否为0x55 0xAA 如果不是则认为无启动程序,报错,是则执行。
所以,虽然在第一个扇区程序从开头写到 RESB 0x1fe-$ 写了510个字节,但是加上0x55 0xAA 就是512字节,作为启动程序。
参考资料: