nasm函数调用约定

64位linux函数调用约定

参数传递,从左到右

整数或者指针 rdi rsi rdx rcx r8 r9

浮点数 xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7

额外的超出的参数从右向左进栈

当所有的参数进栈,RSP 指向栈底,即返回值,第一个参数即为 [RSP+8]

在调用函数之前,RSP 必须 16 字节对齐,不是因为不对齐就运行不了,而是因为有些指令操作栈时必须16字节对齐,如果不对齐可能会发生段错误,比如 movaps%xmm0,-0x70(%rbp) simd指令

这些寄存器被调用函数不能修改,如果需要用到,先入栈保存

rbp, rbx, r12, r13, r14, r15


需要返回的整数存入 RAX 或者 RDX:RAX,需要返回的浮点数存入 xmm0 或者 xmm1:xmm0


需要glibc例子

extern  printf

section .text
global main

add:
    push rbx
    mov rbp, rsp

    add rdi, rsi    ;第一个参数+第二个参数
    mov rax, rdi    ;将和存入 rax

    pop rbx
    ret

main:
    push rbx
    mov rbp, rsp

    mov rdi, 10
    mov rsi, 12
    
    ;此时栈已经16字节对齐
    call add

    mov rdi, fmt
    mov rsi, rax
    
    call printf

    mov rax,0

    pop rbx
    ret

section .data
    fmt db  "10+12=%d", 10, 0
[root@izbp1irxwqt7ei21awv6wvz ccc]# nasm -felf64 main.asm
[root@izbp1irxwqt7ei21awv6wvz ccc]# gcc main.o
[root@izbp1irxwqt7ei21awv6wvz ccc]# ./a.out 
10+12=22


不需要glibc例子

此时需要用到系统调用

extern  printf

section .text
global _start

add:
    push rbx
    mov rbp, rsp

    add rdi, rsi    ;第一个参数+第二个参数
    mov rax, rdi    ;将和存入 rax

    pop rbx
    ret

_start:
    push rbx
    mov rbp, rsp

    mov rdi, 10
    mov rsi, 12
    
    ;此时栈已经16字节对齐
    call add

    ;write
    mov rax, 1      ;系统调用号
    mov rdi, 1      ;stdout
    mov rsi, fmt    ;字符串
    mov rdx, 9      ;长度
    syscall

    pop rbx
    
    ;exit(0)
    mov rax, 60      ;系统调用号
    mov rdi, 0      ;stdout
    syscall

section .data
    fmt db  "10+12=22",10
[root@izbp1irxwqt7ei21awv6wvz ccc]# nasm -felf64 main.asm
[root@izbp1irxwqt7ei21awv6wvz ccc]# ld main.o
[root@izbp1irxwqt7ei21awv6wvz ccc]# ./a.out 
10+12=22



上一篇: nasm常用指令
下一篇: -fPIC 地址无关补充
作者邮箱: 203328517@qq.com