【问题标题】:GCC assembly code shows 32bit registers on 64bit machineGCC 汇编代码在 64 位机器上显示 32 位寄存器
【发布时间】:2016-08-19 13:45:20
【问题描述】:

我正在尝试学习如何使用 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 代码中的这些寄存器/内存位置访问这些传递的参数的最佳方法是什么?如何确定寄存器的内容是参数本身还是存储实际参数的内存位置?

谢谢!

【问题讨论】:

  • 在 x86 64 位处理器上,如果您更改 32 位寄存器的内容,零扩展结果将放入整个 64 位寄存器。使用 32 位寄存器可以缩短指令的编码。 EDI是寄存器RDI的低32位,ESIRSI的低32位
  • @MichaelPetch:我正在尝试通过 ptrace 调用访问这些寄存器。因此,从您的评论来看,即使我尝试访问 rdi,它也应该给我正确的数据,对吗?
  • 如果你在 32 位寄存器中放置一个 vale,它应该与 64 位寄存器的值相同,但宽度为 64 位。所以看64位寄存器是正确的。因此,尽管写入了 EDI,但可以通过 64 位寄存器 RDI 查看内容。
  • 谢谢!如果是字符串,值如何存储?它们是直接存储在寄存器中还是寄存器指向实际值所在的内存位置?
  • 假设您使用的是 AT&T 语法,在这种情况下,如果您看到前面带有 $ 符号的标签,例如 $.LC0,它告诉汇编程序使用标签(这是它的地址)而不是存储在该地址的内容。您通常将指针传递给字符串。 movl $.LC0, %edi 将字符串“some print data”的address移动到EDI中。

标签: c x86-64 ptrace


【解决方案1】:

此代码将参数存储在esiedi

32 位指令更小,因此尽可能首选。另见Why do most x64 instructions zero the upper part of a 32 bit register


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

AMD64 SystemV 调用约定从不使用隐藏指针隐式替换函数 arg。 C原型中的整数/指针args总是直接进入arg-passing寄存器。

按值传递的结构/联合放在一个或多个寄存器中,或者放在堆栈中。

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

【讨论】:

  • @CL.:感谢我的答案中的文档链接清理,特别是在适当的时候注意用类似的维基百科链接替换链接:)
猜你喜欢
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 2014-12-17
  • 1970-01-01
  • 1970-01-01
  • 2015-06-20
  • 2011-10-26
  • 2012-10-22
相关资源
最近更新 更多