概念
汇编语言:用指令助记符、符号地址、标号、伪指令等符号编写程序的语言成为汇编语言。用这种语言书写的程序叫做汇编语言源程序或者称为源程序。
汇编:把汇编语言源程序翻译成在机器上能执行的机器语言程序的过程叫做汇编,完成汇编过程的程序叫做汇编程序。
交叉汇编:一个机器汇编,另一个机器执行。
驻留汇编:一个机器自身汇编,并且汇编结果在自身机器上运行。
汇编语句的格式:
[标号] 指令助记符 [操作数] [; 注解]
其中标号例如:
1 | 1 assume cs:code |
上述代码中code, start, s: 皆为标号,仅表示内存单元的地址,对于”:”的地址标号,仅可在代码段中使用。
- 汇编语言中出现的常数可以有7种:二进制数,八进制数,十进制数,十六进制数,十进制浮点数,十六进制浮点数,字符和字符串。
1 | MOV AL, 01000001B ;二进制数 |
伪指令
类似于C语言中的标识符,常用于数据定义,存储控件分配,条件转移,运算等。
- 定义数据伪指令:
- DB-定义字节,每个数据一个字节。
- DW-定义字,每个数据两个字节。
- DD-定义双字,每个数据四个字节。
- DQ-定义4字,每个数据八个字节。
- DT-定义10个字节,每个数据十个字节,用于压缩式十进制数。
1 | DATA1 DB 5,6,7,100 ;即DATA1为该组数的首地址,从此地址开始存放5,6,7,100每个数一个字节,共占四个字节。 |
段定义伪指令SEGMENT和ENDS
一般来说,一个完整的汇编源程序至少由3个段组成,即堆栈段,数据段和代码段。段定义伪指令可将源程序划分为若干段,以便生成目的代码和链接的时候将同名段进行组合。段定义的一般格式为:
1 | 段名 SEGMENT [定位类型] [组合类型] [类别] |
注意SEGMENT与ENDS须成对使用,缺一不可。
- 设定段寄存器伪指令ASSUME: ASSUME——段寄存器定义伪指令。用于指明各段,放在代码段内,放在段定义语句之后。
格式:ASSUME CS: CODE, DS: DATA, SS: STACK
段分配语句只建立当前段和段寄存器之间的关系,但段分配语句并不能将各段的地址装入段寄存器。
**段组:**
段组伪指令GROUP是用于把源程序模块中的若干个段结合成一个组,并对该段组定义一个段组名。段组伪指令格式如下:
`段组名 GROUP 段名 [, 段名, ......]`
其中段名之间要用逗号分隔。
1 | DATA1 SEGMENT ;第一个数据段 |
在上例中,语句(1)说明DS与DATA1建立联系,语句(2)对DS赋值,语句(3)用DS来访问DATA1段的变量名。语句(4)说明DS与DATA2建立联系,语句(5)对DS赋值,语句(6)用DS来访问DATA2段的变量名。
在该例子中,因为只使用一个段寄存器DS来对应二个数据段,所以,需要切换DS的对应关系(如:语句(4))。但我们也可以用段寄存器DS和ES来分别对应段DATA1和DATA2,这样,方法1就可变成方法2。
1 | DATA1 SEGMENT |
我们还可以用段组来简化段寄存器的使用,把段DATA1和DATA2组成一个数据段。所以,把方法2再改写成方法3的形式。
1 | GSEG GROUP DATA1, DATA2 ;把段DATA1和DATA2定义成一个段组 |
表达式赋值伪指令EQU:EQU伪指令给符号定义一个值,类似于C语言的
#define
凡是出现该符号的地方,汇编是均用其值代替。格式:
符号名 EQU 表达式
1 | 表达式可以是常数、数值表达式、地址表达式、变量、标号或者指令助记符 |
地址定义伪指令$:
$
表示地址计数器的值。地址计数器保存当前正在汇编的指令或数据的偏移地址。汇编程序每扫描一个字节,地址计数器的值加1
1 | JMP $ ;程序跳转到本条指令,即进入死循环状态。该语句一般用于等待中断的发生。 |
过程定义伪指令PROC与ENDP
过程——子程序(可被程序调用),汇编语言规定必须对过程进行定义。过程定义之后就可对调用指令CALL与返回执行RET进行正确的汇编。
如果过程中要用到某些寄存器或者存储单元,为了不破坏原有信息,要将寄存器或存储单元的原有内容压栈保护或存入子程序不用的寄存器或存储单元中。起保护作用的程序段可以放在主程序中,亦可放在子程序中。
过程定义的语句格式为:
1 | 过程名 PROC NEAR/FAR |
其中,NEAR(近过程)表示该过程与调用指令CALL处在同一代码段中(段名相同),只需将返回位置的偏移地址压入堆栈。
FAR(远过程)表示该过程与调用指令CALL处在不同的代码段中(段名不同),需将返回位置的偏移地址与段基址都压入堆栈。
1 | CODE SEGMENT PARA PUBLIC 'CODE' |
- 模块定义伪指令NAME/END
用于定义一个模块。在链接目标模块时将使用该模块名,汇编处理只进行到模块结束语句
格式:
1 | NAME 模块名 |
- END伪指令
一个程序模块只允许有一个END语句,后为主模块真起始地址
格式:END [起始地址标号]
- PUBLIC伪指令
用来说明已知模块中哪些标识符是公共的,可以别其他模块引用
格式:PUBLIC 符号
符号可以是本模块已定义的变量、标号、变量名、过程名等
- EXTERN伪指令
用于说明模块中哪些标识符是外部的,即其他模块中已被PUBLIC伪指令说明的符号
格式:EXTERN 符号名: 类型[, 符号名: 类型...]
- 宏定义伪指令
1 | MOV CL, 4 |