x86 解释,函数参数和局部变量的数量 [英] x86 explanation, number of function arguments and local variables
问题描述
x86-64 系统的 C ABI 如下:寄存器 rdi、rsi、rdx、rcx、r8、r9 用于按该顺序传递参数.堆栈用于第 7 个参数.返回值使用 rax 寄存器.rsp 寄存器包含堆栈指针.
The C ABI for the x86-64 system is as follows: Registers rdi, rsi, rdx, rcx, r8, r9 are used to pass arguments in that order. The stack is used for the 7th argument onward. The return value uses the rax register. The rsp register contains the stack pointer.
blow 函数 bloop
中定义了多少个函数参数?
How many function arguments are defined in the blow function bloop
?
我认为只有一个函数参数,rdi
.这是正确的吗?
I think there is only one function argument, rdi
. is this correct?
在下面的函数 bloop
中声明了多少个局部变量(不是参数)?
How many local variables (not arguments) are declared in the below function bloop
?
我认为没有局部变量.这是正确的吗?
I think there is no local variable. Is this correct?
0000000000001139 <bloop>:
1139: 55 push %rbp
113a: 48 89 e5 mov %rsp,%rbp
113d: 48 83 ec 10 sub $0x10,%rsp
1141: 48 89 7d f8 mov %rdi,-0x8(%rbp)
1145: 48 83 7d f8 29 cmpq $0x29,-0x8(%rbp)
114a: 7f 1b jg 1167 <bloop+0x2e>
114c: 48 8b 05 dd 2e 00 00 mov 0x2edd(%rip),%rax
1153: 48 89 c6 mov %rax,%rsi
1156: 48 8d 3d b5 0e 00 00 lea 0xeb5(%rip),%rdi
115d: b8 00 00 00 00 mov $0x0,%eax
1162: e8 c9 fe ff ff callq 1030 <printf@plt>
1167: 90 nop
1168: c9 leaveq
1169: c3 retq
推荐答案
由于这个asm显然是反优化调试模式的编译器输出(默认的-O0
优化级别),您可以假设所有寄存器参数都在函数入口处溢出到堆栈中.(为什么 clang 用 -O0 生成效率低下的 asm(对于这个简单的浮点和)?)
Since this asm is obviously compiler output from anti-optimized debug mode (the default -O0
optimization level), you can assume that all register args get spilled to the stack on function entry. (Why does clang produce inefficient asm with -O0 (for this simple floating point sum)?)
是的,这使逆向工程变得微不足道,并排除了任何未使用的函数 args 或在它们到达的同一寄存器中传递给 printf 的 args.
So yes, that trivializes reverse engineering and rules out there being any unused function args or args that are passed on to printf in the same register they arrived in.
杂散的nop
和leave
指令的使用意味着这可能是GCC 输出,而不是clang 或ICC.仅与排除 const int foo = 0x29;
之类的可能性真正相关,GCC 不会在 -O0
上优化掉.ICC 和 clang 为让 GCC 制作此 asm 的源生成不同的 asm.我没有检查每个编译器版本,只检查这些编译器的最新版本.
The stray nop
, and use of the leave
instruction means this is probably GCC output, as opposed to clang or ICC. Only really relevant for ruling out the possibility of const int foo = 0x29;
or something, which GCC wouldn't optimize away at -O0
. ICC and clang produce different asm for source that gets GCC to make this asm. I didn't check every compiler version, just recent versions of these compilers.
(此外,这看起来像是对 PIE 可执行文件或共享库的反汇编.在传统的位置相关 ELF 可执行文件中,左侧的地址列将具有更高的地址,并且编译器将使用 mov $imm32,%edi
将静态地址放入寄存器.)
(Also, this looks like disassembly of a PIE executable or shared library. The address column on the left would have higher addresses in a traditional position-dependent ELF executable, and a compiler would have used mov $imm32, %edi
to put a static address in a register.)
所以是的,有一个 64 位整数/指针 arg(它当然到达 RDI),并且对 printf 的调用传递了一个全局或静态 64 位变量的值mov 0x2edd(%rip)、%rsi
,以及放入 LEA 寄存器中的全局/静态格式字符串的地址.
So yes, there's one 64-bit integer/pointer arg (which of course arrives in RDI), and the call to printf passes the value of a global or static 64-bit variable loaded with mov 0x2edd(%rip), %rsi
, and the address of a global/static format string put into a register with LEA.
是的,除非他们完全未使用,否则我看不到当地人.在 -O0
处,gcc 会优化掉 int used;
而不是 int foo = 123;
.有任何局部变量,即使 register const compare = 0x29;
也会让 GCC 到 subq $24, %rsp
而不是 16 (0x10).(请参阅下面的 Godbolt 链接.)而且它实际上不会进行持续传播.
And yes, no locals that I can see unless they're totally unused. At -O0
, gcc will optimize away int unused;
but not int foo = 123;
. Having any locals at all, even register const compare = 0x29;
will get GCC to subq $24, %rsp
instead of 16 (0x10). (See the Godbolt link below.) And it won't actually do constant-propagation.
我可以让 GCC9.3 -O0 从这个源代码中生成这个 asm:
I can get GCC9.3 -O0 to produce exactly this asm from this source code:
#include <stdio.h>
long global_var;
void bloop(long x) {
if (!(x>0x29))
printf("%ld", global_var);
}
on Godbolt with gcc9.3 -O0 -fpie -fverbose-asm
:
# godbolt strips out directives like .section .rodata
.LC0:
.string "%ld"
bloop:
pushq %rbp #
movq %rsp, %rbp #,
subq $16, %rsp #,
movq %rdi, -8(%rbp) # x, x
cmpq $41, -8(%rbp) #, x
jg .L3 #,
movq global_var(%rip), %rax # global_var, global_var.0_1
movq %rax, %rsi # global_var.0_1,
leaq .LC0(%rip), %rdi #,
movl $0, %eax #,
call printf@PLT #
.L3:
nop
leave
ret
nop
没有任何意义;我不知道为什么未优化的 GCC 输出有时会有一个.
The nop
has no purpose; I don't know why unoptimized GCC output sometimes has one.
另见如何去除噪音"来自 GCC/clang 程序集输出? 有关查看编译器输出的更多信息.
See also How to remove "noise" from GCC/clang assembly output? for more about looking at compiler output.
这篇关于x86 解释,函数参数和局部变量的数量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!