为什么 mov ax, [[num] + val] 与将其分解为指令不同

Why mov ax, [[num] + val] isn't the same as breaking it to instructions

我需要使用一个指向数组的指针并将第三个值放在 ax 中。 我的解决方案:

mov bx, [chrs_ptr]
add bx, 2
mov ax,[bx]

但我不明白为什么 mov ax, [[chrs_ptr] + 2] 给我指针值。

因为汇编语言不同于大多数其他编程语言。

大多数 PL 的目标是将其语法作为构建块进行泛化和普遍使用,以构成超出特定单一功能的琐碎语法的表达式。

汇编器是"human readable"特定处理器机器代码的助记符。 IE。特定汇编程序中可用的指令不是由汇编程序创建者设计的(大部分),而是由设计 CPU 本身的硬件工程师定义的。所以你的汇编程序的指令取决于目标处理器,它们就像 1:1 从源代码形式映射到实际的 CPU 指令(除了少数例外,一些汇编程序实际上支持一些伪指令,但通常是 1:1).

因此 emu8086 模拟 8086 CPU(以及该系列的一些后续产品,80286 甚至 80386?我不确定 emu8086 支持什么,因为我不使用它)只有在这些处理器中设计的英特尔指令。

例如在 16 位实模式下有 MOV r16,r/m16 指令,您在第 mov ax,[bx] 行使用它,但是没有 MOV r16,memory-by-indirection-from-other-memory with +2 offset 这样的指令,所以在汇编编程时,您应该了解目标指令集,并使用可用的指令编写您的解决方案。

您可能会质疑为什么有些指令只执行 "that",而不执行 "this",这在您看来似乎很明显,但大多数时候 ISA(指令集架构) 往往是在足以编写实用代码和电路设计实用性之间的很好的折衷,每个机器周期具有合理的功耗和时序特性,以及早期 CPUs 什么手工设计实用,并在head中验证其正确性。

您对 mov ax,[[chrs_ptr]+2] 的提议将需要在单条指令执行中读取两次内存,而内存读取绝非易事(通常会使 CPU 停顿多个机器周期,直到内存芯片已准备好从特定单元传递价值),因此您会立即大大提高 CPU 电路设计的复杂性。喜欢 很多.

或者您可能会质疑为什么汇编程序不为您将其分解为处理器的三个本机指令。

但通常当您需要汇编程序时,您实际上需要 1:1 汇编程序源指令到目标本机代码指令的映射 CPU。因为如果你不需要那个,那为什么根本不需要汇编程序呢,有很多高级语言,它让你对机器有足够的低级控制,但提升了这种对一切的微观管理,比如 C 或 C++ .所以很少有动力去丰富汇编程序 "language" 本身,而且通常当你看到这样的努力时,它最终只是另一种编程语言,当你真正需要时,它被污染得不能代替实际的汇编程序手动编写那几个 CPU 指令,并将其调整到每个字节。

无法将 a memory-indirect addressing mode 编码为 8086 机器码。 16 位寻址模式的 ModRM 字节只能编码极少数可能性:[bx|bp + si|di + disp0/8/16].

的任何子集

这与你不能 mov word ptr [si], [di] (Why isn't movl from memory to memory allowed?)

的原因基本相同

asm 源代码的限制来自机器代码,这与高级语言不同,在高级语言中,您可以根据需要发明编译为更多指令的语法。

我想你是说 emu8086 的汇编程序确实接受了 mov ax,[[chrs_ptr]+2] 而没有错误。 那是因为 EMU8086 的内置汇编器不好,并不总是报告损坏代码的语法错误。

大概是和mov ax, [chrs_ptr+2]一样组装的,忽略多余的方括号。实际上因为它使用 MASM/TASM 语法,它也与 mov ax, chrs_ptr+2

相同

不幸的是,甚至 MASM/TASM 也没有对 mov ax, [[chrs_ptr] + 2] 发出警告。正如 Ross Ridge 指出的那样,除非方括号内有 register 名称,否则方括号并不意味着内存引用。否则括号将被忽略。参见 Confusing brackets in MASM32


IIRC,emu8086 的汇编程序还有其他错误特征,例如 add [bx], 1 假设操作数大小为 "word" 或字节,我忘了是哪个,而不是在不明确的操作数大小上出错。

这基本上很糟糕,如果可能的话请避免它。

或者,如果不是,请使用另一个汇编程序(如 MASM 或 TASM)检查您的代码是否存在语法错误,它们会发出警告,而不是将不可能的代码汇编成执行某些操作的机器代码。 (除了在这种情况下,他们甚至无法禁止这种令人困惑的语法。)

有些人出于其他原因喜欢 MASM 风格的语法,但我不推荐它。 NASM 很好,特别是如果您真的不关心简单的引导加载程序和 .com 程序之外的过时的 16 位分段开发。