【问题标题】:Calling C function in assembly code (gas)在汇编代码中调用 C 函数(gas)
【发布时间】:2013-03-13 10:11:00
【问题描述】:

我找到了一个示例,并正在对其进行气体编辑。

extern printf
.global _start
.data
hello:
db "Hello", 0xa, 0
.text
_start:
mov %rdi, hello
mov %rax, 0
call printf
mov %rax, 0
ret

但它不起作用。怎么了?这是什么意思:

    hello:
db "Hello", 0xa, 0

我明白它的内存范围是什么,但是我不明白这个字符串

db "Hello", 0xa, 0

这里

_start:
mov %rdi, hello
mov %rax, 0
call printf
mov %rax, 0
ret

操作系统:Linux(debian)。英特尔 64 位

【问题讨论】:

标签: assembly x86-64 gnu-assembler


【解决方案1】:

它是null-byte-terminattor。众所周知的 C 字符串。字符串末尾的此类字节表示字符串的结束位置。例如,您将指向您的字符串的指针传递给一个例程,该例程将理解该字符串在内存中的区域是从乞求a[0](在C 术语中)直到看到a[x] == 0

【讨论】:

    【解决方案2】:

    下面声明了一个带有 Hello 的字符串,后跟换行符和空终止符。 C 字符串需要空终止符

    db "Hello", 0xa, 0
    

    要调用 printf,你需要在堆栈上传递参数,所以它会是这样的

    mov hello, (%esp)
    call printf
    

    据我所知,约定是 mov source, destination。你似乎用相反的方式编码。

    【讨论】:

    • 在 64 位 Linux/UNIX 上使用 rdi 作为第一个参数是正确的。 x86-64 上的 Windows 使用 rcx, rdx, r8r9 作为前四个整数/指针参数,其余使用堆栈。 Linux/UNIX 使用 rdi, rsi, rdx, rcx, r8r9 作为前六个参数。如果这应该是 AT&T 语法代码,则源/目标顺序看起来确实颠倒了。
    【解决方案3】:

    所做的只是将字节放入程序中。字节是字符“Hello”,然后是 0xa(这是行终止符),最后是 NULL 字节。在 C 语言中,它类似于 "char *hello = "Hello\n";"

    在您的 _start: 标签处,将 hello 标签的地址放入寄存器 %rdi,将 0 放入 %rax,然后调用 printf 函数。

    【讨论】:

      猜你喜欢
      • 2016-08-27
      • 2011-09-04
      • 2016-09-07
      • 2017-02-18
      • 1970-01-01
      • 1970-01-01
      • 2020-06-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多