堆栈是这样工作的吗?Intel X86汇编



我正在学习英特尔X86汇编和逆向工程,因为我想创建游戏作弊。

我试图理解内存和堆栈是如何工作的。我知道这是后进先出,有些人说把它想象成一摞书,你往上面加,从上面拿。但是你要想象它是向下的而不是向上的吗?

For example:
push 1
push 2 
push 3
pop x
push would equal: 
1
2
3 <- esp
pop would equal:
1
2 <- esp

垂直上下不是唯一可能的可视化方式-我们也可以使用水平:

lower addresses         ...         higher addresses 
+----------------------------------------------+
|  (free stack)  | 3 | 2 | 1 |    (in use)     |
+----------------------------------------------+
^
|
esp

这个可视化允许以"forward "方向,从左到右;参数列表也从最后推到第一个。Push向左扩展堆栈,这感觉仍然很自然。

YMMV

你基本上可以按照你喜欢的方式可视化堆栈。更常见的表示堆栈的方法是说堆栈从高地址到低地址递减。

为了支持这种叙述,堆栈通常被可视化为

+------------------+ <- top of memory = 0x10000
| used_stack       | 
|                  |
+------------------+
| local variables  | <- top of stack = 0xff00 
|   [red zone]     |    <- red zone is guaranteed to be unused
| unused memory    |       by exception handlers
|                  |
| ---------------- |
|    HEAP          | <- dynamically allocated memory
+------------------+ address = 0x0000

我个人认为这是不直观的,因为这颠倒了其他内存结构或数组通常呈现的顺序。在CPU中没有down

| offset     description.    hex dump
+-----------+----------------+------------------------
| 0         | char header[4] | 01 02 03 04
| 8         | int16 width    | 08 00
| 10        | int16 height   | 04 00 
| 12        | int32 size     | 20 00 00 00
vs.
struct FileFormat {
char header[4];
int16_t width{8};
int16_t height{4};
int32_t size{32};
};

当堆栈被想象成钟乳石(像冰柱一样悬挂)时,它在物理上是向下生长的,但它与现实生活中的堆栈失去了联系,就像一堆盘子或一堆书一样,它们会向上生长。

A                                    B
+-------------+                     +--------------+
| ceil of stk | <-high addresses    |  unused      | <-small addresses
| 20 00 00 00 |                     |              |
| 08 00 04 00 |                     |              |
| 01 02 03 04 | <-- top of stack -> | 01 02 03 04  |
|             |                     | 08 00 04 00  |
|             |                     | 20 00 00 00  |
| unused/heap |                     |bottom of stck|
+-------------+                     +--------------+

格式A更方便,至少当你有像

这样的书面文本时
push 1
push 2
push 3

在样式A中,它是这样表示的,在样式B中,值是相反的。

<<

当系统是单cpu并且通常运行单线程进程来控制整个系统时,使堆栈变小是一个特别有用的选择。堆栈被放置在可用内存的顶部,堆被放置在底部,它们会互相增长以满足对方。在现代多线程进程中,它的工作并不那么简单,每个线程都需要一个独立的堆栈,尽管堆可以由整个进程共享。在创建线程时,将选择线程的最大大小,如果空间耗尽,则需要生成某种错误条件。但是,请注意,这里的"线程"one_answers"进程"完全取决于操作系统的设计,CPU只是被告知要运行什么代码。

相关内容

  • 没有找到相关文章

最新更新