太糟糕了,你正在为一个架构混乱的微处理器学习汇编程序。你会得到一些令人困惑的概念,例如 LES 指令。
传统的微处理器有足够大的寄存器来包含一个完整的内存地址。您可以简单地将内存位置的地址加载到寄存器中,然后通过寄存器访问该位置(通常是附近有索引的位置)。
一些机器(尤其是实模式下的 Intel 286,这似乎是您正在编程的)只有 16 位寄存器,但可以寻址 1MB 内存。在这种情况下,寄存器没有足够的位:您需要 20 位,但寄存器只有 16 位。
解决方案是使用包含缺失位的第二个寄存器。一个简单的方案是需要 2 个寄存器,其中一个具有低 16 位,其中一个具有高 16 位,以产生 32 位地址。那么引用两个寄存器的指令就有意义了:你需要两个寄存器来获得一个完整的内存地址。
英特尔选择了一个更混乱的segment:offset 方案:普通寄存器(在您的情况下为 bx)包含低 16 位(偏移量),特殊寄存器(称为 ES)包含 16 位,左移 4 位,并添加到偏移量,以获得生成的线性地址。 ES 被称为“段”寄存器,但除非您阅读有关 Multics operating system circa 1968 的信息,否则这将毫无意义。
(x86 允许地址的“有效地址”或“偏移”部分使用其他寻址模式,例如 es:[bx + si + 1234],但对于内存地址始终只有一个段寄存器。)
[完全实现 Multics 方式时,段和段寄存器确实是一个有趣的想法。如果您不知道这是什么,并且您对计算机和/或信息架构有任何兴趣,请查找 Elliot Organick 关于 Multics 的书并从头到尾阅读。您会对我们在 60 年代后期所拥有的东西感到沮丧,并且似乎在 50 年的“进步”中失去了。如果您想对此进行更长时间的讨论,请参阅my discussion on the purpose of FS and GS segment registers]
x86 中剩下的想法几乎是个笑话,至少它在“现代”操作系统中使用的方式是这样。你真的不在乎;当某些硬件设计师向您展示一台机器时,您必须接受它。
对于 Intel 286,您只需加载段寄存器和索引寄存器即可获得完整地址。每个机器指令必须引用一个索引寄存器和一个段寄存器才能形成完整的地址。对于 Intel 286,有 4 个这样的段寄存器:DS、SS、ES 和 CS。每种指令类型都明确指定一个变址寄存器并隐式选择 4 个段寄存器之一,除非您提供明确的覆盖来说明要使用哪一个。除非您另有说明,否则 JMP 指令使用 CS。除非您另有说明,否则 MOV 指令使用 DS。 PUSH 指令使用 SS,除非你另有说明(在这种情况下你最好不要)。 ES 是“额外”段;您只能通过在指令中显式引用它来使用它(除了隐式使用 DS 和 ES 的块移动 [MOVB} 指令)。
希望对您有所帮助。
最好使用更现代的微处理器,其中段寄存器的愚蠢不是问题。 (例如,32 位模式 x86,其中主流操作系统使用所有段基数 = 0 的平面内存模型。因此您可以忽略分段并将单个寄存器作为指针,只关心地址的“偏移”部分。 )