程序集 8086,为什么后面的指令执行后不修改前面的指令

Assembly 8086, Why later instruction doesn't modify previous one after execution

我是汇编新手,正在尝试找出这段代码:

072A:100 mov word ptr [0107], 4567
072A:106 mov ax, 1234
072A:109 add ax, dx

据我了解,第一条指令将两个字节的值 67 45 放在地址 072A:107 处。最后AX = 4567

我不明白的是为什么较新的指令 mov ax, 1234 不会更改前一个 mov word ptr [0107] 指令的地址 072A:107 处的值,为什么转储没有更改?.

提前致谢。

当你查看反汇编时(在执行第一条指令之前),内存中已经加载了机器代码(我假设这是 DOS COM 文件,所以 cs=ds=ss=0x72A 和第一个 mov 自修改第二个mov).

所以内存的内容已经是(中间部分是十六进制的机器码字节):

072A:100 C70607016745   (mov word ptr [0107], 4567) <- cs:ip points here
072A:106 B83412         (mov ax, 1234)
072A:109 01D0           (add ax, dx)

执行第一条指令后(C7 06 07 01 67 45 - CPU读取6个字节并解码为mov [..],..指令)内存内容将变为:

072A:100 C70607016745   (mov word ptr [0107], 4567)
072A:106 B86745         (mov ax, 4567)  <- cs:ip points here
072A:109 01D0           (add ax, dx)

如果你现在反汇编机器代码,你会看到第二条指令已经是 "mov ax, 4567"... CPU 不知道,原始来源确实说 mov ax, 1234 正如您从内存中的机器代码中看到的那样,无法重建它,内存中的任何地方都没有 1234h 值。

此外,当您从可执行文件中重新加载代码时,它将再次 mov ax, 1234,因为这是在执行之前在汇编步骤之后存储在二进制文件中的内容。

机器代码不是在运行时从源代码构建的,汇编程序在汇编期间确实生成二进制机器代码,所以 "restore" 第二条指令返回 mov ax,1234 没有任何意义(源代码和汇编程序在运行时不相关)。

如果这是某种解释型语言,在执行前准备每条指令,从源代码进行汇编,那么第一条指令将不得不修改源代码以在 "interpretation-time" 处引起自我修改,但大多数解释器不允许任何简单的方法来修改当前解释的源代码。

甚至 toy/simulator-machines 旨在教授汇编(MARS/SPIM 或 8-bit assembler simulator)以 "runtime" 运行二进制机器代码,而不是源代码(尽管它们可能或可能不允许自我修改传播到模拟中,一些模拟器可能会忽略它并保护原始机器代码免受任何奇怪原因的修改。

汇编新手警告:虽然自我修改代码一开始听起来很酷(至少对我来说是这样),但强烈建议不要这样做:1) 在现代 SW 中你不能默认使用它(除非你去启用它需要相当长的时间)2)它会极大地损害现代 CPU 的性能,因为当现代 x86 CPU 在 107h 检测到写入时,它确实已经提取+解码+推测性地执行了几条指令,所以它必须将所有 "future" 的工作扔进垃圾桶,清除内部缓存,然后重新开始,这意味着像 mov ax,1234 这样的指令可能已经在单个周期甚至其他周期中执行指令,可能需要 100+ 个周期。 3) 如果您没有足够的经验来猜测此类代码的所有含义,则很难找到错误。

所以理解这个概念和发生的事情很有价值,但是除非你正在做一些额外的事情,否则不要使用它 niche/specialized,比如 256B intro 并且它为你节省了两个字节,那么它是有效的。