我的程序集实现中的分段错误

时间:2017-12-22 15:45:25

标签: c linux assembly x86-64 calling-convention

我是汇编语言编程的新手,在这里我试图从我的汇编代码中调用C标准库函数put,但我不断得到segmentaion错误。请帮忙; 操作系统:LINUX 16.04 汇编:nasm 机器:intel x86 - 64位

;comiple and build:
;                   nasm -f elf64 -F stabs helloc.asm
;                   gcc -o helloC helloC.o
[SECTION .data]
   msg: db "Hello C",0
[SECTION .bss]

[SECTION .text] 
 extern puts

 global main 
 main:
  push rsp

  push dword msg
  call puts
  add rsp,4

  pop rsp
  ret

1 个答案:

答案 0 :(得分:1)

解释Comments更多,从x86调用约定和代码开始。

x86呼叫约定

在x86中,参数位于堆栈中。所以基本上你的函数调用是x86方式。例如,如果您为x86构建代码,

[SECTION .data]
   msg: db "Hello C",0
[SECTION .bss]

[SECTION .text] 
 extern puts

 global main 
 main:
  push ebp
  mov ebp, esp
  and esp, 0xfffffff0
  sub esp, 0x10

  mov DWORD PTR [esp], msg
  call puts


  mov esp, ebp
  pop ebp
  ret

它可能正常。

x86-64呼叫约定

主要区别在于两件事。

  • 使用8个字节来表示地址,当然
  • 使用6个registeres(rdi,rsi,rdx,rcx,r8,r9)代表前6个参数(rest位于堆栈中)

首先,您应该将push dword msg更改为mov rdi, msg,并且不要在调用后清理堆栈(因为您没有将任何内容推送到堆栈中)

更改后

[SECTION .data]
   msg: db "Hello C",0
[SECTION .bss]

[SECTION .text] 
 extern puts

 global main 
 main:
  push rbp
  mov rbp, rsp
  and rsp, 0xfffffffffffffff0

  mov rdi, msg
  call puts


  mov rsp, rbp
  pop rbp
  ret

编辑:来自System V ABI,对于调用指令堆栈应该是16字节对齐的。所以push rbp对齐,但使用不正确。要改变它,为x86和x86-64制作堆栈保存逻辑。