2016-02-13 89 views
-1
.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。而已。分割故障呼叫printf

为什么它给我一个分段错误?

谢谢!

+2

你知道你可以'mov $ 10,%edx',对吧?现在,这只是在调用var-args函数问题之前,许多忘记至零的rax的副本。我将其中一个链接为您之前问题的可能重复。在一个不需要保留任何空间的函数中,'push'一个虚拟寄存器是一个有用的方法,可以在调用之前对齐堆栈。另请阅读ABI文档。第二个参数不在'%rdx'中。 –

+1

[尝试在x86中添加两个整数,但是当我添加时,我得到垃圾而不是值。我做错了什么?](http://stackoverflow.com/questions/28706080/trying-to-add-two-ints-in-x86-however-when-i-add-i-get-garbage-instead- of-a-val) –

+3

堆栈也需要在16字节的边界上对齐,在这种情况下_RAX_需要为零,因为您没有使用向量寄存器。 –

回答

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位系统V ABI的更多信息可在此document中找到。