汇编语言程序设计(第二版) 刘慧婷 王庆生 主编 课后参考答案

  • Post author:
  • Post category:其他




汇编语言程序设计(第二版) 刘慧婷 王庆生 主编 课后参考答案



第一章



1.1 什么是机器语言?什么是汇编语言?简述汇编语言的特点。

机器语言就是用二进制编码组成的机器指令的集合和一组使用机器指令的规则。汇编语言是对机器指令中的操作码用英文单词的缩写描述,对操作数用标号、变量、常量描述。

汇编语言的特点:

(1)与机器有关:移植性差,但可直接控制硬件。

(2)程序效率高。

(3)局限性:受指令的限制,如考虑存储单元等。

(4)调试困难。



1.2 汇编程序与汇编源程序的区别是什么?

汇编源程序是指用汇编语言编写的程序,而汇编程序特指将汇编源程序汇编成目标文件的编译程序。



1.3 把下列十进制数转换为二进制数和十六进制数。
(1)67 (2)34 (3)254 (4)123

答:(1)1000011,43 (2)100010, 22

(3)1111 1101,FE (4)111 1011,7B



1.4 把下列二进制数转换为十六进制数和十进制数。
(1)01101101      (2)10110010      (3)111111

答:(1)6D,109 (2)B2,178, (3)3F,63



1.5 作下列十六进制数的运算,并转换为十进制数校核。
(1)5A+64      (2)86-49      (3)123-9A      (4)43×2B 

答:(1) BE (2)3D (3) 89 (4) B41



1.6 根据补码定义把下列十进制数表示为8位二进制补码。
(1) 64      (2) -24  

答:(1)0100 0000 (2)[10011000]原=[1110 1000]补



第二章



2.1 简述计算机系统组成。

答:计算机由中央处理器CPU,存储器,输入系统,输出系统组成,由系统总线连接在一起。CPU包括运算器和控制器,运算器执行指令,控制器负责计算机的控制。存储器是计算机的记忆部件,以二进制形式存放程序和数据。输入输出系统包括大容量存储器,如硬盘,以及其他外设,如鼠标,键盘,显示器等。



2.2 简述16位机的各类寄存器的主要作用。

答:(1)数据寄存器:Ax,Bx,Cx,Dx; AX:作为累加器,是算术运算的主要寄存器。在乘除等指令中存放操作数,在I/O指令中使用它与外部设备传送信息。BX:当通用寄存器使用,在计算存储器地址时,作基址寄存器使用。CX:当通用寄存器使用,此外常用来保存计数值,当计数器使用。

DX:当通用寄存器使用,一般在作双字长运算时把DX和AX组合使用,对某些I/O操作,DX用来存放I/O的端口地址。

(2)地址寄存器:Sp,Bp,Si,Di

(3)段寄存器:Cs,Ds,Es,Ss;段寄存器的作用是专用于存储器寻址,用来直接或间接地存放段地址。

(4)专用寄存器:Ip,Flags;Ip寄存器专门存放下一条指令的地址,Flags标志寄存器,又称程序状态寄存器。它是存放条件码标志、控制标志和系统标志的寄存器。



2.3 写出每条汇编指令执行后相关寄存器的值。

Mov ax, 1345H ax=


1345H


_______

Mov ah, 24H ax=


2445H


_______

Mov al, 45H ax=


2445H


_______

Mov bx, 3412H bx=


3412H


_______

Mov al, bh ax=


2434H


_______



2.4实模式下,写出段地址和偏移地址为1234:2002、1430:0042、FF00:0FFF的物理地址。

答:

1234:2002=12340+2002=14342

1430:0042=14300+0042=14342

FF00:0FFF=FF000+0FFF=FFFFF



2.5下列各数均为十进制数,请采用8位二进制补码运算,并回答标志寄存器FLAGS中CF和OF的值,运算结果所代表的十进制数是多少?如果用16位二进制补码运算,其结果所代表的十进制数是多少?FLAGS中CF和OF的值呢?

(1)85+69 (2)85+(-69) (3)85-(-69) (4)85-(69)

答:85=55H,69=45H,-69=BBH,

8位二进制补码运算:

(1)85+69 =55H+45H=9AH=154, CF=0,OF=1

(2)85+(-69)=55H+BBH=10H=16,CF=1,OF=0

(3)85-(-69)=55H-BBH=9AH=154,CF=1,OF=1

(4)85-(69)=55H-45H=10H=16,CF=0,OF=0

16位二进制补码运算:

85=0055H,69=0045H,-69=0FFBBH,

(1)85+69 =0055H+0045H=009AH=154, CF=0,OF=0

(2)85+(-69)=0055H+0FFBBH=0010H=16,CF=1,OF=0

(3)85-(-69)=0055H-0FFBBH=009AH=154,CF=1,OF=0

(4)85-(69)=0055H-0045H=0010H=16,CF=0,OF=0



2.6 给定段地址为0001H,仅通过变化偏移地址寻址,CPU的寻址范围从____00010H_____________到____1000FH_____________。


2.7 有一数据存放在内存20000H单元中,现给定段地址为SA,若想用偏移地址寻到此单元,则SA应满足的条件是:最小为__1001H____________,最大为____2000H________________。


2.8 已知8086系统某存储单元物理地址为:52506H,你认为段基址的最大值、最小值分别是多少?8086微机最多可以有多少个不同的段基址

答:52506=50000+2506,=52500+0006,基地址最大为5250,最小为5000(4251).

段地址取值范围:0000—FFFF。既65536个。



2.9从物理地址为00100H开始到00103H单元中顺序存放的数据为:12H,34H,56H,78H。请画出数据存放示意图,并回答以下问题:

(1)写出00101H字节单元的内容

(2)写出00102H字单元的内容

答案:

(1)(00101)= 34H

(2)(00102)= 7856H



第三章



3.1 写出从汇编语言源程序的建立到产生可执行文件的步骤和上机操作命令。

答:(1)用编辑程序EDIT建立 .ASM源文件

(2)用汇编程序MASM把.ASM文件原文件汇编成.OBJ文件

(3)用连接程序LINK将.OBJ文件转换成.EXE文件

(4)在DOS下直接运行.EXE文件或在DEBUG下调试该.EXE文件



3.2 列表文件.LST是在什么阶段产生的?列表文件.LST中有哪些内容?

答:

.LST 在汇编得到

.obj的同时得到,列表文件报告了汇编过程中产生的很多有价值的参考信息。主要包括源程序和机器语言清单、指令和变量的偏移地址等等。



3.3 写出定义一个代码段的语句,段名为MYPRG。

答:MYPRG segment

assume cs: MYPRG

start:

MYPRG ends

End start



3.4 程序中用什么语句来结束程序的执行?用什么语句来表示程序的结束和指出程序执行的起点?

答:程序的结束:mov ah,4ch

int 21h

程序的结束和指出执行的起点:End start



3.5 汇编语言源程序的文件扩展名是什么?把它改为.EXE扩展名后,可以认为是可执行程序吗?

答:源程序的文件扩展名为*.asm,改扩展名不可以执行。



3.6 列出子目录C:\YOUPRG下的扩展名为.ASM的所有文件,在D盘根目录下建立一个子目录MYPRG,并进入子目录MYPRG,再把C:\YOUPRG下的文件YOU.ASM复制到D:\MYPRG下。写出完成以上要求的DOS命令。
答:(1)列出子目录:C:\YOUPRG>dir *.asm
    (2)建立子目录:D:\>MD MYPRG
    (3)复制: C:\YOUPRG>copy YOU.asm D:\MYPRG


3.7 下图为DEBUG调入的可执行程序,回答以下问题:

(1)程序的起始物理地址是多少?结束地址是多少?

(2)CS寄存器的值是什么?

(3)程序的功能是什么?

(4)写出查看DS:0处内容的DEBUG命令。

(5)程序中2处的INT 21指令执行后有什么结果?

(6)如果要运行这个程序应该用什么DEBUG命令?

(7)DEBUG命令-T=0 4 之后,寄存器AX、DS、DX的值是多少?

答:(1)0B630,0B63E

(2)0B63

(3)显示0B62:0000存储的字符串

(4)-d 0B62:0000

(5)第一处显示字符串,第二处结束程序

(6)-g

(7)(AX)=0962,(DS)=0B62,(DX)=0000



3.8 解释DEBUG程序中的如下调试命令。
  • D , – E, – T, – G, – A , – R

    答:- D 显示内存内容

    • E 修改内存单元内容
    • T 跟踪命令
    • G 运行命令
    • A 汇编命令
    • R 查看或修改寄存器内容


3.9 用DEBUG调入PROG.EXE后,若程序列出如下:

1234:0100 MOV BX, [4000]

1234:0104 MOV AX, [BP]

1234:0106 MOV AH, 1

1234:0108 INT 21

1234:010A MOV DL, AL

1234:010C MOV AH, 2

1234:010E INT 21

1234:0110 RET

列出上面程序的DEBUG命令是( )。

寄存器CS的值为( ),第一条指令的物理地址为( )。

如果要修改寄存器BX为1200H,应键入DEBUG命令( )。

若要修改第二条指令中的BP为BX,应键入DEBUG命令( ) 。

答:(1) U

(2) 1234H

(3) 12440H

(4) R BX

(5) A [0104]



3.10简述在WIN7系统中执行汇编的方法。

DosBox是一款在Windows系统运行DOS程序的环境模拟器。下载安装DosBox,运行该程序,出现DosBox运行界面,运行挂载命令mount,即可以将Dos程序放置在Windows环境下Dos模拟器中运行,其过程为挂载。



3.11 简述DOS系统功能INT 21H调用方法。

答:(1)将调用功能的功能号存入AH寄存器。

(2)如必要,设置该调用功能的入口参数。

(3)执行INT 21H指令。

(4)如必要,按规定取得出口参数(返回参数)。



3.12 Debug命令调试含有“INT 21H”命令的程序段时,如何实现单步执行,“-t”命令为何无法实现?

答:“INT 21H”指令是Dos的系统调用,如果使用“-t”跟踪,则进入DOS系统子程序。如果希望单步执行,可以通过P命令或“-g=x x+1”来实现。



3.13 有主存数据段存放情况如下图所示,请写出代码,输出数据段的字符串“inspire a generation!”。

答: mov ax,145B

mov ds,ax

mov ah,09

mov dx,0

int 21h



第四章



4.1 何为段地址?何为有效地址? 何为物理地址?

答:

例如DS=6542H,指令mov ax,DS:[123A]; 123A为有效地址,6542H为段地址,65420H+0123AH=6665A即物理地址.



4.2 指出以下指令的寻址方式,array是变量。

(1)mov ax, 9

(2)mov byte ptr[bx],9

(3)mov bx,[di] (4)mov ax,bx

(5)mov [si+bx],9

(6)mov array[bx],cx

(7)mov ax, array+9

(8)mov ax, array[bx+di] 答: (1)立即数寻址

(2)寄存器间接寻址

(3)变址寻址

(4)寄存器寻址

(5)基址变址寻址

(6)相对基址寻址

(7)直接寻址

(8)相对基址变址寻址



4.3 假定(DS)=1200H,(SS)=4400H, (BX)=463DH,(BP)=2006H, (SI)=6A00H,位移量D=4524H,以AX寄存器为目的操作数,试写出以下各种寻址方式下的传送指令,并确定源操作数的有效地址EA和物理地址。

(1)立即寻址

(2)直接寻址

(3)使用BX的寄存器寻址;无EA

(4)使用BX的间接寻址

(5)使用BP的寄存器相对寻址

(6)基址变址寻址

(7)相对基址变址寻址

答:(1)操作数在指令中无EA

(2)直接寻址:EA=4524H,物理地址=DS:4524

(3)使用BX的寄存器寻址:无EA

(4)使用BX的间接寻址:EA=463DH,物理地址=DS:463D

(5)使用BP的寄存器相对寻址:MOV AX,[BP+4524],EA=2006+4524,

物理地址=SS:EA

(6)基址变址寻址: MOV AX,[BX+SI],EA= BX+SI,物理地址=DS:EA

(7)相对基址变址寻址:MOV AX,[4524+BX+SI],EA=4524+BX+SI,

物理地址=DS:EA



4.4 在数据段定义了ARRAY数组,其中依次存储了五个字数据,ARRAY的起始地址(第一个数据的地址)为24H,请用不同寻址方式的指令,把第5个字送AX寄存器,指令条数不限。

答:(1)直接寻址

MOV AX,ARRAY+8 或MOV AX,[ARRAY+8] (2)使用BX的间接寻址

LEA BX,ARRAY+8 ;MOV AX,[BX] (3)使用BX的寄存器相对寻址

LEA BX,ARRAY ;MOV AX,[BX+8] (4)基址变址寻址

LEA BX,ARRAY ; MOV SI,8 ; MOV AX,[BX+SI]



第五章



5.1 溢出标志OF与进位标志CF有何作用和区别?

答:处理器对两个操作数进行运算时,按照无符号数求得结果,并相应设置进位标志CF;同时,根据是否超出有符号数的范围设置溢出标志OF。应该利用哪个标志,则由程序员来决定。也就是说,如果将参加运算的操作数认为是无符号数,就应该关心进位;认为是有符号数,则要注意是否溢出。



5.2 有符号数比较大小,当AX < BX时程序转向标号L1,若前导指令为CMP AX, BX,后续指令应为什么?若视为二个无符号数比较大小, 后续指令应为什么?

答:带符号数:JL L1, 无符号数:JB L1



5.3 CMP和TEST指令与其他指令的不同之处在于什么?它们通常都紧跟着跳转指令,用在什么场合?

答:CMP和TESt指令分别执行减法和逻辑与操作,但不回送结果,只影响标志位,通常用以判断两个数的大小或者用以判断操作数的某些位是1或0。



5.4 除了用4CH号系统功能调用结束程序的执行并退出,还有哪些办法?

答:RET指令,INT 20H,但要正确使用。



5.5 V是变量,指出下列错误的指令,说出错误原因,并给出合适的修改。

(1) MOV AX,[DX]

(2) MOV DS,DATA

(3) MOV CS,AX

(4) MOV AX,DL

(5) PUSH AL

(6) ADD [BX],[DI]

(7) LEA [BX],V

(8) MOV [DX],OFFSET V

(9) MOV [SI],2

(10) MUL BX,CX

(11) DIV 5

(12) MOV BYTE[SI],AX

(13) MOV AX,[SI+DI]

(14) SHR AX,4

(15) CMP 6,AX

(16) MOV [FFFF],AX

(17) MOV AX,BX+4

(18) JMP FAR PRO

答:(1) MOV AX,[BX]

(2) MOV DS,BX

(3) MOV ES,AX

(4) MOV AL,DL

(5) PUSH AX

(6) ADD [BX],DI

(7) LEA BX,V

(8) MOV DX,OFFSET V

(9) MOV WORD PTR [SI],AX

(10) MUL BX

(11) DIV BX

(12) MOV BYTE PTR [SI],2

(13) MOV AX,[BX+SI]

(14) SHR AX,1

(15) CMP AX,6

(16) MOV [FFFE],AX

(17) MOV AX,[BX+4]

(18) JMP FAR PTR PRO



5.6 在数据段定义了ARRAY数组,其中依次存储了4个字数据,根据以下要求把第4个字送AX寄存器。

(1)直接寻址

(2)使用BX的间接寻址

(3)使用BX和 ARRAY的寄存器相对寻址

(4)基址变址寻址

(5)MOV以外的其它指令

答:(1)直接寻址

MOV AX,ARRAY+6 或MOV AX,[ARRAY+6]

(2)使用BX的间接寻址

LEA BX,ARRAY+6 ;MOV AX,[BX]

(3)使用BX和 ARRAY的寄存器相对寻址

LEA BX,ARRAY ;MOV AX,[BX+6]

(4)基址变址寻址

LEA BX,ARRAY ; MOV SI,6 ; MOV AX,[BX+SI]

(5)MOV以外的其它指令

SUB AX,AX; ADD AX,[ARRAY+6]



5.7 画出数据在数据段中的存放情况,程序执行后,BX、DI、CX、DX寄存器中的内容是什么? 程序如下:
data  segment
array  dw  20,30,40,20h,30h,-6
buff   db  ‘abcd$’
data  ends
code  segment
	  assume  cs:code,ds:data
start:
	  mov    ax, data
	  mov    ds, ax
			mov    bx, array+1
			mov    di, offset array
			mov    cx, [di+5]
			mov    dl, buff+3
			mov    ah, 4ch
			int    21h
code  ends
			end    start

答: 14 00 1E 00 28 00 20 00 30 00 FA FF 61 62 63 64 $

(BX)=1E00H,(DI)=0000H,(CX)=2000H,(DX)=0064H



5.8 在DEBUG下设置(SP)=20H,设置AX、BX、CX、DX为不同值,把这四个寄存器内容依次压入堆栈,再从堆栈中依次弹出到SI、DI、BP、BX寄存器。写出一段程序实现上述操作,并画出每条入栈指令执行后SP和堆栈中数据的变化。
答:
code segment
	 assume cs:code
start:
	  push AX
	  push BX
	  push CX
	  Push DX
	  Pop  SI
Pop  DI
Pop  BP
Pop  BX
Hlt
Code ends
	 End start


5.9 求出7450H与以下各十六进制数的和及差,并根据结果标出SF、ZF、CF、OF标志位的值。

(1) 1234H (2)5678H (3)9804H (4)E0A0H

答: SF、ZF、CF、OF

(1)1234H+7450H, 1 0 0 1

(2)5678H+7450H, 1 0 0 1

(3)9804H+7450H, 0 0 1 0

(4)E0A0H+7450H, 0 0 1 0



5.10 在数据段有32位的无符号数变量X,Y,按如下格式定义,其中‘?’请用数值代替,用16位指令按要求写出程序。
   X    DW    ?,?
   Y    DW    ?,?
   Z    DW    ?,?,?,?
(1)Z=X+Y。
(2)Z=X-Y。
(3)Z=|X-Y|。
(4)Z=X×Y。
答:(1)X和Y两个字数据相加,和存放在Z中。
	 MOV  AX,X
	 MOV  DX,X+2
	 ADD  AX,Y
	 ADC  DX,Y+2
	 MOV  Z,AX
	 MOV  Z+2,DX
	(2)MOV  AX,X
	 MOV  DX,X+2
	 SUB  AX,Y
	 SBB  DX,Y+2
	 MOV  Z,AX
	 MOV  Z+2,DX
	(3)MOV  AX,X
	 MOV  DX,X+2
	 SUB  AX,Y
	 SBB  DX,Y+2
	 TEST AX,8000H
 JZ  Exit
 NOT AX
 NOT DX
 ADD DX,1
 ADC AX,0
 Exit: MOV  Z,AX
	 MOV  Z+2,DX
	(4)MOV  AX,X
	 MUL  Y
	 MOV  Z,AX
 MOV  Z+2,DX
	 MOV  AX,X+2
	 MUL  Y
	 ADD  Z+2,AX
	 ADC  DX,0
	 MOV  Z+4,DX
	 MOV  AX,X
	 MUL  Y+2
	 ADD  Z+4,AX
 ADC  DX,0
 MOV  Z+6,DX
		 MOV  AX,X+2
	 MUL  Y+2
	 ADD  Z+6,AX
	 ADC  DX,0
	 MOV  Z+8,DX


5.11用移位指令为主实现对AX中的无符号数乘以5,不考虑乘积可能超出16位。
答: MOV  DX,AX
MOV  CL,2
	 SHL  AX,CL
	 ADD  AX,DX


5.12 用移位指令为主实现对AX中的无符号数乘以5,考虑乘积可能超出16位的情况。
答: MOV  DX,0
MOV  BX,AX
	 SHL  AX,1
	 ADC  DX,0
SHL  DX,1
SHL  AX,1
	 ADC  DX,0
	 ADD  AX,BX
	 ADC  DX,0


5.13 把AX中的内容依次倒排序,即第0位移到第15位,第1位移到第14位,…。
答:先设AX值
	Mov  di,0
	Mov  bx,0
	Mov si,1
	Mov cl,2
	Ror ax,1
K: Rol ax,cl
	Mov bx,ax
	And bx,si
	Add di,bx
	Shl,si,1
	Cmp si,0
	Jnz  k
	Mov ax,di


5.14 在数据段有如下定义:
BUFF    DB  ‘ABCD$EFGHIJK$’
		  STR1    DB   12  DUP(?)
		  LEN     DB   ?
用串指令编写程序完成以下操作:
(1) 对字符串STR1全部置‘*’符。
(2) 从左到右把BUFF中的字符串传送到STR1。
(3) 从右到左把BUFF中的字符串传送到STR1。
(4) 比较BUFF与STR1两个字符串是否相等,如相等则DX=1,否则DX=0。
(5) 查找BUFF中有无字符$,把字符$出现的次数计入BX寄存器。
答:
(1) 
MOV  AX,DATA
MOV  DS,AX
MOV  AL,‘*’
LEA  DI,STR1
MOV  CX,STR1-BUFF
CLD
REP  STOSB  
(2) 
MOV  AX,DATA
MOV  DS,AX
MOV  ES,AX
CLD
LEA  SI,BUFF
LEA  DI,STR1
MOV  CX,STR1-BUFF
REP  MOVSB
(3) 
MOV  AX,DATA
MOV  DS,AX
MOV  ES,AX
STD
LEA  SI,STR1-1
LEA  DI,LEN-1
MOV  CX,STR1-BUFF
REP  MOVSB

(4)
MOV  AX,DATA
MOV  DS,AX
MOV  ES,AX
CLD
LEA  SI,BUFF
LEA  DI,STR1
MOV  CX,STR1-BUFF
REPE  CMPSB

(5) 
MOV  AX,DATA
MOV  ES,AX
MOV  BX,0
CLD
MOV  AL,‘$’
LEA  SI,BUFF
MOV  CX,STR1-BUFF
NEXT: REPNE  SCASB
JCXZ  NO-FOUND
INC  BX
JMP  NEXT


5.15 对于给定的AX和BX的值,执行下列程序段,程序将转向哪里?
ADD    AX, BX
	  JNO    L1
JNC    L2
SUB    AX,BX
JNC    L3
JNO    L4
JMP    L5
(1) AX=1234H,  BX=6789H
(2) AX=790EH,  BX=8831H
(3) AX=E002H,  BX=8086H
答:L1,L1,L5


5.16 下面不完整的程序段是比较AX和BX的值,把其中大的数送MAX变量。如果是无符号数,应如何填写指令?如果是有符号数,应如何填写指令?
CMP    AX,BX
(             )   
MOV    MAX,AX
(            )
L1:MOV    MAX,BX  
L2:HLT   

答: JB  L1  
	 JMP  L2  


5.17 在下列程序段的括号中分别填入如下指令,程序执行完后,AX、CX的内容是什么?
(1) LOOP    L1
(2) LOOPE   L1
(3) LOOPNZ  L1
MOV    AX, 6
	  MOV    CX,3
L1:ROL    AX,CL
	TEST   AL,3
(        )

答:(1)AX=0C000H,CX=0000
   (2)AX=0003H,CX=0002
   (3)AX=0C000H,CX=0000


5.18 测试AL寄存器,如果最高位和最低位同时为0,则转L0,如果最高位和最低位只有一位为1,则转L1,如果最高位和最低位同时为1,则转L2。画出流程图,并编写程序段。
答: 
Code segment
	 Assume cs:code
Start:
  
ROR  AL,1
AND  AL,3
JZ   L0
SUB  AL,3
JZ   L2
JMP  L1
L0:
	JMP Exit
L1:
	JMP Exit
L2:
Exit:hlt
code ends
	 end start


5.19 从键盘输入一个英文字母,显示输出其大写。画出流程图,并编写程序段。
答:
Code segment
	 Assume cs:code
Start:
	 Mov ah,1
	 Int 21h
	 sub al,20h
	 mov dl,al
	 mov ah,2
	   int 21h
hlt
code ends
	 end start


5.20 从键盘输入一位数字N,显示输出N个N。画出流程图,并编写程序段。
答:
CODE SEGMENT
ASSUME  CS:CODE
START:
MOV  AH,1
INT 21H
MOV  DL,AL
AND  AL, 0FH
MOV  CL,AL
MOV  CH,0
NEXT: MOV  AH,2
INT 21H
LOOP  NEXT
MOV  4CH
INT 21H
CODE ENDS
  END  START


5.21 在数据段有压缩的BCD码表示的十进制数,写出指令分别完成十进制加法A+B,K+J和减法A-B,K-J。结果放在AX,回答AX的内容。
A  DB 65H,
B  DB 37H 
K  DB 98H
J  DB 69H
答:(1)    MOV Al,A
		   MOV Bl,B
		   ADD AL,BL
	 AAA
SUB AL,BL
	 DAS
	 (2)   MOV Al,K
		   MOV Bl,J
		   ADD AL,BL
	 AAA
SUB AL,BL
	 DAS
(1)A+B=9CH,AX=0102H.A-B=2EH,AX=0028H
(2)K+J=01H,AX=0107H.K-J=2FH,AX=0029H


5.22 用相对基址变址寻址方法求ARRAY行列式的值。
ARRAY    DW  2,3,5
			 DW  1,4,6
			 DW  2,7,9
答:
	   data segment
		 Array dw 2,3,5
			   dw 1,4,6
			   dw 2,7,9
	   data ends
	   code segment
			assume cs:code,ds:data
	   start:
			mov ax,data
			mov ds,ax
			mov ax,0
			 mov bx,0fffah
		  a: mov si,0
			 add bx,6
 cmp bx,13
			 jg  d
		  
b: add ax,array[bx][si]
			 cmp si,3
			 jg  a
add si,2
			 jmp b
		  d: hlt
	 code ends
		  end start



第六章



6.1 画图说明下列数据定义语句所示内存空间的数据,并回答寄存器的值。
ORG  0
ARRAY LABEL  BYTE
DA1  DW 2,9,14,3,315H,-6 
DA2  DB 7,‘ABCDEDFG’
LEN = $-DA2                      
ORG  100H
DA3  DW  DA4
DA4  DB  4  DUP(2 DUP(1,2,3),4)
。。。。。。
MOV  AL,ARRAY+2          (AL)=(    )H
ADD  AL,DA2+1            (AL)=(    )H
MOV  AX,DA2-DA1          (AX)=(    )H
MOV  BL,LEN              (BL)=(    )H
MOV  AX, DA3              (AX)=(    )H
MOV  BX, TYPE  DA4        (BX)=(    )H
MOV  BX, OFFSET  DA4      (BX)=(    )H
MOV  CX, SIZE  DA4        (CX)=(    )H
MOV  DX, LENGTH  DA4      (DX)=(    )H
MOV  BX, WORD PTR  DA4    (BX)=(    )H
MOV  BL, LEN  AND  0FH    (BL)=(    )H
MOV  BL, LEN  GT  5       (BL)=(    )H
MOV  AX, LEN  MOD 5       (AX)=(    )H
答:
MOV  AL,ARRAY+2          (AL)=( 09    )H
ADD  AL,DA2+1            (AL)=( 41    )H
MOV  AX,DA2-DA1          (AX)=( 000c  )H
MOV  BL,LEN              (BL)=(  09   )H
MOV  AX, DA3              (AX)=( 0102  )H
MOV  BX, TYPE  DA4        (BX)=(  0001 )H
MOV  BX, OFFSET  DA4      (BX)=(  0102 )H
MOV  CX, SIZE  DA4        (CX)=(  0004 )H
MOV  DX, LENGTH  DA4      (DX)=(  0004 )H
MOV  BX, WORD PTR  DA4    (BX)=(  0201 )H
MOV  BL, LEN  AND  0FH    (BL)=(  09   )H
MOV  BL, LEN  GT  5       (BL)=(  ff   )H
MOV  AX, LEN  MOD 5       (AX)=(  0004 )H


6.2 变量和标号有哪些区别?变量和标号有哪些属性?如何获取属性值?写出指令。
答:变量是为指令提供的操作数,标号是为指令提供标识,都是为了在指令中引用。它们最主要的属性有:偏移属性,段属性,类型属性。例如:
MOV   BX, OFFSET  VAL ;取偏移属性
MOV   BX, SEG   VAL   ;取段属性
MOV   BX, TYPE  VAL   ;取类型属性


6.3 指令和伪指令的区别在哪里?伪指令可以出现在代码段吗?指令可以在数据段吗?

答:指令只能出现在代码段,定义数据的伪指令通常在数据段,伪指令在代码段两端也可,但不能在指令之间。



6.4 下面的程序能否输出字符0~9?如不能,应如何修改?
CODE    SEGMENT
		ASSUME CS:CODE
		K=30H                
		J  DW  0
START:  MOV  DL, K
		MOV  AH, 2
		INT  21H 
		K=K+1     
		INC  J
		CMP  J, 10
		JNZ  START
		MOV  AH, 4CH
		INT  21H
CODE    ENDS
		END  START
答:通过汇编和连接可以运行,但程序真正意图是输出ASCII码为30H~39H的字符0~9,应作修改。
CODE    SEGMENT
		ASSUME CS:CODE
		K=30H                ;改为 K  DB  30H
		J  DW  0
START:  MOV  DL, K
		MOV  AH, 2
		INT  21H 
		K=K+1     ;K=K+1是伪指令,没生成代码,改为 INC  K 
		INC  J
		CMP  J, 10
		JNZ  START
		MOV  AH, 4CH
		INT  21H
CODE    ENDS
		END  START 


6.5 用16位指令编写完整程序,并上机调试,计算V=(X+Y)*R,其中所有变量均为32位变量,X、Y、R的具体数值由你自己确定,变量定义格式如下:
	X    DW ?,?
	Y    DW  ?,?
	R    DW  ?,?
	V    DW 4 dup(?)
答:(32位指令)
data segment
x dw 1
y dw 2
r dw 3
v dw 4 dup(?)
data ends

code segment
assume cs:code,ds:data
.386p
start:
	mov ax,data
	mov ds,ax
	mov eax,x
	add eax,y
	mov ebx,r
	imul ebx
	mov v,eax
	mov v+4,edx
	mov dl,al
	add dl,30h
	mov ah,2
	int 21h
	mov ah,4ch
	int 21h
code ends
end start


6.6数据定义如下:执行下列指令,填写寄存器的值
ARRAY  LABEL  BYTE
DA1  DW  2,9,14,3 
	  DA2  DB  7,‘ABCDEDF’
LEN = $-DA1                      
MOV  AL,ARRAY+2          (AL)=(      )H
	  ADD  AL,DA2+1             (AL)=(     )H
	  MOV  AX,DA2-DA1          (AX)=(     )H
MOV  AX,DA1+1             (AX)=(    )H
MOV  BL,LEN               (BL)=(     )H

答:  MOV  AL,ARRAY+2          (AL)=(  09  )H
	  ADD  AL,DA2+1             (AL)=(  41  )H
	  MOV  AX,DA2-DA1          (AX)=(  0008 )H
MOV  AX,DA1+1             (AX)=( 0900  )H
MOV  BL,LEN               (BL)=(  10   )H


6.7 定义数据段,满足如下要求:
(1)array为字符串变量:‘inspire a generation!’
(2)data1 为十六进制数:0FEDCBAH
(3)data2为二进制数:10101010B。
(4)data3为100个为零的字节变量。
(5)分配500个字的空间待用。
答: data segment 
		   Array db ‘inspire a generation!’
		   Data1 df  0fedcbah
		   Data2 db 10101010B
		   Data3 db 100 dup(0)
	   dw 500 dup(?)
data ends


6.8 假设程序中,数据段定义如下:
  Data1 db 50 dup(?)
  Data2 dw 10 dup(0)
  Data3 dq  5 dup(2 dup(1,2))

(1)用指令将数据段首地址放入数据段寄存器中。

(2)用一条指令将data2的第一个数据放入BX寄存器中。

(3)将数据段字节数放入CX寄存器。

答:mov ax,data1 mov ds,ax

Mov bx,data2[0]

Mov cx, 50+10

2+20

8



6.9现有数据定义如下:
 Array1 dw  5 DUP(0)
 Array2 EQU BYTE PTR Array1

请说明这两个变量之间的联系。

答:当汇编后,PTR类型操作符使Array2具有Array1相同的段地址和偏移地址,但它的数据类型为字节型。



6.10 给出下列程序段汇编后的结果:
 Val1 EQU  6
 Val2 EQU  3
MOV BX,(Val1 LT 5) AND 20
MOV BX, (VAL2 GE 1) AND 30
MOV BX,(Val2  AND 5) OR (VAL1 GE 5)
MOV BX,(Val2 - VAL1) GE 5
答:MOV BX,0   MOV BX,30   MOV BX,FF   MOV BX,0


6.11设数据段定义如下:
Data segment
   Org 20h
   Data1=4
   Data2=data1+25h
   Data3 db ‘123456’
		 Db 47h,48h
   Count EQU $-data1
  Data ends
回答下列问题:
(1)Data1的偏移地址是多少?     
(2)Count的值是多少?           
答:(1)0020h   (2)0024h


6.12现有一数据区data1,需对其进行按字和按字节访问,请问应如何进行设置?

答:可以利用“LABEL“标签进行设置,如:

Operator_b LABEL byte

Operator_w dw 100dup(0)

其中按字节访问时采用Operator_b变量,按字访问时采用Operator_w变量。



6.13请问什么是PSP,EXE文件和COM文件有何区别?

答:PSP是程序段前缀。程序在执行前调入内存,由DOS确定装入的起始地址,建立PSP,接着再装入程序,其大小为256个字节。EXE文件和COM文件相比,COM文件只有一个段地址,由二进制代码组成,比EXE文件小,并且要求程序从偏移地址0100H单元开始,因为之前存放为PSP。



第七章



7.1 下列程序是在3个数中找出最小的数并放入AL,在括号中填入指令使其完整。
	mov		al,x
	mov		bl,y
    mov		cl,z
	cmp 	al,bl
	(          )
xchg   al,bl
l1: cmp   al, cl
jle  l2
(          )
l2: ret
答:(1)jl  l1
   (2)xchg al,cl


7.2 数据段如下:
data   segment
da1		db	1,2,‘abcd’   
count  = $-da1
			da2    db  9 dup(?)
data   ends
补充括号处的指令,使得程序把DA1数据区数据移到DA2数据区。
mov		ax,data
			mov    ds, ax
mov		es,(       )
mov		cx,(       )
			mov    si, (      )
			(         )
			(         )
答:      mov		es,( AX     )
mov		cx,( COUNT     )
			mov    si, ( OFFSET  DA1     )
			( MOV  DI, OFFSET  DA2        )
			( REP  MOVSB                )


7.3 将AX和BX进行加、减、乘或除的运算,每种运算由用户从键盘上选择。程序中设置寄存器的值,或在DEBUG下设定寄存器值并在DEBUG下运行程序。
答:code segment 
		assume cs:code 
main proc far
		push ds
		sub ax,ax
		push ax
		mov ah,1
		int 21h
		cmp al,31h   ;1加
		jz  ad
		cmp al,32h    ;2减
		jz  su
cmp al,33h   ;3乘
		jz  mu
		cmp al,34h    ;4除
		jz  di
	  ad:ADD AX,BX
		 JMP exit
	  su:SUB AX,BX
		 JMP exit
	  mu:MUL BX
		 JMP exit
	  d:DIV BX
	exit: 
		 ret
main  endp
code ends
end main


7.4 编写程序,从键盘接收一个小写字母,然后找出它的前导字符和后续字符,再按顺序显示这三个字母。
答:code segment 
		assume cs:code 
main   proc far
		push ds
		sub ax,ax
		push ax
		mov ah,1
		int 21h
		cmp al,61h
		jb  exit
		cmp al,7ah
		ja  exit
mov bx,ax
sub al,1h    ;输出前一字符
mov dl,al
mov ah,2
int 21h
mov dl,bl    ;输出当前字符
mov ah,2
int 21h
add dl,1h    ;输出后一字符
mov ah,2
int 21h
   exit:ret
main  endp
code ends
end main


7.5 分别用LOOP循环和条件转移指令实现1+2+3+……+100,并将结果存入AX。
答:(1)code segment 
		assume cs:code 
main  proc  far
		push ds
		sub ax,ax
		push ax
		mov bx,1
mov ax,0
		mov cx,99
	   a:add ax,bx
		 inc bx
	   loop a
	exit:ret
code ends
end main

(2)code segment 
		assume cs:code 
main  proc  far
		push ds
		sub ax,ax
		push ax
		mov bx,1
mov ax,0
		mov cx,99
	   a:add ax,bx
		 inc bx
	   cmp bx,101
	   jnz a
exit:ret
main  endp
code ends
end main


7.6 打印下面图形。
*
**
***
****
*****
******
答:code segment 
		assume cs:code 
main  proc  far
		push ds
		sub ax,ax
		push ax
		mov ax,1
	  a:mov cx,ax
	  b:mov ah,2
mov dl,’*’
int 21h
loop  b
cmp ax,6
jz exit
inc ax
mov ah,2
mov dl,13
int 21h
mov ah,2
mov dl,10
int 21h
jmp a
   exit:ret
code ends
end main


7.7 将AX和BX进行加、减、乘或除的运算,每种运算由用户从键盘上选择。AX和BX可在DEBUG下设置。
答:code segment 
		assume cs:code 
main proc far
		push ds
		sub ax,ax
		push ax
		mov ah,1
		int 21h
		cmp al,31h   ;1加
		jz  ad
		cmp al,32h    ;2减
		jz  su
cmp al,33h   ;3乘
		jz  mu
		cmp al,34h    ;4除
		jz  di
	  ad:ADD AX,BX
		 JMP exit
	  su:SUB AX,BX
		 JMP exit
	  mu:MUL BX
		 JMP exit
	  d:DIV BX
	exit: 
		 ret
main  endp
code ends
end main


7.8 求已知带符号数字节数组ARRAY的平均值,ARRAY的首字节单元为数组元素的个数。
答:
   data segment
	  ARRAY   db  5,01,12,23,45,F3
   data ends

code segment 
		assume cs:code 
start:  
mov ax,data
		mov ds,ax
		mov ax,0  
		mov cl,array 
		mov ch,0
		mov bl,cl
	   lea si,array+1
a:add al,array[si]
inc si
loop a
div bl
	 exit:mov  ah,4ch
		 int 21h
code ends
end start


7.9 编写程序,实现对无符号字数组ARRAY的6个元素从小到大排序。
答: data  segment
	  array  dw 6,5,9,4,5,15,3  ;首地址单元6为元素个数
	data  ends
code  segment
	  assume cs:code,ds:data
start:
		mov   ax, data
		mov   ds, ax
		mov   di, array
k1:     mov   cx, di
		 mov   bx,0
k2:     mov   ax, array[bx]
		cmp   ax, array[bx+2]
		jl   next
		xchg ax,array[bx+2]
		mov array[bx],ax
next:   add  bx,2
		loop k2
		dec  di
		jnz  k1
	 mov   ah,4ch
		int   21h
code  ends
end   start


7.10 数据段有两个等长的字数组,分别求出各自的元素之和,并存入元素后面的单元中,即横向相加。再求出两个数组的对应元素之和,并把和存入新数组SUM中,即纵向相加。
答:data  segment
	  Array1  dw  3, 1,0,1,?     ;设简单数据,第一个为元素个数
	  Array2  dw  3,1,1,0,?
	  Array3  dw  3,3 dup (0)   ;存放array1,2的和
data  ends
code  segment
	  assume cs:code,ds:data
start:
		mov   ax, data
		mov   ds, ax
		mov   ax, 0
		lea   bx, array1+2
		mov   cx, array1
sumh1:  add   ax, [bx]
		add   bx,2
		loop  sumh1
		mov  [bx],ax
	  ;第二个数组累加
  mov   ax, 0
		lea   bx, array2+2
		mov   cx, array2
sumh2:  add   ax, [bx]
		add   bx,2
		loop  sumh2
		mov  [bx],ax
   lea   bx,2
mov   cx, array2
  sum3: mov   ax, array1[bx]
 add   ax, array2[bx]
		mov array3[bx],ax
 add   bx,2
		loop  sum3
exit:   mov   ah,4ch
		int   21h
code  ends
end   start


7.11 编写程序,比较两个从键盘输入的字符串是否相同,如果相同,则显示 ‘YES’,如果不同,则显示发现不同的字符位置。
答:data  segment 
mess1   db     13,10, 'input string1:$'
mess2   db     13,10, 'input string2:$'
mess3   db     13,10, 'YES!$'
mess4   db     13,10, 'no match at $'

st1     label   byte
  max1  db      6
  act1  db      ?
  stok1 db      6 dup(?)

st2    label   byte
  max2   db      6
  act2   db      ?
  stok2  db      6 dup(?)
data  ends

code segment  
		assume cs:code, ds:data,es:data 
start:  mov ax,data
		mov ds,ax
		mov es,ax
		lea dx,mess1
		mov ah,09
		int 21h         ;qust1?
		lea dx,st1
		mov ah,0ah
		int 21h         ;ans1
		lea dx,mess2
		mov ah,09
		int 21h         ;qust2?
		lea dx,st2
		mov ah,0ah
		int 21h         ;ans2
		mov cl,act1
		mov dl,act2
		cmp cl,dl
		jnz nomatch
		mov ch,0
		lea si,stok1
		lea di,stok2
		repe cmpsb
		jnz nomatch
match:  lea dx,mess3
		mov ah,09
		int 21h
		jmp  exit
nomatch:
		lea dx,mess4
		mov ah,09
		int 21h
		sub di,offset stok2
		mov dx,di
		add dl,30h
		mov ah,2
		int 21h
exit:
		mov  ah,4ch
		int 21h        
code ends
	   end start 


7.12 编写程序,从键盘输入一个字符串到BUFF,再输入一个字符到AL,在字符串BUFF中查找是否存在该字符,如果找到,显示发现的字符位置。
答:
data  segment 
mess1   db     13,10, 'input string:$'
mess2   db     13,10, 'input a char:$'
mess3   db     13,10, 'found at $'
mess4   db     13,10, 'no found !$'

st1     label   byte
  max1  db      6
  act1  db      ?
  stok1 db      6 dup(?)

data  ends

code segment   para'code'
		assume cs:code, ds:data 
start:  mov ax,data
		mov ds,ax
		mov es,ax
		lea dx,mess1
		mov ah,09
		int 21h         ;qust1?
		lea dx,st1
		mov ah,0ah
		int 21h         ;ans1
		
		lea dx,mess2
		mov ah,09
		int 21h         ;qust2?
		
		mov ah,1
		int 21h         ;ans2
		lea di,stok1
		repne scasb
		jz match
nomatch:
		lea dx,mess4
		jmp exit
match:  lea dx,mess3

exit:
		mov ah,09
		int 21h
		sub di,offset stok1
		mov dx,di
		and dx,0fh
		add dl,30h
		mov ah,2
		int 21h
		mov ah,4ch
		int 21h        
code ends
	   end start 


7.13 编写程序,从键盘输入一个字符串到BUFF,并按相反顺序显示输出。
答: 
data  segment 
mess1   db     13,10, 'input string:$'
mess2   db     13,10,'$'
st1     label   byte
  max1  db      6
  act1  db      ?
  stok1 db      6 dup(?)
data  ends

code segment   
		assume cs:code, ds:data 
start : mov ax,data
		mov ds,ax
		lea dx,mess1
		mov ah,09
		int 21h         
		lea dx,st1
		mov ah,0ah
		int 21h                 
		lea dx,mess2
		mov ah,09
		int 21h         
		mov cl,act1
		mov ch,0
		mov bx, offset stok1
		add bx, cx
 next:  dec bx
		mov dl, [bx]
		mov ah,2
		int 21h
		loop next
		mov  ah,4ch
		 int 21h       
code ends
	   end start


7.14 编写程序,从键盘输入一个八位的二进制数,显示其十六进制数。
答:code  segment
		assume cs:code
start:
		mov cx,8
		mov bl,0
next:   mov ah,1
		int 21h
		cmp al,30h
		jb  exit
		cmp al,31h
		ja  exit
		sub al,30h
		shl bl,1
		add bl,al
		loop next
		mov cl,4
		mov di,2
out1:   rol bl,cl
		mov dl,bl
		and dl,0fh
		add dl,30h
		cmp dl,39h
		jle dig
		add dl,7
dig:    mov ah,2
		int 21h
		dec di
		cmp di,0
		jnz out1 
exit:   mov   ah,4ch
		int   21h
code  ends
end   start


7.15 字数组ARRAY为有符号数,第一个单元为元素个数N,后面为N个元素,编写程序,求数组元素中的最大值,并把它放入MAX单元。
答:data  segment
	  array  dw  5,9,4,5,15,3
	  max    dw  ?
data  ends
code  segment
	  assume cs:code,ds:data
start:
		mov   ax, data
		mov   ds, ax
		mov   cx, array
		lea   bx, array+2
		mov   ax, [bx]
		mov   max, ax
k1:     mov   ax, [bx]
		cmp   ax, max
		jl    next
		mov   max,ax
next:   add   bx,2
		loop   k1
		mov   ah,4ch
		int   21h
code  ends
end   start


7.16 字数组ARRAY,第一个单元为元素个数N,后面为N个元素,编写程序,把零元素从数组中清除,移动元素位置并修改第一个单元(元素个数)。
答:data  segment
	  array  dw  6,3,4,0,15,0,7
	  loca   dw  999        ;此单元地址为结束标记
data  ends
code  segment
	  assume cs:code,ds:data
start:
		mov   ax, data
		mov   ds, ax
		mov   cx, array
		lea   bx, array+2
next:   cmp   word ptr[bx],0
		jz    move
		add   bx,2
		dec   cx
		cmp   cx,0
		jnz   next
		jmp   exit
move:   dec   array
		mov   di,bx
mnext:
		cmp   di,offset loca
		ja    next
		mov   ax, [di+2]
		mov   [di],ax
		add   di,2
		cmp   di,offset loca
		jnb   next
		jmp   mnext
exit:   mov   ah,4ch
		int   21h
code  ends
end   start



第八章



8.1 过程定义如下,补充括号中的指令。
code   segment
		assume	 cs:code
main   proc  far
(           )
(           )
(           )
…
…
…
ret
main    endp
code    ends
end   main
答:(  PUSH  DS         )
(  XOR  AX,AX       )
(  PUSH  AX         )


8.2 补充下列程序括号中的指令,使得程序对堆栈的操作全部利用程序中定义的TOS堆栈,并画出程序执行后堆栈TOS中的数据。
data   segment
	   dw    100 dup(?)
  tos  label  word
data   ends
code   segment
		assume	 cs:code,ss:data
main   proc  far
(            )
(            )
(            )
push  ds
xor   ax, ax
push  ax
call  far ptr suba
… ;假定此处指令的地址为CS=3400h,IP=30h
…
…
code   ends
end   main
答:(  MOV  AX,DATA        )
(  MOV  SS,AX          )
(  LEA  SP,TOS         )


8.3 主程序从键盘输入一个字符串到BUFF,再输入一个字符到AL,用子程序在字符串BUFF中查找是否存在该字符,如果找到,显示发现的字符位置。用寄存器传递要查找的字符。
答:Data segment
BUFF1 db 16,?,16 dup(?),13,10,'$'
Data ends
Code segment
	 Assume cs:code,ds:data
Main proc far
Push ds
Xor ax,ax
Push ax
	  Mov ax,data
Mov ds,ax
Mov es,ax
Lea dx,BUFF1
Mov ah,10
Int 21h
mov ah,1
int 21h
Lea di,BUFF1+2
Mov cl,BUFF1+1
mov ch,0
Mov ah,0
Repne scasb
Jnz  ye
dec di
mov bx,di
Call BTH
Ye: ret
Main endp
BTH proc near
   mov cx,4
   s:rol bx,1
	 rol bx,1
	 rol bx,1
	 rol bx,1
	 mov al,bl
	 and al,0fh
	 add al,30h
	 cmp al,39h
	 jle d
	 add al,7
   d:mov dl,al
	 mov ah,2
	 int 21h
	 loop s
ret
BTH endp
Code ends
	 End main


8.4 主程序从键盘输入一个八位的二进制数,对其作求补码操作,用子程序对求补后的值以二进制形式显示。(正数的补码=输入)
答:Code segment
Assume cs:code
   Main proc far
	  Push ds
	  Xor ax,ax
	  Push ax
	  Mov bx,0
	  Mov cx,8
A:mov ah,1
  Int 21h
  Shl bx,1
Sub al,30h
Jz b     ;输入为0
INC bx   ;输入为1
B:loop a
Test bx,0080h
Jz   d
XOR bx,00FFh ;取反
INC bx
D:Call disp
Ret
Main endp
disp proc near
   mov cx,8
   shl bx,cl
 ls1:shl bx,1
	 jnc k30
	 mov dl,31h
 jmp outb
k30: mov dl,30h
outb:mov ah,2
	 int 21h
	 loop ls1
ret
disp endp
code ends
	 end main


8.5 主程序从键盘(连续)输入两个四位的十六进制数A和B,用子程序作十六进制计算A+B,并显示计算结果(二进制)。
答:

data segment
   A dw ?
	B dw ?
data ends
Code segment
	 Assume cs:code,ds:data
Main proc far
	Push ds
	Xor ax,ax
	Push ax
	Mov  ax,data
   Mov ds,ax
   Call INH ;输入十六进制数到BX寄存器
	Mov A,bx
	Call INH ;输入十六进制数到BX寄存器
	Mov B,bx
	Call ad
	Ret
Main endp
INH proc near
		 mov   bx,0             ;初始化
mov   ch,4
		mov   cl,4
inchr: mov   ah,1             ;键盘输入
int   21h
cmp   al,30h           
jl    exit              ;非法输入
cmp   al,39h
jle   dig               ;输入是数字0~9
cmp   al,41h
jl    exit              ;非法输入
cmp   al,46h
jg    exit              ;非法输入
sub   al,37h           ;输入是大写a~f
jmp   ls4
dig: sub   al,30h
ls4: shl   bx,cl
add   bl,al
dec   ch
jnz   inchr
	  exit: ret
INH endp
Ad  proc near
Mov ax,a
Mov bx,b
Add bx,ax
Call disp
	Ret 
Ad endp
disp proc near
	 mov cx,16
ls1: shl bx,1
	 jnc l30
	 mov dl,31h
 jmp outb
l30; mov dl,30h
outb: mov ah,2
	  int 21h
	  loop ls1
	  ret
disp endp
Code ends 
	 End main


8.6 某字数组为有符号数,第一个单元为元素个数N,后面为N个元素,编写通用子程序,求数组元素中的最大值,并把它放入MAX单元。
答:MAX_p proc near
  Mov di,[bx]     ;个数地址
Mov si,[bx+2]   ;数组地址
Mov cx,[di]
Mov di,MAX
Xor ax,ax
Next:cmp di,[si]
	 Jg a
	 Mov di,[si]
   A: Add si,2
	 Loop next
 Mov MAX,di
ret
MAX_p endp

8.7 设有一个数组存放学生的成绩(0 ~ 100),编制一个子程序统计0 ~ 59分、60 ~ 69分、70 ~ 79分、80 ~ 89分、90 ~ 100分的人数,并分别存放到scoreE、scoreD、score C、score B及score A单元中。编写一个主程序与之配合使用。 
答:
data segment
Array db 6,9,65,78,68,86,93  ;6为学生人数,后面为6个成绩
ScoreE db ?
scoreD db ?
scoreC db ?
scoreB db ?
scoreA db ?
Data ends
Code segment
	 Assume cs:code,ds:data
Main proc far
Mov ax,data
Mov ds,ax
Mov cl,array
mov ch,0
Call class
Ret
Main endp
Class proc near
Lea si, array
next:
inc si
Mov bl, [si]
Cmp bl,60
Jl e
Cmp bl,70
Jl d
Cmp bl,80
Jl k
Cmp bl,90
Jl b
Mov dl, scoreA
Inc dl
Mov scoreA,dl
loop  next
jmp exit
B: Mov dl, scoreB
Inc dl
Mov scoreB,dl
loop next
jmp exit
k: Mov dl, scoreC
Inc dl
Mov scoreC,dl
loop next
jmp exit
D: Mov dl, scoreD
Inc dl
Mov scoreD,dl
loop next
jmp exit
E: Mov dl, scoreE
Inc dl
Mov scoreE,dl
loop next
jmp exit
exit:ret
class endp
Code ends
	 End main


8.8 用多模块程序设计一个简单的计算器程序,实现整数的加减乘除。运算符可以为:+,-,*,/,=。
答:
public  num1,num2,res
extrn   ad:far,su:far,mu:far,dv:far,el:far
data    segment
num1   db   ?
num2   db   ?
res    dw   ?
data    ends
code    segment
assume  cs:code,ds:data
main proc far 
push ds
sub  ax,ax
push ax
mov  ax,data             
mov  ds,ax
call DTOB
mov num1,bx
call DTOB
mov num2,bx
mov ah,1
int 21h
cmp dl,’+’
jz a
cmp dl,’-’
jz s
cmp dl,’*’
jz m
cmp dl,’/’
jz d
cmp dl,’=’
call el
jmp exit
		   a:call ad
			 jmp exit
		   s:call su
			 jmp exit
		   m:call mu
			 jmp exit
		   d:call dv
		exit:ret
main 	  endp
dtob        proc  near
mov  bx, 0
input:      mov  ah, 1                ;键盘输入
			int  21h
			sub  al, 30h              ;把ascii码转变为数值
jl  exit                  ;如不是数则退出
cmp  al, 9
jg  exit                  ;如不是数则退出
cbw                       ;扩展为字
xchg  ax,  bx             ;交换寄存器
mov  cx, 10
mul  cx                   ;a(n)= a(n-1)×10   
xchg  ax, bx              ;交换寄存器
add  bx,  ax              ;a(n)=a(n)+b(n)
jmp  input
exit:       ret
dtob        endp
code     ends
end main
;------------------
public  ad
extrn   num1:byte,num2:byte,res:word
code    segment
assume  cs:code
ad   proc  near
		mov ah,0
mov al,num1
add al,num2
adc ah,0
mov res,ax
		ret
order   endp
su   proc  near
		mov ah,0
mov al,num1
sub al,num2
sbb ah,0
mov res,ax
		ret
su   endp
mu   proc  near
mov al,num1
mul num2
mov res,ax
		ret
mu   endp
dv   proc  near
mov al,num1
div num2
mov res,ax
		ret
dv   endp
el   proc  near
mov al,num1
cmp al,num2
jz z
mov res,0FFFFH   ;不相等
jmp exit
		  z: mov res,0         ;相等
   exit:ret
el   endp
code    ends
end    


8.9 从键盘输入姓名和电话号码,建立通讯录,通讯录的最大容量为9条记录,程序结束时无须保留通讯录,但程序运行时要保留通讯录信息。程序的人机界面和顺序要求如下:
(1)提示信息INPUT NAME:(调用子程序INNAME录入姓名,序号自动产生)
(2)提示信息INPUT TELEPHONE NUMBER:(调用子程序INTELE录入电话号码)
(3)提示信息INPUT 序号:(调用子程序PRINT显示某人的姓名和电话号码,如果序号不存在,则提示信息 NO THIS NUMB )。
答:Inform struc
  Sn   db  ?
  Name db ‘??????’
  Telen  db  ‘???????????’
Inform ends
Data segment
   Array struc 9 dup(<>)
   Name db ‘INPUT NAME $’
   TEL  db  ‘INPUT TELEPHONE NUMBER $’
   number db   ‘INPUT SEQUENCE NUMBER $’
   err    db   ‘NO THIS NUMB $’
Data ends
code segment
	 assume cs:code,ds:data
main proc far
  push ds
  xor ax,ax
  push ax
 mov ax,data
mov ds,ax
mov cx,0
a:
  call inname
  call intele
  inc cx
  cmp cx,9
  jl a
call print
ret
main endp
inname proc near
push cx  
lea dx,name
  mov ah,9
  int 21h
  mov al, size array
 mul cl
 mov bx,ax
add bx,array
mov [bx].sn,cl
mov di,0
a:mov ah,1
   int 21h
   mov [bx].name[di],al
   inc di
   cmp di,6
   jl a
   pop cx
ret
inname endp
intele proc near
push cx  
lea dx,tel
  mov ah,9
  int 21h
 mov al, size array
 mul cl
 mov bx,ax
add bx,array
mov di,0
a:mov ah,1
   int 21h
   mov [bx].telen[di],al
   inc di
   cmp di,13
   jl a
   pop cx
ret
intele endp
print proc near
lea dx,number
  mov ah,9
  int 21h
mov ah,1
   int 21h
  cmp al,0
  jl ex
  cmp al,8
  jg ex
mov cl,al
  mov al, size array
  mul cl
  mov bx,ax
add bx,array
 mov dx,bx
 mov ah,9 
int 21h
mov dl,13
mov ah,2
 int 21h
mov dl,10
mov ah,2
int 21h
lea dx,[bx].telen
mov ah,9
int 21h
jmp r
ex: lea dx,err
	mov ah,9 
	int 21h
r:
ret
print endp
code ends
	 end main



版权声明:本文为mzc_love原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。