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

时间:2013-06-30 19:30:48

标签: c assembly x86

在流行的x86架构上,可以使用jmp类型指令之一以及call指令来控制执行流程。但这两者都是基本的,还是另一个的“语法糖”?

例如,push指令是语法糖:push eax相当于mov [esp], eax后跟sub esp, 4。因此mov是唯一的基本数据操作。

call也是如此吗?还有其他一些指令可以实现相同的目标吗?

在伪代码中,如果我有权访问,我可以jmp编写函数调用 指令指针:

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

foo:
    pop eax                                  ;; ret
    jmp [eax]

这对x86无效,因为无法直接读取指令指针寄存器eip。到目前为止,我所看到的所有“伎俩”都获得了eip的全部使用call的价值。或者call实际上是规范方式来读取x86上的指令指针?作为一个额外的问题,可以实现C的每个架构是否都需要一种方法来读取指令指针,以便可以实现函数指针?

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

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

[这不是一个深刻的问题;我只是觉得令人感到欣慰的是,知道函数不仅仅是高级编程语言引入的抽象,而且实际上是硬件内在的。]

1 个答案:

答案 0 :(得分:9)

机器指令集可能非常简单;看Wolfram's 2-state, 3 symbol Turing machine.问题是这样的机器很难编程,很难快速运行。

您可以使用其他说明完全模拟呼叫返回:

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

    ; Simulate "ret"
    pop    eax
    jmp    eax

您可以使用mov指令模拟推/弹,并通过添加常量来调整寄存器,如您在问题中所述。

人们向指令集添加指令以使公共序列有效。因此,"呼叫"之所以存在是因为它确实是一项非常有用的任务("调用/返回"对可以通过硬件使用返回地址的内部堆栈进行优化,以避免指令管道中断;这是真正的性能获胜)。

所以,是的,您可以使用计算机提供的最小指令集来实现汇编语言。但正确的附加说明确实有助于实践。 (您可以出于好意,添加您认为可能有用的说明。通常他们不会帮助,这是source of the original RISC/CISC debate)。

Goofball minimal machines:

  • 20世纪70年代生产的真正的小型机(" GRI")只有一条指令:MOV LOC1到LOC2;目标位置是神奇的,这是真正的工作是如何完成的。通过将某些东西移动到位置33(组成),副作用是该值被添加到可以从位置32读取的累加器。它有很多位置做了有趣,方便的事情,所以实质上添加了一个新的有趣的寄存器只是添加有用指令的一个奇怪的变体。我怀疑JMP指令包括将常量移动到充当程序计数器的位置。 (如果你觉得这很奇怪,你还没有遇到PDP-11)。

  • 理论机器是单指令" SUB LOC1从LOC2 jmp到LOC3,如果是负#34;这台机器是通用的,但在你第一次玩具问题后编程并不好玩。

值得注意的是,这两个指令集都没有操作码位或寻址模式位。实际上,指令解码器很简单。