第5章 汇编语言程序设计 5.1 宏汇编语言的基本语法 5.2 伪指令 5.3 宏指令 5.4 汇编语言程序的结构 第5章 汇编语言程序设计 5.1 宏汇编语言的基本语法 5.2 伪指令 5.3 宏指令 5.4 汇编语言程序的结构 5.5 DOS系统功能调用 5.6 汇编语言程序设计方法 5.7 软件调试技术 习题 欢迎辞
汇编语言是用意义明确的助记符来表示指令的操作码、操作数。汇编语言是面向机器的语言,不同的机器有不同的汇编语言。用汇编语言编写的程序具有执行速度快、占用存储空间小、实时性能好等特点。汇编语言被大量用于编写计算机系统程序、实时控制程序等。 用汇编语言编写的程序称为汇编语言源程序(简称汇编语言程序)。计算机必须将汇编语言程序翻译成由机器代码组成的目标程序才能执行。这个翻译过程称为汇编。自动完成汇编过程的软件叫汇编程序。
5.1 宏汇编语言的基本语法 5.1.1 常数、变量和标号 1.常数 常数——没有任何属性的纯数值。在汇编期间,它的值已经完全确定,而且在程序的运行中也不会发生变化。它可以有以下几种类型: ⑴二进制数:以字母B结尾的由一串“0”和“1”组成的序列。例如:0010110B。 ⑵八进制数:以字母o或Q结尾,由若干个0到7的数字组成的序列。例如:255Q、 ⑶十进制数:由若干个0到9的数字组成的序列,可以以字母D结尾,也可以省略字母D。例如:1234D或1234。
⑷十六进制数:以字母H结尾,由若干个0到9的数字和字母A到F组成的序列,且必须以数字开头。例如:56H,0B3FH。 ⑸字符串常数:用引号括起来的一个或多个字符。这些字符以ASCII 码形式存在内存中。例如‘A’的值是41H,而‘B’的值是42H。因此串常量与整数常量可以交替使用。
注意:为了区别由A~F组成的一个字符串是十六进制数还是英文符号,规定凡以字母A~F为起始字符的十六进制数,必须在前面冠以数字“0”。 总之,常数主要以立即数、位移量的形式出现在指令语句或数据定义伪指令中。
⒉ 变量 变量——通常是存放在某些存储单元的数据,这些数据在程序运行期间可以修改。 变量名——表示数据在段中的有效地址,由用户指定。变量名是可选的,如果使用变量名,它代表数据区中第一个数据项的地址。 变量的三个属性: (1)段属性(SEGMENT):表示变量所在段的段首地址 (2)偏移属性(OFFSET):表示变量的偏移地址 (3)类型属性(TYPE):表示变量占用存储单元的字节数。
变量是用数据定义伪指令DB、DW、DD等定义的。 注意:变量也可以定义为一个数据区或存储区,但变量名仅表示该数据区或存储区的第一个数据单元(即数据区或存储区的首地址)。
⒊ 标号 表示一条指令所在的地址,也是指令语句的地址符号,常用作转移指令(包含子程序调用指令)的操作数,即目标地址。 通常由字母数字串组成,但第一个字符必须为字母。最多允许使用31个字符,且可以使用下划线(-)使标号容易阅读。
标号的三个属性: (1)段属性(SEGMENT):表示标号所在段的段基址 (2)偏移属性(OFFSET):表示标号的偏移地址 (3)距离属性(类型属性TYPE):表示标号作为段内或 段间的转移属性 距离属性分为两种: NEAR(近):表示本标号只能被标号所在段内的转 移和调用指令访问(即段内转移)。 FAR(远):表示本标号可以被其他段(不是标号所在段)的转移和调用指令访问(即段间转移)。
5.1.2运算符与表达式 表达式 地址表达式:产生的结果是一个存储器地址,若该地址存放的是数据,一般称它为变量,若存放的是指令,一般称它为标号. 数值表达式:只产生数值结果
运算符主要包括以下6种类型: ⒈ 算术运算符 包括:+、-、*、/、MOD(求余)、SHL(左移) 和右移(SHR) 例:CONT = 14*4 CONT = CONT/8 MOV AL, 21H SHL 2 2. 逻辑运算符 包括:AND、OR、XOR和NOT。只适用于对常数进行逻辑运算。 例: AND DX,PORT AND 0FEH
3.关系运算符 包括:EQ(相等)、NE(不相等)、 LT(小于)、GT(大于)、 LE(小于或等于)、GE(大于或等于)。 结果:若关系为假(不成立),结果为0; 若关系为真(成立),结果为0FFH或0FFFFH。 例: MOV BX,PORT LT 5 例: MOV BX,( (PORT LT 5) AND 20) OR ( (PORT GE 5) AND 30 ) 当PORT<5时,等价 MOV BX, 20 当PORT>5时,等价 MOV BX, 30
⒋ 分析操作符(数值返回运算符) ⑴ 取地址的偏移量 格式:OFFSET 变量名或标号 功能:取变量名或标号所在段的段内偏移量。 ⑵ 取段基址 格式:SEG 变量名或标号 功能:取变量名或标号所在段的段首地址。
功能:返回一个数字值。若TYPE加在变量名前,返回该变量的类型属性;若加在标号前,返回该变量的距离属性。 ⑶ 求变量名或标号的类型值 格式:TYPE 变量名或标号 功能:返回一个数字值。若TYPE加在变量名前,返回该变量的类型属性;若加在标号前,返回该变量的距离属性。 存储器操作数的类型值 属性 类型值 变量 BYTE 1 WORD 2 DWORD 4 标号 NEAR -1 FAR -2
⑷ 求长度 格式:LENGTH 变量名 功能:返回一个变量名所占存储单元(字节、字或双字)的数目。若变量是用重复定义子句说明的,则返回DUP前面的数值;其余返回1。 ⑸ 求大小 格式:SIZE 变量名 功能:返回变量名所占存储单元的字节数,它等于LENGTH和TYPE两个运算符返回值的乘积。
⒌ 综合运算符 (1) PTR运算符 格式:类型 PTR 表达式 功能:用于指出变量、标号或地址表达式的类型属性,新的类型只在当前指令内有效。 例: MOV BYTE PTR [DI],4 ;指明目的操作数为字节类型 JMP DWORD PTR [BP];指明目的操作数为双字类型
(2) THIS运算符 格式:THIS 类型 功能:把它后面指定的类型或距离属性赋给当前的变量、标号或地址表达式。 例: A EQU THIS BYTE B DW 20 DUP(?) 说明:A、B对应同一存储器地址,对变量A为字 节访问,对变量B为字访问,且A和B具有相同的段基址和偏移量。
注:THIS使下面的原标号或原变量有新的名字和类型,但不分配新的存储单元。 例:将数据表原来按字节定义使用,现改为按字定义使用。 WBUFFER1 EQU THIS WORD BUFFER DB 100 DUP(0) 二者段地址,偏移地址相同,类型不同。
⒍ 其他运算符 ⑴ HIGH和LOW运算符 格式: HIGH 表达式 LOW 表达式 功能:从运算对象中分离出高字节或低字节。 例:K1 EQU 1234H MOV AL,LOW K1 ;AL ← 34H MOV BL,HIGH K1 ;BL ← 12H
⑵ SHORT运算符 格式: SHORT 标号 功能:当转移的目标地址与本转移指令的下一条指令之间的字节距离在-128~127范围时,可以用SHORT运算符进行说明。 例10: L1: JMP SHORT L2 ┇ L2: MOV AX,BX 7. 运算符的优先级别(P122 表5-2)
5.2 伪指令 8086宏汇编语言有两种类型的语句: 指令语句:在汇编过程中被翻译成相应的目标代码,经连接后生成可执行的机器指令代码。 伪指令语句:(指示性语句)在汇编时被解释执行,由汇编程序来处理的一类操作,如数据定义,分配存储器等。 5.2.1 伪指令语句的格式 格式:符号名 定义符 操作数;注释 任选字段,必须以分号开始,和指令语句的注释的功能一样。 表示该语句的伪操作功能。定义符由汇编程序规定,宏汇编程序中使用了数十种定义符。 在伪指令语句的前面,可以是常量名、变量名、段名和过程名等。 标号后用“:”——在指令语句中 可以是常数(二、十、十六进制等)、字符串、常量名、变量名、标号和一些专用符号等。
5.2.2 常用伪指令 ⒈ 符号定义伪指令(赋值语句) ⑴ 等值伪指令 格式:符号名 EQU 表达式 功能:将表达式的值赋给符号名。 例: ALFA EQU 100 COUNT EQU ALFA 注意:符号名一旦被EQU定义,就不能再赋值,即不能用EQU再为符号名重新赋值。
⑵ 等号伪指令 格式:符号名 = 表达式 功能:将表达式的值赋给符号名。 说明:可以在程序中不同的地方多次使用以重新为符号名赋值。 例: ALFA = 100 MOV AL,ALFA ;AL←100 ALFA = ALFA+2 ; ALFA = 102
(3) 定义符号名伪指令 格式:符号名 LABEL 类型 功能:定义一个标号或变量,并指定其类型。 例: BARY LABEL WORD;定义BARY为字类型
⒉ 数据定义伪指令 格式:[变量名] DB 表达式 ;定义字节 [变量名] DW 表达式 ;定义字 [变量名] DD 表达式 ;定义双字 [变量名] DQ 表达式 ;定义8个字节 [变量名] DT 表达式 ;定义10个字节 表达式——是赋给变量的初始值,可以有一个,也可 以有多个,常见的有以下几种:
实际上是为数据分配存储单元,并把变量名作为该存储单元的名称。若要定义多个相同类型的数据,可用逗号把这些数据隔开,并依次分配在相邻的存储单元。 ⑴ 数值表达式 实际上是为数据分配存储单元,并把变量名作为该存储单元的名称。若要定义多个相同类型的数据,可用逗号把这些数据隔开,并依次分配在相邻的存储单元。 20H 30H 64H 00H 34H 12H 78H 56H 例: BUF DB 20H,30H BUF1 DW 100 DAT DW 1234H,5678H ;字变量DAT的内容为1234H,占用两个字节单元,下一个字单元即DAT+2单元的内容为5678H,仍是低字节存在低地址单元。 BUF BUF1 DAT
字符串必须用引号括起来,并且不超过256个字符,它们在内存中按地址递增顺序自左向右依次存放字符的ASCII码。 例:STRING DB ‘ABC’ STRING1 DB ‘ How are you? ’ 41H 42H 43H ‘H’ ‘O’ ‘W’ … ? STRING STRING1
⑶ ?——为数据项分配存储单元的一种方法,只是存储单元中不预置确定的值,常用来预留存储单元,存放程序的中间结果或最终结果。 ⑶ ?——为数据项分配存储单元的一种方法,只是存储单元中不预置确定的值,常用来预留存储单元,存放程序的中间结果或最终结果。 例: RESULT DB ?;预置一个字节单元,其值不定 ABC DB 12H , ?, ? , 24H DEF DW ?,895H ,? 12H 24H ABC 95H 08H DEF
⑷ 重复定义子句 DUP——可以为若干个重复数据分 配存储单元。 格式: n DUP (表达式) 说明: n:重复次数 表达式:重复的内容 例: C DB 100 DUP(0) TAB DB 100 DUP(5 DUP(1),2) 注意: (1) DUP操作可以嵌套。 (2)在定义变量及存储单元的同时,也定义了它们的类型属性。同一数据定义语句所定义的各存储单元具有相同的类型。
例: DA1 DB 3 DUP(5,?, 6); 从DA1地址单元开始存放三组“05H,预留,06H”共9个地址单元 DA2 DW 40 DUP(?);从DA2地址单元开始保留40个字共80个地址单元 DA3 DB 10 DUP(1, 2, 3 DUP(30,4);从DA3地址单元开始存放十组“01,02,30,04, … ,30, 04”,共占用80个字节。
05H 06H 01H 02H 1EH 04H : DA1 DA3 共 10 组
段名 SEGMENT [定位类型][组合类型][‘类别名’] ⒊ 段定义伪指令 格式: 段名 SEGMENT [定位类型][组合类型][‘类别名’] ┆段体 段名 ENDS 功能:把模块化分为若干个逻辑段。 每个SEGMENT/ENDS可定义一个逻辑段。 为该段起的名字,用来指出汇编程序为该段分配的存储器起始地址,开始的段名和结束的段名必须相同。 段体为段内的语句序列
4.段寄存器说明伪指令 格式: ASSUME 段寄存器 :段名[,段寄存器 :段名…] 功能:向汇编程序指示当前各段所用的段寄存器,设 定段寄存器与段的对应关系。 注意: ①本伪指令只是指示各逻辑段使用寄存器的情况,并没有对段寄存器内容进行装填。段寄存器的实际值(CS除外)还要由MOV指令在程序中装填数据。 ②也可用来取消段寄存器与段之间的对应关系(用NOTHING),然后再建立新的对应关系。
例: ASSUME DS: NOTHING ASSUME DS: DATAB MOV AX, DATAB MOV DS, AX
自定义符,开始、结束要相同;有三个属性(段地址,偏移地址和距离属性) ⒌ 过程定义伪指令 过程是程序的一部分,它可以被程序调用。每次 可调用一个过程,当过程中的指令执行完后,控制返 回调用它的地方。过程的定义是用过程定义伪指令完 成的。 格式: 过程名 PROC [NEAR / FAR] ┇ 过程体 RET 过程名 ENDP 自定义符,开始、结束要相同;有三个属性(段地址,偏移地址和距离属性) 可有多个RET,一般作为最后一条指令
例: CODE SEGMENT APRC PROC NEAR ADD AX, BX … RET APRC ENDP START: MOV AX, NOM CALL APRC …… CALL APRC ……. CODE ENDS END STAR
⒍ 模块定义及通信伪指令 汇编语言可以把程序划分成许多模块,并对每个 模块独立地进行汇编和调试。 ⑴ 模块开始伪指令 格式:NAME 模块名 功能:指明程序模块的开始,并指出模块名。 说明:模块名是自定义符,不能是系统保留字。若该项缺省,则取TITLE语句中的页标题6个字符;若没有TITLE语句,则取源程序文件名为模块名。
⑵ 模块结束伪指令(源程序结束伪指令) 格式:END 启动标号或过程名 功能:END表示一个模块(源程序)的结束。通知汇编程序源程序到此结束,并给出执行程序的入口位置。 例: START: MOV AX,DATA ┇ END START 注意:1)END与NAME联合使用,当NAME缺省时,END 只表示源程序的结束。 2)汇编处理只进行到END为止。
5.3 宏指令 ⒈ 宏定义及其调用 宏定义格式: 宏指令名 MACRO [形参,形参,┅] ┇ 宏体 ENDM 宏调用的格式为: 宏指令名 [实参,实参,┅] 例:为了实现ASCII码和BCD码之间的相互转换,往往需要把AL中的内容左移或右移4位。设左移4位,可用下列指令序列实现: MOV CL,4 SAL AL,CL
若多次使用,则可用一条宏指令来代替,宏定义如下: SHIFT MACRO MOV CL,4 SAL AL,CL ENDM 例24: ┇ MOV AL,[DI] ADD AL,[SI] SHIFT ;宏调用 MOV [BX],AL ┇
2. 带参数的 宏 SHIFT MACRO X MOV CL,X SAL AL,CL ENDM SHIFT 4
5.4 汇编语言程序的结构 5.4.1 汇编语言源程序的结构 一个标准的汇编语言源程序的框架结构: DATA SEGMENT ┇ 5.4 汇编语言程序的结构 5.4.1 汇编语言源程序的结构 一个标准的汇编语言源程序的框架结构: DATA SEGMENT ┇ DATA ENDS STACK SEGMENT PARA STACK ‘STACK’; STACK ENDS CODE SEGMENT ASSUME CS:CODE,SS:STACK,DS:DATA,ES: DATA START: MOV AX,DATA MOV DS,AX MOV ES,AX 定义数据段 定义堆栈段 定义代码段
MOV SS,AX MOV AX,STACK ┇ MOV AH,4CH INT 21H PRA PROC NEAR ┇ PRA ENDP CODE ENDS END START
5.4.2 汇编语言和DOS操作系统之间的接口 操作系统为每一个用户程序建立了一个程序段前缀区PSP,长度为256个字节,主要存放执行程序的有关信息以及程序和操作系统的接口。 在PSP的开始处(偏移地址IP=0000H)安排了一条INT 20H软中断指令,执行该服务程序后控制就转移到DOS。 代码段在程序段前缀区PSP后面,之后是数据段,堆栈段。
CODE SEGMENT : START PROC FAR PUSH DS MOV AX,0 PUSH AX : : RET START ENDP CODE ENDS END START
结束用户程序返回DOS有两种方法: 1:MOV AH ,4CH INT 21H 2:INT 20H
5.5 DOS系统功能调用 MS-DOS系统中设置了几十个内部子程序,在汇编语言源程序中可采用软中断指令调用它们。 MS-DOS中常用的软中断有8条,系统规定它们的中断类型码为20H—27H, INT 21H是DOS系统功能调用。 INT 21H中断本身包含很多子程序,调用它们时采用统一的格式: 1) 传送入口参数到指定寄存器中 2) 功能号送入AH寄存器 3) INT 21H
1. 键盘输入单字符——1号系统功能调用 格式:MOV AH,1 INT 21H 功能:无入口参数,执行时,系统等待键盘输入,待按下任何一键,系统先检查是否是Ctrl—Break键。若是则退出,否则将键入字符的ASCII码置入AL中,并在屏幕上显示该字符。
2. 键盘输入字符串——0AH号系统功能调用 功能:将键盘输入的字符串写入到内存缓冲区中,必须事先定义一个缓冲区。 缓冲区的第一个字节:该缓冲区存放的字节数。 第二个字节:预留,系统填写实际的字符数。 从第三个开始:存放字符串,回车(0DH)表示结束。 格式: ┇ BUF DB 20 DB ? DB 20 DUP(?) ┇ MOV DX,OFFSET BUF MOV AH,0AH INT 21H
3. 输出单字符——2号系统功能调用 格式: MOV DL,‘A’ MOV AH,2 INT 21H 功能:将DL中的字符送屏幕显示。
⒋ 输出字符串——9号系统功能调用 功能:将指定的内存缓冲区中的字符串在屏幕上显示出来,缓冲区的字符串以“$”为结束标志。 格式: BUF DB ‘GOOD BYE$’ ┇ MOV DX,OFFSET BUF MOV AH,9 INT 21H 结果:显示GOOD BYE 5. 返回操作系统——4CH号系统功能调用 格式: MOV AH,4CH INT 21H
例:利用DOS系统功能调用实现简单人机对话。 DATA SEGMENT BUF DB 100 DB ? DB 100 DUP(?) ;定义键入缓冲区 MSG DB ‘WHAT IS YOUR NAME? $’ DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX
DISP:MOV DX,OFFSET MSG MOV AH,9 ;调用9号功能调用 INT 21H ;显示字符串 KELBD:MOV DX,OFFSET BUF MOV AH,0AH ;调用0AH功能调用 INT 21H ;接收键入的字符串 MOV AH,4CH INT 21H ;返回DOS CODE ENDS END START
5.6 汇编语言程序设计方法 5.6.1 汇编语言程序设计步骤 1) 分析问题 2) 建立数学模型 3) 确定算法 4) 绘制程序流程图 5.6 汇编语言程序设计方法 5.6.1 汇编语言程序设计步骤 1) 分析问题 2) 建立数学模型 3) 确定算法 4) 绘制程序流程图 5) 内存空间分配 6) 编制程序与静态检查 7) 程序调试
5.6.2 汇编语言程序设计方法 1. 简单程序设计 例:假设有多项式形如:f(X)= 5X3 + 4X2 - 3X + 2 ,要求编制程序计算自变量X=5时函数f(X)的值。 分析:f(X)= ( (5X+ 4) X – 3) X + 2 程序: DATA SEGMENT X DW 5 RESULT DW ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX
MOV AX,5 MUL X ADD AX,4 SUB AX,3 ADD AX,2 MOV RESULT,AX MOV AH,4CH INT 21H CODE ENDS END START
2. 分支程序设计 (1)简单分支结构 有两种,相当于高级语言中的IF-THEN和IF-THEN-ELSE结构; 例: 比较两个无符号数的大小。(在A和B单元各有一个8位无符号数,要求比较这两个无符号数,并根据比较结果在屏幕上显示A>B或B>A(假设这两个数不相等))。 DATA SEGMENT A DB 20H B DB 92H DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX
MOV AL,A CMP B,AL JA BGA MOV DL,‘A’ MOV BL,‘B’ JMP DISP BGA: MOV DL,‘B’ MOV BL,‘A’ DISP: MOV AH,2 INT 21H MOV DL,‘>’ MOV DL,BL MOV AH,4CH INT 21H CODE ENDS END START
(2) 多分支程序设计 多分支结构则相当于高级语言中的DO-CASE结构。
3. 循环程序设计 ⑴ 循环程序的结构与组成 ① 循环的初始化部分 ② 循环工作部分 ③ 循环控制部分 ④ 循环结束部分 相当于高级语言中的 DO-UNTIL结构 DO-WHILE结构。 ⑵ 循环控制方法 计数法 条件控制法 在汇编语言程序设计中常采用CX作为循环计数器
已知从BUF单元开始存有20个8位带符号数,要求统计其中的负数个数放在NEGA字节单元,并显示在CRT上(设负数个数在0~9之间)。 例:统计负数个数并显示。 已知从BUF单元开始存有20个8位带符号数,要求统计其中的负数个数放在NEGA字节单元,并显示在CRT上(设负数个数在0~9之间)。 DATA SEGMENT BUF DB 2,-1,56,-38,4,… COUNT EQU 20 NEGA DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA
JNS NEXT ; SF=0(正数), 转NEXT INC DL ;为负,计数器+1 NEXT:INC SI LOOP LP START:MOV AX,DATA MOV DS,AX MOV SI,OFFSET BUF MOV DL,0 ;计数器清0 MOV CX,COUNT ;置循环次数 LP: MOV AL,[SI] AND AL,AL ;置标志位 JNS NEXT ; SF=0(正数), 转NEXT INC DL ;为负,计数器+1 NEXT:INC SI LOOP LP MOV NEGA,DL ;存结果 OR DL,30H ;转换成ASCII码 MOV AH,2 INT 21H ;显示
MOV AH,4CH INT 21H CODE ENDS END START
例: 统计字符串长度。已知在内存中从STR单元开始放有一串字符,以‘$’作为结束标志,长度不超过100字节,要求统计该字符串的长度,并存于LEN单元。 DATA SEGMENT STR DB ‘ABCDJKLLHH┅$’ LEN DB 0 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX
LEA DI,STR ;字符串首地址DI MOV AL,‘$’ ;结束标志 AL LP:CMP AL,[DI] ;比较,是否为‘$’ JZ STOP ;是 ‘$’ (ZF=1),转STOP INC LEN ; 不是,串长+1 INC DI JMP LP STOP:MOV AH,4CH INT 21H CODE ENDS END START
5.6.3 程序设计举例 例1:多字节压缩型十进制数加法 (减法) 已知有两个多字节的压缩型十进制数分别存于从A和B单元开始的数据区中,试将其相加并将十进制结果存于从C单元开始的数据区中。设压缩型十进制数长度为10个字节,被加数、加数和结果的低字节均存于低地址单元。
DATA SEGMENT A DB 12H,38H,63H,… B DB 88H,27H,42H,… C DB 11 DUP(?) N EQU 10 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV SI,OFFSET A MOV DI,OFFSET B MOV BX,OFFSET C
MOV CX,N CLC NEXT:MOV AL,[SI] ADC AL,[DI] DAA MOV [BX],AL INC SI INC DI INC BX LOOP NEXT MOV AL, 00H ADC AL, 00H MOV [BX], AL MOV AH,4CH INT 21H CODE ENDS END START
例2:已知从A单元开始存有10个字节的压缩BCD码,要求编程将其转换为ASCII码并显示在CRT上。 DATA SEGMENT A DB 34H,68H,76H,… N EQU $-A ;A中存放的个数 DATA ENDS STACK SEGMENT PARA STACK ‘STACK’ STA DB 100 DUP (?) STACK ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA, SS:STACK START:MOV AX,DATA MOV DS,AX
OR AL,30H ;将BCD码的高位转成ASCII码 MOV DL,AL MOV AH,2 INT 21H MOV AX,STACK MOV SS,AX MOV BX,OFFSET A MOV CX,N ;置循环次数 LP:MOV AL,[BX] MOV DH,AL ;保存次数 PUSH CX MOV CL,4 SHR AL,CL ;右移4位 POP CX OR AL,30H ;将BCD码的高位转成ASCII码 MOV DL,AL MOV AH,2 INT 21H 显示高位的BCD码
AND DH,0FH OR DH,30H ;将BCD码的低位转成ASCII码 MOV DL,DH INT 21H ;显示低位的BCD码 MOV DL,‘ ’ INT 21H ;显示空格 INC BX LOOP LP MOV AH,4CH INT 21H CODE ENDS END START
例3:将AL寄存器的内容以十六进制形式送屏幕 显示输出.
CODE SEGMENT ASSUME CS:CODE START:MOV BL,AL MOV BH,AL MOV CH,2 MOV CL,04H SHR BL,CL NEXT:CMP BL,09H JA NEXT1 OR BL,30H JMP NEXT2 NEXT1:ADD BL,37H NEXT2:MOV DL,BL MOV AH,02H INT 21H AND BH,0FH MOV BL,BH DEC CH JNZ NEXT MOV AH,4CH INT 21H CODE ENDS END START
练习: 编程将AX寄存器中的16位二进制数中‘1’的个数 放入DL寄存器中。
习题: 1. 从ARRAY开始的单元中存有20个16位无符号数,试编一完整程序找出其中最大数并存入MAX单元 . 2. 将AX寄存器的内容送屏幕显示输出。 3. 从存储器DATA1单元开始连续存放着50个组合BCD码,要求将它们转换成ASCII码,存放在以DATA2单元开始的存储区。高位BCD码转换成的ASCII码 ,放在地址较高的单元。 4. 从存储器DATA1单元开始连续存放着50个组合BCD码,要求将它们转换成ASCII码,存放在以DATA1单元开始的存储区。高位BCD码转换成的ASCII码 ,放在地址较高的单元。