我正在尝试学习汇编,但有一些指令我不完全理解其目的。
C code
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("Argument One - %s\n", argv[1]);
return 0;
}
Assembly
.section __TEXT,__text,regular,pure_instructions
.build_version macos, 10, 14
.intel_syntax noprefix
.globl _main ## -- Begin function main
.p2align 4, 0x90
_main: ## @main
## %bb.0:
push rbp
mov rbp, rsp
sub rsp, 32
lea rax, [rip + L_.str]
mov dword ptr [rbp - 4], 0
mov dword ptr [rbp - 8], edi
mov qword ptr [rbp - 16], rsi
mov rsi, qword ptr [rbp - 16]
mov rsi, qword ptr [rsi + 8]
mov rdi, rax
mov al, 0
call _printf
xor ecx, ecx
mov dword ptr [rbp - 20], eax ## 4-byte Spill
mov eax, ecx
add rsp, 32
pop rbp
ret
## -- End function
.section __TEXT,__cstring,cstring_literals
L_.str: ## @.str
.asciz "Argument One - %s\n"
.subsections_via_symbols
Q1. 子 rsp,32
为什么在没有局部变量的情况下分配32字节的空间?我相信 argc 和 argv 分别保存在寄存器 edi 和 rsi 中。如果这样可以将它们移动到堆栈上,那不是只需要 12 个字节吗?
Q2. lea rax, [rip + L_.str] and mov rdi, rax
我对 L_.str 具有字符串“”参数一 - %s\n”的地址的理解是否正确?根据我的理解, printf 通过寄存器 rdi 访问该字符串。那么,为什么不呢?指令mov rdi, L_.str工作代替?
Q3. mov 双字 ptr [rbp - 4], 0
为什么将零压入堆栈?
Q4. mov dword ptr [rbp - 8], edi and mov qword ptr [rbp - 16], rsi
我相信这些指令是将 argc 和 argv 放入堆栈。使用 edi 和 rsi 是纯粹的约定吗?
Q5. mov dword ptr [rbp - 20], eax
我不知道这是做什么的。