《汇编语言》习题参考答案
1. 课程简介
本课程基于《汇编语言(第 2 版)》郑晓薇 编著,机械工业出版社,可以配合该教材使用。本课程由郑晓薇授权制作,提取教材中的实例以及实验内容,可以在实验楼环境中完成所有实例及实验。实验课程制作符合教材原版实例驱动教学以及实验训练贯穿始终的特点。
本教材可在 当当网 购买(点击链接即可进入购买页面)。
本课程实验列表中的最后模块(本节)为配套教材的习题参考答案,可供读者学习参考。
2. 习题参考答案
汇编语言是一门理论与实践相结合的课程,只有在大量的习题练习和编程训练下,才能很好地掌握基础理论与编程技巧。
本书在编写时采用实例与图示结合的方法使读者能够清楚、直观地看到程序的运行过程,便于更好地理解和掌握汇编语言。在每章内容之后都有相应的实验部分,旨在全面提升读者的综合应用能力和动手操作能力。每章之后的习题强调学习过程中的复习与练习,以加强读者对相关概念的学习与吸收。
本节给出教材各主要章节大部分习题的参考答案,供读者学习使用。
习题一答案
- 1.1
无符号数: 11010011=211=D3H,01110111=119=77H,10000011=131=83H,00101111=47=2FH,10101010=170=AAH
带符号数:11010011= -45=D3H,01110111=+119=77H,10000011= -125=83H,00101111=+47=2FH,10101010= -86=AAH
- 1.2
5E8AH,0BE6H,3DEH,4940H
- 1.3
00011101+00110101=01010010=52H=82, 01001001+11101000=00110001=31H=49, 10111110+01010010=00010000=10H=16, 10011010+11110001=10001011=8BH= -117
- 1.4
00101001+01010011=01111100+00000110=10000010=82H=82, 01110011-00100100=01001111-00000110=01001001=49H=49, 01100110+00011000=01111110+00000110=10000100=84H=84, 0000000100110010+01110101=0000000110100111+00000110 =0000001000000111=0207H=207
- 1.5
000020A3H,FF94H,00003456H,007FH,FFFFEC00H
- 1.6
无符号数:0~65535,0000H~FFFFH;带符号数:-32768~+32767,8000H~7FFFH
- 1.7
(1) 38H 等于十进制数 56,是十进制数 56 的补码,数字 8 的 ASCII 码,十进制数 38 的压缩 BCD 码
(2) FFH 等于十进制数 -1,是带符号数 -1 的补码,无符号数为 255
(3) 5AH 等于十进制数 90,是十进制数 90 的补码,大写字母 Z 的 ASCII 码
(4) 0DH 等于十进制数 13,是十进制数 13 的补码,回车符的 ASCII 码
- 1.8
(1) 108=01101100B=6CH,补码 01101100B,压缩 BCD 码 0000000100001000,ASCII 码 313038H
(2) 46=00101110B=2EH,补码 00101110B,压缩 BCD 码 01000110,ASCII 码 3436H
(3) –15=11110001B=F1H,补码 11110001B,ASCII 码 2D3135H
(4) 254=0000000011111110B=00FEH,补码 0000000011111110B,压缩 BCD 码 0000001001010100,ASCII 码 323534H
- 1.9
(1) 56+63=01110111B,CF=0,SF=0,ZF=0,OF=0 (2) 83-45=00100110B,CF=0,SF=0,ZF=0,OF=0 (3) -74+29=11010011B,CF=0,SF=1,ZF=0,OF=0 (4) -92-37=01111111B,CF=1,SF=0,ZF=0,OF=1
- 1.10
回车、换行、响铃、ESC 键、空格键、@、P、p
习题二答案
- 2.9
最少划分为 16 个逻辑段,最多划分为 65536 个逻辑段(每段 16 个字节)
- 2.10
CS:IP,DS:BX、SI、DI,ES:BX、SI、DI,SS:SP、BP
- 2.11
字节单元保存 8 位数,字单元保存 16 位数。根据源操作数的属性确定要访问的是字节单元还是字单元。
- 2.12
对于字节单元来说,偶地址和奇地址一样;对于字单元而言,最好用偶地址保存,可减少 CPU 的访存次数。
- 2.13
首单元的物理地址=38AE8H,末单元的物理地址=38AE8H+7FFFH=40AE7H
- 2.16
(1)物理地址=27679H
(2) 物理地址=20F92H
(3) 物理地址=20F92H
(2)和(3)的物理地址是一样的。说明逻辑地址不唯一,多个逻辑地址可对应到同一个物理单元上。
- 2.17
代码段 CS:IP 的物理地址=55A84H,堆栈段 SS:SP 的物理地址=4DB65H,数据段 DS:BX 的物理地址=17678H,附加段 ES:DI 的物理地址=2BA41H
- 2.18
当前栈指针所指单元的物理地址是 1522CH。堆栈区中还能保存 254 个字。
- 2.19
执行 E 200
- 2.20
执行 U 100
- 2.21
执行 R CX,然后输入 100
- 2.22
执行 E DS:0 ‘a’ ‘b’ ‘c’ ‘d’
习题三答案
- 3.3
MOV AX,BX ;源操作数为寄存器寻址,EA 无,物理地址 无
MOV AX,1290H ;立即寻址,EA 无,物理地址 无
MOV AX,[BX] ;寄存器间接寻址,EA=1290H, 物理地址=2FBB0H
MOV AX,DS:[1290H] ;直接寻址,EA=1290H, 物理地址=2FBB0H
MOV AX,[BP] ;寄存器间接寻址,EA=6756H, 物理地址=26A56H
MOV [DI][BX],AX ;目的操作数为基址变址寻址,EA=3C06H, 物理地址=32526H
MOV ES:[SI],AX ;寄存器间接寻址,EA=348AH, 物理地址=50CAAH
- 3.7
MOV AX,[CX] ;错。CX不能为间址寄存器
MOV AL,1200H ;错。立即数超出8位寄存器范围
MOV AL,BX ;错。两个操作数不匹配
MOV [SI][DI],AX ;错。两个变址寄存器不能在一起
MOV ES:[DX],CX ;错。DX不能为间址寄存器
MOV [AX],VALUE ;错。AX不能为间址寄存器
MOV COUNT,[SI] ;错。两个操作数不能都是存储单元
- 3.8
;(1)
MOV AX,BX
;(2)
MOV CL,15
;(3)
ADD AX,[BX]
;(4)
MOV [BX+SI],AL
;(5)
MOV AX,VALUE[SI]
;(6)
SUB AX,DS:[2000H]
- 3.9
;(1)
ADD AX,[X+3]
;(2)
MOV BX,3
;(3)
MOV BX,3
MOV Y,AX
ADD AX,X[BX]
MOV SI,OFFSET X
MOV Y,AX
ADD AX,[BX+SI]
MOV Y,AX
- 3.10
立即寻址方式中操作数(立即数)和指令一起存放在代码段中。
习题四答案
- 4.10
;(1)
DATA SEGMENT
X DW 0
Y DW 0
DATA ENDS
;(2)
STRING DB ’Computer’
;(3)
COUNT DB 100 DUP(?)
;(4)
PI EQU 3.14
;(5)
VALUE LABEL BYTE
- 4.11
(1)对。
(2)错。260 超出了字节范围。
(3)错。X3 是字节型,1234H 是字型,不匹配。
(4)对。
(5)错。缺少 DUP。
(6)对。
- 4.12
(1)AL=3。
(2)AX=2103H。
(3)DX=TABLE 的偏移地址。
(4)CL=33H
(5)BX=TABLE 的段地址。
(6)BX=1。
(7)DX=TABLE 的偏移地址。
- 4.13
MOV DX,2012H
MOV AX,5D68H
MOV CX,1003H
MOV BX,49A6H
ADD AX,BX (SUB AX,BX)
ADC DX,CX (SBB DX,CX)
- 4.14
SUB AX,CX
SBB DX,0
- 4.15
MOV AX,extra
MOV ES,AX
- 4.16
;(1)
MOV AL,16
ADD AL,X
MOV BL,5
IMUL BL
MOV Z,AX
;(2)
MOV BL,4
MOV AL,X
IDIV BL
SUB AL,Y
MOV Z,AX
;(3)
MOV AL,X
MOV BL,8
IMUL BL
MOV DX,AX
MOV AH,0
MOV AL,Y
MOV BL,16
IDIV BL
CBW
ADD DX,AX
MOV AH,0
MOV AL,W
IMUL AL
SUB DX,AX
MOV Z,DX
;(4)
MOV AL,X
ADD AL,Y
MOV BL,X
SUB BL,Y
MOV AH,0
IMUL BL
MOV Z,AX
MOV AL,X
IDIV Y
CBW
SUB Z,AX
- 4.17
Z = (5+22-15)*14= 168
- 4.18
从伪指令 END START 处获知程序从 START 标号开始。
- 4.19
(1)减法:
MOV AX,8576H
MOV BX,9988H
SUB AX,BX
结果:AX=EBEEH,CF=1,OF=0,ZF=0,SF=1
(2) 加法:
MOV AX,8576H
MOV BX,9988H
ADD AX,BX
结果:AX=1EFEH,CF=1,OF=1,ZF=0,SF=0
- 4.21
;(1)
MOV AL,56H
MOV BL,34H
ADD AL,BL
DAA
MOV Y1,AL
;(2)
MOV AX,128H
MOV BX,35H
SUB AX,BX
DAS
MOV Y2,AL
;(3)
MOV AL,68H
MOV BL,23H
ADD AL,BL
MOV BL,45H
SUB AL,BL
DAS
MOV Y3,AL
- 4.22
;(1)
MOV AX,0708H
MOV BX,0406H
ADD AL,BL
ADD AH,BH ;不用带进位加
AAA ;加法调整,含进位调整
MOV BX,AX
XCHG AH,AL ;高4位调整
AAA
MOV BH,AL
MOV Z1,BX ;保存十位、各位,百位在CF中
;(2)
MOV AX,0905H
MOV BX,0207H
SUB AL,BL
SUB AH,BH ;不用带借位减
AAS ;减法调整
MOV Z2,AX
;(3)
MOV AX,0102H
MOV BX,0006H
MUL BX ;乘法先不用调整
MOV BX,0303H
SUB AX,BX
AAS ;减法调整
MOV Z3,AX
;(4)
MOV AX,0704H
MOV BX,0108H
ADD AL,BL
ADD AH,BH
AAA ;加法调整
MOV BL,6
AAD ;除法调整
DIV BL
MOV BH,AH ;余数保存在BH
AND AX,000FH
AAA ;商调整
MOV Z4,AX ;保存商
- 4.23
编程序。从键盘输入一个数字,去掉 ASCII 码后保存到 BUFF 单元。
.model small
.data
buff db ?
.code
start:
mov ax,@data
mov ds,ax
mov ah,1 ;键盘输入
int 21h
sub al,30h ;去掉ASCII码
mov buff,al
mov ah,4ch
int 21h
end start
- 4.24
编程序。将键盘输入的小写字母变为大写字母显示在屏幕上。
.model small
.code
start:
mov ah,1 ;键盘输入
int 21h
sub al,20h ;变为大写
mov dl,al
mov ah,2
int 21h
mov ah,4ch
int 21h
end start
- 4.25
X 和 Y 都是字节型数据,编写将两数相加的结果显示出来的程序段。
.model small
.data
x db 12h
y db 34h
.code
start:
mov ax,@data
mov ds,ax
mov al,x
add al,y ;结果为46H
mov ah,al ;AH=46H
and al,0fh ;AL=06H
mov cl,4
rol ah,cl ;AH=64H
and ah,0fh ;AH=04H
add ax,3030h ;AX=3436H
mov bx,ax
mov dl,bh ;显示4
mov ah,2
int 21h
mov dl,bl ;显示6
int 21h
mov ah,4ch
int 21h
end start
- 4.26
编写程序,建立一个 0~9 的平方根表,查表可得某数的平方根。
data segment
x db '0.000','1.000','1.414','1.732','2.000'
db '2.236','2.449','2.646','2.828','3.000' ;建立字符表
y db 5 dup(?) ;存放查到平方根
u db 3 ;要查的数
data ends
code segment
assume cs:code,ds:data
start:
mov ax,data
mov ds,ax
mov al,u ;要查的数
mov cl,5
mul cl ; (u×5=15号单元开始)
mov ah,0
mov bx,ax ;地址保存到bx
mov si,0
let1:
mov al,x[bx] ;取出平方根数字
mov y[si],al ;存入y
inc si
inc bx
loop let1 ;循环取出5次
mov ah,4ch
int 21h
code ends
end start
- 4.27
编写查表程序。建立一个班级姓名表,给出学号,可显示出其姓名。
.model small
.data
x1 db 'zhang yan $' ;姓名为10个字符宽度
x2 db 'li li $'
x3 db 'wang lan $'
x4 db 'zhao xue $'
x5 db 'li jiang $'
u db 3 ;要查的学号
.code
start:
mov ax,@data
mov ds,ax
mov al,u ;给出学号
mov cl,10
mul cl ;u×10=30(号单元开始)
mov ah,0
mov dx,ax ;地址保存到dx
mov ah,9 ;9号功能显示字符串
int 21h
mov ah,4ch
int 21h
end start
- 4.28
编程实现公式计算 Z=X/4+16Y。
.model small
.data
x db 4
y db 6
z db ?
.code
start:
mov ax,@data
mov ds,ax
mov al,x ;
mov cl,2
sar al,cl ; X/4
mov cl,4
mov bl,y
sal bl,cl ;16Y
add al,bl ;X/4+16Y
mov z,al
mov ah,4ch
int 21h
end start
- 4.29
编写程序段,将 AL 中的数乘以 6,与 CL 相减后再除以 3;把商保存到 Y 单元,余数保存到 Y + 1 单元。
.model small
.data
y db ?,?
.code
start:
mov ax,@data
mov ds,ax
mov al,3 ;设al=3
mov cl,6
mul cl ;al×6
mov cl,4 ;设cl=4
sub al,cl ;相减
mov bl,3
idiv bl ; /3
mov y,al ;商
mov y+1,ah ;余数
mov ah,4ch
int 21h
end start
习题五答案
- 5.11
进位标志 CF=1
- 5.12
先把 AX 的值除以 8 等于 0246H,再把高 12 位屏蔽为 0,剩下 AL=06H 加上 30H 变为 ASCII 码显示出来。
- 5.13
判断 X>0,是,Z=X-Y;否则 Z=X 的绝对值
- 5.14
(1) 目的操作数是存储单元时,要用 PTR 伪操作指出单元的属性。
(2) DS 段寄存器使用非法
(3) 立即数使用非法。
(4) 目的操作数不允许是立即数
(5) 两个操作数不允许都是存储单元
(6) 移位次数超过 1 要用 CL 表示。
- 5.15
AND AL,11011111B
- 5.16
(1) AL=30H
(2) AL=B7H
(3) AL=C8H
(4) AL=38H
- 5.27
分支程序设计。完成如下公式的计算,请写出程序。
(X+3)/2 X>0
Y=0 X=0
X×4 X<0
程序:
DATA SEGMENT
X DB 23
Y DB ?
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
MOV DS,AX
MOV AL,X
CMP AL,0
JE SUB2
JG SUB1
MOV CL,2
SAL AL,CL
JMP SHORT SUB2
SUB1:
ADD AL,3
SAR AL,1
SUB2:
MOV Y,AL
MOV AH,4CH
INT 21H
CODE ENDS
END START
- 5.28
设 X、Y、Z 为字节单元。如果 X≥0,Z=4X-Y/16,否则,Z=X 的绝对值。编程序实现。
程序如下:
DATA SEGMENT
X DB 3
Y DB 5
Z DB ?
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV DS,AX
MOV AL,X
CMP AL,0
JL SS1
MOV CL,2
SAL AL,CL
MOV BL,Y
MOV CL,4
SAR BL,CL
SUB AL,BL
JMP OUT1
SS1: NEG AL
OUT1: MOV Z,AL
MOV AH,4CH
INT 21H
CODE ENDS
END START
- 5.29
字数组 M 中有 10 个数据,分类统计其中正数、负数、0 的个数,分别存入 POSI、NEGA、ZERO 单元。
程序如下:
DATA1 SEGMENT
M DW 21,-34,32,112,-324,0,76,0,48,50
POSI DW ?
NEGA DW ?
ZERO DW ?
DATA1 ENDS
CODE1 SEGMENT
ASSUME CS: CODE1,DS:DATA1
START: MOV AX,DATA1
MOV DS,AX
MOV CX,10
LEA SI,M
AGAIN: CMP WORD PTR [SI],0
JL LOWER
JE EQUAL
INC POSI
JMP LPP1
LOWER: INC NEGA
JMP LPP1
EQUAL: INC ZERO
LPP1: ADD SI,2
DEC CX
JNZ AGAIN
MOV AH,4CH
INT 21H
CODE1 ENDS
END START
- 5.30
试编写程序,从键盘接收一英文单词,以空格结束,将其存入 BUF 开始的存储单元中,并在最后加上字符串结束符 ’$’。
主要程序部分:
LEA BX,BUF
LOP: MOV AH,1
INT 21H
CMP AL,20H
JE NEXT
MOV [BX],AL
INC BX
JMP LOP
NEXT: MOV BYTE PTR[BX],’$’
- 5.31
编程。将 AX 寄存器中的 16 位数分成 4 组,每组 4 位,从低到高分别放在 AL,BL,CL,DL 中。
程序段:
START:MOV AX,1234H
MOV BX,AX
AND AL,0FH ;4
AND BL,0F0H ;3
AND AH,0FH
MOV CL,AH ;2
AND BH,0F0H
MOV DL,BH ;1
习题六答案
- 6.11
累加和 TOTAL=83
- 6.12
循环统计 X 中 0 的个数
- 6.13(1) 将 BB1:RCL AL,1 改为 BB1:ROL AL,1
(2) 将
BB2:CMP [BX],’T’
LOOPNE BB2
改为:
DEC BX
BB2:INC BX
CMP [BX],’T’
LOOPNE BB2
- 6.15
计算 Y=1×2+3×4+5×6+7×8+9×10 的程序段。
MOV AL,1
MOV BL,2
MOV DX,0
MOV CX,5
AA1:MUL BL
ADD DX,AX
INC BL
MOV AL,BL
INC BL
LOOP AA1
- 6.16
写程序段。查找 CATT 表中的字符”@”,找到后将 SIGN 单元置 1,否则 SIGN 单元置 0。
catt db 'asd@ddd'
sign db ?
……
mov ax,extra
mov es,ax
mov sign,0
mov al,'@'
lea di,catt
cld
mov cx,7
repnz scasb
jcxz nee
mov sign,1
nee: mov ah,4ch
int 21h
- 6.17
写程序段。在长度为 N 的字数组 VALUE 中统计负数的个数并保存到 AX 中。
value dw 2,-4,-5,3,6,6,-8
n equ ($-value)/2 ;元素个数
……
start: mov ax,data
mov ds,ax
mov cx,n
mov bx,0
mov ax,0
rept1:
mov si,value[bx] ;取出元素
cmp si,0
jge let1 ;≥0 转let1
inc ax ;为负数,ax加1
let1: add bx,2
loop rept1
- 6.18
从键盘输入一个数字,在屏幕上显示出以该数字开始 10 个数字串。
CODE SEGMENT
ASSUME CS:CODE
START: MOV AH,1
INT 21H
MOV CX,10
MOV BL,AL
REPT1: CMP BL,'9'
JLE NEXT
SUB BL,10
NEXT: MOV DL,BL
MOV AH,2
INT 21H
INC BL
LOOP REPT1
MOV AH,4CH
INT 21H
CODE ENDS
END START
- 6.19
编程。比较两个字符串是否相同,统计并显示出相同的字符个数和不同的字符个数。
data segment
bunch1 db 'stadent'
bunch2 db 'studEnt'
data ends
code segment
assume cs:code,ds:data,es:data
start:
mov ax,data
mov ds,ax
mov es,ax
lea si,bunch1
lea di,bunch2
mov bx,0 ;bh=相同的个数,bl=不同的个数
mov cx,7
let1:
mov al,[si]
cmp al,[di] ;两字符比较
jz equl ;相同转equl
inc bl ;不同bl加1
jmp out1
equl: inc bh
out1:inc si
inc di
loop let1
mov dl,'n' ;显示'n',代表不同
mov ah,2h
int 21h
add bl,30h ;加上ASCII码
mov dl,bl ;显示不同的个数
int 21h
mov dl,'e' ;显示'e',代表相同
int 21h
add bh,30h
mov dl,bh ;显示相同的个数
int 21h
mov ah,4ch
int 21h
code ends
end start
- 6.21
STRI 单元存有 10 个字符的字符串,以 0 结尾,编程去掉其中的空格符,并将后续字符向前递补。
DATA SEGMENT
STR DB ‘SDABF G H0’
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
MOV DS,AX
LEA DI,STR
SPACE:MOV CX,10
MOV AL,[DI]
CMP AL,0
JE OUT
CMP AL,20H
JE DELETE
JMP EXIT
SUB CX,DI
MOV SI,DI
DELETE:
MOV BL,[SI+1]
MOV [SI],BL
INC SI
LOOP DELETE
EXIT:JMP SPACE
OUT:MOV AH,4CH
INT 21H
CODE ENDS
END START
- 6.23
将内存中用 ASCII 码表示的 100 以内的十进制数转变为二进制数。十进制数不够 3 位以 20H(空格)补齐。
设计思路:
(1)用 EQU 伪指令获得需转换的十进制数的个数;
(2)用双重循环。外循环控制个数,用 x 作为中间变量;
(3)内循环将一个 3 位十进制数去掉 ASCII 码后按位数扩大 10 倍再相加,保存后即存储为二进制数;
(4)分两个数组保存 ASCII 码表示的十进制数和转换后的二进制数。
程序如下:
; 6-23.asm 将内存中用ASCII码表示的100以内的十进制数转变为二进制数
data segment
score1 db 36h,37h,20h,31h,30h,30h,38h,35h,20h,31h,30h,30h ;即67,100,85,100
x dw ?
n equ 3 ;三位数
num equ (x-score1)/n ;十进制数个数
score2 dw num dup(0) ;保存转换后的二进制数
data ends
code segment
assume cs:code,ds:data
start: mov ax,data
mov ds,ax
mov cx,num
mov si,-2
mov bx,0
rept1: push cx ;保存外循环次数
mov cx,n
rept2: mov al,score1[bx] ;从score1取数
cmp al,30h ;判断是否0-9
jl exit
cmp al,39h
jg exit
and ax,000fh ;去掉ASCII码
xchg ax,x
mov dx,10 ;将ax中前一次形成的数扩大10倍
mul dx
xchg ax,x
add x,ax ;相加后保存到x
exit: inc bx ;取下一位数
loop rept2
pop cx ;弹出外循环次数
add si,2
mov ax,x
mov score2[si],ax ;转换后的数据保存到score2
mov x,0
loop rept1
mov ah,4ch
int 21h
code ends
end start
运行结果:
可以看到,67 转换为 0043,100 转换为 0064,85 转换为 0055。在 DEBUG 下显示的内存单元是十六进制表示,实际存储的是二进制数。
习题七答案
- 7.12
功能:两个字节数相加。X 和 BL 相加保存到 Y。
- 7.13
功能:键盘输入的字符保存到 KEY 单元中,直到按回车为止。
- 7.14
功能:将 X 单元中的十六进制 3AH 变为十进制入栈保存,AH 中为余数。先将 0008H 入栈,再将 0005H 入栈,结果为 58。
- 7.16
写出子程序,从键盘输入一个多位十进制数,并分别保存到 BUFFER 开始的单元中。
KEY_IN PROC
PUSH AX
PUSH BX
MOV BX,0
LET1:MOV AH,1
INT 21H
CMP AL,0DH ;输入回车退出
JZ EXIT
MOV BUFFER[BX],AL ;保存到BUFFER
INC BX
JMP LET1
EXIT:POP BX
POP AX
RET
KEY_IN ENDP
- 7.17
从键盘输入多位数字,转换成十进制数并保存到 X 单元中。
KEY_IN_DEC PROC
PUSH AX
PUSH BX
MOV X,0
MOV BX,0
MOV SI,0
LET1:MOV AH,1
INT 21H
CMP AL,0DH ;输入回车退出
JZ EXIT
MOV BUFFER[SI],AL ;保存到BUFFER
INC SI
JMP LET1
EXIT:MOV CX,SI ;位数放在CX
MOV SI,0
LET2:MOV AL, BUFFER[SI]
SUB AL,30H
MOV AH, 0
XCHG AX,X ;形成十进制数
MOV BX,10
MUL BX
XCHG AX,X
ADD X,AX ;保存
INC SI
LOOP LET2
POP BX
POP AX
RET
KEY_IN _DEC ENDP
- 7.23
写出对内存单元 X 中的补码求真值子程序,补码保存在 AX 中。
calcu proc
push ax
push bx
push si
mov ax,0
mov al,x
and al,al
jns zz
neg al
mov fuhao,'-'
zz:
mov si,0
mov bx,10 ;将ax变为十进制数真值
let1:
mov dx,0
inc si ;统计余数个数
idiv bx
mov y[si], dx ;在y单元保存余数
cmp ax,0
jnz let1
pop si
pop bx
pop ax
ret
calcu endp
- 7.30
编制一个计算数组中所有负数之和的子程序。并利用此子程序分别计算 A 数组和 B 数组中的负数之和,结果分别放在 SUM1 和 SUM2 单元中。
DATA SEGMENT
A DB 9,-8,-7,6,5
B DB -8,7,6,-5,4
SUM1 DB ?
SUM2 DB ?
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
MOV DS,AX
MOV CX,5
MOV SI,OFFSET A
CALL LADD
MOV SUM1,BL
MOV SI,OFFSET B
CALL LADD
MOV SUM2,BL
MOV AH,4CH
INT 21H
LADD PROC NEAR
PUSH CX
PUSH AX
PUSH SI
XOR BL,BL
NEXT: MOV AL, [SI]
AND AL,AL
JNS JJJ
ADD BL,AL
JJJ: INC SI
LOOP NEXT
POP SI
POP AX
POP CX
RET
LADD ENDP
CODE ENDS
END START
习题八答案
- 8.16
宏的作用:DOS 功能调用。功能号用哑元指出。
- 8.17
宏的作用:两个操作数相加,结果保存在第 3 个数中。
- 8.18
宏的作用:DOS 的 2 号显示功能。
- 8.19
宏的作用:定义 VALUE 数组,数组长度和初值由哑元指出。
- 8.20
缺少标号定义 LOCAL LETT1。宏的作用:两个哑元相减,结果为负则求补。
- 8.27
程序:
.model small
.stack 100h
.code
start:
input ;键盘输入
add al,20h ; 大写变为小写
output al ; 显示
mov ah,4ch
int 21h
end start
- 8.28
程序:
.model small
.data
alpha db ‘Computer’
.code
start:
display alpha ;显示字串
mov ah,4ch
int 21h
end start
- 8.29
程序:
.model small
.stack 100h
.code
start:
input ;键盘输入
cmp al,‘-’
jnz start
neg x ;求补
mov ah,4ch
int 21h
end start
- 8.30
程序:
.model small
.stack 100h
.code
start:
input ;键盘输入
mov bl,al
input ;输入第2个数
add al,bl
mov ah,0
aaa ;非压缩BCD码加法调整
add ax,3030h
output ah ;显示高位
output al ;显示低位
mov ah,4ch
int 21h
end start
习题九答案
- 9.26
在屏幕的 row1、rank1 到 row2、rank2 开窗口,清窗口,设置字符颜色为 color。
- 9.27
将光标设置在 5 行 10 列上。
- 9.28
回车换行宏。
- 9.29
读取时钟计数器当前计数值,cx 保存高位,dx 保存低位;判断计数是否到 91 次(5 秒),没到,继续循环读取,到 5 秒后做下面内容。
- 9.30
设置 1CH 号中断的中断向量(win_time),将其保存到中断向量表中。
- 9.35
编程实现在窗口中将键盘输入的小写字母加密后显示出来。
程序如下:
include 9-3.mac ;参见教材9.3.1节示例9-3,9-3.mac宏库
.model small
.data
letter db 'Input Letter: $'
cont db ?
.code
start:
mov ax,@data
mov ds,ax
clearsc ;清屏
clearsw ;窗口清屏
reptt:
;置显示光标
mov ah,2
mov dh,11 ;在11行30列显示
mov dl,30
mov bh,0
int 10h
;显示串
mov ah,9
mov dx,offset letter
int 21h
;置输入光标
mov ah,2
mov dh,15 ;在15行30列输入
mov dl,30
mov bh,0
int 10h
;输入小写字母
mov ah,1
int 21h
add al,20h ;加密
;显示加密后的字符
mov dl,al
mov ah,2
int 21h
;开窗口
mov ah,6
mov al,1 ;上卷1行
mov ch,8 ;从8行30列到15行60列
mov cl,30
mov dh,15
mov dl,60
mov bh,27h ;绿底灰字
int 10h
inc cont ;可输入3次
cmp cont,3
jne reptt
out1:
mov ah,4ch
int 21h
end start
- 9.36
编写程序,在屏幕上显示彩色的 26 个英文字母。
程序如下:
.model small
.data
letter db ?
n='a' ;重复汇编
m=1eh ;蓝底黄字开始
rept 26 ;26个小写字母
db n,m
n=n+1
m=m+1
endm
.code
start:
mov ax,@data ;各个段都在代码段中
mov ds,ax
;开窗口
mov ah,06h
mov al,0
mov bh,37h ;白底黑字0f0h,兰灰底灰白字37h,黄底白字0e7h
mov ch,3 ;从8行30列到15行60列
mov cl,3
mov dh,15
mov dl,60
int 10h
;置光标
locate:
mov ah,2
mov dh,6 ;光标在6行30列
mov dl,30
mov bh,0
int 10h
;显示彩色的26个英文字母
mov bx,offset letter+1
mov bp,bx
mov bx,seg letter+1
mov es,bx
mov ah,13h
mov al,3
mov bh,0
mov cx,26 ;26个字母
int 10h
mov ah,4ch
int 21h
end start
- 9.37
编写程序,在窗口中将键盘输入的一串字符中的大写字母和小写字母的个数分别统计并显示出来。
程序如下:
include 9-4.mac ;参见教材9.5.1节示例9-4,9-4.mac宏库
.model small
.data
mess1 db 'input: $'
mess2 db 29,32 dup(?)
daxie db ?
xiaoxie db ?
.code
start:
mov ax,@data
mov ds,ax
clearsc ;清屏
clearsw 8,30,15,60,27h ;开窗口,绿底灰白字
cursor 12,30 ;置显示光标
;显示提示
mov ah,9
mov dx,offset mess1
int 21h
;输入串
mov al,0
mov ah,10
mov dx,offset mess2
int 21h
;统计
mov cx,0
mov cl,mess2+1 ;输入的个数
mov bx,2 ;从第2个单元存放键入的字母
let1:
mov al,mess2[bx]
test al,20h ;区分大小写
jz let2 ;为0,即大写转
inc xiaoxie ;小写加1
jmp let3
let2:
inc daxie ;大写加1
let3:
inc bx
loop let1
windows 8,30,15,60,27h ;窗口内上卷
cursor 14,30 ;在16行30列显示
add xiaoxie,30h
displ xiaoxie ;显示小写个数
windows 8,30,15,60,27h ;窗口内上卷
add daxie,30h
displ daxie ;显示大写个数
out1:
mov ah,4ch
int 21h
end start
- 9.38
编写对键盘输入一段英文的操作计时的程序。
程序如下:
include 9-4.mac
.model small
.data
letter1 db 'Time start= ','$'
letter2 db 'Time end = ','$'
letter3 db 'Time total= ','$'
input db 100,102 dup(?)
hour db ?
minutes db ?
seconds db ?
persec db ?
cont db 0
.code
start:
mov ax,@data
mov ds,ax
clearsc ;清屏
cursor 2,50 ;置光标
mov ah,9
mov dx,offset letter1 ;显示串1
int 21h
sss:
;读时间并显示
mov ah,2ch ;CH=小时,CL=分,DH=秒,DL=百分秒
int 21h
mov bx,0
mov bl,ch
call disp_2_10 ;显示小时
displ ':' ;显示:
mov bx,0
mov bl,cl
call disp_2_10 ;分
displ ':' ;显示:
mov bx,0
mov bl,dh
call disp_2_10 ;秒
displ ':' ;显示:
mov bx,0
mov bl,dl
call disp_2_10 ;百分秒
sub ch,hour ;计算时间差
sub cl,minutes
sub dh,seconds
sub dl,persec
mov hour,ch ;保存时间差
mov minutes,cl
mov seconds,dh
mov persec,dl
inc cont
cmp cont,2 ;显示2次时间
jz out1
cursor 7,10 ;置输入光标
mov dx,offset input ;键盘输入
mov ah,10
int 21h
cursor 3,50 ;置光标
;显示串2
mov ah,9
mov dx,offset letter2
int 21h
jmp sss
out1:
cursor 4,50 ;置光标
mov ah,9
mov dx,offset letter3 ;显示串3
int 21h
;显示时间差
mov cx,3
mov si,offset hour
mov bx,0
www:
mov bl,[si] ;取出时、分、秒
call disp_2_10 ;3次调用
displ ':' ;显示:
inc si
loop www
mov ah,4ch
int 21h
;子程序。二-十进制数转换。bx值用十进制显示。
disp_2_10 proc
store_ss ;保护现场
mov ax,bx ;bx传参
mov cx,0
mov bx,10 ;将ax变为十进制数
let1:
mov dx,0
inc cx ;统计余数个数
idiv bx
push dx ;保存余数
cmp ax,0
jnz let1
let2: ;显示结果
pop ax ;将余数弹入ax
add ax,0030h ;调整为ascii码
mov dl,al
mov ah,2
int 21h
loop let2
restore_ss ;恢复现场
ret
disp_2_10 endp
end start