简体   繁体   English

“功能”是否是x86硬件的基本组成部分?

[英]Are “functions” a fundamental part of the x86 hardware?

On the popular x86 architecture, execution flow can be controlled with one of the jmp -type instructions, as well as with the call instruction. 在流行的x86架构上,可以使用jmp -type指令之一以及call指令来控制执行流程。 But are both fundamental, or is one "syntactic sugar" for the other? 但是,两者都是根本的,还是另一种?

For example, the push instruction is syntactic sugar: push eax is equivalent to mov [esp], eax followed by sub esp, 4 . 例如, push指令是语法糖: push eax等效于mov [esp], eax后跟sub esp, 4 So mov is the only fundamental data operation. 因此mov是唯一的基本数据操作。

But is this also the case for call ? 但这也可以call吗? Is there some other set of instructions that achieves the same? 还有其他一些指令可以达到相同的目的吗?

In pseudo-code, I could write a function call with jmp if I had access to the instruction pointer: 在伪代码中,如果我可以访问指令指针,则可以使用jmp编写函数调用:

bar:
    push eip    ;; pseudo-code!              ;; call foo
    jmp foo

foo:
    pop eax                                  ;; ret
    jmp [eax]

This isn't valid x86, since the instruction pointer register eip cannot be read directly. 这是无效的x86,因为不能直接读取指令指针寄存器eip And all "tricks" I've seen so far that obtain the value of eip all use call . 到目前为止,我所见过的所有获得eip值的“技巧”都使用call Or is call in fact the canonical way to read the instruction pointer on x86? 还是call实际上是在x86上读取指令指针的规范方法? As a bonus question, does every architecture on which C can be implemented require a way to read the instruction pointer, so that function pointers can be implemented? 作为一个额外的问题,可以在其上实现C的每个体系结构是否都需要一种读取指令指针的方式,以便可以实现函数指针?

int main(int argc, char * argv[])
{
    int (*p)() = strtoul(argv[1]);

    return p();                     // how to implement without
                                    // accessing the instruction pointer?
}

[This isn't a deep question; [这不是一个深层的问题; I would simply find it emotionally gratifying to know that functions are not just an abstraction introduced by high-level programming languages, but actually hardware-intrinsic.] 知道函数不仅是高级编程语言引入的抽象,而且实际上是硬件固有的,这简直让我激动不已。

Machine instructions sets could be pretty trivial; 机器指令集可能微不足道; see Wolfram's 2-state, 3 symbol Turing machine. 请参阅Wolfram的2状态,3符号图灵机。 The problem is that such machines are hard to program and hard to make run fast. 问题是这种机器很难编程,也很难快速运行。

You can completely simulate call return with other instructions: 您可以使用其他说明完全模拟呼叫返回:

    ;  Simulate "call abc":
    push    offset next_location
    jmp     abc
 next_location:

    ; Simulate "ret"
    pop    eax
    jmp    eax

You can obviously simulate the push/pops with mov instructions and adjusting registers by adding constants as you noted in your question. 显然,您可以使用mov指令和通过添加问题中提到的常量来调整寄存器来模拟push / pop。

People add instructions to an instruction set to make common sequences efficient. 人们将指令添加到指令集以使通用序列高效。 Thus, "call" exists because it does a commonly useful task (and "call/ret" pairs can be optimized by hardware using an internal stack of return addresses to avoid instruction pipeline breaks; this is a real performance win). 因此,“调用”之所以存在是因为它执行了通常有用的任务(“调用/返回”对可以由硬件使用内部返回地址堆栈来优化,以避免指令流水线中断;这是真正的性能优势)。

So, yes, you could use a smallest set of instructions offered by a computer to achieve your assembly language purposes. 因此,是的,您可以使用计算机提供的最少指令集来实现汇编语言的目的。 But the right additional instructions really help in practice. 但是正确的附加说明在实践中确实有帮助。 (You can, with good intent, add instructions you think might be useful. Often they don't help, this is the source of the original RISC/CISC debate ). (您可以有意向地添加您认为可能有用的说明。它们通常无济于事,这是RISC / CISC最初的争论源头 )。

Goofball minimal machines: Goofball最小机器:

  • There was real minicomputer ("GRI") produced in the 1970s that had only one instruction: MOV LOC1 to LOC2; 1970年代生产了真正的微型计算机(“ GRI”),它只有一条指令:MOV LOC1至LOC2; the target locations were magic and that's how real work got done. 目标位置是魔术,这就是完成实际工作的方式。 By moving something to location 33 (made up), a sideffect was that the value was added to an accumulator that could be read from location 32. It had lots of locations that did funny, convenient things, so in essence adding a new funny register is just a strange variant of adding useful instructions. 通过将某物移动到位置33(组成),其副作用是将值添加到了可以从位置32读取的累加器中。它具有许多可以完成有趣且方便的操作的位置,因此,实质上是添加了一个新的有趣寄存器只是添加有用指令的一个奇怪的变体。 I suspect JMP instructions consisted of moving a constant to the location that acted as the program counter. 我怀疑JMP指令包含将一个常量移动到充当程序计数器的位置。 (If this seem strange to you, you haven't met a PDP-11). (如果您觉得这很奇怪,则说明您尚未达到PDP-11)。

  • A theory machine is one with the single instruction "SUB LOC1 from LOC2 jmp to LOC3 if negative". 一种理论上的机器就是单指令“如果为负,则从LOC2 jmp到LOC3的SUB LOC1”。 This machine is universal but not fun to program after your first toy problem. 这是一台通用的机器,但是在您遇到第一个玩具问题后就很难编程。

It is interesting to note that both of these instructions sets have no opcode bits or addresssing mode bits. 有趣的是,这两个指令集都没有操作码位或寻址模式位。 The instruction decoder is simple, indeed. 指令解码器确实很简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM