MASM中Group的作用
Masm5以后推出的simplified segment模式及.model标准模型中,都将段组合成一个group,group的作用及优点是什么呢?
一、Group的作用
将组(group)后的所有段加入一个组,位于这些段内的的label(标号)或variables(变量)的偏移地址都参照Group的起始地址进行计算,而不是所在段的起始地址进行计算:
1、多数据段代码举例如下
assume cs:codesg,ss:stacksg,ds:datasg1,es:datasg2
;-------------------------------------------
stacksg segment stack
db 100 dup (0)
stacksg ends
;-------------------------------------------
datasg1 segment
var1 db 6
datasg1 ends
;-------------------------------------------
datasg2 segment
var2 db 9
datasg2 ends
;-------------------------------------------
codesg segment
start:
;-------------------------------------------
mov al,var1
mov al,var2
;-------------------------------------------
mov ax,4c00h
int 21h
codesg ends
end start
如果不定义组,则var1和var2的偏移地址都是0000,编译后代码如下:
如将datasg1和datasg2编入组:
mygroup group datasg1,datasg2
assume cs:codesg,ss:stacksg,ds:mygroup
则编译后代码如下:
可见,编入组后var1和var2都参照mygroup的起始地址计算偏移地址。
2、多代码段代码举例如下
assume cs:codesg,ss:stacksg,ds:datasg
;-------------------------------------------
stacksg segment stack
db 100 dup (0)
stacksg ends
;-------------------------------------------
datasg segment
var1 db 6
datasg ends
;-------------------------------------------
codesg segment
start:
;-------------------------------------------
mov al,var1
jmp far ptr funone
;-------------------------------------------
mov ax,4c00h
int 21h
codesg ends
;-------------------------------------------
assume cs:excode
excode segment
funone:
mov ax,2222h
excode ends
;-------------------------------------------
end start
其中jmp funone由于已经跨段,所以应该是jmp far ptr funone,如果改成jmp funone,编译就会出现错误
将2个代码段加到一个组中,则可以直接jmp funone,代码如下:
cgroup group codesg,excode
assume cs:cgroup,ss:stacksg,ds:datasg
;-------------------------------------------
stacksg segment stack
db 100 dup (0)
stacksg ends
;-------------------------------------------
datasg segment
var1 db 6
datasg ends
;-------------------------------------------
codesg segment
start:
;-------------------------------------------
mov al,var1
jmp funone
;-------------------------------------------
mov ax,4c00h
int 21h
codesg ends
;-------------------------------------------
excode segment
funone:
mov ax,2222h
excode ends
end start
逻辑上codesg和excode组合成一个段,段地址是cgroup的首地址(也就是组中第一个代码段的地址)。
注意:
1、assume ds:mygroup、assume cs:cgroup语句不能少(即将段地址和组地址进行关联),否则组定义无意义。
2、加入组的第一个段和最后一个段之间的距离不能超过65535Byte(想想为什么)。
3、Group并不改变段在内存的位置,只是改变组内代码和数据的访问方式:因为定义在不同段的代码需要通过far ptr来跨段访问 ,数据则需要改变段寄存器来访问,即使根据实际位置并不需要这么做。group将所有属于组内的代码和数据在逻辑上按属于同一段的方式来访问,这个段的段地址就是group的首地址。
二、Group的优点
这样做的好处是cpu在代码跳转或数据访问时,段寄存器不用变更(都参照group的起始地址),减少跨段访问操作,加快程序的执行速度。
三、Group知识扩展
Mams5后对段的定义即划分进行了简化,并给出了标准化建议。如按照标准化定义段,还可以与c、basic、pascal等高级语言进行相互调用。
.model tiny/small/medium/compat/large/huge(6种内存模型)
tiny,代码和数据在一个段中,整个程序只有一个段。
small,代码只有一个段,数据只有一个段。
medium,数据只有一个段,代码可存在多个段。
compat,代码只有一个段,数据可存在多个段。
large,代码和数据都可以有多个段。
huge,代码和数据都可以有多个段,且data array可以超过64K。
.model指令还自动定义group和assume指令,将相应的段加入group,并将段寄存器与group关联,如.model small,就会自动生成
dgroup group _data,const,_bss,stack
assume ds:dgroup。
但注意,这里需要手动为ds赋值:
mov ax,dgroup
mov ds,ax