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