admin 管理员组文章数量: 1086019
2024年12月23日发(作者:urging翻译)
少年易学老难成,一寸光阴不可轻 - 百度文库
汇编语言程序设计 第四版
【课后习题答案】
第1章 汇编语言基础知识
〔习题1.1〕简述计算机系统的硬件组成及各部分作用。
〔解答〕
CPU:包括运算器、控制器和寄存器组。运算器执行所有的算术和逻辑运算;
控制器负责把指指令逐条从存储器中取出,经译码分析后向机器发出各种控制命
令,并正确完成程序所要求的功能;寄存器组为处理单元提供所需要的数据。
存储器:是计算机的记忆部件,它用来存放程序以及程序中所涉及的数据。
外部设备:实现人机交换和机间的通信。
〔习题1.2〕明确下列概念或符号: 主存和辅存,RAM和ROM,存储器
地址和I/O端口,KB、MB、GB和TB。
〔解答〕
主存又称内存是主存储器的简称,主存储器存放当前正在执行的程序和使用
的数据,CPU可以直接存取,它由半导体存储器芯片构成其成本高、容量小、
但速度快。辅存是辅助存储器的简称,辅存可用来长期保存大量程序和数据,
CPU需要通过I/O接口访问,它由磁盘或光盘构成,其成本低、容量大,但速
度慢。
RAM是随机存取存储器的英语简写,由于CPU可以从RAM读信息,也可
以向RAM写入信息,所以RAM也被称为读写存储器,RAM型半导体存储器
可以按地址随机读写,但这类存储器在断电后不能保存信息;而ROM中的信息
只能被读出,不能被修改,ROM型半导体通常只能被读出,但这类存储器断电
- 1 -
少年易学老难成,一寸光阴不可轻 - 百度文库
后能保存信息。
存储器由大量存储单元组成。为了区别每个单元,我们将它们编号,于是,
每个存储单元就有了一个存储地址,I/O接口是由一组寄存器组成,为了区别它
们,各个寄存器进行了编号,形成I/O地址,通常称做I/O端口。
KB是千字节、MB是兆字节、GB是吉字节和TB是太字节,它们都是表示
存储器存储单元的单位。
〔习题1.3〕什么是汇编语言源程序、汇编程序、目标程序?
〔解答〕
用汇编语言书写的程序就称为汇编语言源程序;完成汇编工作的程序就是汇
编程序;由汇编程序编译通过的程序就是目标程序。
〔习题1.4〕汇编语言与高级语言相比有什么优缺点?
〔解答〕
汇编语言与高级语言相比的优点:由于汇编语言本质就是机器语言,它可以
直接地、有效地控制计算机硬件,因而容易产生运行速度快,指令序列短小的高
效目标程序,可以直接控制计算机硬件部件,可以编写在“时间”和“空间”两
方面最有效的程序。
汇编语言与高级语言相比的缺点:由于与处理器密切相关导致通用性差、可
移植性差,汇编语言功能有限,又涉及寄存器、主存单元等硬件细节,编写汇编
语言比较繁琐,调试起来也比较困难,编译程序产生的目标程序往往比较庞大、
程序难以优化,运行速度慢。
〔习题1.5〕将下列十六进制数转换为二进制和十进制表示
(1)FFH (2)0H (3)5EH
- 2 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(4)EFH
(5)2EH (6)10H (7)1FH (8)
ABH
〔解答〕
(1)FFH 11111111B
255D
(2)0H
0D
(3)5EH
94D
(4)EFH
239D
(5)2EH
46D
(6)10H
16D
(7)1FH
31D
(8)ABH
171D
〔习题1.6〕将下列十进制数转换为BCD码表示
(1)12 (2)24
- 3 -
0B
1011110B
11101111B
101110B
10000B
11111B
10101011B
(3)68
少年易学老难成,一寸光阴不可轻 - 百度文库
(4)127
(5)128 (6)255 (7)1234
(8)2458
〔解答〕
(1)12 00010010
(2)24 00100100
(3)68 01101000
(4)127
(5)128
(6)255
(7)1234 0100
(8)2458 1000
〔习题1.7〕将下列BCD码转换为十进制数
(1)10010001 (2)10001001 (3)00110110
10010000
(5)00001000 (6)10010111 (7)10000001
00000010
〔解答〕
(1)91
(2)89
(3)36
(4)90
- 4 -
(4)
8)
(
少年易学老难成,一寸光阴不可轻 - 百度文库
(5)08
(6)97
(7)81
(8)02
〔习题1.8〕将下列十进制数分别用8位二进制数的原码、反码和补码表示
(1)0 (2)-127 (3)127
(4)-57
(5)126 (6)-126 (7)-128
(8)68
〔解答〕
(1)0 +0 00000000 00000000 00000000
-0 10000000 11111111 00000000
(2)-127 11111111 10000000 10000001
(3)127 01111111 01111111 01111111
(4)-57 10101111 11010000 11010001
(5)126 01111110 01111110 01111110
(6)-126 11111110 10000001 10000010
(7)-128 10000000
(8)68 01000100 01000100 01000100
〔习题1.9〕完成下列二进制数的运算
(1)1011+1001 (2)1011-1001 (3)1011×1001 (4)10111000
÷1001
- 5 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(5)1011 ∧1001 (6)1011 ∨1001 (7)~1011 (8)
1011 ? 1001
〔解答〕
(1)1011+1001=10100
(2)1011-1001=0010
(3)1011×1001=1100011
(4)10111000÷1001=10100,余数 1000
(5)1011 ∧ 1001=1001
(6)1011 ∨1001=1011
(7)~1011=0100
(8) 1011?1001=0010(?代表异或)
〔习题1.10〕数码0~9、大写字母A~Z、小写字母a~z对应的ASCII码
分别是多少?ASCII码为0dh、0ah对应的是什么字符?
〔解答〕
数码0~9:30H~39H
大写字母A~Z:41H~5AH
小写字母a~z:61H~7AH
ASCII码为0dh、0ah分别对应回车和换行控制字符。
〔习题1.11〕计算机中有一个“01100001”编码,如果把它认为是无符号
数,它是十进制什么数?如果认为它是BCD码,则表示什么数?又如果它是某
个ASCII码,则代表哪个字符?
〔解答〕
- 6 -
少年易学老难成,一寸光阴不可轻 - 百度文库
十进制无符号数:01100001B=61H=97
BCD码:61
ASCII码:a
〔习题1.12〕简述Intel 80x86系列微处理器在指令集方面的发展。
〔解答〕
1978年Intel,正式推出了16位8086CPU,1979年Intel推出了准16
位微处理器8088,随后,Intel推出了80186/80188,80186/80188指令系统
比8086指令系统新增了若干条实用的指令,涉及堆栈操作、移位指令、过程指
令和边界检测及乘法指令,1982年Intel推出80286 CPU, 80286指令系统
包括全部80186指令及新增的保护指令15条,其中有些保护方式在实方式下也
可以使用,1985年,Intel80x86推出微处理器地进入第三代80386 CPU,
80386指令系统在兼容原来16位指令系统的基础上,全面升级为32位,还新
增了有关位操作、条件设置指令以及控制、调试和测试寄存器的传送指令等,
1989年,Intel推出了80486CPU,80486将浮点处理单元FPU集成进来,还采
用了精简指令集计算机技术RISC和指令流水线方式,还新增了用于多处理器和
内部Cache操作的6条指令,1993年Intel制成了俗称586的微处理器,取名
Pentium。Pentium仍为32位结构,地址总线为32位,对常用的简单指令用
硬件实现,重新设计指令的微代码等,Pentium新增了一条8字节比较交换指
令和一条处理器识别指令,以及4条系统专用指令,1996年推出了MMX
Pentium,新增了57条多媒休指令,1995年Intel推出Pentium Pro新增了3
条指令,1999年推出了PentiumⅢ新增了70条SSE指令,2000年推出的
Pentium4新增了76条SSE2指令
- 7 -
少年易学老难成,一寸光阴不可轻 - 百度文库
〔习题1.13〕什么是DOS和ROM-BIOS?
〔解答〕
DOS是Diskette Operating system的缩写,意思是磁盘操作系统,DOS
主要是面向磁盘的系统软件,说得简单些,就是人与机器的一座桥梁,是罩在机
器硬件外面的一层“外壳”,是1981~1995年的个人电脑上使用的一种主要的
操作系统。BIOS(Basic Input/Output System)即基本输入输出系统,通常
是固化在只读存储器(ROM)中,所以又称为ROM-BIOS。它直接对计算机
系统中的输入、输出设备进行设备级、硬件级的控制,是连接软件程序和硬件设
备之间的枢纽。ROM-BIOS是计算机系统中用来提供最低级、最直接的硬件控
制的程序。
〔习题1.14〕简述PC机最低1MB主存空间的使用情况。
〔解答〕
(1)基本RAM区(00000H—9FFFFH)该区共640KB,由DOS进行管理。
在这个区域中操作系统要占用掉一部分低地址空间,其它则向用户程序开放。
(2)保留区RAM(A0000H--BFFFFFH)该区为系统安排的“显示缓冲存
储区”,共126KB,是显卡上的芯片提供支持,用于存放屏幕显示信息。但这部
分地址空间实际上并没有全部使用。
(3)扩展区ROM(C0000H--DFFFFH)该区128KB,由接口卡上的芯片
提供支持,用于为系统不直接支持的外设安排设备驱动程序。用户固化的程序就
可[安排在这一段,系统的会对它进行确认和连接。
(4)系统区ROM(E0000H--FFFFFH)该区共128KB,由系统占用,它
主要提供ROM--BIOS程序,基本输入输出程序BIOS,是操作系统的重要组成
- 8 -
少年易学老难成,一寸光阴不可轻 - 百度文库
部分,主要用来驱动输入输出设备,也负责系统的上电检测,磁盘引导等初始化
操作,在ROM--BIOS中还有CMOS微机设置程序以及使用的字符图符信息等
内容。
〔习题1.15〕罗列8086CPU的8个8位和16位通用寄存器,并说明各自
的作用。
〔解答〕
(1)数据寄存器:AX称为累加器,使用频度最高,用于算术、逻辑运算
以及与外设传送信息等;BX称为基址寄存器,常用做存放存储器地址;CX称为
计数器,作为循环和串操作等指令中的隐含计数器;DX称为数据寄存器,常用
来存放双字长数据的高16位,或存放外设端口地址。
(2)指针及变址寄存器包括SI,DI,BP,S P,四个寄存器,常用于存储器寻址时
提供地址。SI是源变址寄存器,DI是目的变址寄存器,一般与DS联用确定数
据段和附加段中某一存储单元地址,在串指令中,SI与DS联用、DI和ES联用,
分别寻址数据段和附加段;同时,在串指令中,SI和DI还都具有自动增量或减
量的功能。S P,为堆栈指针寄存器,指示栈顶的偏移地址;BP为基地址指针寄存
器,表示堆栈段中的基地址。S P与BP寄存器均可与SS段寄存器联合使用以
确定堆栈段中的存储单元地址。
〔习题1.16〕什么是标志,它有什么用途?状态标志和控制标志有什么区
别?画出标志寄存器FLAGS,说明各个标志的位置和含义。
〔解答〕
标志用于反映指令执行结果或控制指令执行形式。它是汇编语言程序设计中
必须特别注意的一个方面,状态用来记录运行的结果的状态信息,许多指令的执
- 9 -
少年易学老难成,一寸光阴不可轻 - 百度文库
行都将相应地设置它,控制标志位可由程序根据需要用指令设置,用来控制处理
器执行指令的方式。
CF是进位标志;ZF 是零标志;SF是符号标志;PF奇偶标志;OF溢出标
志;AF辅助进位标志;DF方向标志;IF中断允许标志;TF陷阱标志。
〔习题1.17〕举例说明CF和OF标志的差异。
〔解答〕
溢出标志OF和进位标志CF是两个意义不同的标志。
进位标志表示无符号数运算结果是否超出范围,运算结果仍然正确;溢出标
志表示有符号数运算结果是否超出范围,运算结果已经不正确。
例1:3AH + 7CH=B6H
无符号数运算:58+124=182,范围内,无进位
有符号数运算: 58+124=182 ,范围外,有溢出
例2:AAH + 7CH=(1)26H
无符号数运算:170+124=294,范围外,有进位
有符号数运算:-86+124=28 ,范围内,无溢出
〔习题1.18〕字和双字在存储器中如何存放,什么是“小端方式”?对字
和双字存储单元,什么是它们的对齐地址?为什么要对齐地址?
〔解答〕
字或双字在存储器中占相邻的2个或4个存储单元;存放时,低字节存入
低地址,高字节存入高地址;字或双字单元的地址用它的低地址来表示。80x86
处理器采用的这种“低对低,高对高”的存储形式,被称为“小端方式”;将字
- 10 -
少年易学老难成,一寸光阴不可轻 - 百度文库
单元安排在偶地址,双字节单元安排在模4地址,被称为“地址对齐方式”因为
对于不对齐地址的数据,处理器访问时,需要额外的访问时间,所以通常应该将
数据的地址对齐,以取得较高的存取速度。
〔习题1.19〕什么是8086中的逻辑地址和物理地址?逻辑地址如何转换成
物理地址?请将如下逻辑地址用物理地址表达:
(1)FFFFh:0 (2)40h:17h (3)2000h:4500h (4)B821h:4567h
〔解答〕
在8086处理器中,对应每个物理存储单元都有一个唯一的20位编号,就
是物理地址,从00000H~FFFFFH。
在8086内部和用户编程时,采用的段基地址 : 段内偏移地址形式称为逻辑
地址。
将逻辑地址中的段地址左移二进制4位(对应16进制是一位,即乘以16),
加上偏移地址就得到20位物理地址
如下逻辑地址用物理地址表达:
(1)FFFFh:0=FFFF0H
(2)40h:17h=00417H
(3)2000h:4500h=24500H
(4)B821h:4567h=BC777H (不要算错)
〔习题1.20〕8086有哪4种逻辑段,各种逻辑段分别是什么用途?
〔解答〕
代码段(Code Segment)用来存放程序的指令序列。处理器利用CS : IP
取得下一条要执行的指令。
- 11 -
少年易学老难成,一寸光阴不可轻 - 百度文库
堆栈段(Stack Segment)确定堆栈所在的主存区域。处理器利用SS : SP
操作堆栈中的数据。
数据段(Data Segment)存放当前运行程序所用的数据。处理器利用DS :
EA存取数据段中的数据。
附加段(Extra Segment)是附加的数据段,也用于数据的保存。处理器利
用ES : EA存取数据段中的数据
〔习题1.21〕数据的默认段是哪个,是否允许其他段存放数据?如果允许,
如何实现,有什么要求?
〔解答〕
数据的默认段是安排在数据段,也经常安排在附加段,尤其是串操作的目的
区必须是附加段,允许其它段存放数据,数据的存放比较灵活的,实际上可以存
放在任何一种逻辑段中,这时,只要明确指明是哪个逻辑段就可以了。
〔习题1.22〕什么是操作码、操作数和寻址方式?有哪三种给出操作数的
方法?
〔解答〕
操作码说明计算机要执行哪种操作,它是指令中不可缺少的组成部分,操作
数是指令执行的参与者,也是各种操作的对象,我们把寻找数的方式叫做操作数
的寻址方式。给出操作数的三种方法是直接给出,间接给出,隐藏操作数方式给
出。
〔习题1.23〕什么是有效地址EA?8086的操作数如果在主存中,有哪些
寻址方式可以存取它?
〔解答〕
- 12 -
少年易学老难成,一寸光阴不可轻 - 百度文库
DS存放数据段的段地址,存储器中操作数的偏移地址则由各种主存方式得
到,称之为有效地址EA。8086的操作数如果在主存中,可以存取它的寻址方式
有直接寻址方式、寄存器间接寻址方式、寄存器相对寻址方式、基址变址寻址方
式、相对基址变址寻址方式。
〔习题1.24〕说明下列指令中源操作数的寻址方式?如果BX=2000H,
DI=40H,给出DX的值或有效地址EA的值。
(1) mov dx,[1234h]
(2) mov dx,1234h
(3) mov dx,bx
(4) mov dx,[bx]
(5) mov dx,[bx+1234h]
(6) mov dx,[bx+di]
(7) mov dx,[bx+di+1234h]
〔解答〕
(1)直接寻址,EA=1234H
(2)立即数寻址,DX=1234H
(3)寄存器寻址,DX=2000H
(4)间接寻址,EA=2000H
(5)相对寻址,EA=3234H
(6)基址变址寻址,EA=2040H
(7)相对基址变址寻址,EA=3274H
第2章 8086的指令系统
- 13 -
少年易学老难成,一寸光阴不可轻 - 百度文库
〔习题2.1〕已知DS=2000H、BX=0100H、SI=0002H,存储单元
[20100H]~[20103H]依次存放12 34 56 78H,[21200H]~[21203H]依次存放
2A 4C B7 65H,说明下列每条指令执行完后AX寄存器的内容。
(1) mov ax,1200h
(2) mov ax,bx
(3) mov ax,[1200h]
(4) mov ax,[bx]
(5) mov ax,[bx+1100h]
(6) mov ax,[bx+si]
(7) mov ax,[bx][si+1100h]
〔解答〕
(1)AX=1200H
(2)AX=0100H
(3)AX=4C2AH ;偏移地址=bx=0100h
(4)AX=3412H ;偏移地址=bx=0100h
(5)AX=4C2AH ;偏移地址=bx+1100h=1200h
(6)AX=7856H ;偏移地址=bx+si=0100h+0002h=0102h
- 14 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(7)AX=65B7H ;偏移地址
=bx+si+1100h=0100h+0002h+1100h=1202h
〔习题2.2〕指出下列指令的错误
(1) mov cx,dl
(2) mov ip,ax
(3) mov es,1234h
(4) mov es,ds
(5) mov al,300
(6) mov [sp],ax
(7) mov ax,bx+di
(8) mov 20h,ah
〔解答〕
(1)两操作数类型不匹配
(2)IP指令指针禁止用户访问
(3)立即数不允许传给段寄存器
(4)段寄存器之间不允许传送
(5)两操作数类型不匹配
- 15 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(6)目的操作数应为[ SI ]
(7)源操作数应为 [BX+DI]
(8)立即数不能作目的操作数
〔习题2.3〕已知数字0 ~ 9对应的格雷码依次为:18H、34H、05H、06H、
09H、0AH、0CH、11H、12H、14H,它存在于以table为首地址(设为200H)
的连续区域中。请为如下程序段的每条指令加上注释,说明每条指令的功能和执
行结果。
lea bx,table
mov al,8
xlat
〔解答〕
lea bx,table ;获取table的首地址,BX=200H
mov al,8 ;传送欲转换的数字,AL=8
xlat ;转换为格雷码,AL=12H P35
〔习题2.4〕什么是堆栈,它的工作原则是什么,它的基本操作有哪两个,
对应哪两种指令?
〔解答〕
- 16 -
少年易学老难成,一寸光阴不可轻 - 百度文库
堆栈是一种按“先进后出”原则存取数据的存储区域,位于堆栈段中,使用
SS段寄存器记录其段地址;它的工作原则是先进后出;堆栈的两种基本操作是
压栈和出栈,对应的指令是PUSH和POP。
〔习题2.5〕已知SS = 2200H、SP = 00B0H,画图说明执行下面指令序
列时,堆栈区和SP的内容如何变化?
mov ax,8057h
push ax
mov ax,0f79h
push ax
pop bx
pop [bx]
〔解答〕
mov ax,8057h
push ax
mov ax,0f79h
push ax
pop bx ;bx=0f79h
pop [bx] ;DS:[0f79h]=8057h
- 17 -
少年易学老难成,一寸光阴不可轻 - 百度文库
〔习题2.6〕给出下列各条指令执行后AL值,以及CF、ZF、SF、OF和PF
的状态:
mov al,89h
add al,al
add al,9dh
cmp al,0bch
sub al,al
dec al
inc al
〔解答〕
- 18 -
少年易学老难成,一寸光阴不可轻 - 百度文库
mov al,89h ; AL=89h CF ZF SF OF PF
add al,al ; AL=12h 1 0 0 1 1
; 1000 1001
+1000 1001
10001 0010
add al,9dh
; 0001 0010
+ 1001 1101
1010 1111
cmp al,0bch
; 1010 1111
-1011 1100
* 0100 0011
sub al,al
- 19 -
; AL=0afh 0 0 1 0 1
; AL=0afh 1 0 1 0 1
; AL=00h 0 1 0 0 1
少年易学老难成,一寸光阴不可轻 - 百度文库
dec al ; AL=0ffh 0 0 1 0 1
; 0000 0000
- 0000 0001
*1111 1111
inc al ; AL=00h 0 1 0 0 1
;1111 1111
+0000 0001
*1111 1111
〔习题2.7〕设X、Y、Z均为双字数据,分别存放在地址为X、X+2;Y、
Y+2;Z、Z+2的存储单元中,它们的运算结果存入W单元。阅读如下程序段,
给出运算公式。
mov ax,X
mov dx,X+2
add ax,Y
adc dx,Y+2
- 20 -
少年易学老难成,一寸光阴不可轻 - 百度文库
add ax,24
adc dx,0
sub ax,Z
sbb dx,Z+2
mov W,ax
mov W+2,dx
〔解答〕
W=X+Y+24-Z
〔习题2.8〕请分别用一条汇编语言指令完成如下功能:
(1)把BX寄存器和DX寄存器的内容相加,结果存入DX寄存器。
(2)用寄存器BX和SI的基址变址寻址方式把存储器的一个字节与AL寄
存器的内容相加,并把结果送到AL中。
(3)用BX和位移量0B2H的寄存器相对寻址方式把存储器中的一个字和
CX寄存器的内容相加,并把结果送回存储器中。
(4)用位移量为0520H的直接寻址方式把存储器中的一个字与数3412H
相加,并把结果送回该存储单元中。
(5)把数0A0H与AL寄存器的内容相加,并把结果送回AL中。
- 21 -
少年易学老难成,一寸光阴不可轻 - 百度文库
〔解答〕
(1)ADD DX,BX
(2)ADD AL,[BX+SI]
(3)ADD [BX+0B2H],CX
(4)ADD WORD PTR [0520H],3412H
(5)ADD AL,0A0H
〔习题2.9〕设X、Y、Z、V均为16位带符号数,分别装在X、Y、Z、V
存储单元中,阅读如下程序段,得出它的运算公式,并说明运算结果存于何处。
mov ax,X ;ax=X
imul Y ;=X*Y
mov cx,ax ;cx=X*Y的低16位
mox bx,dx ;bx=X*Y的高16位
mov ax,Z ;ax=Z
cwd
add cx,ax ;cx=Z的低16位+X*Y的低16位
adc bx,dx ;bx=Z的高16位+X*Y的高16位+低位进位
- 22 -
少年易学老难成,一寸光阴不可轻 - 百度文库
sub cx,540 ;cx=Z的低16位+X*Y的低16位-540
sbb bx,0 ;bx=Z的高16位+X*Y的高16位+低位进位-低位借
位
mov ax,V ;ax=V
cwd
sub ax,cx ;ax=V的低16位(-Z的低16位+X*Y的低16位-540)
sbb dx,bx ;dx=V的高16位-(Z的高16位+X*Y的高16位+
低位进位-低位借位)-低位借位
idiv X ;/X
〔解答〕
[V-(X*Y+Z-540)]/X
AX存商,DX存余数
〔习题2.10〕指出下列指令的错误:
(1) xchg [si],30h
(2) pop cs
- 23 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(3) sub [si],[di]
(4) push ah
(5) adc ax,ds
(6) add [si],80h
(7) in al,3fch
(8) out dx,ah
〔解答〕
(1)xchg的操作数不能是立即数
(2)不应对CS直接赋值
(3)两个操作数不能都是存储单元
(4)堆栈的操作数不能是字节量
(5)adc的操作数不能是段寄存器
(6)没有确定是字节还是字操作
(7)in不支持超过FFH的直接寻址
(8)out只能以AL/AX为源操作数
〔习题2.11〕给出下列各条指令执行后的结果,以及状态标志CF、OF、
SF、ZF、PF的状态。
mov ax,1470h
- 24 -
少年易学老难成,一寸光阴不可轻 - 百度文库
and ax,ax
or ax,ax
xor ax,ax
not ax
test ax,0f0f0h
〔解答〕
mov ax,1470h ;AX=1470H CF ZF SF OF PF
and ax,ax ;AX=1470H 0 0 0 0 0
;0001 0100 0111 0000
or ax,ax ;AX=1470H 0 0 0 0 0
xor ax,ax ;AX=0000H 0 1 0 0 1
not ax ;AX=FFFFH 0 1 0 0 1
test ax,0f0f0h ;AX=FFFFH 0 0 1 0 1
注意:MOV和NOT指令不影响标志位;其他逻辑指令使CF=OF=0,根
据结果影响其他标志位。
- 25 -
少年易学老难成,一寸光阴不可轻 - 百度文库
〔习题2.12〕假设例题2.34的程序段中,AX = 08H,BX = 10H,请说明
每条指令执行后的结果和各个标志位的状态。
〔解答〕
指令 ; 执行结果 CF OF SF ZF PF
mov si,ax ; SI=AX=0008H - - - - -
shl si,1 ; SI=2*AX=0010H 0 0 0 0 0
add si,ax ; SI=3*AX=0018H 0 0 0 0 1
mov dx,bx ; DX=BX=0010H 0 0 0 0 1
mov cl,03h ; CL=03H 0 0 0 0 1
shl dx,cl ; DX=8*BX=0080H 0 u 0 0 0
sub dx,bx ; DX=7*BX=0070H 0 0 0 0 0
add dx,si ; DX=7*BX+3*AX=0088H 0 0 0 0 1
注意:逻辑左移N次相当于无符号整数乘以2的N次方,逻辑右移N次相
当于无符号整数除以2的N次方。移位指令根据移位的数据设置CF,根据移位
后的结果影响SF,ZF,PF。在进行一位移位时,根据最高符号位是否改变设置
OF,如改变则OF=1。另外,程序注释用“u”表示标志无定义(不确定),
“-”表示无影响。
〔习题2.13〕编写程序段完成如下要求:
(1)用位操作指令实现AL(无符号数)乘以10
- 26 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(2)用逻辑运算指令实现数字0 ~ 9的ASCII码与非压缩BCD码的互相
转换
(3)把中的双字右移4位
〔解答〕
(1) ;不考虑进位
mov bl,al
mov cl,3
shl al,cl ;*8
add al,bl ;shl bl,1
add al,bl
;考虑进位
xor ah,ah
mov bx,ax
mov cl,3
shl ax,cl
add ax,bx ;shl bx,1
add ax,bx
(2)数字0~9的ASCII码是:30h~39h
- 27 -
少年易学老难成,一寸光阴不可轻 - 百度文库
非压缩BCD码的0~9是:00h~09h
方法一:
and al,0fh ;实现ASCII到非压缩BCD码的转换
or al,30h ;实现非压缩BCD码到ASCII的转换
方法二:
xor al,30h ;求反D5D4位,其他不变
;即高4位为3,则变为0;高4位为0,则变为3
(3) mov cl,4
again: shr dx,1 ;实现逻辑右移
;采用“sar dx,1”,则实现算术右移
rcr ax,1
dec cl
jnz again
〔习题2.14〕已知AL = F7H(表示有符号数-9),分别编写用SAR和IDIV
指令实现的除以2的程序段,并说明各自执行后,所得的商是什么?
〔解答〕
(1)用sar编写
mov al,0f7h ; -9送AL 1111 1001
- 28 -
少年易学老难成,一寸光阴不可轻 - 百度文库
sar al,1 ; 结果:AL=1111 1100B=0FBH 即-5
(2)用idiv编写
mov al,0f7h ; -9送al
cbw ; 字节符号扩展位字
mov bl,2 ; 注意除数不可为立即数
idiv bl ; 结果:商为al=fch (-4)
; 余数:ah=ffh (-1)
结论:符号数的除法用idiv 准确。
〔习题2.15〕指令指针IP是通用寄存器还是专用寄存器?有指令能够直接
它赋值吗?哪类指令的执行会改变它的值?
〔解答〕
指令指针IP不是通用寄存器,不可直接赋值,属于专用寄存器。有且仅有
循环、转移、子程序调用和返回、中断类等指令可以改变它的值。
〔习题2.16〕控制转移类指令中有哪三种寻址方式?
〔解答〕
控制转移类指令的寻址方式:相对寻址、直接寻址方式和间接寻址方式(又
可以分成寄存器和存储器间接寻址)。
- 29 -
少年易学老难成,一寸光阴不可轻 - 百度文库
〔习题2.17〕什么是短转移short jump、近转移near jump和远转移far
jump?什么是段内转移和段间转移?8086有哪些指令可以实现段间转移?
〔解答〕
短转移:指段内-128~127之间的转移,位移量用一个字节表示
近转移:指段内±32K之间的转移,位移量用一个字表示
远转移:指段间1MB范围的转移
段内转移:指在同一个代码段内的转移,可以是短转移或者近转移
段间转移:指转移到另外一个代码段,就是远转移
8086/8088CPU的JMP、CALL和INT n指令可以实现段间转移
〔习题2.18〕8086的条件转移指令的转移范围有多大?实际编程时,你如
何处理超出范围的条件转移?
〔解答〕
8086的条件转移的转移范围:在当前指令地址的 +127~-128之内。
如条件转移的转移范围超出此范围,可在此范围内安排一条无条件转移,再
转移到范围外的目标地址。
〔习题2.19〕假设DS=2000H,BX=1256H,SI=528FH,位移量
TABLE=20A1H,[232F7H]=3280H,[264E5H]=2450H,试问执行下列段内
间接寻址的转移指令后,转移的有效地址是什么?
(1) JMP BX
- 30 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(2) JMP TABLE[BX]
(3) JMP [BX][SI]
〔解答〕
(1)转移的有效地址EA= BX=1256H
(2)转移的有效地址EA= [DS:20A1H+1256H]=[232F7]=3280H
(3)转移的有效地址EA= [DS:1256H+528FH]=264E5H=2450H
〔习题2.20〕判断下列程序段跳转的条件
(1) xor ax,1e1eh
je equal
(2)test al,10000001b
jnz there
(3)cmp cx,64h
jb there
〔解答〕
(1)AX=1e1eh(异或后为0)
(2)AL的D0或D7至少有一位为1
(3)CX(无符号数)< 64h
〔习题2.21〕设置CX = 0,则LOOP指令将循环多少次?例如:
- 31 -
少年易学老难成,一寸光阴不可轻 - 百度文库
mov cx,0
delay: loop delay
〔解答〕
216次。
〔习题2.22〕假设AX和SI存放的是有符号数,DX和DI存放的是无符号
数,请用比较指令和条件转移指令实现以下判断:
(1)若DX > DI,转到above执行;
(2)若AX > SI,转到greater执行;
(3)若CX = 0,转到zero执行;
(4)若AX-SI产生溢出,转到overflow执行;
(5)若SI≤AX,转到less_eq执行;
(6)若DI≤DX,转到below_eq执行。
〔解答〕
(1)若DX > DI,转到above执行
cmp dx,di
ja above ;=jnbe above
(2)若AX > SI,转到greater执行
cmp ax,si
- 32 -
少年易学老难成,一寸光阴不可轻 - 百度文库
jg greater ;=jnle greater
(3)若CX = 0,转到zero执行
cmp cx,0
jz zero ;= jcxz zero
(4)若AX-SI产生溢出,转到overflow执行;
cmp ax,si
jo overflow
(5)若SI≤AX,转到less_eq执行;
cmp si,ax ; cmp ax,si
jle less_eq ; jge less_eq
(6)若DI≤DX,转到below_eq执行。
cmp di,dx ; cmp dx,di
jbe below_eq ; jae below_eq
〔习题2.23〕有一个首地址为array的20个字的数组,说明下列程序段的
功能。
mov cx,20
mov ax,0
mov si,ax
- 33 -
少年易学老难成,一寸光阴不可轻 - 百度文库
sum_loop: add ax,array[si]
add si,2
loop sum_loop
mov total,ax
〔解答〕
将首地址为array得20个字的数组求和,并将结果存入 total 单元中。
〔习题2.24〕按照下列要求,编写相应的程序段:
(1)起始地址为string的主存单元中存放有一个字符串(长度大于6),
把该字符串中的第1个和第6个字符(字节量)传送给DX寄存器。
(2)从主存buffer开始的4个字节中保存了4个非压缩BCD码,现按低
(高)地址对低(高)位的原则,将它们合并到DX中。
(3)编写一个程序段,在DX高4位全为0时,使AX = 0;否则使AX =
-1。
(4)有两个64位数值,按“小端方式”存放在两个缓冲区buffer1和buffer2
中,编写程序段完成buffer1-buffer2功能。
(5)假设从B800h : 0开始存放有100个16位无符号数,编程求它们的
和,并把32位的和保存在中。
(6)已知字符串string包含有32KB内容,将其中的’$’符号替换成空
格。
- 34 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(7)有一个100个字节元素的数组,其首地址为array,将每个元素减1
(不考虑溢出)存于原处。
(8)统计以 ’$’ 结尾的字符串srting的字符个数。
〔解答〕
(1)解答:
mov si,0
mov dl,string[si] ;第1个字符送dl寄存器:mov dl,stirng[0]
mov si,5
mov dh,string[si] ;第6个字符送dh寄存器:mov dl,stirng[5]
(2)解答:
xor si,si ;si清零
mov al,buffer[si] ;第一字节
inc si
mov ah,buffer[si] ;第二字节
mov cl,4
shl ah,cl ;BCD码移到高半字节
or al,ah ;组合成压缩BCD码
mov dl,al ;存入dl寄..
- 35 -
少年易学老难成,一寸光阴不可轻 - 百度文库
inc si
mov al,buffer[si] ;第三字节
inc si
mov ah,buffer[si] ;第四字节
mov cl,4
shl ah,cl ;BCD码移到高半字节
or al,ah ;组合成压缩BCD码
mov dh,al ;存入dh寄..
(3)解答:
test dx,0f000h ; test dh,0f0h
jz next ; jnz next
mov ax,-1 ; mov ax,0
jmp again
next: mov ax,0 ; mov ax,0ffffh
again: ...
(4)解答:
mov ax, word ptr buffer1
sub ax, word ptr buffer2 ;先减低16位
- 36 -
少年易学老难成,一寸光阴不可轻 - 百度文库
mov dx, word ptr buffer1+2
sbb dx, word ptr buffer2+2 ;后减高16位,需减低16位的借
位
(5)解答:
mov ax,0b800h
mov ds,ax ;段地址
xor si,si ;地址偏移量si=0
xor dx,dx ;和的高字dx=0
mov cx,99 ;加的次数
mov ax,[si] ;第一个数
again: inc si ;指向下一个字单元
inc si
add ax,[si] ;加下一个数
jnc noc ;无进位转
inc dx ;有进位dx=dx+1
noc: dec cx ;次数-1
jnz cx,again ;非0继续加
(6)解答1:不使用串操作指令(更好)
- 37 -
少年易学老难成,一寸光阴不可轻 - 百度文库
mov si,offset string
mov cx,8000h ; 32k=2^15=8000h
again: cmp byte ptr [si], ‘$’ ;‘$’ =24h
jnz next ; 不要采用 jz 进行分支
mov byte ptr [si], ‘ ’ ;‘ ’=20h
next: inc si
loop again ; dec cx
; jnz again
(6)解答2:使用串操作指令
mov di,offset string
mov al,’$’
mov cx,8000h
cld
again: scasb
jnz next
mov byte ptr es : [di-1], ‘ ’
- 38 -
少年易学老难成,一寸光阴不可轻 - 百度文库
next: loop again
(7)解答1:
mov si,offset array
mov cx,100
again: dec byte ptr [si]
inc si
loop again
(7)解答2:
xor si,si ; si<--0
mov cx,100 ; 循环次数
again: dec array[si]
inc si
loop again
(7)解答3:
mov si,offset array
mov di,si
mov ax,ds
- 39 -
少年易学老难成,一寸光阴不可轻 - 百度文库
mov es,ax
mov cx,100
cld
again: lodsb
dec al
stosb
loop again
(8)解答:
xor si,si ;si<--0
coun: cmp string[si],'$'
je done
inc si
jmp coun
done: ...
〔习题2.25〕对下面要求,分别给出3种方法,每种方法只用一条指令。
(1)使CF=0 (2)使AX=0 (3)同时使AX=0和CF=0
〔解答〕
(1)解答:
- 40 -
少年易学老难成,一寸光阴不可轻 - 百度文库
clc
and ax,ax
or ax,ax
(2)解答:
xor ax,ax
and ax,0
mov ax,0
(3)解答:
and ax,0
xor ax,ax
sub ax,ax
〔习题2.26〕参照本习题的示意图,分析调用序列,画出每次调用及返回
时的堆栈状态。其中CALL前是该指令所在的逻辑地址;另外,段内直接调用指
令的机器代码的字节数为3,段间直接调用指令则为5个字节。
〔解答〕
主程序转子suba时段内调用:断点1为2000h:0400h+3,
转子是只将IP压栈。
suba转子subb时段间调用:断点2为2000h:0840h+5, 转子时须将cs
段地址和IP压栈
- 41 -
少年易学老难成,一寸光阴不可轻 - 百度文库
suba转子subc时段内调用:断点3为2000h:0c021h+3,转子是只将
IP压栈。
注:压栈时先修改sp再压入断点,弹栈时先弹出断点再修改sp。
〔习题2.27〕已知AX 、BX存放的是4位压缩BCD表示的十进制数,请
说明如下子程序的功能和出口参数。
add al,bl
daa
xchg al,ah
adc al,bh
daa
xchg al,ah
ret
〔解答〕
压缩BCD码加法:AX←AX+BX
出口参数:AX=BCD码和
〔习题2.28〕AAD指令是用于除法指令之前,进行非压缩BCD码调整的。
实际上,处理器的调整过程是:AL←AH×10+AL,AH←0。如果指令系统没有
AAD指令,请用一个子程序完成这个调整工作。
〔解答〕
- 42 -
少年易学老难成,一寸光阴不可轻 - 百度文库
shl ah,1 ;ah=2*a (设原ah=a)
mov dl,ah ;dl=2*a
mov cl,2 ;设定移位次数
shl ah,cl ;ah=8*a
add ah,dl ;ah=10*a
add al,ah ;al=10*a+al
xor ah,ah ;清零ah
int 3 ;返回DOS
注意: 入口:AX中存放有“和”(两非压缩BCD码)
出口:AL中 已为调整后的二进制数
〔习题2.29〕解释如下有关中断的概念:
(1) 内部中断和外部中断
(2) 单步中断和断点中断
(3) 除法错中断和溢出中断
(4) 中断向量号和中断向量表
〔解答〕
(1)内部中断是由于8086CPU内部执行程序引起的程序中断;外部中断
是来自8086CPU之外的原因引起的程序中断;
- 43 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(2)单步中断是若单步标志TF为1,则在每条指令执行结束后产生的中断;
断点中断是供调试程序使用的,它的中断类型号为3通常调试程序时,把程序按
程序的任务分成几段,然后,每段设一个段点;
(3)除法错中断是在执行除法指令时,若除数为0或商超过了寄存器所能
表达的范围产生的中断;溢出中断是在执行溢出中断指令INTO时,若溢出标志
OF为1时产生的中断;
(4)中断向量号是 中断类型号;中断向量表是中断向量号与它所对应的中
断服务程序起始地址的转换表。
〔习题2.30〕试比较INT n和段间CALL指令、IRET和段间RET指令的功
能。
〔解答〕
INT n 响应中断时,除象CALL保护断点外,还应保护FR;段间CALL指
令用在主程序中实现子程序的调用。IRET 返回时,除象RET恢复断点外,还应
恢复FR;子程序执行完成后,应返回主程序中继续执行,这一功能由RET指令
完成。
第3章 汇编语言程序格式
〔习题3.1〕伪指令语句与硬指令语句的本质区别是什么?伪指令有什么主
要作用?
〔解答〕
伪指令语句与硬指令语句的本质区别是能不能产生CPU动作;
- 44 -
少年易学老难成,一寸光阴不可轻 - 百度文库
伪指令的作用是完成对如存储模式、主存变量、子程序、宏及段定义等很多
不产生CPU动作的说明,并在程序执行前由汇编程序完成处理。
〔习题3.2〕什么是标识符,汇编程序中标识符怎样组成?
〔解答〕
为了某种需要,每种程序语言都规定了在程序里如何描述名字,程序语言的
名字通常被称为标识符;
汇编语言中的标识符一般最多由31个字母、数字及规定的特殊符号(如-,
$,?,@)组成,不能以数字开头。
〔习题3.3〕 什么是保留字,汇编语言的保留字有哪些类型,并举例说明。
〔解答
保留字是在每种语言中规定了有特殊意义和功能的不允许再做其它用处的
字符串;汇编语言的保留字主要有硬指令助记、伪指令助记符、运算符、寄存器
名以及预定义符号等。汇编语言对大小写不敏感。如定义字节数和字符串的DB
就是伪指令助记符。
〔习题3.4〕汇编语句有哪两种,每个语句由哪4个部分组成?
〔解答〕
汇编语句有执行性语句和说明性语句;
执行性语句由标号、硬指令助记符、操作数和注释四部分组成;
说明性语句由名字、伪指令助记符、参数和注释四部分组成
- 45 -
少年易学老难成,一寸光阴不可轻 - 百度文库
〔习题3.5〕汇编语言程序的开发有哪4个步骤,分别利用什么程序完成、
产生什么输出文件。
〔解答〕
⒈ 编辑 文本编辑程序 汇编语言源程序.asm
⒉ 汇编 汇编程序 目标模块文件.obj
⒊ 连接 连接程序 可执行文件.exe或.com
⒋ 调试 调试程序 应用程序
〔习题3.6〕区分下列概念:
(1)变量和标号
(2)数值表达式和地址表达式
(3)符号常量和字符串常量
〔解答〕
(1)变量是在程序运行过程中,其值可以被改变的量;标号是由用户自定
义的标识符,指向存储单元,表示其存储内容的逻辑地址。
(2)数值表达式一般是由运算符连接的各种常数所构成的表达式,地址表
达式是由名字、标号以及利用各种的操作符形成的表达式。
(3)在程序中,为了使常量更便于使用和阅读,经常将一些常量用常量定义
语句定义为符号常量,被一对双引号括起来的若干个字符组成的字符序列被称为
字符串常量。
- 46 -
少年易学老难成,一寸光阴不可轻 - 百度文库
〔习题3.7〕假设myword是一个字变量,mybyte1和mybyte2是两个
字节变量,指出下列语句中的错误原因。
(1) mov byte ptr [bx],1000
(2) mov bx,offset myword[si]
(3) cmp mybyte1,mybyte2
(4) mov al,mybyte1+mybyte2
(5) sub al,myword
(6) jnz myword
〔解答〕
(1)1000超出了一个字节范围
(2)寄存器的值只有程序执行时才能确定,而offset是汇编过程计算的偏
移地址,故无法确定,改为lea bx,myword[si]
(3)两个都是存储单元,指令不允许
(4)变量值只有执行时才确定,汇编过程不能计算
(5)字节量AL与字量myword,类型不匹配
(6)Jcc指令只有相对寻址方式,不支持间接寻址方式
〔习题3.8〕OPR1是一个常量,问下列语句中两个AND操作有什么区别?
AND AL,OPR1 AND 0feh
〔解答〕
- 47 -
少年易学老难成,一寸光阴不可轻 - 百度文库
前者为“与”操作硬指令助记符,可汇编成机器代码。
后者为逻辑运算符,在汇编时进行“与”运算,产生具体数值。
〔习题3.9〕给出下列语句中,指令立即数(数值表达式)的值:
(1) mov al,23h AND 45h OR 67h
(2) mov ax,1234h/16+10h
(3) mov ax,NOT(65535 XOR 1234h)
(4) mov al,LOW 1234h OR HIGH 5678h
(5) mov ax,23h SHL 4
(6) mov ax,1234h SHR 6
(7) mov al,’a’ AND (NOT(’a’-’A’))
(8) mov al,’H’ OR 00100000b
(9) mov ax,(76543 LT 32768) XOR 7654h
〔解答〕
注:对于逻辑运算,有关操作数可化为二进制数。
(1)67h
(2)133h
(3)1234h
(4)76h
- 48 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(5)0234h
(6)0048h
(7)41h
(8)68h
(9)7654h
〔习题3.10〕画图说明下列语句分配的存储空间及初始化的数据值:
(1) byte_var DB ’ABC’,10,10h,’EF’,3 DUP(-1,?,3 DUP(4))
(2) word_var DW 10h,-5,’EF’,3 DUP(?)
〔解答〕
(1)从低地址开始,依次是(十六进制表达):
41 42 43 0a 10 45 46 ff - 04 04 04 ff -
04 04 04 ff - 04 04 04
(2)从低地址开始,依次是(十六进制表达):
10 00 FB FF 46 45 - - - - - -
〔习题3.11〕请设置一个数据段mydataseg,按照如下要求定义变量:
(1) my1b为字符串变量:Personal Computer
(2) my2b为用十进制数表示的字节变量:20
(3) my3b为用十六进制数表示的字节变量:20
- 49 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(4) my4b为用二进制数表示的字节变量:20
(5) my5w为20个未赋值的字变量
(6) my6c为100的常量
(7) my7c表示字符串:Personal Computer
〔解答〕
mydataseg segment
my1b db ‘Personal Computer’
my2b db 20
my3b db 14h ;20h
my4b db 00010100b
my5w dw 20 dup(?)
my6c equ 100 ;my6c = 100
my7c equ
mydataseg ends
〔习题3.12〕分析例题3.2的数据段,并上机观察数据的存储形式。
〔解答〕
以字节为单位从低地址向高地址依次是:
16
- 50 -
少年易学老难成,一寸光阴不可轻 - 百度文库
00 12
FFH FFH FFH FFH
00 00 00 00 00 00 00 00
1 2 3 4 5
45H 23H 00 00 00 00 00 00 00 00
‘a’ ‘b’ ‘c’
‘H’ ‘e’ ‘l’ ‘l’ ‘o’ 13 10 ‘$’
12个字符串’month’,每个字符串从低地址到高地址依次是:’
m’ ‘o’ ‘n’ ‘t’ ‘h’
25×4个字节未定义初值的存储单元,操作系统设置为0
〔习题3.13〕修改例题3.3,现在用字定义伪指令dw、字串传送指令movsw
和字符串显示9号功能调用实现。
〔解答〕
.model small
.stack
.data
source dw 3433h,3635h
target dw 40 dup(?),'$'
- 51 -
少年易学老难成,一寸光阴不可轻 - 百度文库
.code
.startup
mov ax,ds
mov es,ax
cld
mov si,offset source
mov di,offset target
mov cx,40
rep movsw
mov si,0
mov dx,offset target
mov ah,9
int 21h
.exit 0
end
〔习题3.14〕变量和标号有什么属性?
〔解答〕
段地址:表示变量和标号所在代码段的段地址;
- 52 -
少年易学老难成,一寸光阴不可轻 - 百度文库
偏移地址:表示变量和标号所在代码段的段内偏移地址;
类型:引用变量时,表示是字节、字、双字等数据量。引用该标号时,表示
它所在同一个段――near类型,还是另外一个段――far类型。
〔习题3.15〕设在某个程序中有如下片段,请写出每条传送指令执行后寄
存器AX的内容:
mydata segment
ORG 100H
VARW DW 1234H,5678H
VARB DB 3,4
ALIGN 4
VARD DD 12345678H
EVEN
BUFF DB 10 DUP(?)
MESS DB ’HELLO’
BEGIN: MOV AX,OFFSET MESS
MOV AX,TYPE BUFF+TYPE MESS+TYPE VARD
MOV AX,SIZEOF VARW+SIZEOF BUFF+SIZEOF MESS
MOV AX,LENGTHOF VARW+LENGTHOF VARD
- 53 -
少年易学老难成,一寸光阴不可轻 - 百度文库
MOV AX,LENGTHOF BUFF+SIZEOF VARW
MOV AX,TYPE BEGIN
MOV AX, OFFSET BEGIN
〔解答〕
MOV AX, OFFSET MESS ;AX=116H
MOV AX, TYPE BUFF+TYPE MESS+TYPE VARD ;AX =
1+1+4 = 06H
MOV AX,SIZEOF VARW+SIZEOF BUFF+SIZEOF MESS ;
AX = 4+10+5 = 19 = 13H
MOV AX,LENGTHOF VARW + LENGTHOF VARD ;AX
= 2+1 = 03H
MOV AX,LENGTHOF BUFF + SIZEOF VARW ;AX =
10+4 =14 = 0EH
MOV AX,TYPE BIGIN ;AX = FF02H (近)
MOV AX,OFFSET BEGIN ;AX =
1BH
〔习题3.16〕利用简化段定义格式,必须具有.MODEL语句。MASM定义
了哪7种存储模式,TINY和SMALL模式创建什么类型(EXE或COM)程序?
设计32位程序应该采用什么模式?
- 54 -
少年易学老难成,一寸光阴不可轻 - 百度文库
〔解答〕
MASM定义的7种存储模式是TINY(微型模式、SMALL(小型模式)、
COMPACT(紧凑模式)、MEDIUM(中型模式)、LARGE(大型模式)、HUGE
(巨大模式)、FLAT(平展模式);TINY用于创建COM类型程序、一般程序
都可以选用SMALL模式;设计32位的程序应该采用FLAT模式。
〔习题3.17〕源程序中如何指明执行的起始点?源程序应该采用哪个DOS
功能调用,实现程序返回DOS?
〔解答〕
源程序中运用STARTUP伪指令指明执行的起始点;源程序应该采用DOS
功能调用的4CH子功能实现程序返回DOS的。
〔习题3.18〕在SMALL存储模式下,简化段定义格式的代码段、数据段和
堆栈段的缺省段名、定位、组合以及类别属性分别是什么?
〔解答〕
段定义伪指令 段名 定位 组合 类别 组名
.CODE _TEXT WORD PUBLIC 'CODE'
.DATA _DATA WORD PUBLIC 'DATA' DGROUP
.DATA? _BSS WORD PUBLIC 'BSS' DGROUP
.STACK STACK PARA STACK 'STACK' DGROUP
〔习题3.19〕如何用指令代码代替.startup和.exit指令,使得例题3.1a能
够在MASM 5.x下汇编通过?
- 55 -
少年易学老难成,一寸光阴不可轻 - 百度文库
〔解答〕
;(文件名)
.model small
.stack
.data
string db ‘Hello,Everybody !’,0dh,0ah.’$’
.code
start: mov ax ,@data
mov ds,ax
mov dx,offset string
mov ah,9
int 21h
mov ax ,4c00h
int 21h
end start
〔习题3.20〕创建一个COM程序完成例题3.1的功能。
〔解答〕
;lt301a,asm
- 56 -
少年易学老难成,一寸光阴不可轻 - 百度文库
.model tiny
.code
.startup
mov dx,offset string
mov ah,9
int 21h
.exit 0
string db 'Hello,Everybody!'0dh,0ah,'$' ;
end
〔习题3.21〕按下面要求写一个简化段定义格式的源程序
(1) 定义常量num,其值为5;数据段中定义字数组变量datalist,它的
头5个字单元中依次存放-1、0、2、5和4,最后1个单元初值不定;
(2) 代码段中的程序将datalist中头num个数的累加和存入datalist的
最后1个字单元中。
〔解答〕
.model small
.stack
.data
- 57 -
少年易学老难成,一寸光阴不可轻 - 百度文库
num equ 5
datalist dw -1,0,2,5,4,?
.code
.startup
mov bx,offset datalist
mov cx,num
xor ax,ax
again: add ax,[bx]
inc bx
inc bx
loop again
mov [bx],ax
.exit 0
end
〔习题3.22〕按下面要求写一个完整段定义格式的源程序
(1)数据段从双字边界开始,其中定义一个100字节的数组,同时该段还
作为附加段;
- 58 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(2)堆栈段从节边界开始,组合类型为stack;
(3)代码段的类别是’code’,指定段寄存器对应的逻辑段;主程序指定
从100h开始,给有关段寄存器赋初值;将数组元素全部设置为64h。
〔解答〕
stack segment para ‘stack’
dw 512 dup(?)
stack ends
data segment
array db 100 dup(?)
data ends
code segment ‘code’
assume cs:code,ds:data,es:data,ss:stack
org 100h
start: mov ax,data
mov ds,ax
mov es,ax
mov di,offset array
mov al,64h
- 59 -
少年易学老难成,一寸光阴不可轻 - 百度文库
mov cx,100
cld
rep stosb
mov ax,4c00h
int 21h
code ends
end start
〔习题3.23〕编制程序完成两个已知双精度数(4字节)A和B相加并将
结果存入双精度变量单元SUM中(不考虑溢出)。
〔解答〕
;
.model small
.stack 256 ;定义堆栈段大小为256个字节
.data
A dd 11223344h ;定义两个双字的数(随意)
B dd 77553311h
sum dd ? ;定义结果,执行后为:88776655h
.code
- 60 -
少年易学老难成,一寸光阴不可轻 - 百度文库
.startup
xor si, si ;相对于变量的位移量清零
mov cx, 2 ;分高低字分别相加,共两次
clc ;清零cf
again: mov ax, word ptr A[si] ;取第一个数的一个字(先低字后高
字)
adc ax, word ptr B[si] ;取第二个数的一个字(先低字后高字)
mov word ptr sum[si], ax ;存和的一个字(先低字后高字)
inc si ;修改位移量指向下一个字(加2)
inc si
loop again ;cx=cx-1 ,if cx<>0 ,jump again
.exit 0
end
〔习题3.24〕编制程序完成12H、45H、0F3H、6AH、20H、0FEH、90H、
0C8H、57H和34H等10个字节数据之和,并将结果存入字节变量SUM中(不
考虑溢出)。
〔解答〕
.startup
xor si, si ;位移量清零
- 61 -
少年易学老难成,一寸光阴不可轻 - 百度文库
mov al, bdata[si] ;取第一个数
mov cx, num-1 ;累加次数
again: inc si ;指向下一个数
adc al, bdata[si] ;累加
loop again ;如未完,继续累加
mov sum, al ;完了,存结果
.exit 0
end
〔习题3.25〕结构数据类型如何说明、结构变量如何定义、结构字段如何
引用?
〔解答〕
结构类型的说明使用一对伪指令STRUCT(MASM5.x是STRUC,功能相
同)和ENDS。它们的格式为:
结构名 STRUCT
… ;数据定义语句
结构名 ENDS
结构变量定义的格式为:
变量名,结构名 〈字段初值表〉
- 62 -
少年易学老难成,一寸光阴不可轻 - 百度文库
引用结构字段,采用圆点“.”操作符,其格式是:
结构变量名.结构字段名。
〔习题3.26〕记录数据类型如何说明,记录变量如何定义,width和mask
操作符是什么作用?
〔解答〕
记录类型的说明采用伪指令RECORD,它的格式为:
记录名 RECORD 位段[,位段…]
定义记录变量的格式:
记录变量名 记录名 〈段初值表〉
Width记录名/记录位段名操作符返回记录或记录位段所占用的位数。
mask记录位段名操作符返回一个8位或16位数值,其中对应该位段的个
位为1,其余位为0。
第4章 基本汇编语言程序设计
〔习题4.1〕例题4.2如果要求算术右移8位,如何修改程序。
〔解答〕
思路: 首先由最高位字节向次低位字节传送……次低位字节向最低位字节
传送(共7次);再判最高位字节符号位,如为0,送00h到最高位字节;如为
1,送ffh到最高位字节。传送可参考例题4.2,不过应从第一号字节送第零号字
节,……最高位字节向次低位字节传送;也可以用循环来完成:
- 63 -
少年易学老难成,一寸光阴不可轻 - 百度文库
.model small
.stack 256
.data
qvar dq 54321h
.code
.startup
mov cx,7
mov si,1
again: mov al, byte ptr qvar[si]
mov byte ptr qvar[si-1],al
inc si
loop again
test al,80h
jz ezz
mov bl,0ffh
jmp done
ezz: mov bl,0
done: mov byte ptr qvar[7],bl
.exit 0
end
〔习题4.2〕例题4.2如果要求算术左移7位,如何用移位指令实现。
〔解答〕
- 64 -
少年易学老难成,一寸光阴不可轻 - 百度文库
思路:可设计外循环体为8个字节左移一次,方法是:最低位字节算术左移
一次, 次低位字节至最高位字节依次带 CF 位循环左移一次(内循环共8
次),外循环体控制执行7次即可。
.model small
.stack 256
.data
qvar dq 54321h
.code
.startup
mov dx, 7 ;外循环次数
mov ax, byte ptr qvar[0] ;最低位字节送ax
lpp: shl ax, 1 ;最低位字节左移一次,其d7移入
CF位
mov si, 1
mov cx, 7 ;内循环次数
again: rcl byte ptr qvar[si], 1 ;高位字节依次左移 P50
inc si
loop again
dec dx
jnz lpp
.exit 0
.end
- 65 -
少年易学老难成,一寸光阴不可轻 - 百度文库
〔习题4.3〕将AX寄存器中的16位数连续4位分成一组,共4组,然后
把这4组数分别放在AL、BL、CL和DL寄存器中。
〔解答〕
思路:设这四组从低位到高位分别放在AL、BL、CL和DL寄存器中。仅列
出代码段:
mov bl, al ;将al中的两组分开
and al, 0fh ;屏蔽高四位后送al
mov cl, 4 ;原al中的数据逻辑右移4次送bl
shr bl, cl
mov dl, ah ;将ah中的两组分开
and dl, 0f0h ;屏蔽低高四位后送dl
mov cl, 4 ;原ah中的数据逻辑右移4次送dl
shr dl, cl
mov cl, ah ;屏蔽高四位后送cl
and cl, 0fh
〔习题4.4〕编写一个程序,把从键盘输入的一个小写字母用大写字母显示
出来。
〔解答〕
getkey: mov ah, 1 ;从键盘输入,出口:al存键值
int 21h
cmp al, 'a' ;判键值是小写字母?
jb getkay
- 66 -
少年易学老难成,一寸光阴不可轻 - 百度文库
cmp al, 'z'
ja getkay
sub al,20h ;是小写字母转换为大写字母
mov dl,al
mov ah, 02h ;显示
int 21h
〔习题4.5〕已知用于LED数码管显示的代码表为:
LEDtable DB 0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8h
DB 80h,90h,88h,83h,0c6h,0c1h,86h,8eh
它依次表示0 ~ 9、A ~ F这16个数码的显示代码。现编写一个程序实现
将lednum中的一个数字(0 ~ 9、A ~ F)转换成对应的LED显示代码。
〔解答〕
.model small
.stack 256
.data
LEDtable DB 0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8h
DB 80h,90h,88h,83h,0c6h,0clh、86h,8eh
lednum DB ?
.code
.startup
mov bx, offset LEDtable
mov al, lednum
- 67 -
少年易学老难成,一寸光阴不可轻 - 百度文库
xlat ;al中存有对应的LED显示代码
.exit 0
end
〔习题4.6〕编制一个程序,把变量bufX和bufY中较大者存入bufZ;若
两者相等,则把其中之一存入bufZ中。假设变量存放的是8位无符号数。
〔解答〕
.model small
.stack 256
.data
bufx db ?
bufY db ?
bufz db ?
.code
.startup
mov al, bufX
mov bl, bufY
cmp al,bl
ja next
mov bufZ, bl
jmp done
next: mov bufZ, al
done: .exit 0
- 68 -
少年易学老难成,一寸光阴不可轻 - 百度文库
end
〔习题4.7〕设变量bufX为有符号16位数,请将它的符号状态保存在
signX,即:如果X大于等于0,保存0;如果X小于0,保存-1(ffh)。编写
该程序。
〔解答〕
.model small
.stack
.data
bufX dw -7
signX db ?
.code
.startup
cmp bufX,0 ;test bufX,80h
jl next ;jnz next
mov signX,0
jmp done
next: mov signX,-1
done: .exit 0
end
〔习题4.8〕bufX、bufY和bufZ是3个有符号16进制数,编写一个比较
相等关系的程序:
(1)如果这3个数都不相等,则显示0;
- 69 -
少年易学老难成,一寸光阴不可轻 - 百度文库
(2)如果这3个数中有两个数相等,则显示1;
(3)如果这3个数都相等,则显示2。
〔解答〕
.model small
.stack 256
.data
bufx dw ?
bufY dw ?
bufz dw ?
.code
.startup
mov ax, bufX
mov bx, bufY
mov cx, bufZ
mov dl, '0'
cmp ax,bx
jnz next1
inc dl
next1: cmp ax,cx
jnz next2
inc dl
next2: cmp bx,cx
- 70 -
少年易学老难成,一寸光阴不可轻 - 百度文库
jnz next3
inc dl
next3: cmp dl,’3’
jb next4
mov dl,’2’
next4: mov ah,02h ;显示
int 21h
.exit 0
end
〔习题4.9〕例题4.8内外循环次数共是多少?如果要求按从大到小排序,
程序如何修改?
〔解答〕
外循环次数是: count-1次 (19次)
内循环次数是: (count-1)!次 ( 19! 次)
内外循环次数共是 count-1 + (count-1)!次 ,即 19+19!次
〔习题4.10〕串操作指令常要利用循环结构,现在不用串操作指令实现字
符串string1内容传送到字符串string2,字符长度为count。
〔解答〕
.model small
.stack 256
.data
- 71 -
少年易学老难成,一寸光阴不可轻 - 百度文库
string1 db 'good morning!'
len = $-string1
string2 db len dup(?)
.code
.startup
mov cx, len ;字符数
mov si, offset string1 ;源指针
mov di, offset string2 ;目标指针
again: mov al, [si] ;送一个字符
mov [di], al
inc si ;修改指针
inc di ;修改指针
loop again ;cx=cx-1,cx=0时退出循环
.exit 0
end
〔习题4.11〕不用串操作指令求主存0040h : 0开始的一个64KB物理段中
共有多少个空格?
〔解答〕
这里仅列出主程序段:
mov ax,0040h ;送段地址
mov ds, ax
xor si, si ;偏移量地址
- 72 -
少年易学老难成,一寸光阴不可轻 - 百度文库
xor cx, cx ;计数(循环次数)
xor dx, dx ;空格计数器清零
again: cmp [si], 20h ;与空格的ASCII码比较
jne next ;不是空格,转
inc dx ;是空格,空格数加1
next: inc si ;修改地址指针
loop again ;cx=cx-1,如cx=0 退出循环
.exit 0
end
〔习题4.12〕编程实现把键入的一个字符,用二进制形式(0 / 1)显示出
它的ASCII代码值。
〔解答〕
.model small
.stack 256
.data
stri1 db 'please input',0dh,0ah,'$'
.code
.startup
mov dx,offset stri1
mov ah,09h
int 21h
mov ah, 01h
- 73 -
少年易学老难成,一寸光阴不可轻 - 百度文库
int 21h
mov cx, 8
again: xor dl,dl
shl al, 1
adc dl, '0'
mov ah,02h
int 21h
loop again
.exit 0
end
〔习题4.13〕编写程序,要求从键盘接收一个数bellN(0 ~ 9),然后响铃
bellN次。
〔解答〕
.model small
.stack
.data
stri1 db 'please input number:1--9',0dh,0ah,'$'
.code
.startup
again: mov dx,offset stri1 ;显示stri1,提示输入
mov ah,09h
int 21h
- 74 -
少年易学老难成,一寸光阴不可轻 - 百度文库
mov ah,01h ;调用输入一个字符
int 21h ;输入一个字符存在al中
cmp al, '1' ;判该字符,如不在‘1’--‘9’
jb again ;重新输入
cmp al, '9'
ja again
and al,0fh ;在‘1’--‘9’,屏蔽高4位
mov cl, al ;振铃次数送cx
xor ch,ch
abc: mov dl, 07h ;调用一次振铃
mov ah, 02h
int 21h
loop abc
.exit 0
end
〔习题4.14〕编写程序,将一个包含有20个有符号数据的数组arrayM分
成两个数组:正数数组arrayP和负数数组arrayN,并分别把这两个数组中的数
据个数显示出来。
〔解答〕
.model small
include
.stack
- 75 -
少年易学老难成,一寸光阴不可轻 - 百度文库
.data
arrayM db 1,2,3,4,5,6,0,-3,-5,-6,0,7,6,90,-18,-23,34,7,9,8 ;源数组
arrayP db 20 dup(?) ;正数数组
arrayN db 20 dup(?) ;负数数组
dispP db 'Plus Number: ','$'
dispN db 0dh,0ah,'Negs Number: ','$'
.code
.startup
mov cx, 20 ;源数组元素数
xor bx, bx ;设bh为正数个数,bl为负数个数,均清零
xor si, si ;源数组地址位移量
again: ;循环20次
mov ax, arrayM[si] ;取一个元素
cmp ax,0 ;判正数
jl Neg
inc bh ;是,正数个数加1
jmp next
Neg: inc bl ;否,负数个数加1
next: inc si ;修改位移量
loop again ;循环次数减1
mov ah,09h ;调用显示字符串功能
mov dx, offset dispP ;显示个数
- 76 -
少年易学老难成,一寸光阴不可轻 - 百度文库
int 21h
mov al,bh
call dispuib ; 调用I/O子程序库中的子程序
mov ah,09h ;调用显示字符串功能
mov dx, offset dispN ;显示个数
int 21h
mov al,bl
call dispuib ; 调用I/O子程序库中的子程序
.exit 0
end
〔习题4.15〕编写计算100个正整数之和的程序。如果和不超过16位字
的范围(65535),则保存其和到wordsum,如超过则显示‘overflow’。
〔解答〕
.model small
.stack
.data
num equ 100
wlist dw num dup(?)
wordsum dw ?
error db 'overflow. $'
.code
.startup
- 77 -
少年易学老难成,一寸光阴不可轻 - 百度文库
mov bx,offset wlist
mov cx,num
xor ax,ax
again: add ax,[bx]
jc next
inc bx
inc bx
loop again
mov [bx],ax
jmp done
next: mov dx,offset error
mov ah,9
int 21h
done: .exit 0
end
〔习题4.16〕编程判断主存0070h:0开始的1KB中有无字符串‘DEBUG’。
这是一个字符串包含的问题,可以采用逐个向后比较的简单算法。
〔解答〕
.model small
.stack
.data
disp1 db 'There is DEBUG in the aera!' ,0dh,0ah,‘$'
- 78 -
少年易学老难成,一寸光阴不可轻 - 百度文库
disp2 db 'There is no DEBUG in the aera!' ,0dh,0ah,‘$'
.code
.startup
mov ax, 0070h ;送段地址
mov ds, ax
xor si, si
mov cx,1024
cmp [si], 'D'
jne next
inc si
cmp [si], 'E'
jne next
inc si
cmp [si], 'B'
jne next
inc si
cmp [si], 'U'
jne next
inc si
cmp [si], 'G'
je yes
- 79 -
;与‘D'比较
;不是,转
1
;同上
;是‘DEBUG',转
;地址指针清零
;是,地址增
少年易学老难成,一寸光阴不可轻 - 百度文库
next: inc si ;不是,地址增1
loop again ;循环
no: mov dx, offset disp2 ;没找到,显示disp2
jmp dsp
yes: mov dx, offset disp1 ;找到,显示disp1
dsp: mov ah, 09h
int 21h
.exit 0
end
〔习题4.17〕编程把一个16位无符号二进制数转换成为用8421BCD码表
示的5位十进制数。转换算法可以是:用二进制数除以10000,商为“万位”,
再用余数除以1000,得到“千位”;依次用余数除以100、10和1,得到“百
位”、“十位”和“个位”。
〔解答〕
.model small
.stack 256
.data
var dw 3546
dbcd db 5 dup(?)
.code
.startup
mov ax, var
- 80 -
少年易学老难成,一寸光阴不可轻 - 百度文库
mov bx, 10000
mov cl, 10
xor si, si
xor dx, dx
again: div bx
mov dbcd[si], al
inc si
xchg ax, bx
div cl
xchg ax, bx
cmp si,5
jnz again
.exit 0
end
〔习题4.18〕没有。。。
〔习题4.19〕--
〔习题4.20〕--
〔习题4.21〕--
〔习题4.22〕过程定义的一般格式是怎样的?子程序入口为什么常有PUSH
指令、出口为什么有POP指令?下面的程序段有什么不妥吗?若有,请改正:
crazy PROC
push ax
- 81 -
少年易学老难成,一寸光阴不可轻 - 百度文库
xor ax,ax
xor dx,dx
again: add ax,[bx]
adc dx,0
inc bx
inc bx
loop again
ret
ENDP crazy
〔解答〕
crazy PROC
push ax
xor ax,ax
xor dx,dx
again: add ax,[bx]
adc dx,0
inc bx
inc bx
loop again
ret
ENDP crazy
- 82 -
;crazy PROC
;
; xor ax,ax
; xor dx,dx
;again: add ax,[bx]
; adc dx,0
; inc bx
; inc bx
; loop again
ret
; crazy ENDP
;
少年易学老难成,一寸光阴不可轻 - 百度文库
〔习题4.23〕子程序的参数传递有哪些方法,请简单比较。
〔解答〕
寄存器、共享变量(公共存储单元)、堆栈
用寄存器传递参数是把参数存于约定的寄存器中,这种方法简单易行,经常
采用;
用变量传递参数是主程序与被调用过程直接用同一个变量名访问传递的参
数,就是利用变量传递参数。如果调用程序与被调用程序在同一个源程序文件中,
只要设置好数据段寄存器DS,则子程序与主程序访问变量的形式相同,也就是
它们共享数据段的变量,调用程序与被调用程序不在同一个源文件中,必须利用
public/extern进行声明,才能用变量传递参数,利用变量传递参数,过程的通
用性比较差,然而,在多个程序段间,尤其在不同程序的模块间,利用全局变量
共享数据也是一种常见的参数传递方法;
用堆栈传递参数是主程序将子程序的入口参数压入堆栈,子程序从堆栈中取
出参数;子程序将出口压入堆栈,主程序弹出堆栈取得它们。
〔习题4.24〕采用堆栈传递参数的一般方法是什么,为什么应该特别注意
堆栈平衡问题。
〔解答〕
采用堆栈传递参数的一般方法是主程序将子程序的入口参数压入堆栈,子程
序从堆栈中取出参数子程序将出口参数压入堆栈,主程序弹出堆栈取得它们。因
为堆栈采用“先进后出”原则存取,而且返回地址和保护的寄存器等也要存于堆
栈,所以要特别注意堆栈平衡问题。
- 83 -
少年易学老难成,一寸光阴不可轻 - 百度文库
〔习题4.25〕什么是子程序的嵌套、递归和重入?
〔解答〕
子程序中又调用子程序就形成子程序嵌套。
子程序中直接或间接调用该子程序本身就形成子程序递归。
子程序的重入是指子程序被中断后又被中断服务程序所调用,能够重入的子
程序称为可重入子程序。
〔习题4.26〕将例题4.7的大写转换为小写字母写成过程,利用AL作为入
口、出口参数完成。
〔解答〕
.model small
.stack 256
.data
stdng db 'HeLLO eveRyboDy ! ' , 0
.code
.startup
mov bx, offset atring
again: mov al, [bx]
call chan ;调用过程
mov [bx] , al
next: inc bx
jmp again
done: .exit 0
- 84 -
少年易学老难成,一寸光阴不可轻 - 百度文库
chan proc ;大写转换为小写字母的过程
or al, al
jz done
cmp al,'A'
jb next
cmp al, 'Z'
ja next
or al, 20h
ret
chan endp
end
〔习题4.27〕请按如下子程序说明编写过程:
;子程序功能:把用ASCII码表示的两位十进制数转换为对应二进制
数
;入口参数:DH=十位数的ASCII码,DL=个位数的ASCII码
;出口参数:AL=对应的二进制数
〔解答〕
astob proc
and dh, 0fh ;十位数的ASCII码转为二进制数
mov al, dh
mul 10 ;al= 10*dh
and dl, 0fh ;个位数的ASCII码转为二进制数
- 85 -
少年易学老难成,一寸光阴不可轻 - 百度文库
add al, dl ;al= 10*dh + dl
ret
astob endp
〔习题4.28〕写一个子程序,根据入口参数AL=0/1/2,分别实现对大写字
母转换成小写、小写转换成大写或大小写字母互换。欲转换的字符串在string
中,用0表示结束。
〔解答〕
Change proc
Push bx ;保护bx
xor bx, bx ;位移量清零
cmp al,0 ;根据入口参数AL=0/1/2,分别处理
jz chan_0
dec al
jz chan_1
dec al
jz chan_2
jmp done
chan_0: mov al,string[bx] ;实现对大写字母转换成小写
cmp al,0
jz done
cmp al,’A’ ;是大写字母
jb next0
- 86 -
少年易学老难成,一寸光阴不可轻 - 百度文库
cmp al,’Z’ ;是大写字母
ja next0
add al, 20h ;转换
mov string[bx], al
next0: inc bx ;位移量加1,指向下一字母
jmp chan_0
chan_1: mov al,string[bx] ;实现对小写字母转换成大写
cmp al,0
jz done
cmp al,’a’ ;是大写字母
jb next1
cmp al,’z’ ;是大写字母
ja next1
sub al, 20h ;转换
mov string[bx], al
next0: inc bx ;位移量加1,指向下一字母
jmp chan_1
chan_2: mov al,string[bx] ;实现对大写字母转换成小写
cmp al,0
jz done
cmp al,’A’ ;是大写字母
jb next2
- 87 -
少年易学老难成,一寸光阴不可轻 - 百度文库
cmp al,’Z’ ;是大写字母
ja next20
add al, 20h ;转换
jmp next2
next20: cmp al,’a’ ;是大写字母
jb next2
cmp al,’z’ ;是大写字母
ja next2
sub al, 20h ;转换
mov string[bx], al
next2: inc bx ;位移量加1,指向下一字母
jmp chan_2
done: pop bx ;恢复bx
ret
change endp
〔习题4.29〕编制一个子程序把一个16位二进制数用十六进制形式在屏幕
上显示出来,分别运用如下3种参数传递方法,并用一个主程序验证它。
(1)采用AX寄存器传递这个16位二进制数
(2)采用wordTEMP变量传递这个16位二进制数
(3)采用堆栈方法传递这个16位二进制数
〔解答〕
(1)采用AX寄存器传递这个16位二进制数
- 88 -
少年易学老难成,一寸光阴不可轻 - 百度文库
.model small
.stack
.data
wdata dw 34abh
.code
.startup
.exit 0
dispa
- 89 -
mov ax,wdata
call dispa
;
proc
push cx
push dx
mov cl,4
mov dl,ah
shr dl,cl
call dldisp
mov dl,ah
and dl,0fh
call dldisp
mov dl,al
shr dl,cl
少年易学老难成,一寸光阴不可轻 - 百度文库
call dldisp
mov dl,al
and dl,0fh
call dldisp
pop dx
pop cx
ret
dispa endp
;
dldisp proc
push ax
or dl,30h
cmp dl,39h
jbe dldisp1
add dl,7
dldisp1: mov ah,2
int 21h
pop ax
ret
dldisp endp
end
(2)采用wordTEMP变量传递这个16位二进制数
- 90 -
少年易学老难成,一寸光阴不可轻 - 百度文库
.model small
.stack
.data
wdata dw 34abh
wordtemp dw ?
.code
.startup
mov ax,wdata
mov wordtemp,ax
call dispa
.exit 0
;
dispa proc
push cx
push dx
mov cl,4
mov dl,byte ptr wordtemp+1
shr dl,cl
call dldisp
mov dl,byte ptr wordtemp+1
and dl,0fh
call dldisp
- 91 -
少年易学老难成,一寸光阴不可轻 - 百度文库
mov dl,byte ptr wordtemp
shr dl,cl
call dldisp
mov dl,byte ptr wordtemp
and dl,0fh
call dldisp
pop dx
pop cx
ret
dispa endp
;
dldisp proc
push ax
or dl,30h
cmp dl,39h
jbe dldisp1
add dl,7
dldisp1: mov ah,2
int 21h
pop ax
ret
dldisp endp
- 92 -
少年易学老难成,一寸光阴不可轻 - 百度文库
end
(3)采用堆栈方法传递这个16位二进制数
.model small
.stack
.data
wdata dw 34abh
.code
.startup
push wdata
call dispa
pop ax
.exit 0
;
dispa proc
push bp
mov bp,sp
push ax
push cx
push dx
mov ax,[bp+4]
mov cl,4
mov dl,ah
- 93 -
;add sp,2
少年易学老难成,一寸光阴不可轻 - 百度文库
shr dl,cl
call dldisp
mov dl,ah
and dl,0fh
call dldisp
mov dl,al
shr dl,cl
call dldisp
mov dl,al
and dl,0fh
call dldisp
pop dx
pop cx
pop ax
pop bp
ret
dispa endp
;
dldisp proc
push ax
or dl,30h
cmp dl,39h
- 94 -
少年易学老难成,一寸光阴不可轻 - 百度文库
jbe dldisp1
add dl,7
dldisp1: mov ah,2
int 21h
pop ax
ret
dldisp endp
end
〔习题4.30〕设有一个数组存放学生的成绩(0 ~ 100),编制一个子程序
统计0 ~ 59分、60 ~ 69分、70 ~ 79分、80 ~ 89分、90 ~ 100分的人数,
并分别存放到scoreE、scoreD、score C、score B及score A单元中。编写一
个主程序与之配合使用。
〔解答〕
.model small
.stack
.data
score db 70,86,90,45,60,96,100,0,... ;全班成绩数组
count equ $-score ;总人数
scoreE db ? ;0--59分人数
scoreD db ? ;60--69分人数
scoreC db ? ;70--79分人数
scoreB db ? ;80--89分人数
- 95 -
少年易学老难成,一寸光阴不可轻 - 百度文库
scoreA db ? ;90--99分人数
.code
.startup
lea bx, score
mov cx, count
again:
mov al,[bx] ;取一个成绩
call tjrs ;调用统计分段人数
inc bx ;调整指针
loog again ;cx-cx-1,cx=0退出循环
.exit 0
tjrs proc ;统计分段人数
cmp al, 60
jae next0 ;al>= 60转
inc scoreE ;al<60,0--59分的人数加1
jmp next4
next0: cmp al, 70
jae next1
inc scoreD
jmp next4
next1: cmp al, 80
jae next2
- 96 -
少年易学老难成,一寸光阴不可轻 - 百度文库
inc scoreC
jmp next4
next2: cmp al, 90
jae next3
inc scoreB
jmp next4
next3: inc scoreA
next4: ret
tjrs endp
end
〔习题4.31〕编写一递归子程序,计算指数函数X n 的值。
〔解答〕
model small
.stack
.data
x dw 5
n dw 6
zish dw ?
.code
.startup
mov bx,x
push bx
- 97 -
少年易学老难成,一寸光阴不可轻 - 百度文库
mov bx,n
push bx
mov bx,x
call zshhsu
pop zish
add sp,2
.exit 0
zshhsu proc
push bx
push ax
push bp
mov bp,sp
mov ax,[bp+8]
cmp ax,0
jne zshhsu1
inc ax
jmp zshhsu2
zshhsu1: dec ax
push bx
push ax
call zshhsu
pop ax
- 98 -
少年易学老难成,一寸光阴不可轻 - 百度文库
pop bx
mul bx
zshhsu2: mov [bp+8],ax
pop bp
pop ax
pop bx
ret
zshhsu endp
end
- 99 -
版权声明:本文标题:汇编语言程序设计(第四版)【课后答案】 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/p/1734980120a1617712.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论