第二章 汇编语言与汇编程序
§ 2.1 机器语言与汇编语言一,机器语言 —— 机器只能识别二进制编码
机器指令 —— 机器能直接执行的一组二进制代码
(命令 )——该二进制代码称为 机器码 (Machine
Code).
如,40H?INC AX 01D8H?ADD AX,BX
指令通常由两部分组成,操作码和操作数
操作码 —— 该指令的功能,即执行什么操作。
操作数 —— 指令 操作对象,指明参加操作的数或操作数的地址。
机器指令的集合?机器语言?用机器语言编写的程序
机器语言程序二,汇编语言机器语言编写程序烦琐,难记忆,不易理解,
易出错。用一些 助记符 来表示指令的操作码,
操作数亦用一些 符号 来表示?符号指令 。
如上,40H?INC AX 01D8H?ADD AX,BX
符号指令与机器指令一一对应。
符号指令的集合?符号语言,又称 汇编语言?用汇编语言编写的程序?汇编语言程序?不能由计算机直接执行,
必须将它翻译成机器语言程序?翻译过程称 汇编?翻译程序为 汇编程序 。
汇编语言源 程序?汇编? 目标程序三、宏 汇编 程序?MASM
允许把一串指令定义为一条宏指令,有宏汇编功能。
如 MASM?系统程序 。宏汇编语言有三类基本指令:符号指令,伪指令,宏指令。
§ 2.2 常用伪指令与常用算符
每一种计算机语言都规定了自己的 符号系统及语法规则 。汇编语言也是如此,除符号指令外,还必须正确使用各种符号。汇编中的各种符号由 伪指令定义,或为汇编的 保留字。
一、汇编语言源程序结构 ——单模块程序结构
参见教材 P,60
一般 程序由三个段组成。教材中程序的小写字母部分均为 程序结构。
STACK SEGMENT STACK
DW 32 DUP(?)
STACK ENDS
DATA SEGMENT
:
DATA ENDS
CODE SEGMENT
BEGIN PROC FAR
ASSUME CS,CODE,SS,STACK,DS,DATA
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATA
MOV DS,AX
:
RET
BEGIN ENDP
CODE ENDS
END BEGIN
定义堆栈段及堆栈长度定义数据段定义代码段将汇编源程序视为 DOS下的子程序将程序段前缀 PSP进栈设置用户数据段返回到 PSP,执行 PSP中的第一条指令
INT 20H,结束程序返回调用程序
因为连接程序为每一个用户程序建立了一个程序段前缀 PSP,在 PSP的开始处安排了一条
INT 20H指令,执行该指令结束当前程序返回调用程序。
而 PSP的地址,其段地址寄存在 DS和 ES中;
偏移地址为 0,将 DS,0000地址进栈,即 PSP
地址进栈。
PSP的长度为 256个字节,即 100H个单元,
主要存放了装入程序与 DOS连接的信息。
结束用户程序返回 DOS有两种方法:
其一,MOV AH,4CH ;返回 DOS
INT 21H
其二,INT 20H ;返回调用程序,便于调试它的机器码是 CD20H,当用 DEBUG调用 EXE
文件时,在 DS,0000单元中便可看到该指令。
DOS在转移控制权时,将 CS指向 EXE程序的代码段,SS指向堆栈段,但 DS和 ES
并不指向用户程序的数据段和附加数据段,而是 指向 PSP。
二,常用伪指令 (P58)
伪指令不产生机器代码,CPU也不会产生某种操作,
它主要告诉汇编程序哪些是数据,哪些是指令,符号约定,程序从何处开始,何处结束,即为汇编控制命令。
伪指令很多,下面主要介绍段定义,过程定义。
1、段定义伪指令?定义一个存储段,一个程序模块可由若干段组成。
格式:
〈 段名 〉 SEGMENT [定位方式 ][组合方式 ][‘类别名’ ]
…… 伪指令或指令
〈 段名 〉 ENDS
功能,定义一个以“段名”为名称的存储段。
定位方式,组合方式,‘类别名’?赋给段名的属性,三个可选项主要用于多模块化程序设计,
以告诉 LINK程序各模块间段如何定位,段与段如何组合,还可连接在一起。一般单模块程序可省略。
段名?给段取名,用来指出汇编程序为该段分配的存储区的起始地址,即 段地址,为一常数,用 SEG运算符取得。
定位方式?相邻两段间应如何衔接,即对该段的起始地址所提出的要求。定位方式有四种选择:
( 1) [PARA](节)?规定段的起始地址总是 16的整数倍,即低四位为零,省略时,系统隐含为此方式,
教材中均默认为 PARA方式 。
( 2) WORD (字)?规定段的起始地址总是 2的整数倍,即低 1位为零。
(3) Byte(字节)?规定段的起始地址总是 1的整数倍,即能 被 1整除,任何地址可为段地址,
不留空隙。
( 4) Page( 页)?规定段的起始地址总是 256的整数倍,即低 8位为零。
组合方式 ——提供本段同其他段的组合关系,有 6种选择方式 。
( 1) [NONE]不选择?表示本段与其他逻辑上不发生关系,尽管物理上可能相邻,但每段都有自己的段首址。 系统隐含该组合方式,单模块程序,各段之间不发生关系,采用不选择方式,
教材中多数例题的数据段,代码段均为不选择方式。
( 2) PUBLIC公共?将同段名,同类别名的段顺序相拼,是否留有空隙取决与定位方式。
( 3) STACK堆栈?将同段名,同类名的段顺序 相拼,
不留空隙,长度相加,构成堆栈段。一个程序模块中至少有一个段为 STACK组合方式的段 。
( 4) COMMON公用?将同名段,同类别名的段相互覆盖,长度取决于最长的段。
( 5) AT表达式?段地址为表达式的值。
( 6) MEMORY?表示将本段定位在其他段的上面
(即最高地址)。
类别名?用单引号括起来的字符串,连接时将同类别名的所有段(段名可不同)存放在连续的存储区。单模块程序可省略类别名。
2,假定伪指令格式,ASSUME〈 段寄存器:段名 〉,……
功能:告诉汇编程序各段名与段寄存器的对应关系,一般在代码段中。
因为,存储器分段管理,程序中的存储单元用逻辑地址的偏移地址来寻址,而段地址一般默认,
所以,代码段一开始就要对段 寄存器与段之间的关系做假定。
3、源程序结束伪指令格式,END [表达式 ]
功能:源程序的最后一个语句,标志整个程序结束,即告诉汇编程序,汇编到此结束。
表达式?为可选项,必须是存储器地址,即程序的启动地址,常为标号。
不带表达式的 END结束的模块不能单独运行,
为子模快。
4、子程序定义伪指令格式,〈 子程序名 〉 PROC [NEAR]或 FAR
:
RET
〈 子程序名 〉 ENDP
PROC…… ENDP必须配对使用。
子程序名有标号属性,一般段内调用为 NEAR或省略,
段间调用为 FAR。
RET为子程序返回指令,返回调用主程序:
段内,[SP] ↑ →IP,SP+2 →SP
段间,[SP] ↑ →IP,[SP+2] ↑ →cs,SP+4→SP
STACK SEGMENT STACK
DW 32 DUP(?)
STACK ENDS
DATA SEGMENT
:
DATA ENDS
CODE SEGMENT
BEGIN PROC FAR
ASSUME CS,CODE,SS,STACK,DS,DATA
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATA
MOV DS,AX
:
RET
BEGIN ENDP
CODE ENDS
END BEGIN
定义堆栈段及堆栈长度定义数据段定义代码段将汇编源程序视为 DOS下的子程序将程序段前缀 PSP进栈设置用户数据段返回到 PSP,执行 PSP中的第一条指令
INT 20H,结束程序返回调用程序
STACK SEGMENT STACK
DW 32 DUP(?)
STACK ENDS
DATA SEGMENT
:
DATA ENDS
CODE SEGMENT
BEGIN PROC FAR
ASSUME CS,CODE,SS,STACK,DS,DATA
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATA
MOV DS,AX
:
RET
BEGIN ENDP
CODE ENDS
END BEGIN
例、两个数据交换。
DT1 DB 11H
DT2 DB 22H
MOV AL,DT1
MOV AH,DT2
MOV DT1,AH
MOV DT2,AL
STACK SEGMENT STACK
DW 32 DUP(?)
STACK ENDS
DATA SEGMENT
DATA ENDS
CODE SEGMENT
BEGIN PROC FAR
ASSUME CS,CODE,SS,STACK,DS,DATA
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATA
MOV DS,AX
:
RET
BEGIN ENDP
CODE ENDS
END BEGIN
上机调试作业,
如,P32,17.
MOV AX,1122H
MOV BX,3344H
MOV CX,5566H
PUSH AX
PUSH BX
PUSH CX
POP BX
POP AX
POP DX
三、常量( P34)
1、常量 —常数和符号常量 —主要给变量赋初值或指令中立即数等。
常数 —汇编中允许的常数有 二进制,十进制,十六进制,字符串 ( ASCII码字符,
用单引号表示,如:’ ABC’)。
符号常量 —程序中可以给常数取名。
用 EQU或,=,伪指令定义。
格式,〈 标识符 〉 EQU〈 表达式 〉 → 数值表达式
〈 标识符 〉 = 〈 表达式 〉
例,AA EQU 10
BB EQU 2*AA+3
CC = 66
MOV AX,AA ; AX=10
MOV AX,BB ; AX=23
MOV AX,CC ; AX=66
注,AA,BB,CC为立即数。
2,数值表达式 —由 常量与运算符组成的有意义的式子,结果为数值。
在 MASM中允许对常量进行三种类型的运算:
( 1)算术运算 —+,-,*,/,MOD(求余),
SHR(右移),SHL(左移)
如,AA EQU 10,
则表达式 → AA * 3+ 2 →32,可以作为操作数。
( 2)逻辑运算 —AND,OR,XOR,NOT,按位运算。
· 注意,将运算符与指令相区别。
例,X EQU 0FFFFH
MOV AX,5555H
AND AX,X AND 0FFH; AX=0055H
( 3)关系运算 —EQ(=),NE( ≠),LT(<),
GT(>),LE( ≤),GE( ≥)
关系运算的结果为两个特殊常量 0FFFFH
( TURE),0( FALSE)。
四,变量( P34) —变量是存储器中的 数据或数据区的符号地址表示,即给存储单元取名。
1、变量的三个属性 —∵ 存储器分段,变量有 三个属性。
( 1) 段属性 —定义变量所在段的段首地址(一般为
DS)。
( 2) 偏移地址 —变量偏离段首址的字节数,即段首址到变量定义语句的字节距离。
( 3) 类型属性 —存取该变量中的数据所需要的字节数。
类型,字节,字,双字,四字,十字节 类型,
一个数据分别占 1,2,4,8,10个单元,其类型由定义的伪指令确定。
2,变量的定义 —一般在数据段或附加数据段中用伪指令定义。
格式:
〈 变量名 〉 DB〈 表达式 〉 ;定义 BYTE字节变量
〈 变量名 〉 DW〈 表达式 〉 ;定义 WORD字变量
〈 变量名 〉 DD〈 表达式 〉 ;定义 DWORD双字变量
〈 变量名 〉 DQ〈 表达式 〉 ;定义 QWORD四字变量
〈 变量名 〉 DT〈 表达式 〉 ;定义 TBYTE十字节变量
EQU伪指令不分配存储单元,但变量定义伪指令要分配存储单元。
表达式确定了变量的 初值 。
· 表达式可以有以下几种形式:
( 1)常量或数值表达式?存入数值。
( 2) ASCII字符串(若串长 ≥2,只能用 DB定义,)
存入 ASCII码值。
( 3)?分配一个空单元,无确定值。
( 4)重复子句,格式,N DUP( 〈 表达式 〉 )?重复 N次,其值由表达式确定。
( 5)地址表达式 → 由常量,变量,标号,间址寄存器( [BP],[BX],[SI],[DI])的内容和运算符等组成有意义的式子。如一个变量名就是一个地址表达式。
可用 DW或 DD定义,若用 DW则取它的偏移地址来初始化变量;若用 DD则其偏移地址和段地址来初始化其变量。
若有多个表达式,用逗号分隔。
例,DATA SEGMENT ;段定义
DT1 DB 10,3*20
DT2 DB ’ ABC’,44H,45H
DT3 DW 100H,- 5
DT4 DD 0FFFFH
DT5 DB 0,?,?,?,0
AA EQU $- DT1; $—汇编地址计数器,
记录当前汇编地址为 14H。
DT6 DB 2 DUP( 0,2 DUP( 2,3))
DT7 DW DT2
DT8 DD DT4
DATA ENDS
存放示意:
DT1 DT2 DT3 DT4
0A 3C 41 42 43 44 45 00 01 FB FF FF FF 00 00
DT5 DT6
00 XX XX XX 00 00 02 03 02 03 00 02 03 02 03
DT7 DT8
02 00 0B 00 DATAL DATAH
从变量中取数据属于直接寻址方式,注意与符号常量区别。
例,MOV AX,AA ;立即寻址,AX=0014H
MOV AX,DT3 ;直接寻址,AX=0100H
MOV AL,DT2+2 ; AL=43H
变量一旦定义,则有类型,指令中类型一致例,MOV AX,DT1 ╳
MOV BL,DT3 ╳
注意区分变量的值与偏移地址:
变量名 偏移地址 变量的值
DT1 0000H 0AH
DT2 0002H 41H
DT3 0007H 0100H
DT4 000BH 0000FFFFH
偏移地址是 16位无符号数
在符号指令中的基址,变址,基址加变址三种寻址中,其 偏移量可以是常数,或符号常量,还可以是变量名 。若是变量名,它给出变量所在段的偏移地址,其意义是 取变量单元中的数据,所以其类型要与另一操作的类型一致。
例,MOV BX,0
MOV AX,DT3[BX] ; AX=0100H
MOV AL,DT3[BX] ╳
常以间址、基址、变址访问一片连续的单元 。
例,LEA BX,DT2 ; BX= 0002H
MOV AL,[BX] ; AL= 41H
MOV AL,[BX+ 1] ; AL= 42H
五,标号?存放某 指令的符号地址,也可以是过程名(过程地址入口)
注:变量?是存放 数据的符号地址。
1,标号的 三个属性
( 1) 段属性 —定义该标号所在段的段首址。
( 2) 偏移地址 —标号偏离段首址的字节数。
( 3) 类型 —两种,NEAR—段内,FAR—跨段
2,标号的定义
( 1)书写在指令前,用:定义,只能为 NEAR
NEXT,MOV AL,[SI] ;定义近标 号 NEXT
( 2)用 PROC…ENDP 伪指令定义过程名例,ABC PROC FAR;定义过程名 ABC为远标号
DEF PROC [NEAR];定义过程名 DEF为近标号六,变量,标号属性运算符前面已知由变量,标号,常量,寄存器内容和运算符组成的式子?地址表达式,它们的结果是地址,所以仍有属性,运算符除可以使用数值表达式的运算符外,
还有一些特别的(最常用)符号。
1,类型运算符 PTR( P36)
格式,〈 类型 〉 PTR〈 地址表达式 〉
类型 → BYTE,WORD,DWORD,NEAR,FAR
五种。
作用?指明表达式的类型,不管他原来有无类型,
均以 PTR前的类型为准。
只改变类型属性,不改变段属性和偏移地址属性。
例 1,DTA DB 33H,44H
MOV AX,DTA ╳
→ MOV AX,WORD PTR DTA √
表示临时改变 DTA为字类型。
例 2,MOV 4[SI],55H ╳
MOV BYTE PTR 4[SI],55H √
INC [BX] ╳
INC WORD PTR [BX] √
明确操作数类型。
例 3,A DW 1122H,3344H; 变量 A为字类型
B EQU BYTE PTR A; 变量 B字节单元
将同一存储单元用不同类型的变量(或标号)
来表示。
如,MOV AX,A
MOV AL,B
执行结果均是,AL= 22H
例 4,NEXT,MOV AX,0 ;定义 NEXT近标号
……
JMP FAR PTR NEXT
临时改变标号的类型为 FAR。
2,跨段前缀符,即跨段或段超越格式,〈 段寄存器名 〉,〈 地址表达式 〉
作用?用来临时改变变量,标号,地址表达式或指定的段属性,且只在所出现的语句中有效,不改变偏移地址和类型。
例,MOV AX,[BP] ;( SS,[BP]) → AX
MOV AX,DS,[BP] ;( DS,[BP]) → AX
3,取段地址算符 SEG?取变量或标号的段地址。
例,MOV AX,SEG DT1 ;取 DT1的段首址
→ AX,段首址为常数,因此立即寻址。
4,取偏移地址算符 OFFSET?取变量或标号的偏移地址。
例,MOV BX,OFFSET DT1 ;取变量 DT1的偏移地址 → BX,立即寻址。
等效,LEA BX,DT1 ;但为直接寻址。
作业,P72,10.
§ 2.3 符号指令的寻址方式一条符号指令,由操作码 (助记符 )指明进行什么样的操作,操作数告之操作的对象,操作数可以放在寄存器或存储单元中,寻找操作数 (地址 )的方式 ——寻址方式。
一、立即寻址 —— 操作数直接放在符号指令中 。
例,MOV AX,2000H ; AX=2000H
助记符 目的 源操作数注:立即数可以是 8位或 16位,负数用补码表示 。
例,MOV BL,- 1; BL=0FFH
MOV CX,- 5; CX=0FFFBH
立即寻址方式主要用来给寄存器或存储单元赋初值,也可以与寄存器或单元进行算术逻辑运算。
因为直接书写在指令中,操作对象直观,清晰,所以常用。
二,寄存器寻址 —— 操作数在指定的寄存器中例,MOV CX,BX ; CX=BX
寄存器可以是 8位或 16位的寄存器。
例,MOV CL,BH ; CL=BH
因为寄存器在 CPU内部,所以采用寄存器寻址可提高运行效率,特别是 AX,用它存放运算结果,则执行指令的时间短些,所以最常用。
三,直接寻址 —— 操作数在内存中,其偏移地址由指令直接给出。
而操作数一般在 DS段 (默认 )。
例,MOV AX,DS:2000H
或 MOV AX,[2000H]; (DS:2000H)?AX
偏移地址,又称 有效地址,此处源操作的 EA=2000H
若偏移地址是数值常量,则应在偏移地址前加段名。
区分立即数与直接寻址。
直接寻址常用已定义的变量表示 。
例,VARX DW 1122H,4455H
VARY DB 33H
MOV AX,VARX; AX=1122H
MOV BX,VARX+ 2 ; BX= 4455H
MOV BL,VARY; BL=33H
MOV VARY+1,AL; (VARY+1)=22H
四,寄存器间接寻址 —— 操作数在内存中,而操作数的地址的 16位偏移量包含 在 SI,DI,BX,BP
之一中,即寄存器的内容为操作数的 EA.
[SI]
[DI]
EA= [BX]
[BP]
1,若以 SI,DI,BX 间址,操作数在 DS段。
例,MOV AX,[SI] ; (DS:[SI])?AX,
即 (DS:[SI])?AL,(DS:[SI+1])?AH
2.若以 BP间址,操作数在 SS段 。
例,MOV AX,[BP] ; (SS:[BP])?AL,(SS:[BP+1])?AH
只有 SI,DI,BX,BP 可作为间址寄存器,如
MOV AX,[CX] ╳
间址时,寄存器的内容是有效地址,所以称为 地址指针,主要用于存取存储单元中的数据,只要修改寄存器内容,用一条指令便可访问一片连续单元。
如,INC SI
五,基址寻址 —— 操作数在存储器中,但操作数的 地址的偏移地址 在 BX或 BP中的内容与指令中给出的 8位或 16位位移量之和。
[BX] 8位或 16位
EA= [BP] + 位移量
1.若以 BX为基址,操作数在 DS段例,MOV BL,2[BX]
或 MOV BL,[BX+2] ; (DS:[BX+2])?BL
2,若以 BP为基址,操作数在 SS段例,MOV BX,6[BP]
或 MOV BX,[BP+6] ; (SS:[BP+6])?BL,
(SS:[BP+7])?BH
所以 BX,BP 称为基址寄存器。
六,变址寻址 —— 操作数在存储器中,但 操作数的偏移地址为 SI或 DI的内容与指令中给定的 8位或 16位位移量之和,与基址寻址类似。
[SI] 8位或 16位
EA= [DI] + 位移量例,MOV AX,- 2[SI]
或 MOV AX,[SI- 2] ; (DS:[SI- 2]) →AL,
(DS:[SI- 1]) →AH
操作数在 DS段,可用于变址的寄存器只能是 SI,DI,
所以称变址寄存器。
七,基址加变址寻址 —— 操作数在存储器中,但操作数的偏移地址 是指令中指定的基址寄存器的内容,
变址 寄存器内容及位移量之和,即前两种方式的组合。
[BX] [DI] 8位或 16
EA= [BP] + [SI] + 位移量例,MOV AX,4[BX][DI]
或 MOV AX,[BX+DI+4]; (DS:[BX+DI+4])? AL (DS:[BX+DI+5]) →AH
以 BX为基址寻址,操作数在 DS段,以 BP为基址寻址,
操作数在 SS段。
小结:
1.以上寻址方式,除立即寻址外,亦可用于目的操作数的寻址。
如,MOV 2[BX],AX; AX→ ( DS,[BX+2])
即 源 操作数 ——7种 方式,目的 操作数 ——6种 寻址方式
2.除以上 7种寻址方式,还有一种 隐含寻址 (implied
addressing),即操作数在符号指令中不显示出来,而隐含某寄存器为操作数。
如,PUSHF 仅有助记符,操作数隐含,源 → F,目的 → [SP]
POPF 源 → [SP],目的 → F
八,存储器寻址中段寄存器的指定
1,因为存储器分段管理,在内存中寻找操作数除了偏移地址外,指令中若没有特别声明,则段有一个 基本约定 → 默认状态,约定关系,P、
41、表 2- 1
访问存储器 约定 可更 偏移的方式 段 换段 地址取指令 CS 无 IP
堆栈操作 (PUSH,
POP,CALL,RET 等 ) SS 无 SP
数 通用数据存取据 (直接寻址,BX,DS CS,SS,ES EA
存 SI,DI,间址 )
取 以 BP间址,基址 SS CS,DS,ES EA
字符串源地址 DS CS,SS,ES SI
字符串目的地址 ES 无 DI
2,跨段或段超越当要否认以上默认状态,到其他段寻找操作数时,必须用 跨段前缀 指明操作数所在段的段寄存器名。
例,MOV AX,ES:[SI]; (ES:[SI]) →AL,(ES:[SI+1]) →AH
MOV AX,DS:[BP]; (DS:[BP]) →AL,(DS:[BP+1]) →AH
MOV AX,CS:[BX]; (CS:[BX]) →AL,(CS:[BX+1]) →AH
注意,显示说明高于默认状态 。
注:实际上,不管是跨段或默认段,操作数的 PA由系统 自动计算,程序中表示都使用逻辑地址,而不使用物理地址。
作业,P71,3.
§ 2.4 常用符号(机器)指令
8088系统有庞大的指令系统,形式多样,功能极强,
用 115个指令助记符 代表 91种操作,可分六大类:①
数据传送指令 ② 算术运算指令 ③ 位操作 (逻辑运算 )指令 ④ 串操作指令 ⑤ 控制转移指令 ⑥ 处理机控制指令。
注:学习时注意 指令格式及功能。
在此先介绍:传送,算术,位操作指令。
一,数据传送指令 —— 最基本、大量、主要操作
1.数据传送指令格式,MOV DST,SRC
目的操作数 源操作数功能:将源操作数传送至目的地址中,源保持不变。
( SRC) → DST
· 传送指令的特点是:把数据从计算机的一个部位传送 到另一个部位,把发送部位 → 源,接收部位 → 目的; 源 → SegReg,Reg,
Mem,Imm;目的 → SegReg,Reg,Mem.
· 两操作数 类型相同,即同为字节或字类型的数据。
· 类型明确,不能出现二义性 (即不能模糊 )。
· CS任何时候都不能为目的操作数,立即数亦不能为目的操作数。
· 源和目的 不能同时为 存储器操作数。
· 不影响任何标志位 (所有传送 )。能实现的传送示意如下,
段寄存器 SegReg ③ ④ 通用寄存器 Reg
CS,DS,ES,SS ①
⑧ ② AX,BX,CX,DX
⑨ ⑤ 立即数 Imm
存储器 Mem BP,SP,DI,SI
⑥ ⑦
由上表可总结出九种形式,P,42、
例:判断下列指令正确与否:
MOV AL,BL √
MOV CX,BX √
MOV BX,DL × 类型不一致
MOV DX,34H √
MOV DS,1234H × 立即数不能送段寄存器
MOV ES,AX √
MOV CS,BX × CS不能作目的操作数
MOV [SI],CX √
MOV [DI],10 × 源为立即数,无类型,
目的类型模糊,二义性
MOV [DI],[SI] × 不能同时为存储器
MOV 2000H,AX × 目的不能为立即数
MOV DS:2000H,AX √
2,数据交换指令格式,XCHG DST,SRC
操作,(DST)(SRC)
即源地址与目的地址中的内容互换
· 交换只能在通用寄存器 Reg之间,存储器 Mem与通用寄存器 Reg之间进行。 至少一方为 Reg.
例,XCHG AX,BX √
XCHG BH,BL √
XCHG AX,1122H ×
XCHG DS,AX ×
XCHG [SI],BP √
XCHG [SI],[DI] ×
3,地址传送指令? 将地址传送至目的
① 传送偏移地址格式,LEA Reg16,Mem
操作:将源操作数提供的寻址方式计算的有效地址
EA → Reg16
例,LEA SI,DS:2000H ; SI=2000H,即 EA→SI
LEA DI,[SI+2] ; DI=2002H
· 区分 MOV SI,DS:2000H; (DS:2000H) →SI
② 传送偏移地址及数据段首地址格式,LDS Reg16,Mem32→ 表示双字类型操作,(Mem32) →Reg16,(Mem32+2) →DS
或 (EA) →Reg16,(EA+2) →DS
亦即源地址指针的第一个字 → Reg16,第二个字 → DS。
用来传送一个目标地址 (段地址和偏移地址 ),常用来为存取非当前数据段中的数据作地址准备。
例:设 DS,1002 33 执行 MOV BX,1000H
1003 44 LDS SI,2[BX]; SI=4433H
1004 55 DS=6655H
1005 66
③ 传送偏移地址及附加数据段首地址指令格式,LES Reg16,Mem32
操作,(EA) →Reg16,(EA+2) →ES
· 除把目标段地址送 ES外,其它同 LDS。
4,查表转换指令格式,XLAT 或 XLAT SRC_ TAB
操作,([BX+AL]) →AL,即将 BX为首址,AL为位移量的字节单元的内容 → AL
· 该指令常用于进行代码转换,转换时先建立相应表。表首址 → BX,
与表有关的某个偏移值 (一般为被传送的字节到表头地址的字节数 ) →AL 。
·该指令的操作数是隐含寻址,不带操作数或带表头地址,
例,利用查表指令,求某数 (0~ 9)的平方值。如查 7的平方。
先建 0~ 9平方表,首址 → BX,待查值 → AL
TAB DB 00H,01H,04H,09H,16H,25H,36H,49H,64H,81H
LEA BX,TAB
MOV AL,7
XLAT ; AL=49BCD
注:以上传送类指令均不影响标志。
BCD数二,算术运算指令
8088提供了加、减、乘、除四种基本算术操作的 20种指令,可进行字节或字运算,也可用于带符号或无符号数的运算。
1,加法运算
① 加法指令格式,ADD DST,SRC
操作,(DST)+(SRC) →DST
即将目的操作数与源操作数相加,结果存入目的地址中,而源地址内容不变。
· 目的 → Reg,Mem 源 → Reg,Mem,Imm
只有 5种形式,P46。
· 两操作数的 类型相同,类型明确,不能同为存储器。
例:判断正确与否:
ADD AL,BX ×
ADD CL,CH √
ADD AX,[BX] √
ADD [BX],28 ×
ADD [BX],[SI] ×
ADD 1000H,AX ×
ADD [SI],BX √
ADD DS,BX ×
加法指令执行后的结果将 影响状态标志 。
例,MOV BL,97H
ADD BL,85H ; BL=1CH
1001 0111
+ 1000 0101
1 0001 1100
CF=1 OF=1⊕ 0=1 SF=0 ZF=0
一般算术运算关心四个算术标志,填入 F中,其余位填
0,F结构,F的格式,
D15 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 OF 0 0 0 SF ZF 0 0 0 0 0 CF
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1
得 F=0801H
② 带进位加法指令格式,ADC DST,SRC
操作,(DST)+(SRC)+CF→DST
· 该指令主要用于 多字节运算,多字节运算时低位字节产生的进位应加到高位。单字节表示一个数的范围小,精度低,为提高精度,可用多个字表示一个数。
如:一个字表示一个数 → 单精度数 (16位 ),两个字表示一个数 → 双精度 (32位 ),多个字 → 多倍精度等。
例,两个双精度数 (32位 )相加
0123FAB5H+0ABC212AH=0BE01BDFH 0123 FAB5
MOV DX,0123H + 0ABC 21 2A
MOV AX,0FAB5H 0BE0 1BDF
ADD AX,212AH ; 先加低字 CF=1 AX=1BDFH
ADC DX,0ABCH ; 高字带进位加 CF=0 DX=0BE0H
CF为前面指令产生的 CF
③ 增量(加 1) 指令格式,INC DST
操作,(DST)+1→DST
例,MOV BX,1
INC BX; BX=0002H
· 该指令不影响 CF,而影响其它标志,规律同 ADD。
· 单操作数指令,只能为 Reg,Mem,类型明确,不能出现二义性。
例,INC CL √
INC [DI] ×? INC BYTE PTR[DI] √
INC 2000H ×
· 该指令常用于修改偏移地址和计数次数。
2,减法指令
① 减法指令格式,SUB DST,SRC
操作,(DST) - (SRC) →DST
② 带借位减指令格式,SBB DST,SRC
操作,(DST) - (SRC) - CF →DST
除两操作数相减以外,再减去 前面指令的进位 (借位 )。
例:双精度数相减
5321A678H- 1234F000H=40ECB678H
MOV AX,0A678H
MOV DX,5321H 5321 A678
SUB AX,0F000H ; CF=1 - 1234 F000
SBB DX,1234H ; CF=0 30EC B678
③ 减量(减 1)指令格式,DEC DST
操作,(DST) - 1→DST
· DEC不影响 CF,其余标志均受影响,影响关系同 ADD
指令。
3,比较指令格式,CMP DST,SRC
操作,(DST) - (SRC) 比较后 影响标志,不回送结果 。
源、目的不变。该指令主要用来判断比较两数的大小,
与是否相等。
作业,P71,4,6,7,(2),(3),9.(3),(4).
三,位操作指令 — 包括逻辑运算与 移位类指令
1,逻辑运算
① 求补指令格式,NEG DST
操作,( DST) +1→DST
即将操作数单元的内容求反加 1后(包括符号位)
又送入原单元中,
例,MOV AX,1 ; AX=0001H (前+ 1)
NEG AX ; AX=0FFFFH (后- 1)
例,MOV BL,0FFH ; BL=0FFH (前- 1)
NEG BL ; BL=01H (后+ 1)
区分,它是进行求补操作,而不是求补码指令。它不管操作数是否带符号,是正是负,也不管是原码补码。
若将执行求码指令前后的数均视为补码形式的符号数,求补指令则将该数变为绝对值相等符号相反的另一个数 。若已知 AX中的一负数的补码,则只要
NEG AX,则求其绝对值。
·单操作数指令,操作数只能是 Reg,Mem,且类型明确。
影响标志,影响规律同减法类指令 。因为求补等效 0 –( DST) → DST
( 2)求反指令格式,NOT DST
操作,( DST) → DST,即将操作数的内容逐位取反后再送入。
例,MOV AX,1
NOT AX ; AX=0FFFEH
·该指令只是执行求反操作,而不是求反码指令,对符号位也求反。
·该指令不影响标志位 。
( 3)逻辑与指令(乘)
格式,AND DST,SRC
操作,( DST) ∧ ( SRC) → DST,两操作数按位逻辑与运算例,MOV AX,5555H
AND AX,0FFH ; AX=0055H→ 屏蔽高位(高位清零),取出低位;即对应位为 0则清 0,对应位为 1则不变?称这种数为 逻辑尺 。
( 4)逻辑或指令格式,OR DST,SRC
操作,( DST) ∨ ( SRC) → DST
即两操作数按位逻辑“或”运算例,MOV AX,8888H;
OR AX,0FFH ; AX=88FFH→ 对应
1位置 1,对应 0位则不变。
( 5)逻辑异或指令格式,XOR DST,SRC
操作,( DST) ⊕ ( SRC) →DST,
即两操作数按位异或例,MOV AX,3333H;
XOR AX,0FFH ; AX=33CCH→ 对应 0不变,对应
1求反例,XOR AX,AX ; AX=0 清零
有 4条指令可达到 AX清 0目的:
MOV AX,0
SUB AX,AX
AND AX,0
三条逻辑指令均为双操作数指令,对源,目的要求同
ADD,SUB指令,
三条逻辑指令均影响标志,使 CF=0,OF=0,而
PF,SF,ZF由结果而定,AF无意义,所以此类指令可用来清 CF,常用于拆字,拼字,
例,将 BX的高四位与 CX的低四位,AX的中间 8位反码,拼成新字送至 AX
如,AX=AAAAH BX=BBBBH
CX=CCCCH→ AX=B55CH
AND BH,0F0H ; 取 BX高四位,BH=B0H
AND CL,0FH ; 取 CL低四位,CL=0CH
AND AX,0FF0H ; 取 AX中间八位,AX=0AA0H
XOR AX,0FF0H ;求反 AX=0550H
OR AH,BH
OR AL,CL ; 拼字 AX=B55CH
(6) 测试指令格式,TEST DST,SRC
操作,(DST) ∧ (SRC) 根据测试结果 影响标志 (规律同 AND),不回送结果 。该指令主要用来检测目的操作数的某些位是 1或 0,根据测试结果,决定转向,
2.移位类指令
(1) 逻辑右移格式,SHR DST,CNT(移位位数为 1或 CL)
操作,0→ → CF
例,MOV AL,0CH ; AL=12
SHR AL,1 ; AL=6
该指令右移一次,等于对无符号数除 2运算,右移 N次,等于除 2N。
例,对 AX中的无符号数进行除 8运算(不考虑余数)
MOV CL,3
SHR AX,CL
( 2)算术右移格式,SAR DST,CNT(移位位数为 1或 CL)
操作,→ CF
例,MOV AX,–8 ; AX=0FFF8H→ - 8
SAR AX,1 ; AX=0FFFCH→ - 4
算术右移一位,等于 对带符号数进行 ÷ 2运算,右移 N
次,等于 ÷ 2N。
(3) 逻辑左移
格式,SHL DST,CNT
操作,CF ← ← 0
(4) 算术左移格式,SAL DST,CNT
操作,CF ← ←0
注,SAL指令与 SHL指令操作一样,即 机器码一样。
例,MOV BL,0CH ; BL=12
SHL BL,1 ; BL=24
左移一位,等于对操作数 (带符号或无符号 )乘 2运算,左移 N次,则乘 2N,但防止溢出,
例,对 AX内容进行乘 10运算 (设无溢出,乘 10后仍为一个字),
∵ AX * 10=AX * (23+2)=AX * 2+AX * 23
MOV BX,AX
SAL BX,1 ; * 2?BX
MOV CL,3
SAL AX,CL ; * 23?AX
ADD AX,BX ; * 10?AX
以上四条移位指令均影响 F标志,CF为最后输入值 。
(5) 循环右移格式,ROR DST,CNT
操作,→ → CF
(6) 循环左移格式,ROL DST,CNT
操作,CF ← ←
例,MOV AL,45H
MOV CL,4
ROL AL,CL ; AL=54H,高四位与低四位互换,
使用 ROR也一样。
(7) 带进位循环右移格式,RCR DST,CNT
操作,→ → CF
(8) 带进位循环左移格式,RCL DST,CNT
操作,CF ← ←
此四条循环移位指令只影响 CF,不影响其它标志。
当想把一个寄存器或单元的内容,移至另一个单元时,
常用带进位移,
前面指令产生的
CF移至最高位前面指令产生的
CF移至最低位例,将 AX中的无符号数乘以 10(AX=F0F0H)。
∵ 结果可能大于 216- 1=65535
∴ 要用两个寄存器存放,即积 → DL,AX
∵ * 10=*( 23+2) ∴ 可用移位和加法实现
XOR DL,DL ;积高位清零
SAL AX,1 ; * 2
RCL DL,1
MOV DH,DL ;* 2?DH,BX
MOV BX,AX
SAL AX,1 ;* 4
RCL DL,1
SAL AX,1 ;* 8?DL,AX
RCL DL,1
ADD AX,BX ;* 10
ADC DL,DH
另解,使用移位 3次的方法 (AX=F0F0H):
MOV BX,AX ;*2?DH:BX
ROL BX,1 ;BX=1110 0001 1110 0001B
MOV DH,BL ;DH=1110 0001B
AND DH,01H ;DH=0000 0001B
AND BX,0FFFEH ;BX=1110 0001 1110 0000B
MOV CL,3 ;* 8?DL,AX
ROL AX,CL ; AX= 1000 0111 1000 0111B
MOV DL,AL ; DL= 1000 0111B
AND DL,07H ; DL= 0000 0111B
AND AX,0FFF8H ; AX= 1000 0111 1000 0000B
ADD AX,BX
ADC DL,DH
作业,P72,5,8,(课本) 9.( 2),( 5),( 6),
§ 2.5 常用 DOS系统功能调用和
ROM BIOS中断服务子程序调用为使结果直观的显示在输出设备上,最简单的方法就是调用 DOS中的输入 /输出子程序。实际上 PC
系统为方便汇编用户提供了 两个程序接口,一个是 DOS系统功能调用,另一个是 ROM中的 BIOS
( Basic Input /OutpuT System)。它们由一系列中断服务子程序构成,由软中断指令 INT N
来调用。
一,DOS系统功能调用
1、调用过程是,
置入口参数功能调用号 → AH
执行 INT 21H
分析出口参数视具体情况而定
2、常用功能调用?键入,输出,打印。
参见 P63、表示 2- 3。
1号 → 键入一个字符 → 无入口参数出口:键入字 符 ASCII码值在 AL中,回显。
2号 → 显示一个字符 → 入口:将显示的字符 ASCII
送 DL → 无出口参数。
5号 → 打印一个字符 → 入口:将打印的字符 ASCII
送 DL → 无出口参数。
8号 → 键入一个字符 → 无入口参数 → 出口:
键入字符 ASCII值在 AL中,不回显,便于保密。
9号 → 显示一串字符 → 入口,DX指字符串首地址,字符串以 ‘ $ ’ 结束 → 无出口参数。
10号 → 键入一串字符 → 入口,DX指向输入缓冲区首址 → 出口:字符串个数在? 首址 +1―单元,字符串在? 首址 +2―单元。
11号 → 检查键盘有无键入 → 无入口参数 →
出口:有键入 AL=0FFH,无键入 AL=0。
例,MOV AH,1
INT 21H 等待键入一个字符 ASCII码值
→ AL
例,MOV AH,2
MOV DL,’ B’ 显示字符 ‘ B’
INT 21H
例,BUF DB ’HELLO’,0DH,0AH,’ $ ’
LEA DX,BUF
MOV AH,9
INT 21H
例,IBUF DB 4,?,4 DUP(?)
MOV DX,0FFSET IBUF
MOV AH,10
INT 21H
显示,HELLO
等待输入 3
个字符缓冲区最大长度实际输入个数存放输入的字符和回车符例,? 镜子? 程序?从键盘输入一串字符,在下一行照原样显示 (P67)。
STACK SEGMENT STACK
DW 32 DUP(?)
STAC ENDS
DATA SEGMENT
OBUF DB ’ ﹥ ’,0DH,0AH,’ $ ’
IBUF DB 0FFH,?,0FFH DUP(?)
DATA ENDS
CODE SEGMENT
BEGIN PROC FAR
ASSUME SS,STACK,CS,CODE,DS,DATA
PUSH DS PSP首址进栈,为返回 DOS设置
SUB AX,AX 返回地址
PUSH AX
MOV AX,DATA 设置用户数据段
MOV DS,AX
MOV DX,OFFSET OBUF
MOV AH,9 显示输入提示 ‘ 〉 ’
INT 21H 并 ↙,换行
LEA DX,IBUF 键入字符串
MOV AH,10 串长在 → IBUF+1
INT 21H 串首址 → IBUF+2
MOV BL,IBUF+1
MOV BH,0 长度 → BX
MOV IBUF[BX+2],’ $ ’ → 串尾存 ‘ $ ’
MOV DL,0AH 因为输入已有 ↙
MOV AH,2 所有只需换行
INT 21H
MOV DX,OFFSET IBUF+2
MOV AH,9 显示键入的串
INT 21H
RET PSP首址出栈 → CS,IP
BEGIN ENDP
CODE ENDS ; 结束用户程序
END BEGIN
FF IBUF
如输入,ABCDE↙ 内存分配 05 +1
41 +2
42
43
44
45
0D $( 24H)
例( P65),键入 4位十进制数,以压缩 BCD形式存入字变量 SW单元中。
IBUF DB 5,?,5 DUP(?)
SW DW?
MOV DX,OFFSET IBUF
MOV AH,10
INT 21H
MOV AX,WORD PTR IBUF+4
AND AX,0F0FH
MOV CL,4
SHL AL,CL
OR AL,AH
MOV BYTE PTR SW,AL
MOV AX,WORD PTR IBUF+ 2
AND AX,0F0FH
SHL AL,CL
OR AL,AH
MOV BYTE PTR SW+ 1,AL
作业,
P73,11,12,13.(作业本)
14.(课本)
二,BIOS基本输入 /输出系统功能调用
BIOS系统由一系列的服务程序构成,也是通过执行软中断指令 INT N 来调用。 BIOS包括系统服务程序和设备驱动程序。其驱动程序和 DOS
驱动程序相似,主要功能是驱动系统中所配置的常用设备,如显示器,键盘,打印机,磁盘驱动器以及异步通讯接口等。用户可方便的控制外设操作,和 DOS相比,它能完成 更复杂的、更细微的 I/O操作 。在此仅介绍键盘、打印机、显示器的服务程序。
1、调用方法和 DOS功能调用相同置入口参数 → 功能号送 AH → 执行 INT N
→ 分析出口参数
2,键盘输入子程序调用指令,INT 16H
有三个功能,功能号为,0~2 ( P68表 2- 4)
例,MOV AH,0
INT 16H
3,打印机服务子程序调用指令,INT 17H
有三个功能,功能号为,0~2
读一个字符 → AL
① AH=0? 功能:打印一个字符?入口:将打印字符
→ AL,打印机号 0~2 →DX 注,BIOS可支持三个打印机,
一般为 0号。
② AH=1 功能:初始化打印机
③ AH=2 功能:读打印机状态例,MOV AL,’ B’
MOV DX,0 打印 ‘ B’字符
MOV AH,0
INT 17H
4,显示子程序调用指令,INT 10H
有 16种功能,功能号为,0~15
参见 P,69?表 2- 5
例,在屏幕的 5行,10列位置显示闪烁的高亮度的‘$’。
MOV AH,0 设显示方式为 80列 × 25行的黑白
MOV AL,2 文本方式
INT 10H
MOV AH,15 读当前显示页号 → BH
INT 10H 因为下面 2号和 9号需设页号
MOV AH,2
MOV DX,050AH 设光标位置在 5行,10列
INT 10H
MOV AH,9 在当前光标位置写字 符和属性
MOV AL,’ $ ’ 设写字符 ‘ $ ’
MOV BL,8FH 字符显示属性 1000 1111
MOV CX,1 写一次
INT 10H 写高亮度闪烁的$
例,在 320× 200彩色图形方式下,在白色背景下,
在( 10,10)的位置写一个绿色点。
MOV AH,15
INT 10H 读显示器状态,暂存
PUSH AX
MOV AX,0600H 6号功能,AL=0 清屏
MOV CX,0 左上角坐标( 0,0)
MOV DX,184FH 右下角坐标( 24,79)
MOV BH,7 常规属性黑底白字
INT 10H 清屏
MOV AH,0
MOV AL,5 置 320× 200彩色图形方式
INT 10H 5?5FH,则设为 1024* 768
5?5BH,则设为 800* 600
MOV AH,11
MOV BH,0 设背景色
MOV BL,7 白色背景
INT 10H
MOV AH,11
MOV BH,1 设彩色组
MOV BL,0 彩色组 0
INT 10H
MOV AH,12
MOV DX,10
MOV CX,10
MOV AL,1
INT 10H 在( 10,10)处写绿色点象点颜色由彩色组和彩色值共同决定
WAT,MOV AH,1 无键入则等待
INT 16H 有键入则顺序执行
JZ WAT
POP AX
MOV AH,0 恢复原显示器状态
INT 10H 第二章结束
* 例,在 800× 600的图形方式下,设白色背景,
画一条品红色线,从( 0,0) ~( 599,599)。
注,
修改画点颜色,可画其他颜色的线,如 AL=0,则画青色线,AL=4则画棕红色线。
设置图形方式,与显示器适配卡有关。
INT 10H与 BIOS版本有关。
利用循环可画各种图形。
MOV AH,15
INT 10H 读显示器状态,暂存
PUSH AX
MOV AH,0
MOV AL,6AH 设显示器方式为 800?600
INT 10H
MOV AH,11
MOV BH,0
MOV BL,7 设白色背景
INT 10H
MOV AH,11
MOV BH,1
MOV BL,1 设彩色组 1
INT 10H
MOV DX,0 设初始点为( 0,0)
MOV CX,0
LOP,MOV AH,12
MOV AL,2
INT 10H 画线
INC DX
INC CX
CMP DX,599
JNE LOP
WAT,MOV AH,1
INT 16H 等待按键
JZ WAT
POP AX
MOV AH,0 恢复显示器状态
INT 10H
§ 2.1 机器语言与汇编语言一,机器语言 —— 机器只能识别二进制编码
机器指令 —— 机器能直接执行的一组二进制代码
(命令 )——该二进制代码称为 机器码 (Machine
Code).
如,40H?INC AX 01D8H?ADD AX,BX
指令通常由两部分组成,操作码和操作数
操作码 —— 该指令的功能,即执行什么操作。
操作数 —— 指令 操作对象,指明参加操作的数或操作数的地址。
机器指令的集合?机器语言?用机器语言编写的程序
机器语言程序二,汇编语言机器语言编写程序烦琐,难记忆,不易理解,
易出错。用一些 助记符 来表示指令的操作码,
操作数亦用一些 符号 来表示?符号指令 。
如上,40H?INC AX 01D8H?ADD AX,BX
符号指令与机器指令一一对应。
符号指令的集合?符号语言,又称 汇编语言?用汇编语言编写的程序?汇编语言程序?不能由计算机直接执行,
必须将它翻译成机器语言程序?翻译过程称 汇编?翻译程序为 汇编程序 。
汇编语言源 程序?汇编? 目标程序三、宏 汇编 程序?MASM
允许把一串指令定义为一条宏指令,有宏汇编功能。
如 MASM?系统程序 。宏汇编语言有三类基本指令:符号指令,伪指令,宏指令。
§ 2.2 常用伪指令与常用算符
每一种计算机语言都规定了自己的 符号系统及语法规则 。汇编语言也是如此,除符号指令外,还必须正确使用各种符号。汇编中的各种符号由 伪指令定义,或为汇编的 保留字。
一、汇编语言源程序结构 ——单模块程序结构
参见教材 P,60
一般 程序由三个段组成。教材中程序的小写字母部分均为 程序结构。
STACK SEGMENT STACK
DW 32 DUP(?)
STACK ENDS
DATA SEGMENT
:
DATA ENDS
CODE SEGMENT
BEGIN PROC FAR
ASSUME CS,CODE,SS,STACK,DS,DATA
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATA
MOV DS,AX
:
RET
BEGIN ENDP
CODE ENDS
END BEGIN
定义堆栈段及堆栈长度定义数据段定义代码段将汇编源程序视为 DOS下的子程序将程序段前缀 PSP进栈设置用户数据段返回到 PSP,执行 PSP中的第一条指令
INT 20H,结束程序返回调用程序
因为连接程序为每一个用户程序建立了一个程序段前缀 PSP,在 PSP的开始处安排了一条
INT 20H指令,执行该指令结束当前程序返回调用程序。
而 PSP的地址,其段地址寄存在 DS和 ES中;
偏移地址为 0,将 DS,0000地址进栈,即 PSP
地址进栈。
PSP的长度为 256个字节,即 100H个单元,
主要存放了装入程序与 DOS连接的信息。
结束用户程序返回 DOS有两种方法:
其一,MOV AH,4CH ;返回 DOS
INT 21H
其二,INT 20H ;返回调用程序,便于调试它的机器码是 CD20H,当用 DEBUG调用 EXE
文件时,在 DS,0000单元中便可看到该指令。
DOS在转移控制权时,将 CS指向 EXE程序的代码段,SS指向堆栈段,但 DS和 ES
并不指向用户程序的数据段和附加数据段,而是 指向 PSP。
二,常用伪指令 (P58)
伪指令不产生机器代码,CPU也不会产生某种操作,
它主要告诉汇编程序哪些是数据,哪些是指令,符号约定,程序从何处开始,何处结束,即为汇编控制命令。
伪指令很多,下面主要介绍段定义,过程定义。
1、段定义伪指令?定义一个存储段,一个程序模块可由若干段组成。
格式:
〈 段名 〉 SEGMENT [定位方式 ][组合方式 ][‘类别名’ ]
…… 伪指令或指令
〈 段名 〉 ENDS
功能,定义一个以“段名”为名称的存储段。
定位方式,组合方式,‘类别名’?赋给段名的属性,三个可选项主要用于多模块化程序设计,
以告诉 LINK程序各模块间段如何定位,段与段如何组合,还可连接在一起。一般单模块程序可省略。
段名?给段取名,用来指出汇编程序为该段分配的存储区的起始地址,即 段地址,为一常数,用 SEG运算符取得。
定位方式?相邻两段间应如何衔接,即对该段的起始地址所提出的要求。定位方式有四种选择:
( 1) [PARA](节)?规定段的起始地址总是 16的整数倍,即低四位为零,省略时,系统隐含为此方式,
教材中均默认为 PARA方式 。
( 2) WORD (字)?规定段的起始地址总是 2的整数倍,即低 1位为零。
(3) Byte(字节)?规定段的起始地址总是 1的整数倍,即能 被 1整除,任何地址可为段地址,
不留空隙。
( 4) Page( 页)?规定段的起始地址总是 256的整数倍,即低 8位为零。
组合方式 ——提供本段同其他段的组合关系,有 6种选择方式 。
( 1) [NONE]不选择?表示本段与其他逻辑上不发生关系,尽管物理上可能相邻,但每段都有自己的段首址。 系统隐含该组合方式,单模块程序,各段之间不发生关系,采用不选择方式,
教材中多数例题的数据段,代码段均为不选择方式。
( 2) PUBLIC公共?将同段名,同类别名的段顺序相拼,是否留有空隙取决与定位方式。
( 3) STACK堆栈?将同段名,同类名的段顺序 相拼,
不留空隙,长度相加,构成堆栈段。一个程序模块中至少有一个段为 STACK组合方式的段 。
( 4) COMMON公用?将同名段,同类别名的段相互覆盖,长度取决于最长的段。
( 5) AT表达式?段地址为表达式的值。
( 6) MEMORY?表示将本段定位在其他段的上面
(即最高地址)。
类别名?用单引号括起来的字符串,连接时将同类别名的所有段(段名可不同)存放在连续的存储区。单模块程序可省略类别名。
2,假定伪指令格式,ASSUME〈 段寄存器:段名 〉,……
功能:告诉汇编程序各段名与段寄存器的对应关系,一般在代码段中。
因为,存储器分段管理,程序中的存储单元用逻辑地址的偏移地址来寻址,而段地址一般默认,
所以,代码段一开始就要对段 寄存器与段之间的关系做假定。
3、源程序结束伪指令格式,END [表达式 ]
功能:源程序的最后一个语句,标志整个程序结束,即告诉汇编程序,汇编到此结束。
表达式?为可选项,必须是存储器地址,即程序的启动地址,常为标号。
不带表达式的 END结束的模块不能单独运行,
为子模快。
4、子程序定义伪指令格式,〈 子程序名 〉 PROC [NEAR]或 FAR
:
RET
〈 子程序名 〉 ENDP
PROC…… ENDP必须配对使用。
子程序名有标号属性,一般段内调用为 NEAR或省略,
段间调用为 FAR。
RET为子程序返回指令,返回调用主程序:
段内,[SP] ↑ →IP,SP+2 →SP
段间,[SP] ↑ →IP,[SP+2] ↑ →cs,SP+4→SP
STACK SEGMENT STACK
DW 32 DUP(?)
STACK ENDS
DATA SEGMENT
:
DATA ENDS
CODE SEGMENT
BEGIN PROC FAR
ASSUME CS,CODE,SS,STACK,DS,DATA
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATA
MOV DS,AX
:
RET
BEGIN ENDP
CODE ENDS
END BEGIN
定义堆栈段及堆栈长度定义数据段定义代码段将汇编源程序视为 DOS下的子程序将程序段前缀 PSP进栈设置用户数据段返回到 PSP,执行 PSP中的第一条指令
INT 20H,结束程序返回调用程序
STACK SEGMENT STACK
DW 32 DUP(?)
STACK ENDS
DATA SEGMENT
:
DATA ENDS
CODE SEGMENT
BEGIN PROC FAR
ASSUME CS,CODE,SS,STACK,DS,DATA
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATA
MOV DS,AX
:
RET
BEGIN ENDP
CODE ENDS
END BEGIN
例、两个数据交换。
DT1 DB 11H
DT2 DB 22H
MOV AL,DT1
MOV AH,DT2
MOV DT1,AH
MOV DT2,AL
STACK SEGMENT STACK
DW 32 DUP(?)
STACK ENDS
DATA SEGMENT
DATA ENDS
CODE SEGMENT
BEGIN PROC FAR
ASSUME CS,CODE,SS,STACK,DS,DATA
PUSH DS
SUB AX,AX
PUSH AX
MOV AX,DATA
MOV DS,AX
:
RET
BEGIN ENDP
CODE ENDS
END BEGIN
上机调试作业,
如,P32,17.
MOV AX,1122H
MOV BX,3344H
MOV CX,5566H
PUSH AX
PUSH BX
PUSH CX
POP BX
POP AX
POP DX
三、常量( P34)
1、常量 —常数和符号常量 —主要给变量赋初值或指令中立即数等。
常数 —汇编中允许的常数有 二进制,十进制,十六进制,字符串 ( ASCII码字符,
用单引号表示,如:’ ABC’)。
符号常量 —程序中可以给常数取名。
用 EQU或,=,伪指令定义。
格式,〈 标识符 〉 EQU〈 表达式 〉 → 数值表达式
〈 标识符 〉 = 〈 表达式 〉
例,AA EQU 10
BB EQU 2*AA+3
CC = 66
MOV AX,AA ; AX=10
MOV AX,BB ; AX=23
MOV AX,CC ; AX=66
注,AA,BB,CC为立即数。
2,数值表达式 —由 常量与运算符组成的有意义的式子,结果为数值。
在 MASM中允许对常量进行三种类型的运算:
( 1)算术运算 —+,-,*,/,MOD(求余),
SHR(右移),SHL(左移)
如,AA EQU 10,
则表达式 → AA * 3+ 2 →32,可以作为操作数。
( 2)逻辑运算 —AND,OR,XOR,NOT,按位运算。
· 注意,将运算符与指令相区别。
例,X EQU 0FFFFH
MOV AX,5555H
AND AX,X AND 0FFH; AX=0055H
( 3)关系运算 —EQ(=),NE( ≠),LT(<),
GT(>),LE( ≤),GE( ≥)
关系运算的结果为两个特殊常量 0FFFFH
( TURE),0( FALSE)。
四,变量( P34) —变量是存储器中的 数据或数据区的符号地址表示,即给存储单元取名。
1、变量的三个属性 —∵ 存储器分段,变量有 三个属性。
( 1) 段属性 —定义变量所在段的段首地址(一般为
DS)。
( 2) 偏移地址 —变量偏离段首址的字节数,即段首址到变量定义语句的字节距离。
( 3) 类型属性 —存取该变量中的数据所需要的字节数。
类型,字节,字,双字,四字,十字节 类型,
一个数据分别占 1,2,4,8,10个单元,其类型由定义的伪指令确定。
2,变量的定义 —一般在数据段或附加数据段中用伪指令定义。
格式:
〈 变量名 〉 DB〈 表达式 〉 ;定义 BYTE字节变量
〈 变量名 〉 DW〈 表达式 〉 ;定义 WORD字变量
〈 变量名 〉 DD〈 表达式 〉 ;定义 DWORD双字变量
〈 变量名 〉 DQ〈 表达式 〉 ;定义 QWORD四字变量
〈 变量名 〉 DT〈 表达式 〉 ;定义 TBYTE十字节变量
EQU伪指令不分配存储单元,但变量定义伪指令要分配存储单元。
表达式确定了变量的 初值 。
· 表达式可以有以下几种形式:
( 1)常量或数值表达式?存入数值。
( 2) ASCII字符串(若串长 ≥2,只能用 DB定义,)
存入 ASCII码值。
( 3)?分配一个空单元,无确定值。
( 4)重复子句,格式,N DUP( 〈 表达式 〉 )?重复 N次,其值由表达式确定。
( 5)地址表达式 → 由常量,变量,标号,间址寄存器( [BP],[BX],[SI],[DI])的内容和运算符等组成有意义的式子。如一个变量名就是一个地址表达式。
可用 DW或 DD定义,若用 DW则取它的偏移地址来初始化变量;若用 DD则其偏移地址和段地址来初始化其变量。
若有多个表达式,用逗号分隔。
例,DATA SEGMENT ;段定义
DT1 DB 10,3*20
DT2 DB ’ ABC’,44H,45H
DT3 DW 100H,- 5
DT4 DD 0FFFFH
DT5 DB 0,?,?,?,0
AA EQU $- DT1; $—汇编地址计数器,
记录当前汇编地址为 14H。
DT6 DB 2 DUP( 0,2 DUP( 2,3))
DT7 DW DT2
DT8 DD DT4
DATA ENDS
存放示意:
DT1 DT2 DT3 DT4
0A 3C 41 42 43 44 45 00 01 FB FF FF FF 00 00
DT5 DT6
00 XX XX XX 00 00 02 03 02 03 00 02 03 02 03
DT7 DT8
02 00 0B 00 DATAL DATAH
从变量中取数据属于直接寻址方式,注意与符号常量区别。
例,MOV AX,AA ;立即寻址,AX=0014H
MOV AX,DT3 ;直接寻址,AX=0100H
MOV AL,DT2+2 ; AL=43H
变量一旦定义,则有类型,指令中类型一致例,MOV AX,DT1 ╳
MOV BL,DT3 ╳
注意区分变量的值与偏移地址:
变量名 偏移地址 变量的值
DT1 0000H 0AH
DT2 0002H 41H
DT3 0007H 0100H
DT4 000BH 0000FFFFH
偏移地址是 16位无符号数
在符号指令中的基址,变址,基址加变址三种寻址中,其 偏移量可以是常数,或符号常量,还可以是变量名 。若是变量名,它给出变量所在段的偏移地址,其意义是 取变量单元中的数据,所以其类型要与另一操作的类型一致。
例,MOV BX,0
MOV AX,DT3[BX] ; AX=0100H
MOV AL,DT3[BX] ╳
常以间址、基址、变址访问一片连续的单元 。
例,LEA BX,DT2 ; BX= 0002H
MOV AL,[BX] ; AL= 41H
MOV AL,[BX+ 1] ; AL= 42H
五,标号?存放某 指令的符号地址,也可以是过程名(过程地址入口)
注:变量?是存放 数据的符号地址。
1,标号的 三个属性
( 1) 段属性 —定义该标号所在段的段首址。
( 2) 偏移地址 —标号偏离段首址的字节数。
( 3) 类型 —两种,NEAR—段内,FAR—跨段
2,标号的定义
( 1)书写在指令前,用:定义,只能为 NEAR
NEXT,MOV AL,[SI] ;定义近标 号 NEXT
( 2)用 PROC…ENDP 伪指令定义过程名例,ABC PROC FAR;定义过程名 ABC为远标号
DEF PROC [NEAR];定义过程名 DEF为近标号六,变量,标号属性运算符前面已知由变量,标号,常量,寄存器内容和运算符组成的式子?地址表达式,它们的结果是地址,所以仍有属性,运算符除可以使用数值表达式的运算符外,
还有一些特别的(最常用)符号。
1,类型运算符 PTR( P36)
格式,〈 类型 〉 PTR〈 地址表达式 〉
类型 → BYTE,WORD,DWORD,NEAR,FAR
五种。
作用?指明表达式的类型,不管他原来有无类型,
均以 PTR前的类型为准。
只改变类型属性,不改变段属性和偏移地址属性。
例 1,DTA DB 33H,44H
MOV AX,DTA ╳
→ MOV AX,WORD PTR DTA √
表示临时改变 DTA为字类型。
例 2,MOV 4[SI],55H ╳
MOV BYTE PTR 4[SI],55H √
INC [BX] ╳
INC WORD PTR [BX] √
明确操作数类型。
例 3,A DW 1122H,3344H; 变量 A为字类型
B EQU BYTE PTR A; 变量 B字节单元
将同一存储单元用不同类型的变量(或标号)
来表示。
如,MOV AX,A
MOV AL,B
执行结果均是,AL= 22H
例 4,NEXT,MOV AX,0 ;定义 NEXT近标号
……
JMP FAR PTR NEXT
临时改变标号的类型为 FAR。
2,跨段前缀符,即跨段或段超越格式,〈 段寄存器名 〉,〈 地址表达式 〉
作用?用来临时改变变量,标号,地址表达式或指定的段属性,且只在所出现的语句中有效,不改变偏移地址和类型。
例,MOV AX,[BP] ;( SS,[BP]) → AX
MOV AX,DS,[BP] ;( DS,[BP]) → AX
3,取段地址算符 SEG?取变量或标号的段地址。
例,MOV AX,SEG DT1 ;取 DT1的段首址
→ AX,段首址为常数,因此立即寻址。
4,取偏移地址算符 OFFSET?取变量或标号的偏移地址。
例,MOV BX,OFFSET DT1 ;取变量 DT1的偏移地址 → BX,立即寻址。
等效,LEA BX,DT1 ;但为直接寻址。
作业,P72,10.
§ 2.3 符号指令的寻址方式一条符号指令,由操作码 (助记符 )指明进行什么样的操作,操作数告之操作的对象,操作数可以放在寄存器或存储单元中,寻找操作数 (地址 )的方式 ——寻址方式。
一、立即寻址 —— 操作数直接放在符号指令中 。
例,MOV AX,2000H ; AX=2000H
助记符 目的 源操作数注:立即数可以是 8位或 16位,负数用补码表示 。
例,MOV BL,- 1; BL=0FFH
MOV CX,- 5; CX=0FFFBH
立即寻址方式主要用来给寄存器或存储单元赋初值,也可以与寄存器或单元进行算术逻辑运算。
因为直接书写在指令中,操作对象直观,清晰,所以常用。
二,寄存器寻址 —— 操作数在指定的寄存器中例,MOV CX,BX ; CX=BX
寄存器可以是 8位或 16位的寄存器。
例,MOV CL,BH ; CL=BH
因为寄存器在 CPU内部,所以采用寄存器寻址可提高运行效率,特别是 AX,用它存放运算结果,则执行指令的时间短些,所以最常用。
三,直接寻址 —— 操作数在内存中,其偏移地址由指令直接给出。
而操作数一般在 DS段 (默认 )。
例,MOV AX,DS:2000H
或 MOV AX,[2000H]; (DS:2000H)?AX
偏移地址,又称 有效地址,此处源操作的 EA=2000H
若偏移地址是数值常量,则应在偏移地址前加段名。
区分立即数与直接寻址。
直接寻址常用已定义的变量表示 。
例,VARX DW 1122H,4455H
VARY DB 33H
MOV AX,VARX; AX=1122H
MOV BX,VARX+ 2 ; BX= 4455H
MOV BL,VARY; BL=33H
MOV VARY+1,AL; (VARY+1)=22H
四,寄存器间接寻址 —— 操作数在内存中,而操作数的地址的 16位偏移量包含 在 SI,DI,BX,BP
之一中,即寄存器的内容为操作数的 EA.
[SI]
[DI]
EA= [BX]
[BP]
1,若以 SI,DI,BX 间址,操作数在 DS段。
例,MOV AX,[SI] ; (DS:[SI])?AX,
即 (DS:[SI])?AL,(DS:[SI+1])?AH
2.若以 BP间址,操作数在 SS段 。
例,MOV AX,[BP] ; (SS:[BP])?AL,(SS:[BP+1])?AH
只有 SI,DI,BX,BP 可作为间址寄存器,如
MOV AX,[CX] ╳
间址时,寄存器的内容是有效地址,所以称为 地址指针,主要用于存取存储单元中的数据,只要修改寄存器内容,用一条指令便可访问一片连续单元。
如,INC SI
五,基址寻址 —— 操作数在存储器中,但操作数的 地址的偏移地址 在 BX或 BP中的内容与指令中给出的 8位或 16位位移量之和。
[BX] 8位或 16位
EA= [BP] + 位移量
1.若以 BX为基址,操作数在 DS段例,MOV BL,2[BX]
或 MOV BL,[BX+2] ; (DS:[BX+2])?BL
2,若以 BP为基址,操作数在 SS段例,MOV BX,6[BP]
或 MOV BX,[BP+6] ; (SS:[BP+6])?BL,
(SS:[BP+7])?BH
所以 BX,BP 称为基址寄存器。
六,变址寻址 —— 操作数在存储器中,但 操作数的偏移地址为 SI或 DI的内容与指令中给定的 8位或 16位位移量之和,与基址寻址类似。
[SI] 8位或 16位
EA= [DI] + 位移量例,MOV AX,- 2[SI]
或 MOV AX,[SI- 2] ; (DS:[SI- 2]) →AL,
(DS:[SI- 1]) →AH
操作数在 DS段,可用于变址的寄存器只能是 SI,DI,
所以称变址寄存器。
七,基址加变址寻址 —— 操作数在存储器中,但操作数的偏移地址 是指令中指定的基址寄存器的内容,
变址 寄存器内容及位移量之和,即前两种方式的组合。
[BX] [DI] 8位或 16
EA= [BP] + [SI] + 位移量例,MOV AX,4[BX][DI]
或 MOV AX,[BX+DI+4]; (DS:[BX+DI+4])? AL (DS:[BX+DI+5]) →AH
以 BX为基址寻址,操作数在 DS段,以 BP为基址寻址,
操作数在 SS段。
小结:
1.以上寻址方式,除立即寻址外,亦可用于目的操作数的寻址。
如,MOV 2[BX],AX; AX→ ( DS,[BX+2])
即 源 操作数 ——7种 方式,目的 操作数 ——6种 寻址方式
2.除以上 7种寻址方式,还有一种 隐含寻址 (implied
addressing),即操作数在符号指令中不显示出来,而隐含某寄存器为操作数。
如,PUSHF 仅有助记符,操作数隐含,源 → F,目的 → [SP]
POPF 源 → [SP],目的 → F
八,存储器寻址中段寄存器的指定
1,因为存储器分段管理,在内存中寻找操作数除了偏移地址外,指令中若没有特别声明,则段有一个 基本约定 → 默认状态,约定关系,P、
41、表 2- 1
访问存储器 约定 可更 偏移的方式 段 换段 地址取指令 CS 无 IP
堆栈操作 (PUSH,
POP,CALL,RET 等 ) SS 无 SP
数 通用数据存取据 (直接寻址,BX,DS CS,SS,ES EA
存 SI,DI,间址 )
取 以 BP间址,基址 SS CS,DS,ES EA
字符串源地址 DS CS,SS,ES SI
字符串目的地址 ES 无 DI
2,跨段或段超越当要否认以上默认状态,到其他段寻找操作数时,必须用 跨段前缀 指明操作数所在段的段寄存器名。
例,MOV AX,ES:[SI]; (ES:[SI]) →AL,(ES:[SI+1]) →AH
MOV AX,DS:[BP]; (DS:[BP]) →AL,(DS:[BP+1]) →AH
MOV AX,CS:[BX]; (CS:[BX]) →AL,(CS:[BX+1]) →AH
注意,显示说明高于默认状态 。
注:实际上,不管是跨段或默认段,操作数的 PA由系统 自动计算,程序中表示都使用逻辑地址,而不使用物理地址。
作业,P71,3.
§ 2.4 常用符号(机器)指令
8088系统有庞大的指令系统,形式多样,功能极强,
用 115个指令助记符 代表 91种操作,可分六大类:①
数据传送指令 ② 算术运算指令 ③ 位操作 (逻辑运算 )指令 ④ 串操作指令 ⑤ 控制转移指令 ⑥ 处理机控制指令。
注:学习时注意 指令格式及功能。
在此先介绍:传送,算术,位操作指令。
一,数据传送指令 —— 最基本、大量、主要操作
1.数据传送指令格式,MOV DST,SRC
目的操作数 源操作数功能:将源操作数传送至目的地址中,源保持不变。
( SRC) → DST
· 传送指令的特点是:把数据从计算机的一个部位传送 到另一个部位,把发送部位 → 源,接收部位 → 目的; 源 → SegReg,Reg,
Mem,Imm;目的 → SegReg,Reg,Mem.
· 两操作数 类型相同,即同为字节或字类型的数据。
· 类型明确,不能出现二义性 (即不能模糊 )。
· CS任何时候都不能为目的操作数,立即数亦不能为目的操作数。
· 源和目的 不能同时为 存储器操作数。
· 不影响任何标志位 (所有传送 )。能实现的传送示意如下,
段寄存器 SegReg ③ ④ 通用寄存器 Reg
CS,DS,ES,SS ①
⑧ ② AX,BX,CX,DX
⑨ ⑤ 立即数 Imm
存储器 Mem BP,SP,DI,SI
⑥ ⑦
由上表可总结出九种形式,P,42、
例:判断下列指令正确与否:
MOV AL,BL √
MOV CX,BX √
MOV BX,DL × 类型不一致
MOV DX,34H √
MOV DS,1234H × 立即数不能送段寄存器
MOV ES,AX √
MOV CS,BX × CS不能作目的操作数
MOV [SI],CX √
MOV [DI],10 × 源为立即数,无类型,
目的类型模糊,二义性
MOV [DI],[SI] × 不能同时为存储器
MOV 2000H,AX × 目的不能为立即数
MOV DS:2000H,AX √
2,数据交换指令格式,XCHG DST,SRC
操作,(DST)(SRC)
即源地址与目的地址中的内容互换
· 交换只能在通用寄存器 Reg之间,存储器 Mem与通用寄存器 Reg之间进行。 至少一方为 Reg.
例,XCHG AX,BX √
XCHG BH,BL √
XCHG AX,1122H ×
XCHG DS,AX ×
XCHG [SI],BP √
XCHG [SI],[DI] ×
3,地址传送指令? 将地址传送至目的
① 传送偏移地址格式,LEA Reg16,Mem
操作:将源操作数提供的寻址方式计算的有效地址
EA → Reg16
例,LEA SI,DS:2000H ; SI=2000H,即 EA→SI
LEA DI,[SI+2] ; DI=2002H
· 区分 MOV SI,DS:2000H; (DS:2000H) →SI
② 传送偏移地址及数据段首地址格式,LDS Reg16,Mem32→ 表示双字类型操作,(Mem32) →Reg16,(Mem32+2) →DS
或 (EA) →Reg16,(EA+2) →DS
亦即源地址指针的第一个字 → Reg16,第二个字 → DS。
用来传送一个目标地址 (段地址和偏移地址 ),常用来为存取非当前数据段中的数据作地址准备。
例:设 DS,1002 33 执行 MOV BX,1000H
1003 44 LDS SI,2[BX]; SI=4433H
1004 55 DS=6655H
1005 66
③ 传送偏移地址及附加数据段首地址指令格式,LES Reg16,Mem32
操作,(EA) →Reg16,(EA+2) →ES
· 除把目标段地址送 ES外,其它同 LDS。
4,查表转换指令格式,XLAT 或 XLAT SRC_ TAB
操作,([BX+AL]) →AL,即将 BX为首址,AL为位移量的字节单元的内容 → AL
· 该指令常用于进行代码转换,转换时先建立相应表。表首址 → BX,
与表有关的某个偏移值 (一般为被传送的字节到表头地址的字节数 ) →AL 。
·该指令的操作数是隐含寻址,不带操作数或带表头地址,
例,利用查表指令,求某数 (0~ 9)的平方值。如查 7的平方。
先建 0~ 9平方表,首址 → BX,待查值 → AL
TAB DB 00H,01H,04H,09H,16H,25H,36H,49H,64H,81H
LEA BX,TAB
MOV AL,7
XLAT ; AL=49BCD
注:以上传送类指令均不影响标志。
BCD数二,算术运算指令
8088提供了加、减、乘、除四种基本算术操作的 20种指令,可进行字节或字运算,也可用于带符号或无符号数的运算。
1,加法运算
① 加法指令格式,ADD DST,SRC
操作,(DST)+(SRC) →DST
即将目的操作数与源操作数相加,结果存入目的地址中,而源地址内容不变。
· 目的 → Reg,Mem 源 → Reg,Mem,Imm
只有 5种形式,P46。
· 两操作数的 类型相同,类型明确,不能同为存储器。
例:判断正确与否:
ADD AL,BX ×
ADD CL,CH √
ADD AX,[BX] √
ADD [BX],28 ×
ADD [BX],[SI] ×
ADD 1000H,AX ×
ADD [SI],BX √
ADD DS,BX ×
加法指令执行后的结果将 影响状态标志 。
例,MOV BL,97H
ADD BL,85H ; BL=1CH
1001 0111
+ 1000 0101
1 0001 1100
CF=1 OF=1⊕ 0=1 SF=0 ZF=0
一般算术运算关心四个算术标志,填入 F中,其余位填
0,F结构,F的格式,
D15 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
0 0 0 0 OF 0 0 0 SF ZF 0 0 0 0 0 CF
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1
得 F=0801H
② 带进位加法指令格式,ADC DST,SRC
操作,(DST)+(SRC)+CF→DST
· 该指令主要用于 多字节运算,多字节运算时低位字节产生的进位应加到高位。单字节表示一个数的范围小,精度低,为提高精度,可用多个字表示一个数。
如:一个字表示一个数 → 单精度数 (16位 ),两个字表示一个数 → 双精度 (32位 ),多个字 → 多倍精度等。
例,两个双精度数 (32位 )相加
0123FAB5H+0ABC212AH=0BE01BDFH 0123 FAB5
MOV DX,0123H + 0ABC 21 2A
MOV AX,0FAB5H 0BE0 1BDF
ADD AX,212AH ; 先加低字 CF=1 AX=1BDFH
ADC DX,0ABCH ; 高字带进位加 CF=0 DX=0BE0H
CF为前面指令产生的 CF
③ 增量(加 1) 指令格式,INC DST
操作,(DST)+1→DST
例,MOV BX,1
INC BX; BX=0002H
· 该指令不影响 CF,而影响其它标志,规律同 ADD。
· 单操作数指令,只能为 Reg,Mem,类型明确,不能出现二义性。
例,INC CL √
INC [DI] ×? INC BYTE PTR[DI] √
INC 2000H ×
· 该指令常用于修改偏移地址和计数次数。
2,减法指令
① 减法指令格式,SUB DST,SRC
操作,(DST) - (SRC) →DST
② 带借位减指令格式,SBB DST,SRC
操作,(DST) - (SRC) - CF →DST
除两操作数相减以外,再减去 前面指令的进位 (借位 )。
例:双精度数相减
5321A678H- 1234F000H=40ECB678H
MOV AX,0A678H
MOV DX,5321H 5321 A678
SUB AX,0F000H ; CF=1 - 1234 F000
SBB DX,1234H ; CF=0 30EC B678
③ 减量(减 1)指令格式,DEC DST
操作,(DST) - 1→DST
· DEC不影响 CF,其余标志均受影响,影响关系同 ADD
指令。
3,比较指令格式,CMP DST,SRC
操作,(DST) - (SRC) 比较后 影响标志,不回送结果 。
源、目的不变。该指令主要用来判断比较两数的大小,
与是否相等。
作业,P71,4,6,7,(2),(3),9.(3),(4).
三,位操作指令 — 包括逻辑运算与 移位类指令
1,逻辑运算
① 求补指令格式,NEG DST
操作,( DST) +1→DST
即将操作数单元的内容求反加 1后(包括符号位)
又送入原单元中,
例,MOV AX,1 ; AX=0001H (前+ 1)
NEG AX ; AX=0FFFFH (后- 1)
例,MOV BL,0FFH ; BL=0FFH (前- 1)
NEG BL ; BL=01H (后+ 1)
区分,它是进行求补操作,而不是求补码指令。它不管操作数是否带符号,是正是负,也不管是原码补码。
若将执行求码指令前后的数均视为补码形式的符号数,求补指令则将该数变为绝对值相等符号相反的另一个数 。若已知 AX中的一负数的补码,则只要
NEG AX,则求其绝对值。
·单操作数指令,操作数只能是 Reg,Mem,且类型明确。
影响标志,影响规律同减法类指令 。因为求补等效 0 –( DST) → DST
( 2)求反指令格式,NOT DST
操作,( DST) → DST,即将操作数的内容逐位取反后再送入。
例,MOV AX,1
NOT AX ; AX=0FFFEH
·该指令只是执行求反操作,而不是求反码指令,对符号位也求反。
·该指令不影响标志位 。
( 3)逻辑与指令(乘)
格式,AND DST,SRC
操作,( DST) ∧ ( SRC) → DST,两操作数按位逻辑与运算例,MOV AX,5555H
AND AX,0FFH ; AX=0055H→ 屏蔽高位(高位清零),取出低位;即对应位为 0则清 0,对应位为 1则不变?称这种数为 逻辑尺 。
( 4)逻辑或指令格式,OR DST,SRC
操作,( DST) ∨ ( SRC) → DST
即两操作数按位逻辑“或”运算例,MOV AX,8888H;
OR AX,0FFH ; AX=88FFH→ 对应
1位置 1,对应 0位则不变。
( 5)逻辑异或指令格式,XOR DST,SRC
操作,( DST) ⊕ ( SRC) →DST,
即两操作数按位异或例,MOV AX,3333H;
XOR AX,0FFH ; AX=33CCH→ 对应 0不变,对应
1求反例,XOR AX,AX ; AX=0 清零
有 4条指令可达到 AX清 0目的:
MOV AX,0
SUB AX,AX
AND AX,0
三条逻辑指令均为双操作数指令,对源,目的要求同
ADD,SUB指令,
三条逻辑指令均影响标志,使 CF=0,OF=0,而
PF,SF,ZF由结果而定,AF无意义,所以此类指令可用来清 CF,常用于拆字,拼字,
例,将 BX的高四位与 CX的低四位,AX的中间 8位反码,拼成新字送至 AX
如,AX=AAAAH BX=BBBBH
CX=CCCCH→ AX=B55CH
AND BH,0F0H ; 取 BX高四位,BH=B0H
AND CL,0FH ; 取 CL低四位,CL=0CH
AND AX,0FF0H ; 取 AX中间八位,AX=0AA0H
XOR AX,0FF0H ;求反 AX=0550H
OR AH,BH
OR AL,CL ; 拼字 AX=B55CH
(6) 测试指令格式,TEST DST,SRC
操作,(DST) ∧ (SRC) 根据测试结果 影响标志 (规律同 AND),不回送结果 。该指令主要用来检测目的操作数的某些位是 1或 0,根据测试结果,决定转向,
2.移位类指令
(1) 逻辑右移格式,SHR DST,CNT(移位位数为 1或 CL)
操作,0→ → CF
例,MOV AL,0CH ; AL=12
SHR AL,1 ; AL=6
该指令右移一次,等于对无符号数除 2运算,右移 N次,等于除 2N。
例,对 AX中的无符号数进行除 8运算(不考虑余数)
MOV CL,3
SHR AX,CL
( 2)算术右移格式,SAR DST,CNT(移位位数为 1或 CL)
操作,→ CF
例,MOV AX,–8 ; AX=0FFF8H→ - 8
SAR AX,1 ; AX=0FFFCH→ - 4
算术右移一位,等于 对带符号数进行 ÷ 2运算,右移 N
次,等于 ÷ 2N。
(3) 逻辑左移
格式,SHL DST,CNT
操作,CF ← ← 0
(4) 算术左移格式,SAL DST,CNT
操作,CF ← ←0
注,SAL指令与 SHL指令操作一样,即 机器码一样。
例,MOV BL,0CH ; BL=12
SHL BL,1 ; BL=24
左移一位,等于对操作数 (带符号或无符号 )乘 2运算,左移 N次,则乘 2N,但防止溢出,
例,对 AX内容进行乘 10运算 (设无溢出,乘 10后仍为一个字),
∵ AX * 10=AX * (23+2)=AX * 2+AX * 23
MOV BX,AX
SAL BX,1 ; * 2?BX
MOV CL,3
SAL AX,CL ; * 23?AX
ADD AX,BX ; * 10?AX
以上四条移位指令均影响 F标志,CF为最后输入值 。
(5) 循环右移格式,ROR DST,CNT
操作,→ → CF
(6) 循环左移格式,ROL DST,CNT
操作,CF ← ←
例,MOV AL,45H
MOV CL,4
ROL AL,CL ; AL=54H,高四位与低四位互换,
使用 ROR也一样。
(7) 带进位循环右移格式,RCR DST,CNT
操作,→ → CF
(8) 带进位循环左移格式,RCL DST,CNT
操作,CF ← ←
此四条循环移位指令只影响 CF,不影响其它标志。
当想把一个寄存器或单元的内容,移至另一个单元时,
常用带进位移,
前面指令产生的
CF移至最高位前面指令产生的
CF移至最低位例,将 AX中的无符号数乘以 10(AX=F0F0H)。
∵ 结果可能大于 216- 1=65535
∴ 要用两个寄存器存放,即积 → DL,AX
∵ * 10=*( 23+2) ∴ 可用移位和加法实现
XOR DL,DL ;积高位清零
SAL AX,1 ; * 2
RCL DL,1
MOV DH,DL ;* 2?DH,BX
MOV BX,AX
SAL AX,1 ;* 4
RCL DL,1
SAL AX,1 ;* 8?DL,AX
RCL DL,1
ADD AX,BX ;* 10
ADC DL,DH
另解,使用移位 3次的方法 (AX=F0F0H):
MOV BX,AX ;*2?DH:BX
ROL BX,1 ;BX=1110 0001 1110 0001B
MOV DH,BL ;DH=1110 0001B
AND DH,01H ;DH=0000 0001B
AND BX,0FFFEH ;BX=1110 0001 1110 0000B
MOV CL,3 ;* 8?DL,AX
ROL AX,CL ; AX= 1000 0111 1000 0111B
MOV DL,AL ; DL= 1000 0111B
AND DL,07H ; DL= 0000 0111B
AND AX,0FFF8H ; AX= 1000 0111 1000 0000B
ADD AX,BX
ADC DL,DH
作业,P72,5,8,(课本) 9.( 2),( 5),( 6),
§ 2.5 常用 DOS系统功能调用和
ROM BIOS中断服务子程序调用为使结果直观的显示在输出设备上,最简单的方法就是调用 DOS中的输入 /输出子程序。实际上 PC
系统为方便汇编用户提供了 两个程序接口,一个是 DOS系统功能调用,另一个是 ROM中的 BIOS
( Basic Input /OutpuT System)。它们由一系列中断服务子程序构成,由软中断指令 INT N
来调用。
一,DOS系统功能调用
1、调用过程是,
置入口参数功能调用号 → AH
执行 INT 21H
分析出口参数视具体情况而定
2、常用功能调用?键入,输出,打印。
参见 P63、表示 2- 3。
1号 → 键入一个字符 → 无入口参数出口:键入字 符 ASCII码值在 AL中,回显。
2号 → 显示一个字符 → 入口:将显示的字符 ASCII
送 DL → 无出口参数。
5号 → 打印一个字符 → 入口:将打印的字符 ASCII
送 DL → 无出口参数。
8号 → 键入一个字符 → 无入口参数 → 出口:
键入字符 ASCII值在 AL中,不回显,便于保密。
9号 → 显示一串字符 → 入口,DX指字符串首地址,字符串以 ‘ $ ’ 结束 → 无出口参数。
10号 → 键入一串字符 → 入口,DX指向输入缓冲区首址 → 出口:字符串个数在? 首址 +1―单元,字符串在? 首址 +2―单元。
11号 → 检查键盘有无键入 → 无入口参数 →
出口:有键入 AL=0FFH,无键入 AL=0。
例,MOV AH,1
INT 21H 等待键入一个字符 ASCII码值
→ AL
例,MOV AH,2
MOV DL,’ B’ 显示字符 ‘ B’
INT 21H
例,BUF DB ’HELLO’,0DH,0AH,’ $ ’
LEA DX,BUF
MOV AH,9
INT 21H
例,IBUF DB 4,?,4 DUP(?)
MOV DX,0FFSET IBUF
MOV AH,10
INT 21H
显示,HELLO
等待输入 3
个字符缓冲区最大长度实际输入个数存放输入的字符和回车符例,? 镜子? 程序?从键盘输入一串字符,在下一行照原样显示 (P67)。
STACK SEGMENT STACK
DW 32 DUP(?)
STAC ENDS
DATA SEGMENT
OBUF DB ’ ﹥ ’,0DH,0AH,’ $ ’
IBUF DB 0FFH,?,0FFH DUP(?)
DATA ENDS
CODE SEGMENT
BEGIN PROC FAR
ASSUME SS,STACK,CS,CODE,DS,DATA
PUSH DS PSP首址进栈,为返回 DOS设置
SUB AX,AX 返回地址
PUSH AX
MOV AX,DATA 设置用户数据段
MOV DS,AX
MOV DX,OFFSET OBUF
MOV AH,9 显示输入提示 ‘ 〉 ’
INT 21H 并 ↙,换行
LEA DX,IBUF 键入字符串
MOV AH,10 串长在 → IBUF+1
INT 21H 串首址 → IBUF+2
MOV BL,IBUF+1
MOV BH,0 长度 → BX
MOV IBUF[BX+2],’ $ ’ → 串尾存 ‘ $ ’
MOV DL,0AH 因为输入已有 ↙
MOV AH,2 所有只需换行
INT 21H
MOV DX,OFFSET IBUF+2
MOV AH,9 显示键入的串
INT 21H
RET PSP首址出栈 → CS,IP
BEGIN ENDP
CODE ENDS ; 结束用户程序
END BEGIN
FF IBUF
如输入,ABCDE↙ 内存分配 05 +1
41 +2
42
43
44
45
0D $( 24H)
例( P65),键入 4位十进制数,以压缩 BCD形式存入字变量 SW单元中。
IBUF DB 5,?,5 DUP(?)
SW DW?
MOV DX,OFFSET IBUF
MOV AH,10
INT 21H
MOV AX,WORD PTR IBUF+4
AND AX,0F0FH
MOV CL,4
SHL AL,CL
OR AL,AH
MOV BYTE PTR SW,AL
MOV AX,WORD PTR IBUF+ 2
AND AX,0F0FH
SHL AL,CL
OR AL,AH
MOV BYTE PTR SW+ 1,AL
作业,
P73,11,12,13.(作业本)
14.(课本)
二,BIOS基本输入 /输出系统功能调用
BIOS系统由一系列的服务程序构成,也是通过执行软中断指令 INT N 来调用。 BIOS包括系统服务程序和设备驱动程序。其驱动程序和 DOS
驱动程序相似,主要功能是驱动系统中所配置的常用设备,如显示器,键盘,打印机,磁盘驱动器以及异步通讯接口等。用户可方便的控制外设操作,和 DOS相比,它能完成 更复杂的、更细微的 I/O操作 。在此仅介绍键盘、打印机、显示器的服务程序。
1、调用方法和 DOS功能调用相同置入口参数 → 功能号送 AH → 执行 INT N
→ 分析出口参数
2,键盘输入子程序调用指令,INT 16H
有三个功能,功能号为,0~2 ( P68表 2- 4)
例,MOV AH,0
INT 16H
3,打印机服务子程序调用指令,INT 17H
有三个功能,功能号为,0~2
读一个字符 → AL
① AH=0? 功能:打印一个字符?入口:将打印字符
→ AL,打印机号 0~2 →DX 注,BIOS可支持三个打印机,
一般为 0号。
② AH=1 功能:初始化打印机
③ AH=2 功能:读打印机状态例,MOV AL,’ B’
MOV DX,0 打印 ‘ B’字符
MOV AH,0
INT 17H
4,显示子程序调用指令,INT 10H
有 16种功能,功能号为,0~15
参见 P,69?表 2- 5
例,在屏幕的 5行,10列位置显示闪烁的高亮度的‘$’。
MOV AH,0 设显示方式为 80列 × 25行的黑白
MOV AL,2 文本方式
INT 10H
MOV AH,15 读当前显示页号 → BH
INT 10H 因为下面 2号和 9号需设页号
MOV AH,2
MOV DX,050AH 设光标位置在 5行,10列
INT 10H
MOV AH,9 在当前光标位置写字 符和属性
MOV AL,’ $ ’ 设写字符 ‘ $ ’
MOV BL,8FH 字符显示属性 1000 1111
MOV CX,1 写一次
INT 10H 写高亮度闪烁的$
例,在 320× 200彩色图形方式下,在白色背景下,
在( 10,10)的位置写一个绿色点。
MOV AH,15
INT 10H 读显示器状态,暂存
PUSH AX
MOV AX,0600H 6号功能,AL=0 清屏
MOV CX,0 左上角坐标( 0,0)
MOV DX,184FH 右下角坐标( 24,79)
MOV BH,7 常规属性黑底白字
INT 10H 清屏
MOV AH,0
MOV AL,5 置 320× 200彩色图形方式
INT 10H 5?5FH,则设为 1024* 768
5?5BH,则设为 800* 600
MOV AH,11
MOV BH,0 设背景色
MOV BL,7 白色背景
INT 10H
MOV AH,11
MOV BH,1 设彩色组
MOV BL,0 彩色组 0
INT 10H
MOV AH,12
MOV DX,10
MOV CX,10
MOV AL,1
INT 10H 在( 10,10)处写绿色点象点颜色由彩色组和彩色值共同决定
WAT,MOV AH,1 无键入则等待
INT 16H 有键入则顺序执行
JZ WAT
POP AX
MOV AH,0 恢复原显示器状态
INT 10H 第二章结束
* 例,在 800× 600的图形方式下,设白色背景,
画一条品红色线,从( 0,0) ~( 599,599)。
注,
修改画点颜色,可画其他颜色的线,如 AL=0,则画青色线,AL=4则画棕红色线。
设置图形方式,与显示器适配卡有关。
INT 10H与 BIOS版本有关。
利用循环可画各种图形。
MOV AH,15
INT 10H 读显示器状态,暂存
PUSH AX
MOV AH,0
MOV AL,6AH 设显示器方式为 800?600
INT 10H
MOV AH,11
MOV BH,0
MOV BL,7 设白色背景
INT 10H
MOV AH,11
MOV BH,1
MOV BL,1 设彩色组 1
INT 10H
MOV DX,0 设初始点为( 0,0)
MOV CX,0
LOP,MOV AH,12
MOV AL,2
INT 10H 画线
INC DX
INC CX
CMP DX,599
JNE LOP
WAT,MOV AH,1
INT 16H 等待按键
JZ WAT
POP AX
MOV AH,0 恢复显示器状态
INT 10H