2011-09-08 35 views
6

les组装指令的目的是什么?Les指令的目的是什么?

为什么我们需要加载es注册?书中给出了下面的例子:

les bx, p   ; Load p into ES:BX 
mov es:[bx], al  ; Store away AL 

为什么我们需要加载在这种情况下esbx?我们为什么使用es:[bx]?如果p指向内存100h,则不是esbx 100h = 200h(bx+es)?

回答

9

它太糟糕了,你正在学习一个凌乱的架构微处理器的汇编程序。您会遇到混淆的概念,例如LES指令。

传统的微处理器有足够大的寄存器来包含完整的存储器地址。您可以简单地将一个内存位置的地址加载到一个寄存器中,然后通过该寄存器访问该位置(通常是附带索引的位置)。有些机器(特别是Intel 286似乎是你正在编程的),只有16位寄存器,但可以处理1mB的内存。在这种情况下,寄存器没有足够的位:您需要20位,但寄存器只有16位。

解决方案是让第二个寄存器包含缺失的位。一个简单的方案是要求2个寄存器,其中一个具有较低的16位,其中一个具有较高的16位,以产生32位地址。然后引用两个寄存器的指令是有意义的:你需要得到一个完整的内存地址。

Intel选择了一种混乱的方案:索引寄存器(bx在你的情况下)包含低16位,而另一个寄存器(称为ES)包含16位左移4位,并添加到索引寄存器,得到结果地址。 ES被称为“段”寄存器,但除非您阅读大约1968年的Multics operating system,否则这将毫无意义。

[段和段寄存器在完全实现Multics方式时确实是一个有趣的想法。如果您不知道这是什么,并且您对计算机和/或信息架构有兴趣,请查找关于Multics的Elliot Organick书,并阅读其封面。你会对我们在60年代后期所发生的事情感到沮丧,并且似乎已经在50年的“进步”中失去了。]

在x86中剩下的想法几乎是一个笑话,至少是它的方式用于“现代”操作系统。你并不在乎;当一些硬件设计师给你提供一台机器时,你必须像现在一样使用它。

对于Intel 286,您只需加载段寄存器和索引寄存器即可获取完整地址。每台机器必须引用一个索引寄存器和一个段寄存器,以形成一个完整的地址。对于英特尔286,有4个这样的分段重定向器:DS,SS,ES和CS。每种指令类型都明确指定一个索引寄存器,并隐式选择4个段寄存器中的一个,除非你提供了一个明确的覆盖来说明使用哪一个。除非另有说明,JMP说明使用CS。除非另有说明,MOV说明使用DS。 PUSH指令使用SS,除非你另有说明(在这种情况下,你最好不要)。 ES是“额外”部分;只能通过在指令中明确引用它来使用它(除了块移动[MOVB}指令,它隐式使用DS和ES)。

希望有所帮助。

最好使用更先进的微处理器,其中段寄存器愚蠢不是问题。

+0

您的回答*主要*正确。但是,所有现代x86处理器都使用段寄存器。即使在大多数情况下都是平坦的64位模式下,你仍然有GS和FS不平坦。如果有的话,这个细分市场的恶性现在比你在文章中描述的要复杂得多。 –

+2

是的,他们这样做,但OP不需要听到这种并发症。目前的利用率(x64)也不是真实分段寄存器最糟糕的痕迹。这样的耻辱,请参阅Multics参考。 (安迪格罗夫在80年代中期在一次谈话中站了起来,炸了他的堆栈......英特尔设计了386段寄存器来真正实现Multics,而且他被Unix的微软忽视了,我们应该接受我们所接受的)。 –

+2

非常感谢! “*您需要20位,但寄存器只有16位。*“我完全忘记了我正在使用16位CPU! –

3

p指向一个带段和偏移量部分的32位FAR指针(与只有偏移量部分的NEAR指针相反)。 LES将加载段:抵消到ES:BX

否则,您将不得不使用三条指令。 一个用于加载BX,另两个用于加载ES(段寄存器不能直接从存储器加载,但必须加载到通用寄存器,然后加载到段寄存器中)。

哦,是的,是的,Wallyk提到保护模式有一个好处(虽然这是旁边的问题点)。 这里,ES将被解释为选择器,而不是实际的片段。

此上下文中的段(地址)是物理地址的一部分:
将段向左移动4位(即将其乘以2^4 = 16),并添加偏移量以获取物理来自segment:offset的地址。相反,选择器是指向所谓描述符表中的条目的指针(即,选择器指向描述符)并且用于保护模式。 描述符表(例如GDT)可以包含关于存储器块的信息条目,包括关于物理存储器地址,块大小,访问权限等的信息(还有一些稍微其他用途)。

5

8086段寄存器csdses,和ss是原始机制,通过该16位寄存器可以寻址超过64K的存储器。在8086/8088中,有20位地址(1024 K)被生成。后续版本的x86处理器增加了新的方案来解决更多问题,但是从一对16位值生成20+位地址是基本原因。

在所谓的“实模式”(8086/8088/80186/80286原生)中,地址是通过将段寄存器的内容乘以16(或等价地向左移四位)和添加偏移量。

在保护模式下(可用于80386和更高版本),段寄存器选择一个包含基本物理地址的“描述符”。例如,操作数es:[bx]bx添加到该物理地址以生成操作数地址。