汇编中的内存分配和寻址

2024-01-06

我正在尝试学习汇编,但有一些指令我不完全理解其目的。

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

我不知道这是做什么的。


Q1.子 rsp,32

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

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

lea 正在获取存储在“code”段中的字符串的地址。它已移至 rdi,用作 printf 的参数之一。

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

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

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

更有可能的是0dword 是单独的东西,因为如果编译器真的想要存储零扩展argc,编译器将在具有 32 位的寄存器中进行零扩展mov, like mov ecx, edi ; mov [rbp-8], rcx。可能这个额外的零是一个临时返回值,后来由于显式的原因决定不使用它return 0;而不是从末端掉下来的隐含的main? (main很特别,我认为 clang 确实为返回值创建了一个内部临时变量。)

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

优化关了?它存储 rsi,然后从 [rbp - 16] 加载 rsi。 rsi 保存你的 argv 函数 arg ( ==&argv[0]). The x86-64 System V ABI 在 RDI、RSI、RDX、RCX、R8、R9 中传递整数/指针参数,然后在堆栈上传递 https://stackoverflow.com/q/2535989.

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

这是用以下内容加载 rsiargv[1],作为第二个参数printf。 (出于同样的原因,main 的第二个参数位于 rsi 中)。

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

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

优化关了?它存储 printf 的返回值,但从不使用它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

汇编中的内存分配和寻址 的相关文章

  • 如何检查图像对象与资源中的图像对象是否相同?

    所以我试图创建一个简单的程序 只需在单击图片框中更改图片即可 我目前只使用两张图片 所以我的图片框单击事件函数的代码 看起来像这样 private void pictureBox1 Click object sender EventArgs
  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • UML类图:抽象方法和属性是这样写的吗?

    当我第一次为一个小型 C 项目创建 uml 类图时 我在属性方面遇到了一些麻烦 最后我只是将属性添加为变量 lt
  • 如何在列表框项目之间画一条线

    我希望能够用水平线分隔列表框中的每个项目 这只是我用于绘制项目的一些代码 private void symptomsList DrawItem object sender System Windows Forms DrawItemEvent
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 指针问题(仅在发布版本中)

    不确定如何描述这一点 但我在这里 由于某种原因 当尝试创建我的游戏的发布版本进行测试时 它的敌人创建方面不起作用 Enemies e level1 3 e level1 0 Enemies sdlLib 500 2 3 128 250 32
  • 在 Visual Studio 2008 上设置预调试事件

    我想在 Visual Studio 中开始调试程序之前运行一个任务 我每次调试程序时都需要运行此任务 因此构建后事件还不够好 我查看了设置的 调试 选项卡 但没有这样的选项 有什么办法可以做到这一点吗 你唯一可以尝试的 IMO 就是尝试Co
  • C - 找到极限之间的所有友好数字

    首先是定义 一对友好的数字由两个不同的整数组成 其中 第一个整数的除数之和等于第二个整数 并且 第二个整数的除数之和等于第一个整数 完美数是等于其自身约数之和的数 我想做的是制作一个程序 询问用户一个下限和一个上限 然后向他 她提供这两个限
  • 将目录压缩为单个文件的方法有哪些

    不知道怎么问 所以我会解释一下情况 我需要存储一些压缩文件 最初的想法是创建一个文件夹并存储所需数量的压缩文件 并创建一个文件来保存有关每个压缩文件的数据 但是 我不被允许创建许多文件 只能有一个 我决定创建一个压缩文件 其中包含有关进一步
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • 从路径中获取文件夹名称

    我有一些路c server folderName1 another name something another folder 我如何从那里提取最后一个文件夹名称 我尝试了几件事 但没有成功 我只是不想寻找最后的 然后就去休息了 Thank
  • 如何衡量两个字符串之间的相似度? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 给定两个字符串text1 and text2 public SOMEUSABLERETURNTYPE Compare string t
  • for循环中计数器变量的范围是多少?

    我在 Visual Studio 2008 中收到以下错误 Error 1 A local variable named i cannot be declared in this scope because it would give a
  • 如何将单个 char 转换为 int [重复]

    这个问题在这里已经有答案了 我有一串数字 例如 123456789 我需要提取它们中的每一个以在计算中使用它们 我当然可以通过索引访问每个字符 但是如何将其转换为 int 我研究过 atoi 但它需要一个字符串作为参数 因此 我必须将每个字
  • Qt表格小部件,删除行的按钮

    我有一个 QTableWidget 对于所有行 我将一列的 setCellWidget 设置为按钮 我想将此按钮连接到删除该行的函数 我尝试了这段代码 它不起作用 因为如果我只是单击按钮 我不会将当前行设置为按钮的行 ui gt table
  • 在 Dynamics CRM 插件中访问电子邮件发件人地址

    我正在编写一个 Dynamics CRM 2011 插件 该插件挂钩到电子邮件实体的更新后事件 阶段 40 pipeline http msdn microsoft com en us library gg327941 aspx 并且在此阶
  • 如何使用 std::string 将所有出现的一个字符替换为两个字符?

    有没有一种简单的方法来替换所有出现的 in a std string with 转义 a 中的所有斜杠std string 完成此操作的最简单方法可能是boost字符串算法库 http www boost org doc libs 1 46
  • 如何在 C++ BOOST 中像图形一样加载 TIFF 图像

    我想要加载一个 tiff 图像 带有带有浮点值的像素的 GEOTIFF 例如 boost C 中的图形 我是 C 的新手 我的目标是使用从源 A 到目标 B 的双向 Dijkstra 来获得更高的性能 Boost GIL load tiif
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob
  • 使用 libcurl 检查 SFTP 站点上是否存在文件

    我使用 C 和 libcurl 进行 SFTP FTPS 传输 在上传文件之前 我需要检查文件是否存在而不实际下载它 如果该文件不存在 我会遇到以下问题 set up curlhandle for the public private ke

随机推荐