X86-64 NASM调用外部C函数

时间:2019-02-12 19:50:28

标签: c nasm x86-64 calling-convention abi

我对汇编语言很陌生,但是对c有一点了解。我正在玩外部函数调用,如

extern _printf
str db "Hello", 0
push str
call _printf

但是找不到使用外部函数的任何教程,除了scanf和printf。例如strcmp?我该如何呼叫strcmp?

2 个答案:

答案 0 :(得分:3)

这是我的答案。但是它特定于x86-64。请注意,将参数推入函数时,通常将前6个寄存器分别放置在寄存器rdirsirdxrcxr8和{ {1}}。其余的被推入堆栈。此规范称为System V ABI(请注意,Windows使用另一种约定,称为“ Microsoft x64调用约定”)。

r9

答案 1 :(得分:1)

编辑:我在这里犯了一些错误,有关详细信息,请参见评论!

这是32位版本(以下为64位):

SECTION .data
    ; global functions in this file
    global main

    ; extern functions
    extern strcmp

hworld: ; our first string
    db "hello world", 0

hworld2: ; our second string
    db "hello world2", 0

SECTION .text

;=============================================================================
; The program entrypoint
;
main:

    ; int rv = strcmp("hello world", "hello world2");
    push    hworld2
    push    hworld
    call    strcmp

    ; _exit(rv);
    mov     ebx, eax
    mov     eax, 1
    int     0x80

然后您可以使用以下命令进行编译:

nasm -f elf main.s -o main.o
cc -m32 main.o -o hello_world

这是64位版本:

SECTION .data
    ; global functions in this file
    global main

    ; extern functions
    extern strcmp

hworld: ; our first string
    db "hello world", 0

hworld2: ; our second string
    db "hello world2", 0

SECTION .text

;=============================================================================
; The program entrypoint
;
main:

    ; int rv = strcmp("hello world", "hello world2");
    mov     rsi, hworld2
    mov     rdi, hworld
    call    strcmp

    ; _exit(rv);
    mov     rdi, rax
    mov     rax, 60
    syscall

然后您可以使用以下命令编译x64版本:

nasm -f elf64 main.s -o main.o
cc main.o -o hello_world

并运行它:

$ ./hello_world 
$ echo $?
206