【问题标题】:Segmentation Fault call printf分段错误调用 printf
【发布时间】:2016-02-13 23:17:54
【问题描述】:
.text
    .global main
main:
  pushq $10
  popq %rdx
  movq $formatString, %rdi
  call printf
    mov $0,%rax
    ret
.data
 formatString:
.string "%d\n"

这段代码给了我一个分段错误。 这很简单。将 10 压入堆栈。从堆栈中弹出 10 并将其放入 rdx。将我的 formatString 移动到 rdi。调用 printf。就是这样。

为什么会出现分段错误?

谢谢!

【问题讨论】:

  • 你知道你可以mov $10, %edx,对吧?现在,这只是调用 var-args 函数问题之前许多忘记零的 rax 的副本。我将其中一个链接为您上一个问题的可能重复项。 push 使用虚拟寄存器是在 call 之前对齐堆栈的有用方法,在函数中不需要保留任何空间。另外,请阅读 ABI 文档。第二个参数没有进入%rdx
  • 堆栈还需要在 16 字节边界上对齐,在这种情况下,RAX 需要为零,因为您没有使用向量寄存器。

标签: assembly x86 printf x86-64 libc


【解决方案1】:

这段代码可以工作:

.text
    .global main
main:
  add $-8, %rsp             # Stack is misaligned by 8 after call to main
                            # Subtract 8 to align it on 16-byte boundary
  xor %rax, %rax            # RAX = 0 since no vector registers used for calling printf 
                            # This is important for functions that take variable 
                            # number of arguments
  movq $formatString, %rdi  # First parameter (format) in RDI
  movq $10, %rsi            # second parameter in RSI not RDX
  call printf

  add $8, %rsp              # Restore stack to proper state
  ret

.data
 formatString:
.string "%ld\n"             # If printing longs use %ld

除了add $-8, %rspadd $8, %rsp 进行堆栈对齐之外,您还可以使用任何将堆栈调整8 个字节的东西。 push %rbxpop %rbx 也可以。

您也可以替换:

 movq $formatString, %rdi  # First parameter (format) in RDI

与:

leaq formatString(%rip), %rdi

后者使用 RIP 相对寻址而不是绝对寻址。

有关 Linux 64 位 System V ABI 的更多信息,请参阅document

【讨论】:

    猜你喜欢
    • 2014-12-27
    • 2018-06-06
    • 2013-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    相关资源
    最近更新 更多