了解反汇编的C代码:dec%eax和movl $ 0x0,-0x8(%ebp) [英] Understanding disassembled C code: dec %eax and movl $0x0,-0x8(%ebp)
问题描述
我试图理解一段反汇编代码中的行,如下所示.我想知道以下内容:
I'm trying to understand the lines in a piece of disassembled code as shown below. I'd like to know the following:
- dec%eax:为什么减少eax寄存器? eax寄存器的初始值是什么?
- movl $ 0x0,-0x8(%ebp):为什么我们将值0x0移动到堆栈上? movl是否不存储32位值(4个字节)?如果是这样,为什么将值存储在基指针下方8个字节而不是4个字节?
这是反汇编的二进制文件:
Here's the disassembled binary:
Contents of section .text:
0000 554889e5 48c745f8 00000000 905dc3 UH..H.E......].
Contents of section .rodata:
0000 48656c6c 6f00 Hello.
Contents of section .comment:
0000 00474343 3a202855 62756e74 7520352e .GCC: (Ubuntu 5.
0010 342e302d 36756275 6e747531 7e31362e 4.0-6ubuntu1~16.
0020 30342e31 30292035 2e342e30 20323031 04.10) 5.4.0 201
0030 36303630 3900 60609.
Contents of section .eh_frame:
0000 14000000 00000000 017a5200 01781001 .........zR..x..
0010 1b0c0708 90010000 1c000000 1c000000 ................
0020 00000000 0f000000 00410e10 8602430d .........A....C.
0030 064a0c07 08000000 .J......
Disassembly of section .text:
0000000000000000 <my_function>:
0: 55 push %ebp
1: 48 dec %eax
2: 89 e5 mov %esp,%ebp
4: 48 dec %eax
5: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%ebp)
c: 90 nop
d: 5d pop %ebp
e: c3 ret
这是C代码:
void my_function () {
char* my_string = "Hello";
}
推荐答案
您正在分解64位代码,就好像它是32位代码一样.除非您专门重写了反汇编程序或使用objcopy
或其他方法将64位机器代码复制到32位ELF目标文件中,否则通常无法实现.
You're disassembling 64-bit code as if it were 32-bit code. This is not normally possible unless you specifically override your disassembler or use objcopy
or something to copy 64-bit machine-code into a 32-bit ELF object file.
x86-64将0x40..f字节重新用作REX前缀,而不是inc/dec的1字节编码. DEC EAX实际上是REX.W前缀,因此对于正常的帧指针设置,该指令为mov %rsp, %rbp
.
x86-64 repurposed the 0x40..f bytes as REX prefixes instead of 1 byte encodings of inc/dec. The DEC EAX is actually a REX.W prefix, so the instruction is mov %rsp, %rbp
for the normal frame-pointer setup.
这也说明了堆栈指针下方红色区域的前8个字节的使用. (x86-64 System V有一个红色区域,i386 System V没有红色区域;在存储在它下面之前,它会移动ESP.)并且它解释了指针的-8
而不是-4
,因为x86-64具有8字节指针.
This also explains the use of the top 8 bytes of the red-zone below the stack pointer. (x86-64 System V has a red-zone, i386 System V doesn't; it would move ESP before storing below it.) And it explains -8
instead of -4
for the pointer, because x86-64 has 8-byte pointers.
0
字节是因为您要拆装未链接的.o
.链接器将使用字符串的绝对地址填充这四个字节的零.
The 0
bytes are because you're disassembling a .o
that isn't linked. Those 4 bytes of zeros will be filled in with the string's absolute address by the linker.
GCC在这里使用mov r/m64, sign_extended_imm32
使用32位绝对地址作为立即数来存储指向内存的8字节指针.
GCC is using a mov r/m64, sign_extended_imm32
here to store an 8-byte pointer to memory using a 32-bit absolute address as an immediate.
将其放入寄存器中,我们将为非PIE可执行文件获得常规的mov r32, imm32
(隐式零扩展至64位).但是此代码(使用默认的-O0
调试模式")需要内存中的整个8字节指针.它仍然可以使用32位绝对地址而不是相对RIP的LEA到寄存器+单独的存储区中,但是必须将其显式符号扩展为64位.
To put it in a register, we'd get the normal mov r32, imm32
(with implicit zero extension to 64-bit) for a non-PIE executable. But this code (with the default -O0
"debug mode") needs the whole 8-byte pointer in memory. It can still use a 32-bit absolute address instead of a RIP-relative LEA into a register + separate store, but it has to be explicit sign-extension to 64-bit.
这篇关于了解反汇编的C代码:dec%eax和movl $ 0x0,-0x8(%ebp)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!