[翻译]如何用汇编创建一个基础内核 (三)
2011-03-12 23:45
573 查看
原文是 OSDev Wiki上的一个 Tutorials 文章。
1,第一个启动扇区
2,使用BIOS写消息
3,看看机器码
4,不用BIOS向屏幕打印输出
5,中断
6,进入保护模式
7,非实模式
8,32 位打印输出
附录A,更多资讯
3,看看机器码
上代码:
; nasmw encode.asm -f bin -o encode.bin
mov cx, 0xFF
times 510-($-$$) db 0
db 0x55
db 0xAA
C:\osdev\debug encode.bin
别把代码写入磁盘。windows用户使用 DEBUG高度, linux用户使用 Hexdump命令。
在“-”之后键入“d”看看二进制文件。("?"查看帮助,"q"退出) 。你会看到一些如下的东西:
0AE3:0100 B9 FF 00 00 00 00 etc...
在 http://www.baldwin.cx/386htm/MOV.htm 和 http://www.baldwin.cx/386htm/s17_02.htm查看 mov 指令的 opcode相关介绍。
也就是说,你在转储中看到的,唯一一个寄存器(CX=1)到在基础 opcode 编码中编码为‘B8’。
但在当你用 ECX替换 CX时,会发生什么事:
mov ecx, 0xFF
times 510-($-$$) db 0
db 0x55
db 0xAA
0AE3:0100 66 B9 FF 00 00 00 00 etc...
"66" 是汇编器在默认模式下,以按地址大小覆盖操作数前缀的生成方式。当你使用NASM生成二进制文件时,它是16位格式的。同样,当你使用 bits 指令来改变字长模式时,会生成不同的操作码:
[BITS 32]
2 mov cx, 0xFF
times 510-($-$$) db 0 db 0x55
db 0xAA
这实际上并没有改变处理器的模式,但它确实有助于解决后面的字节序列。
地址
地址编码有点复杂:
mov cx, [temp]
temp db 0x99
times 510-($-$$) db 0
db 0x55
db 0xAA
0AE3:0100 8B 0E 04 00 99 00 00 00 etc...
“8B”是opcode
"0E"是帮助opcode解释的 Mod R/M 字节
在 http://www.baldwin.cx/386htm/s17_02.htm 的17.2.1节查看 “ModR/M and SIB Bytes”。
解释,参见图17-2(译注,指上面的连接中的图17-2),可见这个字节是包含有不同的域的,
参照这个图表可以更容易理解这个规则。查看“0E”,你会看到右边标“disp 16”,这是指是
按16位偏移来解释,“0400” 就是这个16位的偏移。若你不清楚为什么是 “0X0004”,这是因为
Intel处理器是小端的。一个数的小端是在前面的。
“99”就理所当然是在0x0004处字节的修正了。(8B的是0x0000)
有另一种 按地址大小覆盖操作数的前缀是“67”,就是上面的“66”一样。
造成这种现象有许多原因。当我们从16位实模式转入32位保护模式时,我们的代码也将发生变化。
而注意到这种细节,可以减少对这种转换的错误认识 。
(第三篇END)
1,第一个启动扇区
2,使用BIOS写消息
3,看看机器码
4,不用BIOS向屏幕打印输出
5,中断
6,进入保护模式
7,非实模式
8,32 位打印输出
附录A,更多资讯
3,看看机器码
上代码:
; nasmw encode.asm -f bin -o encode.bin
mov cx, 0xFF
times 510-($-$$) db 0
db 0x55
db 0xAA
C:\osdev\debug encode.bin
别把代码写入磁盘。windows用户使用 DEBUG高度, linux用户使用 Hexdump命令。
在“-”之后键入“d”看看二进制文件。("?"查看帮助,"q"退出) 。你会看到一些如下的东西:
0AE3:0100 B9 FF 00 00 00 00 etc...
在 http://www.baldwin.cx/386htm/MOV.htm 和 http://www.baldwin.cx/386htm/s17_02.htm查看 mov 指令的 opcode相关介绍。
也就是说,你在转储中看到的,唯一一个寄存器(CX=1)到在基础 opcode 编码中编码为‘B8’。
但在当你用 ECX替换 CX时,会发生什么事:
mov ecx, 0xFF
times 510-($-$$) db 0
db 0x55
db 0xAA
0AE3:0100 66 B9 FF 00 00 00 00 etc...
"66" 是汇编器在默认模式下,以按地址大小覆盖操作数前缀的生成方式。当你使用NASM生成二进制文件时,它是16位格式的。同样,当你使用 bits 指令来改变字长模式时,会生成不同的操作码:
[BITS 32]
2 mov cx, 0xFF
times 510-($-$$) db 0 db 0x55
db 0xAA
这实际上并没有改变处理器的模式,但它确实有助于解决后面的字节序列。
地址
地址编码有点复杂:
mov cx, [temp]
temp db 0x99
times 510-($-$$) db 0
db 0x55
db 0xAA
0AE3:0100 8B 0E 04 00 99 00 00 00 etc...
“8B”是opcode
"0E"是帮助opcode解释的 Mod R/M 字节
在 http://www.baldwin.cx/386htm/s17_02.htm 的17.2.1节查看 “ModR/M and SIB Bytes”。
解释,参见图17-2(译注,指上面的连接中的图17-2),可见这个字节是包含有不同的域的,
参照这个图表可以更容易理解这个规则。查看“0E”,你会看到右边标“disp 16”,这是指是
按16位偏移来解释,“0400” 就是这个16位的偏移。若你不清楚为什么是 “0X0004”,这是因为
Intel处理器是小端的。一个数的小端是在前面的。
“99”就理所当然是在0x0004处字节的修正了。(8B的是0x0000)
有另一种 按地址大小覆盖操作数的前缀是“67”,就是上面的“66”一样。
造成这种现象有许多原因。当我们从16位实模式转入32位保护模式时,我们的代码也将发生变化。
而注意到这种细节,可以减少对这种转换的错误认识 。
(第三篇END)
相关文章推荐
- [翻译]如何用汇编创建一个基础内核
- [翻译]如何用汇编创建一个基础内核 (五)
- [翻译]如何用汇编创建一个基础内核 (六)
- [翻译]如何用汇编创建一个基础内核 (七)
- [翻译]如何用汇编创建一个基础内核 (四)
- [翻译]如何用汇编创建一个基础内核 (八)
- [翻译]如何用汇编创建一个基础内核 (二)
- 如何用汇编创建一个基础内核
- 如何创建一个安全的Docker基础镜像
- 如何创建一个基础jQuery插件
- 如何创建一个安全的Docker基础镜像
- 如何创建一个在任何进程任何帐户任何会话都能存取的内核对象
- [翻译] - <Entity Framework> - 快速入门: 用 EMD 工具在已有数据库的基础上创建一个模型
- 如何创建一个安全的Docker基础镜像
- Linux内核分析课程--通过反汇编一个简单的c程序,分析汇编代码并理解计算机如何工作的
- java基础--如何创建一个线程
- 基础教学——如何用maven工具创建一个springmvc+mybatis的项目
- 一个小白从零基础自学Android编程笔记之如何创建菜单
- 整理: 如何创建一个在任何进程任何帐户任何会话都能存取的内核对象
- 如何创建一个UITableView(步骤详解 没有任何编程基础都能学会 )