在汇编代码中调用C函数(气体)

时间:2013-03-23 16:36:23

标签: assembly x86-64 gas

我找到了一个例子,并正在为气体进行编辑。

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

os:linux(debian)。英特尔64位

4 个答案:

答案 0 :(得分:2)

以下是更正后的注释列表:

        .extern printf
        .global main

        .section .data
hello:  .asciz "Hello\n"

这定义了一个以空字符结尾的字符串,相当于C中的“Hello \ n”

        .section .text
main:
        movq $hello, %rdi
        movq $0, %rax
        call printf

这相当于 printf(hello)。要调用vararg函数,需要在rax中使用浮点寄存器的数量,在这种情况下为零。

        movq $0, %rax
        ret

这相当于 return 0

使用'cc -o x x.s'组装并链接。

答案 1 :(得分:1)

这是null-byte-terminattor。众所周知为C-string。字符串末尾的这个字节表示字符串结束的位置。例如,您将指针传递给字符串以调用例程,例程将理解内存中此类字符串的区域来自于求a[0](在C术语中),直到看到a[x] == 0。 / p>

答案 2 :(得分:0)

所有这一切都是将字节放入程序中。字节是字符“Hello”,后跟0xa(行终止),最后是NULL字节。在C中,它将类似于“char * hello =”Hello \ n“;”

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

答案 3 :(得分:0)

以下声明一个带Hello的字符串,后跟换行符和null终止符。 C字符串

需要空终止符
db "Hello", 0xa, 0

要调用printf,您需要在堆栈上传递参数,这样就像

mov hello, (%esp)
call printf

据我所知,惯例是mov source,destination。你似乎已经反过来编码了它。