我刚刚开始阅读有关英特尔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中的值)
答案 0 :(得分:9)
首先,我觉得有必要指出你似乎在这里谈论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最初会将所有段寄存器设置为与{{1 (也就是说,在调用程序之前,它们都指向DOS决定将程序加载到内存中的任何地方)。 EXE文件格式稍微复杂一些,并且允许指定单独的“数据段”,在这种情况下,操作系统会在启动程序之前将CS
和DS
设置为指向该段。在EXE程序中,DOS通常也会为它们设置一个单独的堆栈段(ES
)。
SS
行告诉汇编程序“假设以下代码将在地址100h加载”。在实模式代码中,诸如此类的地址始终相对于The ORG 100h
(因此只要将CS
设置为正确的值来编写代码,程序就可以实际加载到内存中的许多位置相对于CS
而言是100h。
默认情况下,相对于CS
计算数据操作的大多数地址(例如MOV
)(对于某些说明,您可以通过明确更改)指定要使用的不同段,但是否以及如何执行此操作取决于操作码和您使用它的方式)。但是,有一些指令默认设计为使用其他段。总之,最好阅读您想知道的每个操作码的文档,以确定它如何使用哪个段注册。
答案 1 :(得分:1)
获取intel 8088/86手册。这一切都在那里解释。
是的,你可以改变它们,你必须能够改变它们才能使它们变得有用。默认情况下使用明显的段(代码代码,数据数据),但有些地方可以在数据指令中指定其他段。
组织0x100表示此代码(或org指令后面的数据)从段内的地址0x100开始。