语句种类和格式 汇编语言有两种类型,一种是指令语句,另一种是伪指令语句。
指令语句有着与其对应的机器指令。
伪指令语句没有对应的机器指令
在宏汇编语言中,还有一种特殊的语句,称为宏指令语句。
在汇编语言中,不仅有各种类型的运算符,还有许多操作符。通过运算符、操作符及括号把常数和符号连起来就得到表达式。 表达可分为数值表达式和地址表达式。
数值表达式 数值表达式指的是在汇编过程中能够由汇编程序计算出数值的表达式,所以组成数值表达式的各部分必须在汇编时就能完全确定。
常数
十进制常数
十六进制常数
二进制常数
八进制常数
字符串常数(串常数)
总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ;程序名:masm16.asm ;功能:验证 masm16 的汇编指令 ;======================================== assume cs:code,ds:data data segment ;定义不同值的变量 data1 db 12H ;十六进制 data2 db 00101011B ;二进制 data3 db 12Q ;八进制 data4 db 'A' ;字符串 data ends code segment start: mov ax,data mov ds,ax ;传送常量 mov al,12H mov al,00101011B mov al,12Q mov al,'A' ;传送变量 mov al,data1 mov al,data2 mov al,data3 mov al,data4 ; mov ax,4c00h int 21h code ends end start
算数运算符
总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 ;程序名:masm16.asm ;功能:验证 masm16 的汇编指令 ;======================================== assume cs:code,ds:data data segment ;定义不同值的变量 data1 db 12H ;十六进制 data2 db 00101011B ;二进制 data3 db 12Q ;八进制 data4 db 'A' ;字符串 data ends code segment start: mov ax,data mov ds,ax ;传送常量 mov al,12H+2 mov al,00101011B-0BH mov al,12Q/2 mov al,('A'-21H)*2 ;传送变量 mov al,data1+2 mov al,data2-0BH ;错误变量在编译后表示内存地址,而在 ;8086汇编中修改内存地址只能使用加法和减法。 ;mov al,data3/2 ;mov al,(data4-21H)*2 mov ax,4c00h int 21h code ends end start
关系运算符
总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ;程序名:masm16.asm ;功能:验证 masm16 的汇编指令 ;======================================== assume cs:code,ds:data data segment ;关系比较符 data1 db 12H GT 1024H ;十六进制 data2 db 00101011B LT 30H ;二进制 data3 db 12Q NE 0 ;八进制 data4 db 'A' EQ 40H ;字符串 data ends code segment start: mov ax,data mov ds,ax ;传送变量 mov al,data1 mov al,data2 mov al,data3 mov al,data4 ; mov ax,4c00h int 21h code ends end start
关系不成立结果为0,关系成立结果为0FFFFH(-1)。不要理所当然的认为关系不成立结果为-1。
逻辑运算符 逻辑运算符包括按位操作的 “与”(AND)、”或”(OR)、”异或”(XOR)、”非”(NOT)、左移(SHL)、右移(SHR)。 例如:
总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ;程序名:masm16.asm ;功能:验证 masm16 的汇编指令 ;======================================== assume cs:code,ds:data code segment start: mov ax,1 shl 3 add cx,1024 shr 4 or al,3 and 47h and bl,not(7 or 54h) ; mov ax,4c00h int 21h code ends end start
逻辑运算符是伪指令,它是由汇编程序在编译时完成。
在数值表达式中使用操作符 汇编语言中有如下操作符可用在数值表达式中:HIGH、LOW、LENGTH、SIZE、OFFSET、SEG、TYPE、WIDTH 和 MASK 等。
HIGH
LOW
总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ;程序名:masm16.asm ;功能:验证 masm16 的汇编指令 ;======================================== assume cs:code code segment start: mov ax,HIGH (1234H + 5) mov ax,HIGH 1234H + 5 mov ax,LOW 1234H - 3 ; mov ax,4c00h int 21h code ends end start
运算符和操作符的优先级
地址表达式
变量和标号 变量和标号分别代表存储单元。变量表示的存储单元中存放的数值;标号表示的存储单元中存放的指令代码。
数据定义语句 一般格式如下:
[变量名] 数据定义符 表达式 [,表达式,…,表达式] ;注释
例如:
1 2 3 VARB DB 3 VARW DW -12345 DB 1
变量名是可选的,如果使用变量名,那么它就直接代表该语句所定义若干数据项中的第一项数据。各表达式间用逗号隔开。 例如:
变量名是一段数据的起始地址。数据段的第一个数据是ds:0
定义字节变量 定义一个字节大小的变量。定义字节变量的数据定义符是 db
1 2 3 count db 100 db 0DH,0AH,'$' table db 0,1,4,9,16
定义字变量 每个变量可存储两个字节。定义字变量的数据定义符是 dw 例如:
1 2 3 flag dw 2FCDH,1024,-1 VECT dw 0 dw 2047
定义双字变量 每一双字变量占四字节存储单元。定义双字变量数据定义符 dd 例如:
1 2 vector dd 4 far ptr dd 12345678H,0
定义未初始化变量 变量定义时使用问号(?),表示这是一个未初始化的变量。 例如:
1 2 3 inbufff db 5,?,?,8,? varw dw ? oldv dd ?
定义字符串 定义字节数据伪指令 db 也可方便用于定义字符串。字符串要用引号括起来,单引号和双引号都可以。 例如:
1 2 3 MESS1 db 'hello!' 相同于 MESS1 db 'H','E','L','L','O','!'
用引号把字符串括起来,要比把每一个字符用引号括起来方便
1 MESS2 db "How are you ?",0DH,0AH,24H
在定义变量数据时,需要注意 “字” 和 “双字”大小的变量,在内存中是小端存储(即 “高高低低” 原则)
1 2 3 varb db 12h varw dw 1234h vard dd 12345678h
定义其他类型的变量 定义 8 字节数据变量,使用定义符是 DQ,定义 10 字节数据变量,定义符是 DT 。 例如:
重复操作符 DUP 有时需要定义数组,有时还需要定义数据缓冲区。为此,汇编语言提供了重复操作符 DUP 。 例如:
1 buffer db 8 dup(0) ;定义由8个字节组成的缓冲区,每个字节的初始值为0。
总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 ;程序名:masm16.asm ;功能:验证 masm16 的汇编指令 ;======================================== assume cs:code,ds:data data segment VARB DB 3 VARW DW -12345 DB 1 BUFF DB 100, 3+4, 5*6 MESS1 db 'hello!' MESS2 dd 12345678h MESS3 DT 1234H MESS4 DQ 1234H MESS5 db 8 dup(12H) data ends code segment start: mov ax,data mov ds,ax xor ax,ax xor bx,bx ;变量名的本质 mov al,VARB mov bl,ds:0 mov ax,VARW mov bx,ds:1 ; mov ax,4c00h int 21h code ends end start
变量和标号 变量表示内存单元,这种内存单元中存放的数值。标号也表示内存单元,这种内存单元中存放的是机器指令。
变量和标号的属性 变量和标号具有如下三种属性:
段值:变量或标号对应的内存单元所在段的段值。
偏移,变量或标号对一个存储单元的起始地址的段内偏移。
类型,变量的类型主要是 BYTE(字节)、WORD(字)和 DWORD(双字); 标号类型主要是 NEAR(近)、far(远)。近:表示段内标号,远,表示段间标号。
析值操作符
操作符 SEG 返回变量或标号所在段的段值 例如:
1 2 mov ax,SEG VARW mov ds,ax
操作符 OFFSET 返回变量或标号的偏移 例如:
1 2 3 mov bx,OFFSET VARW add di,OFFSTE VARW+2 mov si,OFFSET VARB
lea 是汇编指令,由对应的硬编码。OFFSET 是伪指令,由编译器解析。
操作符 TYPE 返回变量或标号的类型,类型用数值表示。
常见的类型和对应的数值如下: BYTE 1 WORD 2 DWORD 4 NEAR -1 FAR -2
变量的类型值是对应类型的变量所占用的字节数,而标号的类型值却没有实际的物理意义。
操作符 LENGTH 返回利用 DUP 定义的数组中元素的个数。如果变量定义语句中没有 DUP,则返回 1。 如果嵌套使用 DUP 则返回最外层的重复数。 例如:
1 2 3 mov cx,LENGTH VARW mov cx,LENGTH BUFF mov cx,LENGTH MESS
操作符 SIZE 返回用 DUP 定义的数组占用的字节数,可按下式计算: SIZE 变量 = (LENGTH 变量) * (TYPE 变量) 例如:
1 2 3 mov cx,SIZE VARW mov cx,SIZE BUFF mov cx,SIZE MESS
属性操作符
操作符 PTR
mov [si],1
是错误的指令,因为指针寄存器所指的存储器操作数的类型,即要访问的存储器操作数是字节类型还是字类型。
程序员要在源程序中明确指明,要访问的存储器操作数是字节类型还是字类型。这可利用 PTR 操作符来指明。
1 2 mov word ptr [si],1 mov byte ptr [si],1
ptr 是最常用的合成操作符,用在地址表达式前,用于指定或临时改变变量和标号的类型。 一般格如下:
类型 ptr 地址表达式
其中,类型可以是 BYTE、WORD、DWORD、NEAR 和 FAR。无论地址表达式的类型是什么,当前均以 ptr 前面的类型为准。
操作符 THIS 操作符 THIS 的一般格式如下:
THIS 类型
其中类型可以是 BYTE、WORD、DWORD、NEAR 和 FAR 等。它会返回一个具有指定类型的存储器操作数。
操作符 THIS 一般使用在符号定义语句中,从而定义一个具有类型、段值和偏移三属性的表示存储器操作数的符号。 例如:
1 2 MY_BYTE EQU THIS BYTE MY_WORD DW ?
总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 ;程序名:masm16.asm ;功能:验证 masm16 的汇编指令 ;======================================== assume cs:code,ds:data data segment VARB DB 3 VARW DW -12345 DB 1 BUFF DB 100, 3+4, 5*6 MESS1 db 'hello!' MESS2 dd 12345678h MESS3 DT 1234H MESS4 DQ 1234H MESS5 db 8 dup(12H) MY_BYTE EQU THIS BYTE MY_BYTE1 db ? data ends code segment start: ;SEG 获取变量所在的段值 mov ax, SEG VARB mov ds,ax ; mov bx,offset VARW add di,offset VARW+2 ; mov ax,TYPE VARW mov ax,LENGTH MESS4 mov ax,LENGTH MESS5 mov bx,size VARB mov bx,size MESS5 ; mov al,byte ptr VARW mov bx,word ptr BUFF ;mov ax,MY_BYTE ;报错数据类型不匹配 mov al,MY_BYTE ; mov ax,4c00h int 21h code ends end start
常用伪指令语句和源程序组织 符号定义语句 通过符号定义语句,可把常数、表达式等用符号来表示。恰当地使用符号定义语句,不仅可大大方便程序的书写和阅读,对程序的调试和修改很有利。
等价语句 EQU 等价语句的一般格式如下:
符号名 EQU 表达式
用符号来代表常数或数值表达式。
1 2 3 4 5 COUNT EQU 100 BUFF_LEN EQU 4*COUNT LTX EQU 1 RDX EQU LTX+50 INBUFFER DB COUNT,?,COUNT DUP(?)
用符号表示一个字符串。可用一个简短的符号表示一个复杂的字符串,以后当汇编程序遇到所定义的符号时,就用字符串代替。 例如:
1 HELLO EQU "How are you !"
重新定义关键字或指令助记符。即给汇编怨言的关键字或指令助记符起一个别名。 例如:
1 2 MOVE EQU MOV COUNT EQU CX
安排上述语句后,可用 MOVE 代替指令助记符 MOV,用 COUNT 代表寄存器 CX 。
例如:
1 2 MOVE AX,CX MOV COUNT,100
伪代码THIS,为伪代码紧接着的变量声明一个别名,并自定义分配类型。 例如:1 2 3 4 5 VARW EQU THIS WORD VARB DB 2 DUP(0) FLAG DW ? FALG1 EQU BYTE PTR FLAG FLAG2 EQU BYTE PTR FLAG+1
在这之后可使用这些符号 例如:1 2 3 MOV AX,VARW MOV AL,FLAG1 MOV FLAG2,AL
可自定义类型BYTE、WORD、DWORD、NEAR和FAR。伪代码THIS仅有改变数据类型的作用,并不会为这个别名分配存储单元。
总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 ;程序名:masm16.asm ;功能:验证 masm16 的汇编指令 ;======================================== assume cs:code,ds:data data segment COUNT EQU 100 BUFF_LEN EQU 4*COUNT LTX EQU 1 RDX EQU LTX+50 INBUFFER DB COUNT,?,COUNT DUP(?) ; HELLO EQU "How are you !" ; MOVE EQU MOV COUNTS EQU CX ; VARW EQU THIS WORD VARB DB 2 DUP(0) FLAG DW ? FLAG1 EQU BYTE PTR FLAG FLAG2 EQU BYTE PTR FLAG+1 data ends code segment start: mov ax,data mov ds,ax ; move ax,COUNT move ax,BUFF_LEN move COUNTS,RDX MOV AX,VARW MOV AL,FLAG1 MOV FLAG2,AL ; mov ax,4c00h int 21h code ends end start
等号语句(=) 汇编语言还专门提供了等号语句来定义符号常量,即用符号表示一个常量。 等号语句一般格式如下:
符号名 = 数值表达式
例如:
数值表达式中不能含有向前引用的符号名称。用等号语句定义的符号可被重定义。 例如:
1 2 3 ABCD = 1 ABCD = 100 ABCD = 2 * ABCD +1
定义符号名 定义符号名的一般格式:
其中类型可以是 BYTE、WORD、DWORD、NEAR 和 FAR 等。 该语句的功能是为LABLE伪指令,下面紧接着的变量声明别名,属性都一样除了类型可以自定义。 例如:
1 2 BUFFER LABEL WORD BUFF DB 100 dup(0)
LABLE伪指令声明的标号,不会为其分配存储空间
再如:
1 2 QUIT LABEL FAR EXIT: MOV AH,4CH
这样指令 “MOV AH,4CH” 就有了两个标号QUIT和EXIT,但它们的类型不同。
总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 ;程序名:masm16.asm ;功能:验证 masm16 的汇编指令 ;======================================== assume cs:code,ds:data data segment XX = 10 YY = 20+300/4 ABCD = 1 ABCD = 100 ABCD = 2 * ABCD + 1 BUFFER LABEL WORD BUFF DB 10 dup(0CCH) data ends code segment start: mov ax,data mov ds,ax ;相当于这条汇编指令,定义了两个不同属性的标号。 QUIT LABEL FAR EXIT: MOV AH,4CH ; mov ax,offset BUFF mov ch,BUFF mov bx,offset BUFFER mov dx,BUFFER ; call QUIT call far ptr EXIT int 21h mov ax,4c00h int 21h code ends end start
LABEL 不仅可以用在数据段的变量,还可用在代码段的标号。
段定义语句 为了与存储器的分段结构相对应,汇编与越南的源程序也由若干个段组成。段定义语句就是用来按段组织程序和利用存储器的。
段的开始和结束 段定义的一般格式:
1 2 3 段名 segment [定位类型] [组合类型] ['类别'] ........ 段名 ENDS
段使用设定语句 汇编程序根据段开始语句和段结束语句判断出源程序的划分,为了有效地产生目标代码,汇编程序还要来哦姐各程序段与段寄存器地对应关系。段寄存器与程序段的对应关系由段使用设定语句说明。 段使用设定语句格式如下:
assume 段寄存器名:段名[,段寄存器名:段名,….]
段寄存器名可以是 CS、DS、SS 和 ES。段名可任意定义,一般使用固定且有意义的段名,如code、data、stack等等。 assume 伪指令中的段名也可以是特别关键字nothing,它表示某个段寄存器不再与任何段有对应关系。
总结 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ;程序名:masm16.asm ;功能:验证 masm16 的汇编指令 ;======================================== data1 segment XXX dw 1 YYY dw 2 data1 ends data2 segment BBB dw 3 CCC dw 4 data2 ends code segment assume cs:code,ds:data1,es:data2 start: mov ax,data1 mov ds,ax mov ax,data2 mov es,ax ; mov ax,XXX assume ds:data2,es:nothing mov ax,data2 mov ds,ax mov ax,XXX mov ax,4c00h int 21h code ends end start
ORG语句 汇编程序在对源程序汇编的过程中,使用地址计数器来把偶你当前正在汇编的指令或者变量的偏移地址。通常情况下偏移地址是逐步增减的,但是程序员可以只用ORG 语句调整当前的偏移地址。 ORG 语句格式如下:
ORG 数值表达式
总结 1 2 3 4 5 6 7 8 9 10 11 12 13 ;程序名:masm16.asm ;功能:验证 masm16 的汇编指令 ;======================================== assume cs:code code segment ORG 100H start: mov ax,1234h mov ax,4c00h int 21h code ends end start
$ 符号 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ;程序名:masm16.asm ;功能:验证 masm16 的汇编指令 ;======================================== assume cs:code,ds:data data segment string db 'hello!' len = $-string data ends code segment ORG 100H start: mov ax,1234h jmp $+9 org $+4 mov ax,2 mov ax,len mov ax,4 mov ax,4c00h int 21h code ends end start
$ 表示当前数据所在的偏移地址,可以用在代码段和数据段。
第一个完整的源程序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 ;程序名:T3-1.ASM ;功能:显示信息"HELLO" ;======================== assume cs:code,ds:data,ss:sseg sseg segment dw 256 dup(?) sseg ends ;--------------------------------- val1 equ 1 val2 equ 2 val3 equ 3 data segment mess db 'HELLO',0dh,0ah,'$' BUFF db 1,2,3,10 dup(0) data ends code segment start: ;mov ax,data mov ax,seg mess mov ds,ax; mov al,LENGTH BUFF mov al,val1*val2/val3 mov ax,1234h GT 1024h mov ax,high(1234h+5) mov ax,high 1234h+5 mov ax,low 1234h-3 ;设数据段寄存器 L1: mov dx,offset mess mov ah,9 ;显示信息 "HELLO" int 21h mov ax,4c00h int 21h code ends