assembly - x86 解释,函数参数和局部变量的数量
问题描述
x86-64 系统的 C ABI 如下: 寄存器 rdi、rsi、rdx、rcx、r8、r9 用于按顺序传递参数。堆栈用于第 7 个参数。返回值使用 rax 寄存器。rsp 寄存器包含堆栈指针。
吹函数中定义了多少个函数参数bloop
?
我认为只有一个函数参数,rdi
. 这个对吗?
在下面的函数中声明了多少个局部变量(不是参数)bloop
?
我认为没有局部变量。这个对吗?
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
优化级别)的编译器输出,因此您可以假设所有寄存器 args 在函数入口时都溢出到堆栈中。 (为什么clang用-O0产生效率低下的asm(对于这个简单的浮点和)?)
所以是的,这使逆向工程变得微不足道,并排除了任何未使用的函数 args 或 args 在它们到达的同一个寄存器中传递给 printf。
指令的杂散nop
和使用leave
意味着这可能是 GCC 输出,而不是 clang 或 ICC。仅与排除const int foo = 0x29;
GCC 不会优化的可能性或某事真正相关-O0
。 ICC 和 clang 为让 GCC 生成这个 asm 的源代码生成不同的 asm。我没有检查每个编译器版本,只是检查了这些编译器的最新版本。
(此外,这看起来像是对 PIE 可执行文件或共享库的反汇编。在传统的位置相关的 ELF 可执行文件中,左侧的地址列将具有更高的地址,并且编译器会习惯mov $imm32, %edi
将静态地址放入寄存器中。)
所以是的,有一个 64 位整数/指针 arg(它当然到达 RDI),并且对 printf 的调用传递了加载的全局或静态 64 位变量的值mov 0x2edd(%rip), %rsi
,以及全局/静态格式的地址将字符串放入 LEA 的寄存器中。
是的,除非他们完全未使用,否则我看不到当地人。在-O0
,gcc 将优化int unused;
但不会int foo = 123;
。有任何本地人,甚至register const compare = 0x29;
会得到 GCCsubq $24, %rsp
而不是 16 (0x10)。(请参阅下面的 Godbolt 链接。)它实际上不会进行持续传播。
我可以让 GCC9.3 -O0 从此源代码中准确生成这个 asm:
#include <stdio.h>
long global_var;
void bloop(long x) {
if (!(x>0x29))
printf("%ld", global_var);
}
在使用 gcc9.3 的 Godbolt 上-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 输出有时会有一个。
另请参阅如何从 GCC/clang 程序集输出中删除“噪音”?有关查看编译器输出的更多信息。
推荐阅读
- java - 使用注入 java 和 spring boot 的 RestTemplate 类进行单元测试
- active-directory - Active Directory 联合身份验证服务 response_mode=form_post 尝试发布以响应应用程序
- java - Selenium WebDrive Java Firefox Headless 不工作
- angular - ngFor 中的 Kendo Datepickers
- vb.net - 我正在尝试创建一个在用户单击表单加载时创建的图片框时发生的事件
- arm - Zynq 7020 内存映射和 JTAG 访问
- python-3.x - 如何修复:我的自定义 RNN 单元中的不可微函数
- python - Pandas:如果不是最大值,则替换为 0 的列
- xcode - 总是隐藏 Xcode 控制台
- python - 使用 requests 模块将“curl -X PUT ... - G ...”转换为 python