在 x86_64 AT&T 中调用 scanf 时出现分段错误

Posted

技术标签:

【中文标题】在 x86_64 AT&T 中调用 scanf 时出现分段错误【英文标题】:Segmentation error upon calling scanf in x86_64 AT&T 【发布时间】: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:***.com/questions/39679848/… 一次推送和一次sub rsp, 8 也会使堆栈错位。 ABI 要求它在运行 CALL 之前是 16B 对齐的(这会推送 8B 返回地址)。 【参考方案1】:
leaq    -8(%rbp), %rsi

在此指令中,您指的是%rbp 寄存器,但您忘记实际初始化它!

【讨论】:

以上是关于在 x86_64 AT&T 中调用 scanf 时出现分段错误的主要内容,如果未能解决你的问题,请参考以下文章

使用 GNU 汇编器在 x86_64 中调用 printf

AT&T x86_32 汇编_002_使用C库函数

AT&T x86_32 汇编_003_数据段

AT&T x86_32 汇编_004_数据传递

AT&T x86_32 汇编_001_一个示例程序.md

AT&T 语法中的 3 或 4 参数 x86 程序集[重复]