【问题标题】:Assembly 8086, Why later instruction doesn't modify previous one after execution汇编 8086,为什么后面的指令在执行后不修改前面的指令
【发布时间】:2025-12-20 10:50:09
【问题描述】:

我是汇编程序的新手,想弄清楚这段代码:

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 处的值,为什么不更改转储?

提前谢谢你。

【问题讨论】:

  • 您的问题到底是什么?为什么mov ax, 1234 不显示为mov ax, 4567 而是..?您是否尝试过执行一次代码然后再次生成反汇编?
  • 注意片段。 'word ptr [107]' 不一定是 CS:[107]
  • 自修改代码很久以前就不再实用了。现代处理器在执行指令之前就预取和预解码指令。照原样,此代码需要两者之间的特殊指令,如cpuid 之类的序列化指令。
  • @Pooshkis 改写问题的标题怎么样?像“为什么后面的指令,由前一个修改,在执行时不会重置”之类的东西?您当前的似乎更像是在问为什么mov ax,1234 不修改先前的指令,希望很清楚,它不写入任何内存,因此根本无法修改任何指令。还是您有其他想法而提议的标题没有说明?
  • @HansPassant:有趣的事实:x86 的实际硬件实现比纸上要求的 i-cache 一致性更强,因为正如 Andy Glew 解释的那样,与纸上规范一样弱会很慢 @987654321 @。我认为任何 x86 最需要的就是采取跳转以避免过时的指令获取,但是现代 OoO-exec 机器窥探已经在管道中的地址。 (导致自我修改代码的机器清除速度非常慢。)

标签: assembly word instructions mov


【解决方案1】:

当您查看反汇编时(在执行第一条指令之前),内存已经加载了机器代码(我假设这是 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 - 6个字节被CPU读取并解码为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,因为这是在执行组装步骤之后存储在二进制文件中的内容。

机器代码不是在运行时从源代码构建的,汇编器在汇编期间确实生成二进制机器代码,因此没有什么可以将第二条指令“恢复”回mov ax,1234(源代码和汇编器在运行时不相关) .

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

甚至设计用于教授装配的玩具/模拟器机器(MARS/SPIM,或8-bit assembler simulator)在“运行时”使用二进制机器代码而不是源代码运行(尽管它们可能允许也可能不允许自我修改传播进入模拟,一些模拟器可能会忽略它并保护原始机器代码不因任何奇怪的原因而被修改)。

对组装新手的警告:虽然代码的自我修改一开始可能听起来很酷(至少对我来说是这样),但强烈建议不要这样做:1)在现代软件中默认情况下不能使用它(除非你做了很多启用它的长度)2)它严重损害了现代 CPU 的性能,因为当现代 x86 CPU 在 107h 检测到写入时,它确实已经提取+解码+推测性地执行了几条指令,因此它必须抛出所有这些“未来”工作到垃圾中,清除内部缓存,然后重新开始,这意味着像 mov ax,1234 这样的指令可能已经在单个周期甚至其他指令中执行,可能会花费 100 多个周期。 3) 如果您没有足够的经验来猜测此类代码的所有含义,它会导致难以发现错误。

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

【讨论】:

    最近更新 更多