【问题标题】:NASM x86_64 scanf segmentation faultNASM x86_64 scanf 分段错误
【发布时间】:2015-01-09 11:10:37
【问题描述】:

我是 nasm 新手,我真的很想学习如何使用用户输入来存储数字。使用 scanf 时,我无法摆脱分段错误。我在网上搜索过,但没有找到任何解决此问题的方法。 我试过这个code,但它对我不起作用。

谁能解释一下我做错了什么?

global main

extern printf, scanf

section .data
   msg: db "Enter a number: ",10,0
   format:db "%d",0

section .bss
   number resb 4

section .text
main:
   mov rdi, msg
   mov al, 0
   call printf

   push number
   push format
   call scanf
   ret

提前致谢!

【问题讨论】:

    标签: assembly nasm x86-64


    【解决方案1】:

    x86-64 calling convention 通常不会推送参数。此外,您必须告诉一个具有可变参数计数的函数,您提供了多少个浮点参数。

    这行得通:

    global main
    extern printf, scanf
    
    section .data
       msg: db "Enter a number: ",10,0
       format:db "%d",0
    
    section .bss
       number resb 4
    
    section .text
    main:
       sub  rsp, 8       ; align the stack to a 16B boundary before function calls
    
       mov rdi, msg
       mov al, 0
       call printf
    
       mov rsi, number
       mov rdi, format
       mov al, 0
       call scanf
    
       add   rsp, 8      ; restore the stack
       ret
    

    顺便说一句:如果您想使用浮点数,您必须在调用函数之前将堆栈对齐到 16 字节边界。

    【讨论】:

    • 我觉得有点奇怪整数不需要堆栈对齐但浮点需要。浮点数通过寄存器(至少前八个)传递,因此不需要从堆栈中读取它们。但我猜printf 无论如何都会从堆栈中推送/弹出它们。
    • @Zboson:我的 GDB 告诉我,XMM 寄存器将存储在局部变量(堆栈)中。要存储 XMM 寄存器,内存必须对齐,这显然不是(或不正确)由 glibc 完成的。
    • 我不明白为什么 System V AMD64 ABI 会通过 XMM0-7 中的前八个浮点数将其存储在堆栈中。
    • @Zboson:Gnu 以神秘的方式移动。 :-)
    • @Zboson: printf 是一个可变参数函数,gcc 为VA_ARG 等生成代码的方式是将 XMM 寄存器溢出到堆栈中,以便它可以索引它们,如果 AL!=0。 (glibc 的 printf 是用 C 语言编写的,由 gcc 编译)。我用 sub/add 而不是 push/pop 修复了这个答案,只是为了让初学者最清楚地知道只有 RSP 很重要,而不是保存/恢复寄存器。不过,push/pop 通常效率更高。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 2014-01-31
    • 2013-12-22
    • 1970-01-01
    • 2013-07-24
    • 2012-06-26
    相关资源
    最近更新 更多