Assembly .code16和.code32 x86程序集的对象转储
我有以下汇编代码(在Linux上): 我首先在顶部添加Assembly .code16和.code32 x86程序集的对象转储,assembly,x86,x86-16,disassembly,objdump,Assembly,X86,X86 16,Disassembly,Objdump,我有以下汇编代码(在Linux上): 我首先在顶部添加.code16生成一个16位代码,然后用.code32替换它生成一个32位代码。 我使用以下两个命令编译它们: gcc -m32 -nostdinc -c file.s ld -m elf_i386 -o file.exe file.o 然后,我用 objdump -d file.exe 对于第一种情况(.code16),我得到以下输出: 08048054 <_start>: 8048054: fa
.code16
生成一个16位代码,然后用.code32
替换它生成一个32位代码。
我使用以下两个命令编译它们:
gcc -m32 -nostdinc -c file.s
ld -m elf_i386 -o file.exe file.o
然后,我用
objdump -d file.exe
对于第一种情况(.code16
),我得到以下输出:
08048054 <_start>:
8048054: fa cli
8048055: 31 c0 xor %eax,%eax
8048057: 8e d8 mov %eax,%ds
8048059: 8e c0 mov %eax,%es
804805b: 8e d0 mov %eax,%ss
08048054 <_start>:
8048054: fa cli
8048055: 66 31 c0 xor %ax,%ax
8048058: 8e d8 mov %eax,%ds
804805a: 8e c0 mov %eax,%es
804805c: 8e d0 mov %eax,%ss
我理解
66
操作数前缀部分。使我困惑的是印刷的汇编助记符。对于.code32
案例,是否也应该打印xor%eax,%eax
?或者,它应该为.code16
案例打印xor%ax,%ax
?有人能澄清一下吗?.code 16
告诉汇编程序假定代码将以16位模式运行,例如,使用66
操作数大小前缀作为32位操作数大小,而不是默认的16位操作数大小。但是,您可以将其组装并链接到elf32二进制文件中,这意味着文件元数据仍然指示32位代码。(没有x86-16 Linux ELF文件)
Objdump根据文件元数据进行反汇编,因此作为32位代码,使用-mi8086
。您得到的大小与32位反汇编的二进制文件相匹配
如果在16位模式下汇编长度不同的指令,您可能会看到中断,如
add $129, %ax # 129 doesn't fit in an imm8
如果汇编为16位指令,则它将没有前缀和imm16源操作数。解码为32位指令时,它将有一个imm32源操作数,这将占用操作码后面的总字节数。对于任一模式,操作数大小前缀都会更改指令其余部分(不包括前缀)的长度。顺便说一句,在这种特殊情况下,在英特尔CPU上,(预)解码速度会减慢,因为指令的其余部分的前缀长度会发生变化。()
无论如何,用错误的代码大小反汇编该指令将导致反汇编程序与指令边界不同步,因此它将最终测试解释它的模式
如果您正在生成普通的用户空间代码(不是切换模式或需要16位的内核),.code32
和.code64
是无用的。他们只是让你把机器代码放到错误的ELF文件中。()
顺便说一句,移动到
%ss
会隐式防止中断,直到下一条指令之后。(应该设置堆栈指针)。这样可以避免cli/sti
。.code 16
告诉汇编程序假定代码将在16位模式下运行,例如使用66
操作数大小前缀作为32位操作数大小,而不是默认的16位操作数大小。但是,您可以将其组装并链接到elf32二进制文件中,这意味着文件元数据仍然指示32位代码。(没有x86-16 Linux ELF文件)
Objdump根据文件元数据进行反汇编,因此作为32位代码,使用-mi8086
。您得到的大小与32位反汇编的二进制文件相匹配
如果在16位模式下汇编长度不同的指令,您可能会看到中断,如
add $129, %ax # 129 doesn't fit in an imm8
如果汇编为16位指令,则它将没有前缀和imm16源操作数。解码为32位指令时,它将有一个imm32源操作数,这将占用操作码后面的总字节数。对于任一模式,操作数大小前缀都会更改指令其余部分(不包括前缀)的长度。顺便说一句,在这种特殊情况下,在英特尔CPU上,(预)解码速度会减慢,因为指令的其余部分的前缀长度会发生变化。()
无论如何,用错误的代码大小反汇编该指令将导致反汇编程序与指令边界不同步,因此它将最终测试解释它的模式
如果您正在生成普通的用户空间代码(不是切换模式或需要16位的内核),.code32
和.code64
是无用的。他们只是让你把机器代码放到错误的ELF文件中。()
顺便说一句,移动到
%ss
会隐式防止中断,直到下一条指令之后。(应该设置堆栈指针)。您可以通过这种方式避免cli/sti。它看起来像16位(一个字),似乎被翻译成双世界xoring,意思是,这包括16位以上,只是为了确保它们为零。编译为32位,正如您所期望的那样,这是有效的,因为您实际上是在将ax(al和ah,两者一起组装一个字)归零。正如你的指令所说,更高的位不会被触及。因此,正如我所想,32位代码是完全正确的,16位代码似乎很小心,尽管编译为16位,但更高的16位代码中不会出现垃圾,因为它是与-m32组合在一起的,-m32选项获胜。它只是对32位处理器的机器代码进行反汇编。16位机器代码实际可用的实际情况并不多。如果您想使用16位操作码解释来反汇编代码,那么使用objdump-d-mi8086 file.exe
@HansPassant:我相信-m32
在这里没有作用,因为它是手写程序集。如果我错了,请纠正我。-m32
仅适用于gcc生成的程序集。它看起来像16位(一个字),似乎被翻译成双世界xoring,意思是,这包括16位以上,只是为了确保它们为零。编译为32位,正如您所期望的那样,这是有效的,因为您实际上是在将ax(al和ah,两者一起组装一个字)归零。正如你的指令所说,更高的位不会被触及。因此,正如我所想,32位代码是完全正确的,16位代码似乎很小心,尽管编译为16位,但更高的16位代码中不会出现垃圾,因为它是与-m32组合在一起的,-m32选项获胜。它只是将机器代码反汇编为32位