GCC汇编代码在64位机器上显示32位寄存器

时间:2016-08-19 13:45:21

标签: c x86-64 ptrace

我正在尝试学习如何使用ptrace库来跟踪所有系统调用及其参数。我被困在获取传递给系统调用的参数。 我浏览了许多在线资源和SO问题,并发现在64位机器上,参数存储在寄存器rax(sys call number), rdi, rsi, rdx, r10, r8, r9中 以相同的顺序。检查this website

为了证实这一点,我写了一个简单的C程序如下

#include<stdio.h>
#include<fcntl.h>
int main() {
  printf("some print data");
  open("/tmp/sprintf.c", O_RDWR);
}

并使用gcc -S t.c为此生成汇编代码,但生成的汇编代码如下所示

    .file   "t.c"
    .section    .rodata
.LC0:
    .string "some print data"
.LC1:
    .string "/tmp/sprintf.c"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    movl    $2, %esi
    movl    $.LC1, %edi
    movl    $0, %eax
    call    open
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
    .section    .note.GNU-stack,"",@progbits

正如您所看到的,此代码会在esiedi上存储参数。 为什么会这样?

另外请指导我从C代码访问这些寄存器/内存位置传递参数的最佳方法是什么?我怎样才能弄清楚寄存器的内容是参数本身还是存储实际参数的存储位置?

谢谢!

1 个答案:

答案 0 :(得分:0)

  

此代码存储esiedi

上的参数

32位指令较小,因此在可能的情况下是首选。另请参阅Why do most x64 instructions zero the upper part of a 32 bit register

  

如何判断寄存器的内容是参数本身还是存储实际参数的存储位置?

AMD64 SystemV调用约定永远不会隐式地用隐藏指针替换函数arg。 C原型中的整数/指针args总是直接进入arg传递寄存器。

按值传递的

结构/联合进入一个或多个寄存器,或进入堆栈。

完整的详细信息记录在the ABI中。查看标记维基中的更多链接。 http://www.x86-64.org/documentation.html现在已经关闭了,所以我在github上链接了当前版本。