段结构伪指令

汇编语言程序是按段来组织程序和使用存储器的,段结构伪指令的作用是在汇编语言程序中定义逻辑段,指明段的名称、范围、定义类型、组合类型和类别等。

完整端定义由 SEGMENT、ENDS、ASSUME 和 ORG 等。

完整端定义的一般格式如下:

1
2
3
4
段名  SEGMENT [类型属性列表]
.
.
段名 ENDS

其中, SEGMENT 表示逻辑段的开始,ENDS 表示逻辑段的结束。

段首伪指令 SEFMENT

该指令标志着一个段的开始,并可以给段赋予边界属性、组合类型、使用类型和类型别名等属性。

格式:段名 SEFMENT [边界类型] [组合属性] [使用类型] [‘类别名’]

段名由用户指定,对属性如不指定,采用默认值,若指定,必须按照以上次序。

边界类型:边界类型指明该段装入内容时,对段起始边界的要求。有以下四种。

  • BYTE(字节边界):表示本段从一个字节的边界开始,即任一地址开始。
  • WORD(字边界):表示本段从一个偶字节的边界开始,所以段的起始地址一定可以被2整除,用二进制表示,最后一位为0。
  • PAPA(节边界):表示本段从一个小节的边界开始(一个小节为16个字节),所以段的起始地址一定可以被16整除,用二进制表示,最后4位为0。
  • PAGE(页边界):表示本段从一个页的边界开始,存储器从0号单元开始,每256个字节为一页,所以段的起始地址一定可以被256整除,用二进制表示,最后8位为0。

注:省略边界类型时,默认 PAPA。

合并类型:指示连接程序本段与同段名同类别的其他段合并与否以及合并方式。有以下5种。

  • NONE;表示本段与其他段无连接关系,因此在逻辑上是分离的。
  • PUBLIC;连接程序在满足边界类型的前提下,将本段与其他段具有相同段名并且也用 PUBLIC 说明的段放在连续的存储空间中,形成一个新的逻辑段,其长度为各段长度之和。
  • COMMON:产生一个覆盖段,连接程序将相同段名、相同类别的 COMMON 段重叠放置,共享一个存储区,覆盖段的长度是各段最大长度。
  • STACK:用于指定一个堆栈段,连接程序对 STACK 和 PUBLIC 段同样处理,此外还要指示装入程序把合并后的段基址送入 SS ,并将 SP 设置成堆栈段的长度。
  • AT节地址:表示本段可定位在表达式所指定的小节边界上。

类型名:写在一对单引号中的名字,由用户自己选定。

段尾伪指令 ENDS

该伪指令标志着一个段的结束。

格式:段名 ENDS

注:段名必须与 SEGMENT 指令中的段名一致。

段寻址伪指令 ASSUME

用来说明各个段寄存器分别装入哪个逻辑段的段起始地址。

格式:ASSUME 段寄存器名:段名,段寄存器名:段名...

ORG 伪指令

设置其后的指令或数据的起始地址,使指令或数据从指定的偏移地址开始存放。

格式:ORG 表达式

注:表达式的值应在 0000H–0FFFFH 之间。

地址计数器 $

表示下一个可用单元的地址。

eg:

1
2
3
4
ORG 0050H                 ; 使变量从偏移地址 005H 开始存放
DATA1 DW 1,2,3,4
ORG $+30H ;使变量从偏移地址 0088H 开始存放
DATA2 DB 'ABCD'

完整端定义结构

典型结构格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
数据段名    SEGMENT         ;数据段开始
.
.
数据段名 ENDS ;数据段结束
堆栈段名 SEFMENT ;堆栈段开始
.
.
堆栈段名 ENDS ;堆栈段结束
代码段名 SEGMENT ;代码段开始
ASSUME ... ;代码段装填
START: ...
.
.
MOV AH,4CH
INT 21H ;返回 DOS
.
.
代码段名 ENDS ;代码段结束
END START

过程定义伪指令

在程序设计中,通常把一些相对独立的语句序列组成一个过程,供程序调用执行,过程又称为子程序,过程定义伪指令 PROC/ENDP 的格式如下:

1
2
3
4
5
过程名  PROC [NEAR|FAR]
.
.
RET ;返回指令
过程名 ENDP

定义一个过程必须在一个逻辑段中,过程名相当于标号,表示本过程的符号地址,过程有 NEAR 和 FAR 两种,NEAR 类型的过程仅供段内调用,FAR 类型的过程可供段间调用。类型默认 NEAR。

模块定义伪指令

NAME 伪指令

用于给源程序汇编以后得到的目标程序指定一个模块名,连接目标程序时,将使用该模块名表示目标程序。

格式:NAME 模块名

TITLE 伪指令

用于给程序指定一个标题,一般不超过60个字符,以后的列表文件会在每一页的每一行显示这个标题。

格式:TITLE 文本

END 伪指令

指示用标号指定的地址作为程序执行的启动地址。

格式:END [标号]

注:如果源程序中没有用 NAME 伪指令指定模块名,则汇编程序将 TITLE 伪指令给出的标题名中前6个字符作为模块名,如果源程序中即无 NAME 伪指令,也无 TITLE 伪指令,则汇编程序将源程序的文件名作为模块名。

宏指令

宏指令定义、调用和展开

宏定义 MACRO/ENDM 格式:

1
2
3
4
宏指令名 MACRO [形参列表]
.
. ; 宏体
ENDM

在宏定义时,宏指令名必须唯一,允许修改的部分作为形式参数来表示,在宏调用时使用实参代替。

宏调用格式:

宏指令名 [实参列表]

宏展开:用宏定义中宏体的目标代码替换宏调用。

宏操作符

连接操作符 &

在宏定义时,&作为形参的前缀或后缀,宏展开时,连接操作符&前后的两个符号连接在一起构成新的符号。

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SHIFT_VAR MARCO RM,DIRECT,COUNT
MOV CL,COUNT
S&DIRECT RM,CL
ENDM
SHIFT_VAR AX,HL,2

SHIFT_VAR BX,HR,3

两次调用的宏展开分别如下:
+MOV CL,2
+SHL AX,CL

+MOV CL,3
+SHR BX,CL

表达式操作符 %

格式:%表达式

在宏调用时,表达式操作符强制后面的表达式立即求值,并将表达式的值作为实参替换。

文本操作符 <>

在宏调用时,若某个实参中包含逗号或空格等间隔符,则必须用文本操作符将该实参括起来,以保证将他作为一个单独的参数而不是多个参数。

字符操作符 !

格式:!字符

指示宏指令在汇编时,把后面的字符当做普通的字符对待,而不使用它的特殊含义。

宏注解符 ;;

格式:;;文本

LOCAL 伪指令

宏定义中如果包含标号或变量名,且在同一个源程序中调用多次,则在宏展开时,就要产生多个相同的变量名或标号,为了避免这种错误,可在宏定义中使用 LOCAL 伪指令。

格式:LOCAL <局部符号表>

LOCAL 指定的变量名或标号在宏展开时会自动生成 ?? XXXX 的符号,XXXX 的范围在 0000H - 0FFFFH。

重复汇编

重复汇编结构有三种,分别使用 REPT、IPR 和 IRPC。

REPT/ENDM 伪指令

格式:

1
2
3
4
REPT 数值表达式
.
.
ENDM

REPT/ENDM 伪指令指示汇编程序重复执行重复块的指令序列,重复次数由数字表达式的值确定。

IRP/ENDM 伪指令

格式:

1
2
3
4
IPR 形式参数,<实参数>
.
.
ENDM

IPR/ENDM 伪指令指示汇编程序使重复块的内容重复多次,重复次数等于实参数的个数。每次重复都用一个实参数替换形式参数,直到用完为止。

IRPC/ENDM 伪指令

格式:

1
2
3
4
IRPC 形式参数,串
.
.
ENDM

IRPC/ENDM 伪指令指示汇编程序使重复块的内容重复多次,重复次数等于串中的数字或符号的个数。每次重复用串中的一个数字或符号替换形式参数。如果串中有空格,需要用<>括起来。

条件汇编

根据条件来确定否把一段源代码汇编成对应的目标代码。有以下两种格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
格式1:
IFXX 条件
.
. ;语句序列1
ELSE
.
. ;语句序列2
ENDIF
格式2:
IFXX 条件
.
. ;语句序列
ENDIF