【发布时间】:2016-09-29 10:32:19
【问题描述】:
我对 Assembly 很陌生,我正在尝试创建一个使用 scanf 从用户那里接收数字的程序。然后它输出“结果:(数字)” 运行代码时,我不断收到分段错误。 这是我现在得到的代码:
.global main
mystring: .asciz"input\n"
formatstring: .asciz" %d"
resultstring: .asciz "Result: %ld\n"
main:
movq $0, %rax
movq $mystring, %rdi
call printf
call inout
movq $0, %rax
movq $resultstring, %rdi
call printf
jmp end
inout:
pushq %rbp
subq $8, %rsp
leaq -8(%rbp), %rsi
movq $formatstring, %rdi
movq $0, %rax
call scanf
popq %rbp
ret
end:
movq $0, %rdi
call exit
我怀疑“inout”方法有问题。有什么解决方案可以让这个程序正常工作吗?
【问题讨论】:
-
在
inout中,您没有设置rbp,仅将旧值压入堆栈,然后您访问rbp-8内存(访问发生在scanf 内部),它可能指向任何地方。顺便说一句,“我不断收到分段错误”表明您缺乏努力,通过调试,您应该能够判断它在哪条指令处出现段错误,以及 CPU 的状态是什么(寄存器值、代码地址、堆栈内容).. . 但那时你不需要问 SO,因为你可能会自己看到scanf的%rsi参数是假的。 -
而且你不会在 scanf 调用后恢复
rsp,使用错误的rsp值执行pop %rbp。此外,您应该确保rsp在调用scanf时对齐。检查这个:cs.lmu.edu/~ray/notes/gasexamples(看起来足够短,也许完整,4秒快速查看) -
可以在此处找到一些关于似乎类似问题的 cmets:stackoverflow.com/questions/39679848/…
-
一次推送和一次
sub rsp, 8也会使堆栈错位。 ABI 要求它在运行 CALL 之前是 16B 对齐的(这会推送 8B 返回地址)。