MASM 字符串指令 - 在实模式下段寄存器覆盖前面的 LEA?

MASM string instructions - segment register override on preceding LEA in real mode?

对于 8086,可以覆盖源索引 SI 的段以使用 ES 而不是 DS。在一本书(旧的 Scanlon)中,我找到了这个 MASM 代码:

LEA SI,ES:HERE
LEA DI,ES:THERE
MOVSB

由于 LEA 仅检索内存地址的偏移量(8086 为 16 位), MOVSB 如何知道 SI 指的是 ES 段而不是 DS 段? LEA 是否正在更改 SI 的默认段?我在找到的许多页面和手册中都没有读到任何相关内容。

该代码看起来有误。如果没有段覆盖前缀,movsb 将始终使用 DS:SIES:DI。除非您不得不担心古老处理器的勘误表,否则您可以通过为 movsb 提供段覆盖前缀来使此代码正常工作。 es:MOVSB 会告诉它使用 ES:SI 而不是 DS:SImovsb 总是复制到 ES:DI;没有段覆盖前缀会改变它。

如果保证 DS 在此位置等于 ES,则代码实际上可能是正确的。旧的汇编器有他们自己的想法,有时必须使用有趣的段覆盖来让汇编器开心。

我在DOSBOX下安装了MASM6.11,做了一些实验。 这是数据段的内存映射:

 0000               dseg segment para public 'data'
 0000 41 42 43 44   src db 'ABCD'
 0004               dseg ends

 0000               eseg segment para public 'data'
 0000 5A 5A 5A 5A   dummy db 'ZZZZ'
 0004 31 32 33 34   dst db '1234'
 0008               eseg ends

 0000               cseg segment para public 'code'
                    assume cs:cseg, ds:dseg, es:eseg

结果是代码:

LEA SI,ES:HERE
LEA DI,ES:THERE
MOVSB

错误:根本不考虑段,它在任何情况下都从 DS 复制到 ES(OP-CODE 是 A4):

8D 36 0000 R
8D 3E 0004 R
A4

为了实现从ES到ES的拷贝你这样写:

LEA SI,ES:HERE
LEA DI,ES:THERE
MOVS ES:THERE, ES:HERE

转换为:

8D 36 0000 R
8D 3E 0004 R
26: A4

语法 ES MOVSBES:MOVSB 我在答案中读到的语法不适用于 MASM 6.11(但它们实际上对应于什么翻译过来就是:26是ES的代码)。