x86 解释,函数参数和局部变量的数量 [英] x86 explanation, number of function arguments and local variables

查看:53
本文介绍了x86 解释,函数参数和局部变量的数量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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.

杂散的nopleave 指令的使用意味着这可能是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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆