从Intel开发手册看x86指令格式(含手动将指令转化为机器码的方法)

目录

1.参考资料

2.指令机器码格式整体介绍

3.简单汇编指令翻译为机器码(练习查表)

表2-2

例题1:mov ecx,9

1.找到mov指令,对应需要的机器码格式

2.查表2-2

验证机器码是否正确

例题2:mov cx,9

验证机器码是否正确

4.ModR/M和偏移量

ModR/M字段组成

例题3:mov eax,[ebx]

1.找到mov指令,对应需要的机器码格式

2.查Mod R/M表

3.查Reg/Opcode

Reg代表寄存器的编号

​编辑Opcode为操作码的扩展部分,这里没有

验证机器码是否正确

ModR/M快速转换为十六进制

例题4:mov edx,[ebx+2]

验证机器码是否正确

例题5:mov word ptr [bx+si+5],0x1234

1.找到mov指令,对应需要的机器码格式

2.查表2-1

表2-1

验证机器码是否正确

5.SIB字段

例题6:add edx,[eax+ebx*2]

1.找到add指令,对应需要的机器码格式

2.求ModR/M字段

3.求SIB字段

验证机器码是否正确

6.其他说明

例题7:add dword ptr [ecx+ebx*8+0x7c00],0x12345678

1.找到add指令,对应需要的机器码格式

2.求ModR/M字段

​编辑

3.求SIB字段

4.偏移量和立即数

验证机器码是否正确


1.参考资料

Intel的软件开发手册卷2:下载链接:https://cdrdv2.intel.com/v1/dl/getContent/671110

2.指令机器码格式整体介绍

Instruction Prefixes为指令前缀,Opcode为操作码,Displacement为偏移,Immediate为立即数

注:ModR/M和SIB在本文后面会详细介绍

(摘自卷2:Intel 64 and IA-32 Architectures Instruction Format) 

3.简单汇编指令翻译为机器码(练习查表)

表2-2

(325383-sdm-vol-2abcd-dec-24.pdf的第36页)  

例题1:mov ecx,9

mov ecx,9翻译为机器码

1.找到mov指令,对应需要的机器码格式

ecx寄存器是16位的,对应r32(r为register寄存器的缩写),数字9写入e

cx寄存器,因此9为32位的,即imm32(imm为immediate number的缩写,即立即数)

(325383-sdm-vol-2abcd-dec-24.pdf的第772页) 

2.查表2-2

查表可知,机器码由两部分组成,B8+rd和id,rd是寄存器编号,可从表2-2查到,如下:

ecx寄存器的编号为1,因此机器码的第一部分为B8+1==B9,第二部分为32位的立即数为09 00 00 00

因此机器码为B9 09 00 00 00

验证机器码是否正确

https://defuse.ca/online-x86-assembler.htm#disassembly在线反汇编网站

输入机器码,架构选x86,之后点击Disassemble

结果是正确的:

例题2:mov cx,9

和例题1类似,为b9 09 00,但是需要多考虑一点:b9 09 00是16位模式下的指令,如果在x86架构下,需要借助反转前缀0x66,因为默认操作尺寸为32位的,而如果想要执行16位的指令,需要翻转前缀0x66,因此最终的机器码为66 b9 09 00

验证机器码是否正确

结果是正确的:

4.ModR/M和偏移量

ModR/M字段组成

位0~位2:R/M,位3~位5:Reg/Opcode,位6~位7:Mod

Mod和R/M确定寻址方式

例题3:mov eax,[ebx]

1.找到mov指令,对应需要的机器码格式

eax为32位寄存器,r32代表32位寄存器,r/m32代表32位的寄存器或者32为内存,而[ebx]为32位有效地址

发现机器码格式为8B /r,其中/r代表纯寄存器操作数,其中r32为纯寄存器,而r/m32不为纯寄存器,也有可能是32为有效地址(m32)

2.查Mod R/M表

一般带"/r"是需要查Mod R/M表的,可以看表2-2的左上角:

在表2-2中,可以看到[ebx]中Mod对应的二进制为00,R/M对应的二进制为011

填到下面:

3.查Reg/Opcode

Reg/Opcode表示Reg或者Opcode

Reg代表寄存器的编号

mov eax,[ebx]对应mov r32,r/m32,r32为纯寄存器,eax对应r32,因此需要查eax寄存器的编号,为二进制000

填到下面: 

Opcode为操作码的扩展部分,这里没有

ModR/M字段转为十六进制为0x3,加上0x8b操作码,因此机器码为8b 03

验证机器码是否正确

结果是正确的:

ModR/M快速转换为十六进制

如果每次都要将查到的ModR/M转化为16进制是比较麻烦的,可以通过Value of ModR/M Byte (in Hexadecimal)来快速定位:

还是以mov eax,[ebx]为例:采用横纵坐标定位的方法

直接定位到0x03

ModR/M字段后可以跟偏移量(可选)或者立即数(可选),参见例题4

例题4:mov edx,[ebx+2]

操作码同例3,为8b

ModR/M:为0x53

[ebx+2]的2为disp8(为displacement 8-bit,即8为偏移量)

表的注释给出了disp8应该跟在ModR/M的后面,因此机器码为8b 53 02

验证机器码是否正确

结果是正确的:

例题5:mov word ptr [bx+si+5],0x1234

1.找到mov指令,对应需要的机器码格式

/0为Reg/Opcode的Opcode数字部分,/0代表八进制的000,填上即可:

2.查表2-1

mov word [bx+si+5],0x1234中bx和si为16位寄存器,需要到表2-1去查:

表2-1

 填上去:

二进制0100 0000转十六进制为0x40,0x40后面要依次跟着disp8(0x05)和立即数(0x34,0x12)

组合起来就是C7 40 05 34 12(16位下的机器码)

最后加上前缀:在x86架构下需要反转操作数尺寸(0x66)和反转有效地址尺寸(0x67),因为x86下操作数尺寸和有效地址尺寸都是32位的

因此x86下的机器码为67 66 C7 40 05 34 12

验证机器码是否正确

结果是正确的:

5.SIB字段

SIB字段占一个字节,由三个部分组成

(325383-sdm-vol-2abcd-dec-24.pdf第31页) 

 Scale:倍率 Index:索引寄存器编号 Base:基址寄存器编号

例题6:add edx,[eax+ebx*2]

1.找到add指令,对应需要的机器码格式

操作码由两部分组成:03和/r,/r显然需要求ModR/M字段,需要找edx寄存器编号

2.求ModR/M字段

[eax+ebx*2]由两部分组成[eax]+[ebx*2],因此需要查[--][--]

ModR/M为0x14,注意到[--][--]有一个注释1

 注释1是这样写的:

除了求出ModR/M字段,还需要求SIB字段

3.求SIB字段

去查32位下SIB表:

(325383-sdm-vol-2abcd-dec-24.pdf的第37页)

[eax+ebx*2]中基址寄存器为eax,索引寄存器为ebx

基址寄存器eax的Base为二进制的000

填上去:

 ebx*2的SS为二进制的01,Index为二进制的011

填上去:

也可以通过横纵坐标定位的方法快速求SIB字段:

二进制的01011000为十六进制的58

因此机器码为03 14 58

验证机器码是否正确

结果是正确的:

6.其他说明

ModR/M和SIB字段后面也可以根据需要依次添加偏移量和立即数

例题7:add dword ptr [ecx+ebx*8+0x7c00],0x12345678

1.找到add指令,对应需要的机器码格式

注意到机器码由三部分组成:0x81、/0和id(id为双字的立即数)

/0需要查ModR/M表

2.求ModR/M字段

/0为Reg/Opcode的Opcode数字部分,/0代表八进制的000,填上即可:

+0x7c00大于8位,为32位偏移(32位下偏移只能取8位或32位,不能取16位)

填上即可:

 二进制的10000100对应十六进制的84

注释2提到了

如果有SIB'字段需要跟在ModR/M后面,因为[ecx+ebx*8+0x7c00]中ebx*8涉及到了倍率,因此要求SIB字段

3.求SIB字段

ecx为基址寄存器,ebx为索引寄存器

SIB字段为0xd9

4.偏移量和立即数

依次添加偏移量和立即数(注意顺序:先添加偏移量后添加立即数)

0x7c00写成32位的00 7c 00 00,立即数0x12345678写成78 56 34 12

因此机器码为:81 84 d9 00 7c 00 00 78 56 34 12

即:

验证机器码是否正确

结果是正确的:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangcoder

赠人玫瑰手有余香,感谢支持~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值