我对调用函数时如何将内容传递给堆栈感到有些困惑,我有以下程序集:
.data
str:
.asciz "%d %d %d %d %d %d %d %d %d %d\n"
.text
__entry:
pushq %rbp
movq %rsp, %rbp
leaq str(%rip), %rdi
movq $1, %rsi
movq $2, %rdx
movq $3, %rcx
movq $4, %r8
movq $5, %r9
movq $6, -4(%rbp)
movq $8, -8(%rbp)
movq $9, -12(%rbp)
movq $10, -16(%rbp)
call _printf
popq %rbp
ret
.global _main
_main:
pushq %rbp
movq %rsp, %rbp
call __entry
popq %rbp
ret
但是当我运行程序时,我得到了大量的垃圾值。寄存器中传递的值很好,但堆栈中传递的值不是。我检查了调用约定,它说"其他参数在堆栈上传递。",它们应该"对齐到16字节边界"。
两个问题:
和
答案 0 :(得分:1)
您的核心问题是,在加载堆栈上的所有参数之前,通过减少堆栈指针忽略了在堆栈上分配空间。当然,printf会立即删除堆栈指针下方区域中的任何内容,从而导致垃圾打印输出。
您还需要修复堆栈偏移:movq
一次移动8个字节,因此每个插槽大8个字节。
您的固定代码如下所示:
pushq %rbp
movq %rsp, %rbp
sub $32,%rsp # new
leaq str(%rip), %rdi
movq $1, %rsi
movq $2, %rdx
movq $3, %rcx
movq $4, %r8
movq $5, %r9
movq $6, -8(%rbp) # fixed: offsets are multiples of 8, not 4
movq $8, -16(%rbp) # fixed
movq $9, -24(%rbp) # fixed
movq $10, -32(%rbp) # fixed
xor %eax,%eax # new: %al=0 FP register args
call _printf
add $32,%rsp # new
popq %rbp
ret
一切都应该再次奏效。通常,您使用push
通过堆栈加载参数。例如,您的函数调用如下所示:
pushq %rbp
movq %rsp, %rbp
leaq str(%rip), %rdi
movq $1, %rsi
movq $2, %rdx
movq $3, %rcx
movq $4, %r8
movq $5, %r9
push $6 # push rightmost argument
push $8 # push second-to-last argument
push $9 # ...
push $10
xor %eax,%eax # tell printf to expect 0 floating point args
call _printf
add $32,%rsp # pop arguments off the stack
popq %rbp
ret