【问题标题】:Neccessity of push and pop operands on CPUsCPU 上推送和弹出操作的必要性
【发布时间】:2012-04-26 16:40:37
【问题描述】:

为什么我们有 push 和 pop 之类的命令?

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


例如不会:

pushl %eax

相当于:

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

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


我能看到的唯一真正好处是,如果同时进行这两项操作会提供一些优势;但是我不明白它是怎么做到的。

【问题讨论】:

  • 节省空间,x86其实是CISC设计,何乐而不为。
  • @harold 它没有提供额外的功能,这就是为什么不提供。 CPU 仍然在这两个操作上花费时间。
  • 是的.. 但它是一个 CISC 设计,因此它旨在通过提供“做很多”的指令来使汇编程序员更容易使用。另请参阅:leaveenterrep movsb 等。它确实也节省了大量字节空间。

标签: assembly stack cpu cpu-architecture att


【解决方案1】:

但是,CALL 指令也没有理由。毕竟,您可以通过以下方式模拟通话:

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

也不需要RET 指令,因为您可以使用以下命令对其进行模拟:

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

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

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

在 70 年代后期,64 KB 是很多 RAM,而 RAM 则要慢得多。每个指令字节都是宝贵的,从内存中获取指令需要大量开销。取指令花费的时间比执行时间长的情况并不少见。因此,通过尽可能少的指令字节对事物进行编码,可以获得巨大的性能提升。

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

关于调用程序:

汇编语言中调用过程的标准方式是传入参数然后call过程。例如,这会传递两个 dword 值:

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

【讨论】:

  • 我认为subl $4, %esp 在调用之前是必需的,或者至少在中断之前是必需的;另外,为什么%esp 在您的示例中有返回地址?
  • @Hawken:你必须把返回地址放在某个地方。
  • 但是为什么返回地址在栈指针处呢?这是假设您清除了用于被调用函数的堆栈变量吗?
  • @Hawken:标准调用约定先推送参数,然后再推送返回地址。 (实际上,call 指令压入了返回地址。)所以返回地址总是在堆栈的“顶部”(即由 SP 指向)。
  • @Hawken:查看我的附加信息,尤其是有关调用约定的信息的链接。
【解决方案2】:

嗯。如果您有两条指令,那么它们可能会占用更多空间。这需要cpu传输更多数据。这需要更多时间。两条单独的指令通常也需要更多的 CPU 资源。即使 cpu 将它们并行化,提取器、解码器还有更多工作...... 如果您尝试删除所有但绝对必要的指令,您最终会得到图灵机。终极风险,但在实践中不是很有效。

【讨论】:

    【解决方案3】:

    1 个操作码 > 2 个操作码,至少在您尝试降低 CPU 使用率时。

    【讨论】:

    • 我明白了,这可以节省部分可执行文件的内存,但仍然必须执行这两个操作。也许这就是启发 RISC 架构的东西?
    • 嗯,它可能激发了 RISC 架构的消亡
    • @hanspassant 为什么? RISC 每条指令的可预测性更高,CISC 似乎什么都不做,除了创建一个“快捷方式”,它仍然需要相同的时间来执行(不是多少快捷方式)。根据我对 CISC 的了解,由于这些快捷方式,它在许多情况下都比较慢。如果我理解正确,addl %eax,%ebx 之类的东西会浪费时间在运行addl 之前检查%eax%ebx 是否是内存地址,因为它需要支持使用内存地址代替寄存器。
    • @Hawken:您可能想了解更多关于 RISC 与 CISC 的信息。人们会期望,如果 RISC 明显更好(即更快),人们会更多地使用它们。是的,RISC 每条指令的可预测性更高。但是在 RISC 处理器上编写的程序将需要比在 CISC 处理器上的等效程序更多的指令字节。而且指令获取不是免费的。
    • @hanspassant 我听说 RISC 的主要问题是采用率低;有传言称,由于 PowerPC 芯片对便携式设备产生过多热量,而 PowerPC 因采用率低而开发不足,因此 Apple 已切换。
    猜你喜欢
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 2011-06-30
    • 2012-09-28
    • 1970-01-01
    • 1970-01-01
    • 2018-06-12
    • 2010-11-02
    相关资源
    最近更新 更多