Assembly 在x86汇编中,每条指令编译成多少个“是”?
字节数是相邻指令之间的地址差:Assembly 在x86汇编中,每条指令编译成多少个“是”?,assembly,x86,gnu-assembler,instruction-set,Assembly,X86,Gnu Assembler,Instruction Set,字节数是相邻指令之间的地址差: push %ebp mov %esp,%ebp sub $0x28,%esp 0x004012d0:推送%ebp;1字节 0x004012d1:mov%esp,%ebp;2字节 0x004012d3:低于$0x28,%esp 如果只有文本,则转到此处:和此处:并计算每条指令、前缀和操作数如果汇编代码为文本,则必须使用汇编程序例程来获取 二进制表示,因此指令的大小。当然,这取决于硬件 例如,这里有一个open()。第一条指令位于[main+0],
push %ebp
mov %esp,%ebp
sub $0x28,%esp
0x004012d0:推送%ebp;1字节
0x004012d1:mov%esp,%ebp;2字节
0x004012d3:低于$0x28,%esp
如果只有文本,则转到此处:和此处:并计算每条指令、前缀和操作数如果汇编代码为文本,则必须使用汇编程序例程来获取
二进制表示,因此指令的大小。当然,这取决于硬件
例如,这里有一个open()。第一条指令位于[main+0],第二条位于[main+1],因此第一条指令为1字节。第三条指令位于[main+3],因此第二条指令是两个字节。您无法从清单中看出第三条指令有多长,因为它没有显示4的地址。指令。您不必根据助记符确定指令大小。以下是一些特殊情况:
- 如果在16位段中,
需要mov eax,0
前缀,而在32位段中则不需要。您需要知道段的大小0x66
- 在32位或16位模式下,您可以将
编码为addeax,1
(0x40
)或inceax
(0x83 0xc0 0x01
)。也就是说,有些助记符可以用多种方式编码addeax,1
- 内存操作数
可以将[eax]
编码为基或索引。如果它是索引,那么在MOD/RM之后将有一个额外的SIB字节eax
- 在64位模式下,您可以使用REX前缀
对寄存器0x4x
-r8
进行编码。但是,您可以使用r15
作为某种类型的null REX字节,这将在指令中添加另一个字节0x40
- 即使显式段与隐式段相同,也可以使用段替代
还有许多其他方法可以使用更多或更少的字节对指令进行编码。一个好的汇编程序应该总是使用最短的汇编程序,但它肯定不是体系结构所要求的。好的方面是,如果您学习《英特尔IA-32软件开发人员手册》第2卷,您应该能够自己完成。如果可能,请汇编程序生成一个清单。这将显示您的源代码,接下来是指令的二进制表示,您需要做的就是计算有多少字节,然后得到大小。您想在运行时使用它吗?ie
asm\U大小(“mov esp,ebp”)
?这种东西依赖于硬件架构。这不是一个“分析”问题,而是一个“查找合适的“字典”问题。在Linux中,您可以使用objdump-d可执行文件
查看操作码,然后您将看到每个指令索引的大小,指令编码,特别是在x86/x64上,是不明确的,两者都是指两个汇编助记符可以描述同一条指令(xchg ax,ax
和nop
),一个汇编助记符可能有两个二进制操作码(inc eax
,32位-都0x40
和0xff 0xc0
)。它们有时甚至出于某种原因故意含糊不清,比如NOP
指令,请看,许多旧指令也可以用VEX或EVEX前缀重新编码,因此它们将有多个不同的表示形式length@L乌夫·恩霍克:这不太准确。使用VEX或EVEX编码为AVX的SSE指令的行为略有不同:*它们具有不同的启用要求。例如,VEX需要CR4.OSXSAVE和XCR0中的各种位。*128位AVX指令清除YMM或ZMM的高位,而相应的SSE指令保持高位不变
push %ebp
mov %esp,%ebp
sub $0x28,%esp
0x004012d0 <main+0>: push %ebp ;1 byte
0x004012d1 <main+1>: mov %esp,%ebp ;2 bytes
0x004012d3 <main+3>: sub $0x28,%esp