我刚刚开始阅读有关Intel 8086的文章,并对它的内存有疑问。
我读到地址总线为20位宽,这意味着地址空间为1MB,并且该空间分为多个段。
问题是:
这四个段寄存器CS
,DS
,SS
和ES
是只读的,还是我可以设置它们的值,它们的默认值是什么?
我看到了以下汇编教程:
ORG 100h
MOV AX, 0B800h ; set AX = B800h (VGA memory).
MOV DS, AX ; copy value of AX to DS.
MOV CL, 'A' ; CL = 41h (ASCII code).
MOV CH, 01011111b ; CL = color attribute.
MOV BX, 15Eh ; BX = position on screen.
MOV [BX], CX ; w.[0B800h:015Eh] = CX.
RET
关于第一行,是否表示此代码将存在于代码段空间或整个地址空间中的地址
0x100
中和线:
MOV [BX], CX
这是否意味着每次我在
MOV
指令中引用地址时,都应从数据段的起始地址中估算出该地址? (因为他写道目的地是值+数据段reg中的值)
最佳答案
首先,我不得不指出您似乎在这里谈论8086“实模式”寻址,这是一种非常古老的处理方式,几乎不再使用。几乎所有现代操作系统都在“受保护的模式”下运行,该模式支持许多增强功能(例如,平面32位和64位内存空间寻址,虚拟内存等),这些功能会改变所有这些功能的工作方式。
据我所知,当今大多数操作系统甚至都不再具有以这种方式(以实模式运行)的代码,因此,如果您有兴趣学习用于对现代PC进行编程的汇编语言,则可能需要寻找更多最新资源以供学习。
话虽如此,假设您确实有某些理由要这样做(例如,使用某些嵌入式处理器),或者出于历史目的只是出于好奇:
是的,可以修改8086实模式段寄存器。与修改更通用的寄存器相比,执行此操作的指令和选项受到更多限制(例如,没有指令将值直接直接加载到段寄存器中,这就是为什么在您引用的代码中,值是首先将其加载到AX
,然后将AX
加载到DS
),并且也可以根据您使用的段寄存器而有所不同。
通常,您永远都不想直接修改CS
(“代码段”)寄存器,因为这将导致立即更改处理器正在运行的代码(可能以您确实不想要的方式)。修改CS
的通常方法是使用“跳远”或“长调用”指令,这将同时更新CS
和IP
(指令指针)。同样,SS
(“堆栈段”)通常在程序执行开始时设置,并且从不更改(但从技术上讲,如果您有某些确实令人信服的理由这样做,则可以这样)。DS
和ES
是通用数据段寄存器,程序更改它们非常普遍,但是它们希望最好地访问要使用的内存(如上面的示例代码所示)。
至于这些寄存器的初始值,通常是由操作系统在调用程序代码之前确定的。传统上,在MS-DOS中,有两种方法可以编写程序:.COM文件或.EXE文件。 (上面代码中的ORG 100h
行表明它打算作为COM程序运行。)在COM情况下,MS-DOS最初会将所有段寄存器设置为与CS
相同(即是,它们都指向DOS在调用程序之前决定将程序加载到内存中的任何位置。 EXE文件格式稍微复杂一些,允许指定一个单独的“数据段”,在这种情况下,操作系统将在启动程序之前将DS
和ES
设置为指向该段。在EXE程序中,DOS通常也会为它们设置一个单独的堆栈段(SS
)。The ORG 100h
行告诉汇编器“假定以下代码将在地址100h处加载”。在实模式代码中,此类地址始终相对于CS
(因此,只要将CS
设置为正确的值以使代码相对于100h,该程序实际上就可以加载到内存中的许多位置。到CS
)。
默认情况下,大多数数据操作地址(例如MOV
)将相对于DS
计算(对于某些说明,您可以通过显式指定要使用的其他段来更改地址,但是是否以及如何执行此操作取决于操作码以及您的使用方式)。但是,有一些指令默认情况下旨在使用其他段。总而言之,最好阅读您想了解的每个操作码的文档,以确定它如何使用哪个段寄存器。
关于assembly - 8086中段寄存器的值是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18837627/