Assembly x86解释,函数参数和局部变量的数量
x86-64系统的C ABI如下:寄存器rdi、rsi、rdx、rcx、r8、r9用于按该顺序传递参数。堆栈用于第7个参数之后的值。返回值使用rax寄存器。rsp寄存器包含堆栈指针 在blow函数Assembly x86解释,函数参数和局部变量的数量,assembly,x86-64,reverse-engineering,Assembly,X86 64,Reverse Engineering,x86-64系统的C ABI如下:寄存器rdi、rsi、rdx、rcx、r8、r9用于按该顺序传递参数。堆栈用于第7个参数之后的值。返回值使用rax寄存器。rsp寄存器包含堆栈指针 在blow函数bloop中定义了多少个函数参数 我认为只有一个函数参数,rdi。这是正确的吗 0000000000001139 <bloop>: 1139: 55 push %rbp 113a: 48 89 e5
bloop
中定义了多少个函数参数
我认为只有一个函数参数,rdi
。这是正确的吗
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
在下面的函数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
0000000000001139:
1139:55%rbp
113a:48 89 e5 mov%rsp,%rbp
113d:48 83欧共体10分$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
114c:48 8b 05日第二个月第二个月第二个月第二个月第二个月第二个月第二个月第二个月第二个月第二个月第二个月
1153:4889C6MOV%rax%rsi
1156:48 8d 3d b5 0e 00 lea 0xeb5(%rip),%rdi
115d:b8 00 mov$0x0,%eax
1162:e8 c9 fe ff ff呼叫1030
1167:90不
1168:c9-q
1169:c3 retq
由于此asm显然是反优化调试模式下的编译器输出(默认的-O0
优化级别),您可以假设所有寄存器参数在函数项上溢出到堆栈。()
是的,这使逆向工程变得简单化,并排除了在到达的同一寄存器中传递给printf的任何未使用的函数arg或arg
杂散的nop
,以及使用leave
指令意味着这可能是GCC输出,而不是clang或ICC。仅与排除const int foo=0x29的可能性真正相关代码>或其他GCC不会在-O0
上优化的东西ICC和clang为源代码生成不同的asm,使GCC生成此asm。我没有检查每个编译器版本,只是检查这些编译器的最新版本
(同样,这看起来像是PIE可执行文件或共享库的反汇编。左侧的地址列在传统的位置相关ELF可执行文件中会有更高的地址,编译器会使用mov$imm32,%edi
将静态地址放入寄存器。)
所以是的,有一个64位整数/指针arg(当然是在RDI中到达的),对printf的调用传递一个全局或静态64位变量的值,该变量加载了mov 0x2edd(%rip),%rsi
,以及一个全局/静态格式字符串的地址,该字符串被放入LEA寄存器中
是的,我看不到当地人,除非他们完全不用。在-O0
,gcc将优化int unused代码>但不是intfoo=123代码>。有任何局部变量,甚至寄存器常量compare=0x29
将GCC设置为subq$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);
}
nop
没有目的;我不知道为什么未优化的GCC输出有时会有一个
有关查看编译器输出的更多信息,请参见。mov
和nop
都是指令。指令是处理器执行的东西,是组成机器程序的东西。如果您不熟悉这个概念,阅读有关汇编编程的教程可能会有所帮助
函数使用的指令在很大程度上与它有多少参数和局部变量无关。如果出现nop
和一些mov
指令,则不会告诉您函数的参数和变量
它告诉您的是这些指令有哪些操作数。如果您不熟悉什么是操作数或x86指令如何使用操作数,我必须再次请您参考教程,因为这超出了本问题的范围
识别函数参数的一般方法是检查函数使用的调用方保存的寄存器,而无需事先为它们赋值。虽然这不是一个简单的方法,但它通常是最好的启发式方法
在函数中,使用调用方保存的寄存器rdi
、rsi
和rax
。其中,只有rdi
的原始值对功能有影响。对于rsi
和rax
,函数会覆盖它们的原始值,而不查看它们。因此,这些不太可能是函数参数(rax
在SysV调用约定中从未用于函数参数)。因此,函数在rdi
中可能有一个参数。我看不到调用方分配的堆栈插槽的任何访问权限,因此也不太可能隐藏任何额外的参数
仍然可能是函数被编写为在rsi
或其他一些寄存器中有参数,而这些参数只是没有使用。如果没有额外的信息(例如调试符号、调用站点的反汇编等),我们永远无法确定
至于局部变量:一般来说,当一个C函数被编译成汇编程序时,没有办法重构它使用的局部变量,因为编译器可以优化局部变量,直到它们的存在无法识别为止。它还可以出于各种目的添加额外的局部变量
但是,在您的特定情况下,该函数很可能是用o编译的