一,表达式
在汇编指令和伪指令中,凡是以常数、符号地址为操作数的地方,都可以换用表达式。表达式包括数值表达式和地址表达式。
1)常量
1> 数值常量 1010H
2> 符号常量
伪指令: <符号名> EQU <表达式>
功能:定义所指符号常量所代表的常量的值
说明:表达式可以是常数、指令助记符、伪指令助记符、寄存器名字或其他自定义的符号
例子: VA EQU 100 ;表达式为常数
NUM EQU VA+100 ;表达式为数值表达式
OPE EQU ADD ;表达式为指令助记符
伪指令: <符号名> = <常数表达式>
功能:定义所指符号常量所代表的常量的值
说明:“=”之后只能是常数,对于字符和字符串汇编时按照整数处理
例子: VA = 100
NUM = 3*100
NUM =VA+500
2)数值表达式
1> 算术表达式
+ - * / MOD
例如:2 MOD 5
2> 逻辑表达式
SHR、SHL、NOT、AND、OR、XOR
例如:A = 1001
A SHL 2 为0100
3> 关系表达式
EQ、NE、LT、LE(小于等于)、GT、GT
例如:NUM =50 则 NUM EQ 30 为 0
NUM GT 30 为 1
3)变量和符号
汇编中变量的属性有:BYTE、WORD、DWORD、QWORD(4字节)、TBYTE(10字节);Q:quad T:ten
变量定义:[<变量名>] 变量定义伪指令 <表达式>
伪指令主要为:DB、DW(1字)、DD(2个字)、DQ、DT 而在MASM 6.x以上汇编器中为BYTE、WORD、DWORD、QWORD(4字节)、TBYTE(10字节)
表达式为:常数、EQU或“=”定义的符号常量、各种类型表达式、“?”(不定义初始值只保留空间)、和DUP子句
例子:A DW 1234H ;A单元存放的是34H 而A+1单元存放的是12H
DUP子句定义:
<重复次数> DUP (<操作数1>……<操作数2>)
DW 20H DUP (0,0) ; 20H的十进制为32 定义空间大小为字 的32个单元,初始值为 (0,0)
BUFF DW 20H DUP (0,0) ; 定义BUFF为空间大小为字 的32个单元,初始值为 (0,0)
变量说明:
A DW X ; A字节存放变量X的偏移地址
A DD X ; A字节高位存放变量X的段地址,低位存放的是X的偏移地址
标号:标号也表示存储单元,只是这种存储单元存放的是机器指令代码,而变量存储数值
NEXT:MOV AL , [SI]
4)地址表达式
数值表达式的运算结果是一个数值常量,只有大小没有属性。
地址表达式一般为一个存储单元的地址或数值,汇编中存储单元有段地址、偏移地址和属性
1> 析值操作符
也称数值回送操作符或制止操作符,把存储单元地址一部分作为数值返回,相当于立即数,数值在汇编时由MASM自动计算出来。
主要的析值操作符及使用格式:
SEG/OFFSET/TYPE 变量或标号名
LENGTH/SIZE 变量名
(1)SEG: 返回变量所在段的段值
MOV AX,SEG NUM ;NUM所在段的起始地址存入AX
(2)OFFSET:返回变量或标号的偏移
MOV AX,SEG NUM ;NUM所在段的偏移地址存入AX
(3)TYPE:返回变量或标号的类型,类型用数值表示,常用的类型和对应的数值:
字节(BYTE) :1 字(WORD):2 双字(DWORD):4
近(NEAR): -1 远(FAR): -2
变量的类型值的对应类型的变量所占的字节数,标号的类型值没有实际的物理意义
(4)LENGTHOF:返回利用DUP定义的数组中元素的个数
如果没有使用DUP,返回1
如果嵌套使用DUP,返回最外层的重复数
(5)SIZEOF:返回利用DUP定义的数组占用的字节数,因此:
SIZEOF变量 = (LENGTH 变量)* (TYPE 变量)
2> 类型操作符
为了提高访问变量,标号和一般存储器操作数的灵活性,汇编语言提供了类型操作符,达到按指定属性访问的目的。
1)PTR
如在语句:MOV [SI] 1 中,无法确定给SI指向的存储单元中送字还是字节
MOV WORD PTR [SI] 1;指明字类型
MOV BYTE PTR [SI] 1 ;指明字节类型
PTR是最常用的合成操作符,用在地址表达式前,用于指定或临时改变变量和标号的类型。
格式: <类型> PTR <地址表达式>
类型可以是TYPE中的类型
2)THIS
THIS <类型>
功能:建立一个新的标号、变量或地址表达式的类型属性
该标号、变量或地址表达式的段地址和偏移地址是下一个能分配的存储单元的段地址和偏移地址
A EQU THIS BYTE
B DW 2235H ;A和B具有相同的段地址和偏移地址
二,常用的汇编伪指令
1)段定义伪指令
<段名> SEGMENT [ <定位类型>] [<组合类型>] [<类别>]
BUF DB 10 DUP(0)
MESS DB ‘Hello’,'$',0DAH,65H
<段名> ENDS
段的定义可以嵌套不能交叉
2)假定伪指令 ASSUME
格式: ASSUME <段寄存器>:<段名>[,<段寄存器>:<段名>]
功能: 指明 段寄存器和程序段 的对应关系
例如:ASSUME CS:CODE,DS:DATA ;CS寄存器对应CODE段,DS寄存器对应DATA段
伪指令不能给寄存器和附加寄存器赋值,需呀指令语句
3)置汇编地址计数器 ORG伪指令
格式:ORG <数值表达式>
功能:告诉汇编程序,本伪指令下面的内存变量从"数值表达式"所指定的偏移地址处开始分配内存;
汇编地址计数器的值可以用伪指令ORG设置
例子:
假设有如下定义,且变量WORD1的偏移量为0:
WORD1 DW 1234H ;offset = 0
BYTE1 DB 56H
WORD2 DW 0abcdH
ORG 1 ;设置$的值为1 其后的变量从偏移地址为1的内存地址开始分配内存
BYTE2 DB ?
WORD3 DW ?
BYTE3 DB ?
由于伪指令"ORG 1"的作用,其后面所定义的变量要从偏移地址为"1"的内存地址处开始分配内存;
4)符号名定义伪指令LABEL
格式:<变量名或符号> LABEL <类型> 其中,数据类型就是常用的数据类型:BYTE、WORD、DWORD、结构类型、记录类型、NEAR、FAR,等等;
功能:符号名定义伪指令LABEL与存储单元别名操作符THIS的功能类似,该伪指令定义一个指定的符号名,该符号名的段地址和段内偏移地址与下面紧跟着的一条变量定义语句中定义的变量的相应属性完全相同;但是该符号的类型是新指定的;前面5种类型是变量的类型,后面2种类型是标号的类型;如果格式中的"数据类型"是前面5种类型之一,那么,符号名就是变量名;如果格式中的"数据类型"是后面2中类型之一,那么,符号名就是标号名;
例如:
WBUFFER LABEL WORD ;
WBUFFER与BUFFER具有相同的段地址和段内偏移地址,但是它们的数据类型不同;
BUFFER DB 200 DUP(?)
NEXT1 LABEL FAR ;NEXT1与NEXT具有相同的段地址和段内偏移地址,但是,NEXT1是"远标号",NEXT是"近标号"
NEXT: MOV AX,BX
标号NEXT1和NEXT可用于不同的情况:当在同一个模块内部转移时,可使用近标号NEXT;当在不同的模块之间转移时,可使用远标号NEXT1;
5)源程序结束伪指令 END
格式:END <标号> ;如果远程序定义了标号,则END之后带标号
三,汇编程序上机过程
一个源程序必须至少包含一个 代码段和END伪指令。数据段、附加数据段和堆栈段由程序具体功能而定
1)开发环境
汇编语言的源程序需要编译和连接后才能在计算机上执行。
汇编语言源程序扩展名规定为.ASM。
用MASM编译源程序后,将产生源程序的目标程序文件,其扩展名为.OBJ。
再经过连接程序(LINK)把目标程序文件与库文件或其他目标文件连接在一起形成可执行文件(扩展名为.EXE)。
这时就可以运行该程序了。DOS下可直接键入可执行程序的文件名从而运行该程序。
2)上机过程
1> 编辑一个汇编语言源程序,可以使用各种文本编辑软件,如Windows记事本、MS-DOS自带的EDIT软件等。使用EDIT时可在DOS提示符下键入:
C:\MASM>EDIT 文件名.ASM(回车)
例子:下面给出一个汇编语言源程,它是求1+2+3+……+50的和并存入SUM单元中。其源程序文件为ex66.asm。
程序如下:
DATA SEGMENT ORG 100HSUM DW ? DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATASTART: MOV AX,DATAMOV DS,AXMOV CX,32HMOV BX,1MOV AX,0 LP: ADD AX,BX INC BXLOOP LPMOV SUM,AXMOV AH,4CHINT 21HCODE ENDSEND START
用户编写好上面程序后,在DOS下键入命令:
C:\MASM> EDIT EX66.ASM
进入编辑程序中输入上述程序并保存于磁盘(编辑与保存的方法请参见DOS操作系统中EDIT的使用)。
2> 汇编源程序
对汇编语言源程序进行汇编时,汇编程序对.ASM文件进行扫描,若源程序中有错,则结束汇编后,指出源程序中的错误。这时,可通过屏幕上提供的信息修改源程序(回到EDIT编辑状态),再经过汇编,直到得到无错误的目标程序。注意,目标程序的扩展名为.OBJ。
汇编命令的格式是:
C:\MASM>MASM 文件名(回车) 或 C:\MASM>MASM 文件名;(回车)
这里,MASM是存放汇编程序MASM.EXE的子目录。编译、连接和调试汇编程序时,要求在计算机上要装有MASM.EXE、LINK.EXE和DEBUG.EXE程序,可以将这些程序放入MASM子目录下。如果子目录不同,可以设置具体路径。下面就以程序EX66.ASM为例,对汇编过程作—个具体介绍。
首先键入: C:\MASM>MASM EX66(回车)
屏幕上将出现如下提示信息:
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981—1985,1987. All right sreserved,
Object filename[EX66.OBJ](回车)
Source listing [NUL.LST]:(回车)
Cross-reference[NUL.CRF]:(回车)
51610+437910 Bytes symbol space free
0 Warning Errors
0 Severe Errors
屏幕各行表示的含义如下:
Object filename[EX66.OBJ]:表示要求输入目标程序名,方括号里的内容是程序默认的文件名,如果不改变,可直接输入回车。
SourcelistingINUL.LST]:要求输入列表文件名,列表文件给出源程序和汇编后的机器语言程序清单,并给出符号表,这样便于程序的调试。方括号里缺省的内容是不建立该文件,如果认可,可直接输入回车。如果需要列表文件,可输入列表文件名(扩展名可以省略)。
Cross-reference[NUL.CRF]:要求输入索引文件名,方括号里的内容是不建立该文件,如果认可,可直接输入回车。如果需要索引文件,可输入索引文件名(扩展名可以省略)。:三个提示输入完毕,如果程序无误,则出现:
51610+437910Bytessymbolspacefree
0 Warning Errors
0 Severe Errors
表示汇编成功。在该目录下可以看到EX66.OBJ文件(使用DOS下的DIR命令)。
汇编时,不需要系统提示上述过程,在使用命令的:
C:\MASM>MASM 文件名;(回车)
如果源程序有语法错误,则汇编程序提示源程序有错,必须回到编辑源程序下,根据提示的错误信息重新修改源程错误,然后再进行汇编,直到汇编没有错误为止。
3> 连接程序
经过汇编产生的目标程序并不是可执行的程序,必须经过连接才可以执行。连接程序可以将若干个目标模块连同库子程序连接在一起,连接程序可以使用DOS下的LINK.EXE,具体的命令格式是在DOS提示符下键入:
C:\MASM>LINK文件名(回车)
C:\MASM>LINK文件名;(回车)
连接后,产生扩展名为.EXE的可执行文件。下面是E66.OBJ文件连接的具体过程:
首先键入:
C:LMASM>LINK EX66(回车)
屏幕上将出现如下提示信息:
Microsoft (R) OverlayLinker Version 3.60
Copyright (C) MicrosoftCorp 1983—1987. Allrightsreserved.
Run File[EX66.EXE]:(回车)
List File[NUL.MAP]:(回车)
Libraries [.LIB]:(回车)
其中:
Run Filel EX66.EXE]:要求输入可执行文件的名称,默认是EX66.EXE,一般采用默认文件名,直接回车。
List File[NUL.MAP]:表示是否要建立连接影像文件,若要建立,则输入文件名:若不建立,则直接按回车键。
Libraries[.LIB]:表示是否用到库文件,若不需要,则直接输入回车键。
连接时,不需要系统提示上述过程,使用命令:
C:\MASM>LINK 文件名;(回车)
4> 程序的执行
当建立了可执行文件后,就可以在DOS下输入该文件名,
C:LMASM>文件名(回车)
对于E21文件,可以键入:
C:\MASM>EX66(回车)
5> 调试程序
1. DEBUG操作命令
DEBUG主要命令格式、功能表
命 令 | 格 式 | 功 能 |
汇编 | A 地址 A | 从指定的地址开始进行汇编 从上次A命令结束位置开始汇编 |
显示内存单元内容 | D 地址 D 地址范围 D | 从指定地址开始显示地址单元内容 显示指定范围内存单元内容 从上次D命令结束的位置开始显示 |
修改内存单元内容 | E 地址 内容表 E 地址 | 用内容表中的内容代替指定地址开始的内容 显示和修改从指定地址开始的内容 |
运行 | G=地址 G G=地址,断点 | 从指定地址开始执行,直到结束 从当前位置开始执行,直到结束 从指定地址开始执行,直到断点结束 |
装入 | L[地址] | 把N命令给出的文件装入指定的开始地址或CS:100开始的内存区 |
文件名 | N 文件名 | 预先定义一个文件名,便于L命令装入该文件或W命令写入文件 |
退出 | Q | 结束DEBUG运行,退回DOS |
显示和修改寄存器 | R R 寄存器名 | 显示所有寄存器的内容 显示并修改指定寄存器的内容 |
跟踪 | T[=地址],[值] T | 从指定的地址开始,执行一条或数条指令 从当前位置开始执行一条指令 |
反汇编 | U=地址 U 地址范围 U | 从指定的地址开始反汇编成汇编语言源程序 把指定范围的机器指令反汇编成汇编语言源程序 从上次U命令结束位置开始反汇编直到满1页为止 |
写盘 | W | 把指定地址或CS:100开始的内存块(块字节长度由BX:CX指定)以N命令给出文件名写入磁盘 |
2.DEBUG应用举例
源程序已经以EX66.asm为文件名编辑存入磁盘,并进行汇编、链接通过无错误。其操作方法如下:
(1) 装入DEBUG和待调试的可执行程序
DEBUG EX66.EXE
或:DEBUG
-N EX66.EXE
-L
(2) 返汇编
-U
12B5:0000 B8B412 MOV AX,12B4
12B5:0003 8ED8 MOV DS,AX
12B5:0005 BB0100 MOV BX,0001
12B5:0008 B80000 MOV AX,0000
12B5:000B B93200 MOV CX,0032
12B5:000E 03C3 ADD AX,BX
12B5:0010 43 INC BX
12B5:0011 E2FB LOOP 000E
12B5:0013 A30000 MOV [0000],AX
12B5:0016 B44C MOV AH,4C
12B5:0018 CD21 INT 21
12B5:001A 8A4608 MOV AL,[BP+08]
12B5:001D 98 CBW
12B5:001E 50 PUSH AX
12B5:001F 8B4604 MOV AX,[BP+04]
注:上述反汇后的程序中,INT 21后的指令是内存中的随机代码指令,程序执行到MOV AH,4CH和INT 21H后并结束程序通回到DOS系统,不会继续执行后面随机代码指令;反汇编后,必须记下程序存放数据的数据段的段地址、源数据单元和结果单元的偏移量地址,如上例中,数据段段地址为12B4H,偏移量地址是0000H。
(3) 执行程序
-G
则屏幕显示:
Program terminated normally (表示程序运行正常结束)
(4)显示结果单元内容
例如,显上例72中结果单元的内容,则键入命令:
D 12B4:0000
则屏幕显示:
12B4:0000 FB 04 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
12B4:0010 B8 B4 12 8E D8 BB 01 00-B8 00 00 B9 32 00 03 C3 ............2...
12B4:0020 43 E2 FB A3 00 00 B4 4C-CD 21 8A 46 08 98 50 8B C......L.!.F..P.
12B4:0030 46 04 03 C6 50 E8 58 FF-83 C4 06 8B F8 83 FF FF F...P.X.........
12B4:0040 75 0C 8B 5E 04 8A 07 2A-E4 8B F8 2B FE 47 57 8B u..^...*...+.GW.
12B4:0050 46 04 03 C6 50 8D 46 81-50 E8 66 64 83 C4 06 8B F...P.F.P.fd....
12B4:0060 C7 88 46 80 8D 45 01 03-F0 8D 46 80 50 FF 56 06 ..F..E....F.P.V.
12B4:0070 83 C4 02 8B 5E 04 8A 07-2A E4 89 86 7A FF 3B C6 ....^...*...z.;.
从显示的结果可知,SUM字单元内容为04FBH。
(5)退出DEBUG
- Q