【问题标题】:C function calling problems in assembly汇编中的C函数调用问题
【发布时间】:2018-12-01 15:50:05
【问题描述】:
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... 在不同文件中指定第一行和最后一行。我不明白这个消息有人可以帮助我吗?

【问题讨论】:

  • 您未对齐堆栈。另外,你忘了pop rbp
  • 你能以正确的方式编写我的代码吗?
  • 只需删除push rdi/rsi/rbx 以及三个pops,而是在ret 之前添加pop rbp。正如保罗所说,你还应该在"%d" 之后添加一个,0,尽管从技术上讲它是有效的,因为无论如何你后面都是零。
  • @Jester,第一次格式转换会覆盖零。然后 fscanf 继续读取格式,该格式现在不再以 null 结尾(对于几个字节,在 x86 内存中反向布局的 int)
  • 好吧,您仍然需要添加pop rbp。如果你必须保留那些无用的推送(问你的教授为什么他坚持保留调用者保存的寄存器和甚至没有被触及的rbx)然后添加另一个push 来对齐堆栈。

标签: c assembly x86-64 calling-convention


【解决方案1】:

您有以下问题:

  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归零和rip-relative寻址如下:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-27
    相关资源
    最近更新 更多