NASM X86-64 вызывает внешние функции - PullRequest
0 голосов
/ 12 февраля 2019

Я очень новичок в сборке, но знаю немного о.Я играю с внешними вызовами функций, такими как

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

, но не могу найти никаких руководств, использующих функции extern, кроме scanf и printf.Например, strcmp?Как я могу вызвать strcmp в моем случае?

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Вот мой ответ.Это специфично для x86-64, хотя.Помните, что при передаче аргументов в функцию вы обычно помещаете первые 6 в регистры rdi, rsi, rdx, rcx, r8 и r9.Остальные выталкиваются в стек.Спецификация для этого называется System V ABI (обратите внимание, что Windows использует другое соглашение, называемое «Соглашение о вызовах Microsoft x64»).

    segment .data     ; or use .rodata for read-only data.
str1    db      "Hello", 0x0
str2    db      "Hellx", 0x0
fmt     db      "Comparison = %d", 0xa, 0x0

segment .text
    global main
    extern strcmp, printf
    default rel             ; RIP-relative addressing for [name] is what you want.

main:
    ; Create a stack-frame, re-aligning the stack to 16-byte alignment before calls
    push rbp
    mov rbp, rsp

    ; Prepare the arguments for strcmp.
    lea rdi, [str1]
    lea rsi, [str2]

    ; Call strcmp, return value is in rax.
    call strcmp

    ; Prepare arguments for printf.
    lea rdi, [fmt]
    mov esi, eax  ; int return value from strcmp -> 2nd arg for printf
    xor eax, eax  ; Indicate no floating point args to printf.

    ; Call printf
    call printf

    ; Return 0 (EXIT_SUCCESS), and destroy the stack frame.
    xor eax, eax
    leave            ; or just pop rbp because RSP is still pointing at the saved RBP
    ret
0 голосов
/ 12 февраля 2019

Редактировать: я сделал несколько ошибок здесь, подробности смотрите в комментариях!

Вот 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
...