【问题标题】:Issue understanding how to access memory from the stack问题理解如何从堆栈访问内存
【发布时间】:2019-10-16 15:42:10
【问题描述】:

我正在尝试自学组装,但在堆栈和访问堆栈之间的交互方面遇到了一些困难。我正在使用 x86 64 位系统,并且正在执行一个简单的程序,将 5 和 2 推入堆栈(按此顺序),然​​后调用一个函数。所以,如果字长是 2 个字节,那么我应该能够通过 [esp+2] 计算返回地址来得到 2。但是,我得到 0,因为当我使用 edg 并逐步执行时,值(通过将其移动到寄存器中)是 00000002000000,所以我可以使用 [esp+8] 访问它,然后使用 [esp+16] 访问它,但是,是否意味着字长为 4?那么这是否意味着单词的大小取决于系统的位?甚至只是使用的寄存器呢?而是因为在 64 位系统上堆栈的每个段的大小是 8 个字节?

【问题讨论】:

  • 在 x86 术语中,“单词”总是 2 个字节。但这不是“字长”或寄存器宽度。 “字长”对于 x86-64 来说不是一个有用的概念;它本身支持 1、2、4 和 8 字节的操作数大小(向量寄存器中的 SSE、AVX 和 AVX512 支持 16、32 和 64)。实际数据总线比整数寄存器等宽。
  • @David C. Rankin 他们是两个完全不同的问题。这与将参数传递给函数无关,而是关于从机器到机器的每个段的寄存器和堆栈的不同大小......
  • 这就是为什么它被列为“可能的重复”并且没有进行关闭投票。它明确地解决了 x86_64 调用约定,例如RDI, RSI, RDX, RCX, R8, and R9, etc... 与您的 "I am using a x86 64 bit system and was doing a simple program that pushes 5 and 2 into the stack (in that order) and then call a function." 相关,这不是在 x86 64 上传递值的方式。

标签: assembly x86-64 cpu-registers callstack


【解决方案1】:

是不是因为堆栈的每个段的大小在 64 位系统上是 8 个字节?

是的。

当你推送这些东西然后调用一个函数时,这就是你的堆栈:

+-----------------+
|        5        | RSP+0x10
+-----------------+
|        2        | RSP+0x08
+-----------------+
|   Return Addr   | RSP+0x00
+-----------------+

同样,在 32 位系统上,您正在为您的堆栈查看此内容:

+-----------------+
|        5        | ESP+0x08
+-----------------+
|        2        | ESP+0x04
+-----------------+
|   Return Addr   | ESP+0x00
+-----------------+

顺便说一句,请记住 64 位寄存器以 R 开头(RSPRAX 等)。此外,根据您的操作系统,您可能会错误地通过堆栈传递参数。 64 位系统对前 N 个参数使用寄存器,然后从那时起使用堆栈。根据您是传递整数/指针还是浮点数,寄存器会有所不同。出于您的目的,使用 SystemV,前 6 个通过 RDIRSIRDXRCXR8R9(按此顺序)传递。 64 位 Windows 使用 RCXRDXR8R9 作为前 4 个(按此顺序)。现在这在您学习时并不重要,但随着您开始调用其他模块/OS API,它会变得越来越重要。

【讨论】:

  • 我正在使用 linux。这是否使用您所说的第一个顺序?
  • 是的,@FordSmith.
猜你喜欢
  • 1970-01-01
  • 2011-11-28
  • 2012-11-08
  • 2011-10-31
  • 2014-08-06
  • 2015-11-05
  • 2015-06-29
  • 2021-11-30
  • 2018-09-22
相关资源
最近更新 更多