assembly - CPU 上压入和弹出操作的必要性

标签 assembly stack cpu cpu-architecture att

为什么我们有push和pop这样的命令?

据我了解,poppush 基本上与执行 a (mov then add) 相同和 (sub then mov) 分别在 esp 上。

<小时/>

例如不会:

pushl %eax

相当于:

subl $4, %esp
movl %eax, (%esp-4)

如果堆栈访问不是(%esp-4),请纠正我,我仍在学习汇编

<小时/>

我能看到的唯一真正的好处是同时执行这两项操作是否会带来一些优势;但我不明白怎么会这样。

最佳答案

但是,也没有理由使用 CALL 指令。毕竟,您可以使用以下方式模拟调用:

sub esp,4
mov [esp-4], offset return_address
jmp myproc

也不需要 RET 指令,因为您可以使用以下命令来模拟它:

mov eax,[esp]
add esp,4
jmp [eax]

如果您仔细观察,您会发现许多可以通过组合其他指令来模拟的指令。有什么意义?

这些类型问题的答案 Root 于 x86 处理器系列及其之前的处理器的悠久历史。设计人员研究了程序员如何使用处理器,并创建了在执行速度和内存使用方面高效的指令集。

在 70 年代末,64 KB 的 RAM 已经很大了,而且 RAM 的速度要慢得多。每个指令字节都很宝贵,仅仅从内存中获取指令就会产生巨大的开销。指令获取时间比执行时间长的情况并不少见。因此,通过用尽可能少的指令字节进行编码,可以获得巨大的性能提升。

与 CPU 时钟速度相比,RAM 的速度仍然慢得令人难以置信,因此通过尽可能少的指令字节进行编码仍然可以获得好处。确实,我们拥有的大型 CPU 缓存有很大帮助,分支预测和预取逻辑也有很大帮助,但从 RAM 传输到 CPU 缓存的每个字节仍然很昂贵。节约指令编码是值得的。

关于调用过程:

用汇编语言调用过程的标准方法是推送参数,然后调用该过程。例如,这传递两个双字值:

push eax
push ebx
call proc    ; pushes the return address and jumps to proc
...

proc:
  ; at this point, [esp] contains the return address

ret 指令将返回地址弹出到指令指针中。

当然,必须有人清理堆栈。调用者可以通过递增堆栈指针来清理堆栈。或者被调用的过程可以使用ret 8清理堆栈,这将弹出返回地址并递增堆栈指针。

参见http://www.delorie.com/djgpp/doc/ug/asm/calling.html有关调用约定的更多信息。

关于assembly - CPU 上压入和弹出操作的必要性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10155692/

相关文章:

windows - 如何将 .asm 文件汇编并链接到 Win32 可执行文件?

c - 为什么这个程序会分配以下金丝雀值和汇编代码?

c++ - 为什么删除指向堆栈的指针是错误的?

java - 从内部类 StackofStacks<T> 访问外部类

Java线程与CPU核心的关系

python - 在运行 python 程序时,是否可以强制您的计算机投入更少的 CPU 来换取更多的时间?

assembly - 需要 AT&T 汇编语法的良好来源

assembly - NASM指令序列

data-structures - FILO 总是 LIFO 吗?

java - 使用 appium 的一个应用程序的 Cpu 内存使用情况