程序集中的内存分配和寻址 [英] Memory allocation and addressing in Assembly

查看:113
本文介绍了程序集中的内存分配和寻址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习汇编,那里有一些我不完全了解其目的的说明.

I am trying to learn assembly and there a couple of instructions whose purpose I do not fully understand.

C代码

#include <stdio.h>

int main(int argc, char* argv[])
{
    printf("Argument One - %s\n", argv[1]);
    return 0;
}

组装

    .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. sub rsp,32

当没有局部变量时,为什么要为32个字节分配空间?我相信argc和argv分别保存在寄存器edi和rsi中.如果可以将它们移动到堆栈上,那岂不是只需要12个字节?

Why is space allocated for 32 bytes when there are no local variables? I believe argc and argv are saved in the registers edi and rsi respectively. If its so that they can be moved onto the stack, wouldn't that require only 12 bytes?

Q2. lea rax,[rip + L_.str] mov rdi,rax

我是否理解L_.str具有字符串"Argument One-%s \ n""的地址是正确的?据我了解,printf可通过寄存器rdi访问此字符串.指令 mov rdi,L_.str 代替吗?

Am I correct in understanding that L_.str has the address of the string ""Argument One - %s\n"? From what I've understood, printf gets access to this string through the register rdi. So, why doesn't the instruction mov rdi, L_.str work instead?

Q3. mov dword ptr [rbp-4],0

为什么零被压入堆栈?

Why is zero being pushed onto the stack?

Q4. mov dword ptr [rbp-8],edi mov qword ptr [rbp-16],rsi

我相信这些指令是将argc和argv放入堆栈.使用edi和rsi是否纯粹是惯例?

I believe these instruction are to get argc and argv onto the stack. Is it pure convention to use edi and rsi?

Q5. mov dword ptr [rbp-20],eax

我不知道这是怎么做的.

I haven't a clue what this does.

推荐答案

Q1. sub rsp,32

Q1. sub rsp, 32

这是分配用于存储某些数据的空间.尽管它分配了32个字节,但是该代码仅使用该分配空间的前16个字节,即[rbp-8](0:edi)处的qword和[rbp-16](rdi)处的qword.

This is allocating space that is used to store some data. Although it allocates 32 bytes, the code is only using the first 16 bytes of that allocated space, a qword at [rbp-8] (0:edi) and a qword at [rbp-16] (rdi).

Q2. lea rax,[rip + L_.str]和mov rdi,rax

Q2. lea rax, [rip + L_.str] and mov rdi, rax

lea正在获取存储在代码"段中的字符串的地址.它已移至rdi,后者用作printf的参数之一.

The lea is getting the address of a string stored in the "code" segement. It's moved to rdi which is used as one of the parameters for printf.

Q3. mov dword ptr [rbp-4],0 ... mov dword ptr [rbp-8],edi

Q3. mov dword ptr [rbp - 4], 0 ... mov dword ptr [rbp - 8], edi

它在[rbp-8]处存储一个由0:edi组成的64位小字节序值.我不确定为什么要这样做,因为以后再也不会从该qword加载它.

This stores a 64-bit little endian value composed of 0:edi at [rbp - 8]. I'm not sure why it's doing this, since it never loads from that qword later on.

未优化的代码将其寄存器参数存储到内存中是正常的,调试信息可以告诉调试器在哪里寻找和修改它们,但是不清楚为什么clang将edi中的argc零扩展为64位

It's normal for un-optimized code to store their register arguments to memory, where debug info can tell debuggers where to look for and modify them, but it's unclear why clang zero-extends argc in edi to 64 bits.

0 dword更有可能是分开的,因为如果编译器确实要存储零扩展argc,则编译器将在具有32位mov的寄存器中零扩展,例如; mov [rbp-8], rcx.可能这个额外的零是一个返回值的临时值,由于显式的return 0;而不是由于main的结尾而隐式的一个,它后来决定不使用该值. (main很特殊,我认为clang确实会为返回值创建一个内部临时变量.)

More likely that 0 dword is something separate, because it if the compiler really wanted to store a zero-extend argc, compilers will zero-extend in registers with a 32-bit mov, like mov ecx, edi ; mov [rbp-8], rcx. Possibly this extra zero is a return-value temporary which it later decides not to use because of an explicit return 0; instead of the implicit one from falling off the end of main? (main is special, and I think clang does create an internal temporary variable for the return value.)

Q4 mov qword ptr [rbp-16],rsi ... mov rsi,qword ptr [rbp-16]

Q4 mov qword ptr [rbp - 16], rsi ... mov rsi, qword ptr [rbp - 16]

优化关闭了吗?它存储rsi,然后从[rbp-16]加载rsi. rsi拥有argv函数arg(== &argv[0]). x86-64系统V ABI在RDI,RSI,RDX,RCX,R8,R9中然后在堆栈上传递整数/指针args .

Optimization off? It stores rsi then loads rsi from [rbp - 16]. rsi holds your argv function arg ( == &argv[0]). The x86-64 System V ABI passes integer/pointer args in RDI, RSI, RDX, RCX, R8, R9, then on the stack.

... mov rsi,qword ptr [rsi + 8]

... mov rsi, qword ptr [rsi + 8]

这正在向rsi加载argv[1]的内容,作为printf的第二个arg. (出于与main的第二个arg在rsi中相同的原因).

This is loading rsi with the contents of argv[1], as the 2nd arg for printf. (For the same reason that main's 2nd arg was in rsi).

x86-64 System V调用约定也是在调用没有FP args的varargs函数之前将AL清零的原因.

The x86-64 System V calling convention is also the reason for zeroing AL before calling a varargs function with no FP args.

Q5. mov dword ptr [rbp-20],eax

Q5. mov dword ptr [rbp - 20], eax

优化关闭了吗?它存储了printf的返回值,但是从不使用它.

Optimization off? It's storing the return value from printf, but never using it.

这篇关于程序集中的内存分配和寻址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆