汇编中的C函数调用问题

时间:2018-12-01 15:50:05

标签: c assembly x86-64 calling-convention

section .data
text db 'Put a number',10,0
scanform db '%d'
number dw 0

section .text
extern printf,scanf

global main
main:
push rbp
mov rbp,rsp
push rdi
push rsi
push rbx

mov rdi,text
mov rax,0
call printf

mov rsi,number
mov rdi,scanform
mov rax,0
call scanf

pop rbx
pop rsi
pop rdi
ret

这是我的代码,我整天都在编写其他代码,但是我没有遇到任何问题,但是现在当我调用scanf时,写程序收到信号SIGSEV,segfault ...在不同文件中指定了第一行和最后一行。我不明白此消息,有人可以帮助我吗?

1 个答案:

答案 0 :(得分:4)

您遇到以下问题:

  1. 您忘记了pop rbp
  2. 您未对齐需要16字节对齐的堆栈。
  3. 您不会将格式字符串终止为零(感谢Paul指出了这一点)。
  4. 您使用%d写入4个字节的整数,但仅使用dw分配了2个字节。
  5. 建议将整数对齐为4个字节。

可能的固定版本:

section .data
number dd 0
text db 'Put a number',10,0
scanform db '%d', 0

section .text
extern printf,scanf

global main
main:
push rbp
mov rbp,rsp
push rdi
push rsi
push rbx
push rbx ; for alignment

mov rdi,text
mov rax,0
call printf

mov rsi,number
mov rdi,scanform
mov rax,0
call scanf

pop rbx
pop rbx
pop rsi
pop rdi
pop rbp
ret

由于rsirdi是调用者保存的寄存器,而rbx没有被触摸,因此可以简化代码。我还更改为xor归零和相对撕裂寻址,如下所示:

section .data
number dd 0
text db 'Put a number',10,0
scanform db '%d', 0

section .text
extern printf,scanf

global main
main:
push rbp

lea rdi, [rel text]
xor eax, eax
call printf

lea rsi, [rel number]
lea rdi, [rel scanform]
xor eax, eax
call scanf

pop rbp
ret