I need to use a pointer to an array and put the third value in ax. My solution:
mov bx, [chrs_ptr] add bx, 2 mov ax,[bx]
But I couldn't figure out why mov ax, [[chrs_ptr] + 2]
gives me the pointer value.
因为汇编程序与大多数其他编程语言不同。
大多数PL旨在将其语法作为组成部分进行通用化和通用化,以构成超出特定单个功能的普通语法的表达方式。
汇编器是特定处理器的机器代码的“人类可读”助记符。即,特定汇编程序中可用的指令不是由汇编程序创建者设计的(大多数情况下),而是由设计CPU本身的硬件工程师定义的。因此,汇编程序的指令取决于目标处理器,就像从源代码形式到实际CPU指令的1:1映射一样(除了少数例外,某些汇编程序实际上确实支持少量伪指令,但通常为1:1 )。
因此,模拟8086 CPU的emu8086(以及该家族中随后的少数几个80286甚至80386?我不确定emu8086支持什么,因为我不使用它)在那些处理器中仅设计了Intel指令。
例如,MOV r16,r/m16
在第16行实模式中有一条mov ax,[bx]
指令,您正在使用,但是没有类似的指令MOV r16,memory-by-indirection-from-other-memory with +2 offset
,因此在汇编中进行编程时,您应该了解目标指令集,并使用可用的指令编写解决方案。
您可能会质疑为什么某些指令只执行“那个”,而不执行“这个”,您似乎认为这很明显,但是大多数情况下,ISA(指令集体系结构)往往在两者之间做出很好的折衷。足够编写实用的代码,并且可以在电路中进行实际设计,并在每个单个机器周期内具有合理的功耗和时序特征,并且对于早期的CPU而言,可以手工进行实际设计并验证其正确性。
您的建议mov ax,[[chrs_ptr]+2]
在一条指令执行过程中需要两次读取内存,而读取内存绝非易事(通常会使CPU停顿多个机器周期,直到内存芯片准备好从特定单元传递值为止),因此您将立即提高CPU电路设计的复杂性。喜欢很多。
也许您可能会质疑为什么汇编程序不会将其分解为处理器的三个本机指令。
但是通常在需要汇编程序时,实际上实际上需要将汇编程序源指令的1:1映射到目标CPU的本机代码指令。因为如果不需要,那么为什么还要使用汇编语言,有很多高级语言,它们可以使您对计算机进行足够的低级控制,但是可以增强对诸如C或C ++之类的所有内容的微管理。 。因此,很少有动力去丰富汇编程序的“语言”本身,通常当您看到这样的努力时,它最终会变成另一种编程语言,当您真的需要编写时,它太脏了以至于无法代替实际的汇编程序使用手动处理这几条CPU指令,并将其调低至每个字节。
无法在8086机器代码中对内存间接寻址模式进行编码。16位寻址模式的ModRM字节只能编码很少的可能性:的任何子集[bx|bp + si|di + disp0/8/16]
。
基本上是您无法删除的原因mov word ptr [si], [di]
(为什么不允许在内存之间移动?)
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)指出的那样,除非方括号内有寄存器名称,否则方括号并不表示内存引用。否则将忽略括号。请参阅MASM32中令人困惑的括号
IIRC,emu8086的汇编程序还有其他缺点,例如add [bx], 1
假定操作数大小为“字”或字节,但我忘记了这些功能,而不是在不确定的操作数大小上出错。
这基本上是可怕的,如果可能的话,请避免使用它。
否则,请使用将发出警告的另一个汇编程序(如MASM或TASM)检查代码中的语法错误,而不是将不可能的代码组合到执行某些操作的机器代码中。(除非在这种情况下,即使他们也无法禁止这种令人困惑的语法。)
有些人出于其他原因喜欢MASM样式的语法,但我不建议这样做。NASM很不错,尤其是如果您真的不关心简单的引导加载程序和.com程序之外的过时16位分段开发时。