我试图理解汇编如何处理参数和返回值。
到目前为止,我了解到%eax是返回值,要加载单个参数,我需要加载
%rip + offset
%rid
通过使用
leaq var(%rip), %rdi
.
为了进一步了解参数,我创建了一个c程序,它接收10个参数(11个参数包括格式化字符串),以尝试找出寄存器的顺序。然后我在Mac上使用gcc将C代码转换成汇编代码。
以下是我使用的C代码:
#include <stdio.h>
int main(){
printf("%s %s %s %s %s %s %s %s %s %s", "1 ", "2", "3", "4", "5", "6", "7", "8", "9", "10");
return 0;
}
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 13
.globl _main ## -- Begin function main
.p2align 4, 0x90
_main: ## @main
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
.cfi_offset %rbx, -40
.cfi_offset %r14, -32
.cfi_offset %r15, -24
subq $8, %rsp
leaq L_.str.10(%rip), %r10
leaq L_.str.9(%rip), %r11
leaq L_.str.8(%rip), %r14
leaq L_.str.7(%rip), %r15
leaq L_.str.6(%rip), %rbx
leaq L_.str(%rip), %rdi
leaq L_.str.1(%rip), %rsi
leaq L_.str.2(%rip), %rdx
leaq L_.str.3(%rip), %rcx
leaq L_.str.4(%rip), %r8
leaq L_.str.5(%rip), %r9
movl $0, %eax
pushq %r10
pushq %r11
pushq %r14
pushq %r15
pushq %rbx
callq _printf
addq $48, %rsp
xorl %eax, %eax
addq $8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
.cfi_endproc
## -- End function
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "%s %s %s %s %s %s %s %s %s %s"
L_.str.1: ## @.str.1
.asciz "1 "
L_.str.2: ## @.str.2
.asciz "2"
L_.str.3: ## @.str.3
.asciz "3"
L_.str.4: ## @.str.4
.asciz "4"
L_.str.5: ## @.str.5
.asciz "5"
L_.str.6: ## @.str.6
.asciz "6"
L_.str.7: ## @.str.7
.asciz "7"
L_.str.8: ## @.str.8
.asciz "8"
L_.str.9: ## @.str.9
.asciz "9"
L_.str.10: ## @.str.10
.asciz "10"
.subsections_via_symbols
.text
.globl _main ## -- Begin function main
_main: ## @main
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
subq $8, %rsp
leaq L_.str.10(%rip), %r10
leaq L_.str.9(%rip), %r11
leaq L_.str.8(%rip), %r14
leaq L_.str.7(%rip), %r15
leaq L_.str.6(%rip), %rbx
leaq L_.str(%rip), %rdi
leaq L_.str.1(%rip), %rsi
leaq L_.str.2(%rip), %rdx
leaq L_.str.3(%rip), %rcx
leaq L_.str.4(%rip), %r8
leaq L_.str.5(%rip), %r9
movl $0, %eax
pushq %r10
pushq %r11
pushq %r14
pushq %r15
pushq %rbx
callq _printf
addq $48, %rsp
xorl %eax, %eax
addq $8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
.data
L_.str: ## @.str
.asciz "%s %s %s %s %s %s %s %s %s %s"
L_.str.1: ## @.str.1
.asciz "1 "
L_.str.2: ## @.str.2
.asciz "2"
L_.str.3: ## @.str.3
.asciz "3"
L_.str.4: ## @.str.4
.asciz "4"
L_.str.5: ## @.str.5
.asciz "5"
L_.str.6: ## @.str.6
.asciz "6"
L_.str.7: ## @.str.7
.asciz "7"
L_.str.8: ## @.str.8
.asciz "8"
L_.str.9: ## @.str.9
.asciz "9"
L_.str.10: ## @.str.10
.asciz "10"
我知道在代码的开头,基指针被推到堆栈上,然后被复制到堆栈指针中供以后使用。
然后leaq将每个字符串加载到每个寄存器中,这些寄存器将用作printf的参数。
我想知道的是为什么寄存器
r10
r11
r14
r15
在第一个参数加载到内存和寄存器之前
rsi
rdx
rcx
r8
在第一个参数之后把r9加载到内存中?还有为什么你
和
代替
r12
r13
?