tsembrace 发表于 2011-8-19 11:50:31

关于自定义的段占用内存空间

本帖最后由 tsembrace 于 2011-8-19 12:40 编辑

---------------------------------------------------------------------------------------------------------------
在王爽汇编实验5(2)中有这样一个问题:

“对于如下定义的段:

name segment

   ...

name ends

如果段中的数据占N个字节,则程序加载后,其实际占用空间?“

当时在做这道题时候,只是通过debug加载多个类似程序,然后观察,得出实际占用空间为16×(+1)字节。即对于设定的段空间,如果在预设时候的数据不足16字节×m{m=(+1)},编译器会自动给其增补内存空间以达到(16×m)个字节空间。

当时只是以为这就是规则,而没有深入去考虑为什么制定这样的规则?---------------------------------------------------------------------------------------------------------------


对于程序而言,数据段的设置是为了方便使用,而使用数据段则需要知道其段地址。

举例如下:

a segment

db 16 dup(0)

a ends

b segment

db 23 dup(0)

c ends

c segment

db 38 dup(0)

c ends

以上a\b\c三个数据段实际占用的内存空间分别为16、32、48byte。程序加载后内存空间分配如下:

ds:0~0ffh ------>psp

ds:100h~10fh ------>a段

ds:110h~12fh------> b段

ds:130h~15fh ------>c段

由上可见,a\b\c段的地址范围分别可以表示如下:

(ds+10):0~0fh------>a段

(ds+11):0~1fh------>b段

(ds+13):0~2fh------>c段

即a\b\c段的段地址可以分别表示为(ds+10)\(ds+11)\(ds+13);写到这里,有些人可能会问:abc段地址同样可以设置为ds啊,只需要偏移地址对应起来就可以啊。这当然没错;可只有当设为(ds+10)\(ds+11)\(ds+13)时候,对应的(段地址:0)才能指向各区的首地址,而段地址选用ds的话,各区的首地址偏移地址分别为100h\110h\130h。

---------------------------------------------------------------------------------------------------------------


再回想一下汇编程序中的常用做法,如下例:

assume cs:codesg,ds:data1,es:data2

data1 segment

   db 2 dup (0)

data1 ends

data2 segment

   db 4 dup (0)

data2 ends

codesg segment

    mov ax,data1

    mov ds,ax

    mov bx,0

    mov ax,data2

    mov es,ax

    mov bp,0

    ......

codesg ends

在编译器处理过程中‘data1'这个标号已经对应了data1这个数据区的段地址,并且该段地址使得该区首单元的偏移地址为0。

假设,编译器不增补至16的整数倍字节。那么上面这个程序中的data1\data2如何设置段地址才能使得首地址偏移地址为0?答案是:有些情况下做不到。因为如果不增补的话,data1地址范围为(ds+100h):0~(ds+100h):1;data2地址范围为(ds+100h):2~(ds+100h):5;对于data1段来说,可以做到,设段地址为(ds+100h)即可使其首单元偏移地址为0;而对于data2段来说,无论怎么样设置段地址,其首单元偏移地址总不会为0.

---------------------------------------------------------------------------------------------------------------



通过上面的分析,基本上可以总结出以下几方面:

1、段空间首单元的偏移地址设为0,在很多时候都可以方便我们的编程设计,理清思路;但不是所有的情况都方便,或者说不是所有情况都必须使首单元的偏移地址设0.

2、在需要设0,或者说设0方便的情况下,编译器提供了"将程序中的各段空间增补为16的整数倍字节"的功能,其原因就是为了使该段首单元偏移地址可以设为0,同时用相应标号如”codesg"、"datasg"预存可以使其首单元偏移地址为0的段地址。举例如下:

assume cs:codesg,ds:a,es:b

a segment

   db 2 dup (0)

a ends



b segment

   db 4 dup (0)

b ends



codesg segment

    mov ax,a

    mov ds,ax

    mov bx,0

    mov ax,b

    mov es,ax

    mov bp,0

    ......

codesg ends

3、在不需要设0,或者说设0并不方便的情况下,则可以用如下数据定义格式:

assume cs:codesg,ds:datasg

datasg segment

   db 2 dup (0)   ;a区

   db 4 dup (0)   ;b区

datasg ends



codesg segment

    mov ax,datasg

    mov ds,ax

    mov bx,0

   ......

codesg ends

4、补充说明:

对于assume cs:codesg,ds:datasg语句,编译器并不会执行设置cs和ds的功能,只是“假设”。真正实现cs对应codesg,使ds对应datasg的语句分别是“end start"(注明程序开始入口)和"mov ax,datasg/mov ds,ax"语句。

□_□ 发表于 2011-8-19 18:14:31

英文啊,看到头晕了!不过还是要顶住学!
加油!LZ
页: [1]
查看完整版本: 关于自定义的段占用内存空间