丹 青

 

汇编学习-汇编中的分段和段地址的定位

首先说明以下的内容都是摸索出来的,不敢说一定正确,有不对的地方还请指正。

我在学习汇编的过程中一直不明白操作系统是如何分段的和如何将一个段地址赋给寄存器(如有个段data segment 那么 mov ax,data 是如何实现的)经过查找资料和摸索基本了解了其中原理,记录如下:

首先看如何分段,比如有如下代码

data segment

db ‘data’

data ends

我最初的理解是:当程序运行时在获得这个分段的信息后,会自动在内存中查找一段长为64K的未使用空间给这个段使用。我以为一个段固定必须是64K,并且不一定会被分配到内存的哪个地方。后来在实践中发现我的理解是错误的。

事实是:一个段最大占用空间为64K,而最小分配的空间是16个字节,并且总以16的倍数来分配空间。(如果段里面没有定义任何数据则不分配空间)

如上面你那个段在代码中分配的空间如下图所示:

clip_image002

那么如果程序中有多个段呢:

data segment

db ‘data’

data ends

data2 segment

db ‘data2’

data2 ends

data3 segment

db ‘data3’

data3 ends

这段代码在内存中分配的空间如下图所示:

clip_image004

我们看到,如果有多个段,则是按我们定义的顺序连续存放。而不是我设想的系统自己找可用空间随意存放。

下面我们再看一下如 mov ax,data 是如何实现的。

首先看下面的汇编源代码

assume cs:code,ds:data,ss:stack

data segment

db 'data'

data ends

stack segment

db 'stack'

stack ends

code segment

db 'code'

first:

mov ax,data

mov ds,ax

mov ax,stack

mov ss,ax

mov bx,data2

code ends

data2 segment

db 'data2'

data2 ends

data3 segment

db 'data3'

data3 ends

end first

在这段代码中,有5个段,他们的段名称分别是 data,stack,code,data2,data3

我们写程序的时候并不知道这段程序最终会被放置到内存的哪个地方,所以当我们想使用某个段的时候,就只能使用 mov ax,data(段名称) 这样的代码来指定将data代表的段地址分配给ax寄存器,在生成exe并运行后操作系统需要将实际的段地址替换掉data。如

mov ax,data实际运行后在内存会变成如 mov ax,0aba。这个过程就是重定位。

操作系统重定位的相关信息都保存在生成的exe文件中:

首先是文件头:

clip_image006

然后是程序部分:

clip_image008

在文件头中关于重定位的部分有以下字节:

06H—07H 重定位项的个数。

clip_image010

从图中的06H-07H得到值为0003,则表示程序中有3个重定位项

那么这3个重定位项的位置分别在哪呢?我们可以根据第一个重定位项的偏移量来获得

18H—19H 第一个重定位项的偏移量

clip_image012

从图中的18H-19H得到值为001E,也就是第一个重定位项在头文件的1E处开始,每4个字节表示一个位置,其中高位的2个字节为重定位项所在段相对于程序第一行的偏移量,低位的2个字节为重定位项相对于所在段的第一个字节的偏移量。

从头文件中的1E除开始,我们能获得如下3个地址:

clip_image014

00 02 00 05 (行偏移量为2,字节偏移量为5)

00 02 00 0A (行偏移量为2,字节偏移量为A)

00 02 00 0F (行偏移量为2,字节偏移量为F)

根据这些信息我们就能找到对应的字节的是需要重定位的,如下图:

clip_image016

他们分别是

B8 0000 对应汇编代码中的mov ax,data

B8 0001 对应汇编代码中的mov ax,stack

BB 0004 对应汇编代码中的mov bx,data2

我们看到,data 被替换为0000,stack被替换为0001,data2被替换为0004

那么这个0000,0001,0004分别表示什么呢,他们表示对应的段相对于程序第一行的偏移量。

0000为第一行正好是data段

0001 为第二行,正好是 stack 段

0004为第五行,正好是data2段

假设操作系统运行这个程序后分配的段地址为0aba 那么操作

data 的段地址就是 0aba+0000 = 0aba

stack 的段地址就是 0aba+0001=0abb

data2 的段地址就是 0aba+0004=0abe

操作系统就会根据重定向的信息将

mov ax,data 替换为 mov ax,0aba

mov ax,stack 替换为 mov ax,0abb

mov bx,data2 替换为 mov bx,0abe

从而完成重定向的过程。

再次声明我初学汇编,上述见解如果有错误之处期望大家指正,谢谢!

posted on 2011-12-01 13:23  丹 青  阅读(2215)  评论(0编辑  收藏  举报

导航