----[x86实模式] 内存地址空间分布 CPU合成内存地址的方式 程序中段的加载 启动区格式要求----

2015.03.25-26

读《汇编语言》—王爽、《x86汇编语言:由实模式到保护模式》— 李忠、《30天自制操作系统》—川合秀实

整理笔记。


1 实模式

在实模式下,处理器的内存寻址方式和8086处理器相同。


2 计算机开机过程

任何一台使用Intel 系列CPU的PC机只要一开机,CPU就工作在实模式下。CPU从地址FFFF0H处开始执行指令,这是一条跳转指令,这条跳转指令会跳到系统BIOS真正的启动代码处(进行硬件检测和初始化)。启动代码执行完毕后,调用int19h进行操作系统的引导,将计算机交由操作系统控制。


如果你的机器装的是DOS,那么在DOS加载后CPU仍以实模式工作。如果你的机器装的是Windows,那么Windows加载后,将由Windows将CPU切换到保护模式下工作,因为Windows是多任务系统,它必须在保护模式下运行。Windows启动完成后,如果在Windows中运行一个DOS下的程序,那么Windows将CPU切换到虚拟8086下运行该程序。或者是这样,你点击开始菜单在程序项中进入MS-DOS方式,这时,Windows也将CPU切换到虚拟8086模式下运行。《汇编语言》第三版– 王爽。

也就是说,将CPU由实模式到保护模式的切换是由操作系统完成的


3 实模式下内存地址空间

8086处理器有20根地址线,寻址范围为0x00000~ 0xFFFFF(1M)。

----[x86实模式] 内存地址空间分布 CPU合成内存地址的方式 程序中段的加载 启动区格式要求----_第1张图片
Figure 1. 实模式下的内存地址空间

实模式下的内存地址空间是各个存储器件的地址的逻辑组合,各个存储器中的存储单元的地址与内存地址空间中的地址一一对应。


[1]处1KB内容是系统BIOS程序加载的(实际占用可能小于1KB);[2]处512字节内容是BIOS从磁盘/硬盘的第1柱面第1磁道的第1扇区读来的程序(此程序刚好512字节);[3]处128KB是显卡存储器的地址;[4]处256KB是存储BIOS程序的ROM存储器的地址。其中,最后64KB是存储系统BIOS程序的ROM存储器的地址,前192KB是其它存储BIOS程序的ROM存储器的地址。]


在系统BIOS执行完毕后,可用的RAM地址空间为0x00400~ 0x07bff以及0x0800 ~ 0x9ffff。


4 实模式下内存空间的访问

8086处理器(CPU)内的寄存器都是16位的,地址线上的地址由CPU提供。CPU用两个16位的值合成一个20位的值:将一个16位的值乘以16(相当于这个16位的值保存在20位寄存器的低16位中,然后将低16位往高位移动了4位)再加上另一个16位的值。将这个由2个16位合成的值提供给20根地址线作为访问内存的地址值。被乘以16的那个值被称为段基址,没有被乘以16的那个值被称为偏移地址。


CPU在实模式下,段寄存器中的值就是段基址,如果想要通过汇编程序访问某个内存单元,那么就需要指定一个段寄存器和一个偏移地址或以“段基址值:偏移地址值”的格式。CPU会将段寄存器的值乘以16再与偏移地址相加后,才将这个结果提供给地址线;用段基址和偏移地址的形式给出的表达式,CPU也会给段基址乘以16与偏移地址相加后,才将这个结果提供给地址线。

----[x86实模式] 内存地址空间分布 CPU合成内存地址的方式 程序中段的加载 启动区格式要求----_第2张图片

Figure 2. 实模式下访问内存(得出内存地址)的方式


这就是说,在汇编程序中,得用段基址:偏移地址的方式访问内存,因为CPU形成内存地址的方式是“段基址* 16 + 偏移地址”。

按照“段:偏移地址”的方式访问内存是CPU对内存的一种管理方式。


5 程序段和内存段的关系(程序的加载)

实模式下的内存的段基址低4位都为0(段基址左移4位),段基址至少要是16的倍数。所以,内存中连续的两个段之间至少也会相差16字节,也就是说内存段之间以16字节对齐。


汇编编译器将汇编程序中的“段名segment … 段名ends”伪指令对中的段名解释成一个程序段,程序加载器能够根据汇编编译器的解释将程序段加载到一个空闲的内存段中。


如果汇编程序中未定义段,汇编编译器将所有的程序当成一个程序段,第一条语句作为程序的入口地址,程序加载器加载最终的可执行文件到内存中时,它首先找到能够容纳下整个程序的内存段,将程序加载到内存段中;如果汇编程序中有多个段,汇编编译器能识别程序入口地址所在的程序段,程序加载器加载这样的可执行文件时,首先去找到一块能够容纳下整个程序的内存空间,然后将包含程序入口地址的程序段加载到这段空闲内存空间第一个内存段中,然后将其余的段按照在程序中定义的顺序加载到这段空闲内存空间的后续内存段中,各个内存段以16字节对齐;如果汇编程序中有多个段,但没有包含程序入口地址的段,那么汇编编译器将程序中的第一个段作为程序入口地址,程序加载器按照各个段的定义顺序将它们载入内存中。(这是大多数加载器加载程序的方法,如果要写一个自己的加载器,不这么加载程序完全可以)
assume	cs:code, ds:data, ss:stack

data	segment
	dw	0123h, 0456h, 0789h, 0abch, 0defh, 0fedfh, 0cbah, 0987h
data	ends


stack	segment
	dw	0, 0, 0, 0, 0, 0, 0, 0
stack	ends


code	 segment
start:
	mov	ax, stack
	mov	ss, ax
	mov	sp, 16
	
	mov	ax, data
	mov	ds, ax
	
	push	ds:[0]
	push	ds:[2]
	pop	ds:[2]
	pop	ds:[0]
	
	mov	ax, 4c00h
	int	21h
code 	ends
end	start           //告诉汇编编译器start标号处为程序的入口地址

编译、连接此汇编程序,用debug调试器调试此程序,得到各个程序段对应的内存内存段:

Figure 3. 程序段在内存中的内存段

code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。(因为每个段的内容都未超过16字节)


6 ORG

ORG是由编译器处理的伪指令。它告知加载器,后续的程序应被加载至本内存段的哪个偏移地址处。它对段无效。

assume cs:code

code segment
	jmp	my_label

	;org 5h

	my_label:
		mov	ax, 0
		
		mov	ax,4c00h
		int 21h
code ends
end

将此段汇编程序编译、连接,用debug调试器观看生成的指令:

Figure 4. 指令的参数为偏移地址

将程序中的注释去掉,再将程序编译、连接,用debug观看生成的指令:

----[x86实模式] 内存地址空间分布 CPU合成内存地址的方式 程序中段的加载 启动区格式要求----_第3张图片
Figure 5. org指定程序加载的偏移值

程序加载器能够根据汇编编译器对org伪指令的处理信息而将org后面的指令装载到org指定的偏移地址处。同时修改某些指令的参数。


7 磁盘启动区要求

软盘的柱面:磁盘(软盘内存储数据的介质)的两面的相同位置的2磁道构成一个柱面。

BIOS读软盘第一个扇区时,磁盘内不同地方的内容有不同的含义。以下是FAT12格式软盘第一扇区各内容的含义:

表格 1. Windows (开机)读软盘第一个扇区的读法

偏移

长度/字节

内容/含义

(参考)值

0

3

跳转到软盘指令开始处的跳转指令

jmp l_start(l_start为软盘内第一条指令处的标号)

3

8

第一个扇区的名字

"xnlosipl"

11

2

软盘每个扇区的大小(字节为单位)

必须为512

13

1

每簇的扇区数

必须为1

14

2

保留扇区数/FAT的起始位置/Boot记录占用扇区

一般为1

16

1

FAT的个数

必须为2

17

2

根目录文件数的最大值

一般为224

19

2

扇区总数

(必须为)2880

21

1

介质描述符

必须为0xf0

22

2

每FAT扇区数

必须为9

24

2

每磁道扇区数

必须为18

26

2

磁头数

必须为2

28

4

隐藏/不使用的扇区数

必须为0

32

4

如果偏移19处值为0,由这个值表示总扇区数

2880

36

1

中断13h的驱动器号

固定为0

37

1

未使用

固定为0

38

1

扩展引导标记

固定为0x29

39

4

卷列序号

0xffffffff

43

11

软盘名称

"xnlhello-os"

54

8

软盘格式名称

"FAT12   "(8字节,空格填充)

62

448

(引导)代码、数据及其它填充字符

……

510

2

标明软盘有无所需的启动代码(在第一个扇区内)

0x55aa(为0x55aa表明有)

这些规定都是指电平信号(在二进制编辑器中可直接书写就可得到它们)。在软盘内每个偏移内组织的数据要符合“表格 1”中的要求。这样,软盘内的数据才会得到计算机的正确解释


启动区外,除下图有2个地方有规定(非必须)内容外,其它地方的内容无规定。



[x86OS] Note Over.

[2015.04.01]

你可能感兴趣的:(----[x86实模式] 内存地址空间分布 CPU合成内存地址的方式 程序中段的加载 启动区格式要求----)