钱晓捷新版汇编语言程序设计习题答案
汇编语言基础知识
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.20、8086有哪4种逻辑段,各种逻辑段分别是什么用途?(解答)
代码段(Code Segment)用来存放程序的指令序列。处理器利用CS : IP取得下一条要执行的指令
•堆栈段(Stack Segment)确定堆栈所在的主存区域。处理器利用SS : SP操作堆栈中的数据
•数据段(Data Segment)存放当前运行程序所用的数据。处理器利用DS : EA存取数据段中的数据
•附加段(Extra Segment)是附加的数据段,也用于数据的保存。处理器利用ES : EA存取数据段中的数据
第二章8086指令系统
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 ;AX=1200h
(2) mov ax,bx ; AX=0100h
(3) mov ax,[1200h] ; AX=4C2Ah
(4) mov ax,[bx] ; AX=3412h
(5) mov ax,[bx+1100h] ; AX=4C2Ah
(6) mov ax,[bx+si] ; AX=7856h
(7) mov ax,[bx][si+1100h] ; AX=65B7h
2.2指出下列指令的错误
(1) mov cx,dl 两操作数类型不匹配
(2) mov ip,ax IP 指令指针禁止用户访问
(3) mov es,1234h 立即数不允许传给段寄存器
(4) mov es,ds 段寄存器之间不允许传送
(5) mov al,300 两操作数类型不匹配
(6) mov [sp],ax 目的操作数应为[ BP ]
(7) mov ax,bx+di 源操作数应为 [BX+DI]
(8) mov 20h,ah 立即数不能作目的操作数
2.3已知数字0 ~ 9对应的格雷码依次为:18H、34H、05H、06H、09H、0AH、0CH、11H、12H、14H,它存在于以table为首地址(设为200H)的连续区域中。请为如下程序段的每条指令加上注释,说明每条指令的功能和执行结果。
lea bx,table ;获取table的首地址,BX=200H
mov al,8 ;传送欲转换的数字,AL=8
xlat ;转换为格雷码,AL=12H
2.4什么是堆栈,它的工作原则是什么,它的基本操作有哪两个,对应哪两种指令?
堆栈是一种按“先进后出”原则存取数据的存储区域。
堆栈的两种基本操作是压栈和出栈,对应的指令是PUSH和POP。
2.5已知SS = FFA0H、SP = 00B0H,画图说明执行下面指令序列时,堆栈区和SP的内容如何变化?
mov ax,8057h
push ax
mov ax,0f79h
push ax
pop bx ;bx=0f79h
pop [bx] ;DS:[0f79h]=8057h
2.6 给出下列各条指令执行后AL值,以及CF、ZF、SF、OF和PF的状态:
mov al,89h AL=89h CF ZF SF OF PF
add al,al AL=12h 1 0 0 1 1
add al,9dh AL=0afh 0 0 1 0 1
cmp al,0bch AL=0afh 1 0 1 0 1
sub al,al AL=00h 0 1 0 0 1
dec al AL=0ffh 0 0 1 0 1
inc al AL=00h 0 1 0 0 1
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
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寄存器。 ADD DX,BX
(2)用寄存器BX和SI的基址变址寻址方式把存储器的一个字节与AL寄存器的内容相加,并把结果送到AL中。 ADD AL,[BX+SI]
(3)用BX和位移量0B2H的寄存器相对寻址方式把存储器中的一个字和CX寄存器的内容相加,并把结果送回存储器中。 ADD [BX+0B2H],CX
(4)用位移量为0520H的直接寻址方式把存储器中的一个字与数3412H相加,并把结果送回该存储单元中。 ADD WORD PTR [0520H],3412H
(5)把数0A0H与AL寄存器的内容相加,并把结果送回AL中。 ADD AL,0A0H
2.9;设X、Y、Z、V均为16位带符号数,分别装在X、Y、Z、V存储单元中,阅读如下程序段,得出它的运算公式,并说明运算结果存于何处。
为了避免与操作数地址混淆,将题中X,Y,Z,V 字操作数改为A,B,C,D
mov ax,X ;ax=A
imul Y ;dx,ax = A*B (将操作数看作符号数,以下同)
mov cx,ax
mov bx,dx ;bx,ax <-- dx,ax =A*B
mov ax,Z ;ax = C
cwd ;dx,ax =C (扩展符号后为双字)
add cx,ax
adc bx,dx ;bx,cx <-- bx,cx+dx,ax=A*B+C
sub cx,540
sbb bx,0 ;bx,cx<-- A*B+C-540
mov ax, V ;ax= D
cwd ;dx,ax= D (扩展符号后为双字)
sub ax, cx
sbb dx, bx ;dx,ax = dx,ax - bx,cx = D-(A*B+C-540)
idiv X ;运算结果:[D-(A*B+C-540h)]/A ;ax存商,dx存余数
2.10;
(1) xchg [si],30h xchg的操作数不能是立即数
(2 ) pop cs 不能对CS直接赋值
(3) sub [si],[di] 两个操作数不能都是存储单元
(4)push ah 堆栈的操作数不能是字节量
(5) adc ax,ds adc的操作数不能是段寄存器
(6) add [si],80h 没有确定是字节还是字操作
(7) in al,3fch in不支持超过FFH的直接寻址
(8) out dx,ah out只能以AL/AX为源操作数
2.11; 给出下列各条指令执行后的结果,以及状态标志CF、OF、SF、ZF、PF的状态。 指令 AX的值 CF OF SF ZF PF
Mov ax,1407h 1470h - - - - -
And ax,ax 1470h 0 0 0 0 0
Or ax,ax 1470h 0 0 0 0 0
Xor ax,ax 0 0 0 0 1 1
Not ax 0ffffh - - - - -
Test ax,0f0f0h 0ffffh 0 0 1 0 1
注意: 1. mov, not指令不影响标志位
2. 其他逻辑指令使CF=OF=0, 根据结果影响其他标志位。
2.12; 假设例题2.32的程序段中,AX = 08H,BX = 10H,请说明每条指令执行后的结果和各个标志位的状态。
指令 注释 执行结果 CF OF SF ZF PF
mov si,ax si=ax si=0008h - - - - -
shl si,1 si=2*ax si=0010h 0 0 0 0 0
add si,ax si=3*ax si=0018h 0 0 0 0 1
mov dx,bx dx=bx dx=0010h - - - - -
mov cl,03h cl=03h - - - - -
shl dx,cl dx=8*bx dx=0080h 0 u 0 0 0
sub dx,bx dx=7*bx dx=0070h 0 0 0 0 0
add dx,si dx=7*bx+3*ax dx=0088h 0 0 0 0 1
注意:
1. 左移N次相当于乘于2的N次方,右左移N次相当于除乘于2的N次方。
2. 移位指令根据是否移入“1”到CF,设置CF,根据移位后的结果影响SF,ZF,PF。根据最高符号位是否改变设置OF,如改变 OF=1.
3. ‘ u ’表示无定义,‘ - ’表示无影响。
2.13 编写程序段完成如下要求:
(1) 用位操作指令实现AL(无符号数)乘以10
;不考虑进位mov bl,al
mov cl,3
shl al,cl
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码与非压缩BCD码的互相转换
数字0~9的ASCII码是:30h~39h
非压缩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
mov cl,4
again: shr dx,1 ;实现逻辑右移
;采用“sar dx,1”,则实现算术右移
rcr ax,1
dec cl
jnz again
(3) 把DX:.AX中的双字右移4位
MOV CL, 4
SHR AX, CL
MOV BL, DL
SHR DX, CL
SHL BL, CL
OR AH, BL
2.14; 已知AL = F7H(表示有符号数-9),分别编写用SAR和IDIV指令实现的除以2的程序段,并说明各自执行后,所得的商是什么?
(1)用sar编写
mov al,0f7h ;-9送al
sar al,1 ;结果:al=0fbh 即-5
(2)用idiv编写
mov al,0f7h ;-9送al
cbw ;字节符号扩展位字
mov bl,2 ;注意除数不可为立即数
idiv bl ;结果:商为al=fch (-4)
; 余数为ah=ffh (-1)
结论:符号数的除法 用idiv 准确
2.15、已知数据段500h ~600h处存放了一个字符串,说明下列程序段执行后的结果:
mov si,600h
mov di,601h
mov ax,ds
mov es,ax
mov cx,256
std
rep movsb
2.16、说明下列程序段的功能
cld
mov ax,0fefh
mov cx,5
mov bx,3000h
mov es,bx
mov di,2000h
rep stosw
2.17、指令指针IP是通用寄存器还是专用寄存器?有指令能够直接它赋值吗?哪类指令的执行会改变它的值?调试程序DEBUG环境下,如何改变IP数值?
2.18、控制转移类指令中有哪三种寻址方式?
2.19; 什么是短转移short jump、近转移near jump和远转移far jump?什么是段内转移和段间转移?8086有哪些指令可以实现段间转移?
短转移:指段内-128~127之间的转移,位移量用一个字节表示
近转移:指段内±32K之间的转移,位移量用一个字表示
远转移:指段间1MB范围的转移
段内转移:指在同一个代码段内的转移,可以是短转移或者近转移
段间转移:指转移到另外一个代码段,就是远转移
8086/8088CPU的JMP、CALL和INT n指令可以实现段间转移
2.20; 8086的条件转移指令的转移范围有多大?实际编程时,你如何处理超出范围的条件转移?
8086的条件转移的转移范围:在当前指令地址的 +127---- -128之内。
如条件转移的转移范围超出此范围,可在此范围内安排一条无条件转移,再转移到范围外的目标地址。
2.21; 假设DS=2000H,BX=1256H,SI=528FH,位移量TABLE=20A1H,[232F7H]=3280H,[264E5H]=2450H,试问执行下列段内间接寻址的转移指令后,转移的有效地址是什么?
(1)JMP Bx ;转移的有效地址EA=BX=1256h
(2)JMP tABLE[Bx] ;转移的有效地址EA=[ds:20a1h+1256h]=[232f7]=3280h
(3)JMP [Bx][si] ;转移的有效地址EA=[ds:1256h+528fh]=264e5h=2450h
2.22、判断下列程序段跳转的条件
(1) xor ax,1e1eh
je equal
;AX=1e1eh(异或后为0)
(2)test al,10000001b
jnz there
;AL的D0或D7至少有一位为1
(3) cmp cx,64h
jb there
;CX(无符号数)< 64h
2.23; 设置CX = 0,则LOOP指令将循环多少次?例如
mov cx,0 ;不循环,因为一进入循环就判 cx=0? 如cx=0 就退出循环
delay:loop delay
循环次数是2的16次方,即2^16=65536。
2.24 假设AX和SI存放的是有符号数,DX和DI存放的是无符号数,请用比较指令和条件转移指令实现以下判断:
(1)若DX > DI,转到above执行
cmp dx,di
ja above ;=jnbe above
(2)若AX > SI,转到greater执行
cmp ax,si
jg greater ;=jnle greater
(3)若CX = 0,转到zero执行
cmp cx,0 jcxz zero
jz zero
(4)若AX-SI产生溢出,转到overflow执行;
cmp ax,di
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.25有一个首地址为array的20个字的数组,说明下列程序段的功能。
mov cx,20
mov ax,0
mov si,ax
sum_loop:
add ax,array[si]
add si,2
loop sum_loop
mov total,ax
; 答:将首地址为array得20个字的数组求和,并将结果存入 total 单元中。
2.26 按照下列要求,编写相应的程序段:
(1) 起始地址为string的主存单元中存放有一个字符串(长度大于6),把该字符串中的第1个和第6个字符(字节量)传送给DX寄存器。
mov si,0
mov dl,string[si] ;第1个字符送dl寄存器
mov si,5
mov dh,string[si] ;第6个字符送dh寄存器
(2) 从主存buffer开始的4个字节中保存了4个非压缩BCD码,现按低(高)地址对低(高)位的原则,将它们合并到DX中。
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寄..
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) 编写一个程序段,在DX高4位全为0时,使AX = 0;否则使AX = -1。
test dx,0f000h
jz zero
mov ax,-1
jmp done
zero: mov ax,0
done: ret
(4) 有两个64位数值,按“小端方式”存放在两个缓冲区buffer1和buffer2中,编写程序段完成buffer1-buffer2功能。
lea bx,buffer1
lea dx,buffer2
mov cx,8 ;8个字节
xor si,si ;si=0
clc ;CF=0
(5) 假设从B800h : 0开始存放有100个16位无符号数,编程求它们的和,并把32位的和保存在DX.AX中。
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继续加
ret
(6) 已知字符串string包含有32KB内容,将其中的’$’符号替换成空格。
mov si,offset string
mov cx,8000h ;32k=2^15=8000h
again: cmp [si],’$’
jnz next
mov [si],20h ;if [si]=’$’ [si]<-- ’ ’
next: inc si
loop again
(7) 有一个100个字节元素的数组,其首地址为array,将每个元素减1(不考虑溢出)存于原处。
xor si,si ;si<--0
mov cx,100 ;循环次数
again: dec array[si]
dec cx
jnz again
(8) 统计以 ’$’ 结尾的字符串srting的字符个数。
xor si,si ;si<--0
coun: cmp string[si],’$’
je done
inc si
jmp coun
done: ret
2.27; 对下面要求,分别给出3种方法,每种方法只用一条指令。
(1)使CF=0 : clc ; and ax,ax ;or ax,ax
(2)使AX=0 : xor ax,ax ; and ax,0 ;mov ax,0
(3)同时使AX=0和CF=0: and ax,0 ;xor ax,ax ;sub ax,ax
2.28、参照本习题的示意图,分析调用序列,画出每次调用及返回时的堆栈状态。其中CALL前是该指令所在的逻辑地址;另外,段内直接调用指令的机器代码的字节数为3,段间直接调用指令则为5个字节。
2.29 已知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.34; 补充例2.38,当有溢出时显示“Error! Overflow!”,无溢出时显示“OK”。
okmsg db ‘OK’, ‘$’errmsg db ‘Error ! Overflow !’, ‘$’ …
mov ax,X
sub ax,Y
jo overflow
mov dx,offset okmsg
jmp next
overflow: mov dx,errmsg
next: mov ah,9
int 21h
错误:
mov ax,X
sub ax,Y
jo overflow
mov dx,offset okmsg
okmsg db ‘OK’, ‘$’
mov dx,errmsg ;错误1:数据定义在代码中
mov ah,9
int 21h
overflow: errmsg db ‘Error ! Overflow !’, ‘$’
mov dx,errmsg ; 错误2:缺少JMP指令
mov ah,9
int 21h
2.37 从键盘输入一个字符串(不超过255个),将其中的小写字母转换成大写字母,然后按原来的顺序在屏幕上显示。
;xt237.asm
.model small
.stack
.data
array db 255
db 0
array1 db 255 dup('$')
array2 db 0dh,0ah,'$'
.code
.startup
mov ah,0ah ; 键盘输入字符串
mov dx,offset array
int 21h
mov dx,offset array2 ; 回车换行
mov ah,09h
int 21h
mov bx,offset array1
again: mov al,[bx]
cmp al,'$'
jz done
cmp al,'a' ; 小于a和大于z的字符不是小写字母
jb next
cmp al,'z'
ja next
sub al,20h ; 在a和z之间的字符才是小写字母,转换为大写
mov [bx],al ; 保存到原位置
next: inc bx
jmp again
done: mov dx,offset array1
mov ah,09h
int 21h
.exit 0
end
第三章汇编语言程序格式
3.1; 硬指令:每个硬指令就是一个处理器指令,在CPU执行时产生相应功能;
伪指令:伪指令并不产生处理器指令,它通常用于辅助汇编程序对源程序进行汇编。
3.5 汇编语言程序的开发有哪4个步骤,分别利用什么程序完成、产生什么输出文件。
⒈ 编辑 文本编辑程序 汇编语言源程序.asm
⒉ 汇编 汇编程序 目标模块文件.obj
⒊ 连接 连接程序 可执行文件.exe或.com
⒋ 调试 调试程序 应用程序
3.6 将第2章习题2.36采用简化段定义格式编写成一个完整的源程序。
;xt236.asm 简化段定义格式
.model small ;定义程序的存储模式(小模式)
.stack ;定义堆栈段(默认1024个字节)
.data ;定义数据段
str1 ab ’Input Number:0~9 : ’,0dh,0ah,’$’
str2 ab ’Error!’,0dh,0ah,’$’
.cade ;定义代码段
.startup ;说明程序的起始点,建立ds,ss的内容。
mov ah,09h ;显示str1字符串
mov dx,offset str1
int 21h
gtekey: mov ah,1 ;调用BIOS判断按键功能
int 16h
jz getkey ;如 zf = 0,无键按下,等待
cmp al,‘0’ ;有键按下,键值与‘0’比较
jb error ;如 < ‘0’,出错处理
cmp al, ‘9 ’ ;有键按下,键值与 ‘9’比较
ja error ;如 〉‘9’,出错处理
mov ah,02h ;调用DOS显示字符功能,显示该数字
mov dl,al
int 21h
.exit 0 ;终止程序执行,返回DOS
error: mov ah,09h ; 出错,调用DOS 功能显示str2字符串
mov dx,offset str2
int 21h
jmp getkey ;等待按键
end ; 汇编结束
3.7、将第2章习题2.37采用完整段定义格式编写成一个完整的源程序。
;xt307.asm
stack segment
dw 512 dup(?)
stack ends
data segment
array db 255
db 0
array1 db 255 dup('$')
array2 db 0dh,0ah,'$'
data ends
code segment 'code'
assume cs:code, ds:data, ss:stack
start: mov ax,data
mov ds,ax
mov ah,0ah ; 键盘输入字符串
mov dx,offset array
int 21h
mov dx,offset array2 ; 回车换行
mov ah,09h
int 21h
mov bx,offset array1
again: mov al,[bx]
cmp al,'$'
jz done
cmp al,'a' ; 小于a和大于z的字符不是小写字母
jb next
cmp al,'z'
ja next
sub al,20h ; 在a和z之间的字符才是小写字母,转换为大写
mov [bx],al ; 保存到原位置
next: inc bx
jmp again
done: mov dx,offset array1
mov ah,09h
int 21h
mov ax,4c00h
int 21h
code ends
end start
3.9; 假设myword是一个字变量,mybyte1和mybyte2是两个字节变量,指出下列语句中的错误原因。
(1) mov byte ptr [bx],1000 ;1000超出了一个字节范围
(2) mov bx,offset myword[si];寄存器的值只有程序执行时才能确定,
;而offset是汇编过程计算偏移地址,故无法确定
;可以改为lea bx,myword[si]
(3) cmp mybyte1,mybyte2 ;两个都是存储单元,指令不允许
(4) mov al,mybyte1+mybyte2 ;变量值只有执行时才确定,汇编过程不能计算
(5) sub al,myword ;字节量AL与字量myword,类型不匹配
(6) jnz myword ;Jcc指令只有相对寻址方式,不支持间接寻址方式
3.10 OPR1是一个常量,问下列语句中两个AND操作有什么区别?
AND AL,OPR1 AND 0feh
前者为“与”操作硬指令助记符,可汇编成机器代码。
后者为逻辑运算符,在汇编时进行“与”运算,产生具体数值。
3.11给出下列语句中,指令立即数(数值表达式)的值
注:对于逻辑运算,有关操作数可化为二进制数。
(1)mov al,23h AND 45h OR 67h ; 67h
(2)mov ax,1234h/16 + 1Oh ; 133h
(3)mov ax,NOT(65535 XOR 1234h) ; 1234h
(4)mov al, LOW 1234h OR HIGH 5678h ; 76h
(5)mov ax,23h SHL 4 ; 0234h
(6)mov ax, 1234h SHR 6 ; 0048h
(7)mov al,’a’ AND (NOT(’a’-’A’)) ; 41h
(8)mov al,’H’ OR 00100000b ; 68h
(9)mov ax,(76543 LT 32768) XOR 7654h ; 7654h
3.12; 为第2章例题2.52定义变量count、block、dplus和dminus。
假设block开始的数据块有32个字节数据:16个正数+100 (64h),16个负数 -48 (0doh)
分别连续分布:
block db 16 dup(100),16 dup(-48) ;也可以是任意字节数据,随意分布。
dplus db 32 dup(?) ;为正数预留存储空间
dminus db 32 dup(?) ;为负数预留存储空间
count equ 32 ;字节数
3.15; 请设置一个数据段mydataseg,按照如下要求定义变量:
(1) my1b为字符串变量:Personal Computer
(2) my2b为用十进制数表示的字节变量:20
(3) my3b为用十六进制数表示的字节变量:20
(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.18; 变量和标号有什么属性?
段地址:表示标号所在代码段的段地址;
偏移地址:表示标号所在代码段的段内偏移地址;
类型:引用该标号时,表示它所在同一个段near类型,还是另外一个段far类型。
3.19; 设在某个程序中有如下片段,请写出每条传送指令执行后寄存器AX的内容:
mydata segment
ORG lO0h
VARW DW l234H,5678H
VARB DB 3,4
AGLIN 4
VARD DD 12345678H
EVEN
BUFF DB 10 DUP(?)
MESS DB ’HELLO’
MOV AX, OFFSET VARB + OFFSET MESS ;AX = 4+16H = 1AH
MOV AX, TYFE TYPE BUFF+TYPE MESS+TYPE VARD;AX = 1+1+4 = 06H
MOV AX,SIZE VARW+SIZE BUFF+SIZE MESS;AX = 4+10+5 = 19 = 13H
MOV AX,LENGTH VARW + LENGTH VARD ;AX = 2+1 = 03H
MOV AX,LENGTH BUFF + SIZE VARW ;AX = 10+4 =14 = 0EH
MOV AX,TYPE BIGIN ;AX = FF02H (近)
MOV AX,OFFSET BEGIN ;AX = 1BH
3.22; 在SMALL存储模式下,简化段定义格式的代码段、数据段和堆栈段的缺省段名、定位、组合以及类别属性分别是什么?
段定义伪指令 段名 定位 组合 类别 组名
.CODE _TEXT WORD PUBLIC ’CODE’
.DATA _DATA WORD PUBLIC ’DATA’ DGROUP
.STACK STACK PARA STACK ’STACK’ DGROUP
3.25; 按下面要求写一个简化段定义格式的源程序
(1) 定义常量num,其值为5;数据段中定义字数组变量datalist,它的头5个字单元中依次存放-1、0、2、5和4,最后1个单元初值不定;
(2) 代码段中的程序将datalist中头num个数的累加和存入datalist的最后1个字单元中。
.model small
.stack
.data
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.26; 按下面要求写一个完整段定义格式的源程序
(1) 数据段从双字边界开始,其中定义一个100字节的数组,同时该段还作为附加段;
(2) 堆栈段从节边界开始,组合类型为stack;
(3) 代码段的类别是’code’,指定段寄存器对应的逻辑段;主程序指定从100h开始,给有关段寄存器赋初值;将数组元素全部设置为64h。
stack segment para ‘stack’
dw 512 dup(?)
stack ends
data segment
dword 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
mov cx,100
cld
rep stosb
mov ax,4c00h
int 21h
code ends
end start
3.27; 编制程序完成两个已知双精度数(4字节)A和B相加并将结果存入双精度变量单元SUM中(不考虑溢出)。
解答
;xt327.asm
.model small
.stack 256 ;定义堆栈段大小为256个字节
.data
anum dd 11223344h ;定义两个双字的数(随意)
bnum dd 77553311h
sum dd ? ;定义结果,执行后为:88776655h
.code
.startup
xor si, si ;相对于变量的位移量清零
mov cx, 2 ;分高低字分别相加,共两次
clc ;清零cf
again:mov ax, anum[si] ;取第一个数的一个字(先低字后高字)
adc ax, bnum[si] ;取第二个数的一个字(先低字后高字)
mov sum[si], ax ;存和的一个字(先低字后高字)
inc si ;修改位移量指向下一个字(加2)
inc si
loop again ;cx=cx-1 ,if cx<>0 ,jump again
.exit 0
end
3.28 编制程序完成12H、45H、0F3H、6AH、20H、0FEH、90H、0C8H、57H和34H等10个字节数据之和,并将结果存入字节变量SUM中(不考虑溢出)。
.startup
xor si, si ;位移量清零
mov al, bdata[si] ;取第一个数
mov cx, num-1 ;累加次数
again: inc si ;指向下一个数
adc al, bdata[si] ;累加
loop again ;如未完,继续累加
mov sum, al ;完了,存结果
.exit 0
end
第四章 基本汇编语言程序设计
4.3; 思路:设这四组从低位到高位分别放在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
cmp al, ’z’
ja getkay
sub al,20h ;是小写字母转换为大写字母
mov ah, 09h ;显示
int 21h
4.8; (1) 将jmp table[bx]指令改为:mov dx, table[bx]
(2) 去掉源程序中:.exit 0---end之间的语句
4.17; .model small
.stack 256
.data
stri1 db ’please input number:1--9’,odh,oah,’$’
.code
.startup
again: mov dx,offset stri1 ;显示stri1,提示输入
mov ah,09h
int 21h
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 cx, al ;振铃次数送cx
.repeat
mov dl, 07h ;调用一次振铃
mov ah, 02h
int 21h
mov dx ,0ffffh ;延时
abc: dec dx
jnz abc
.untilcxz ;cx=cx-1,cx=0 退出
.exit 0
end
4.22;crazy PROC ;crazy PROC
push ax ;
xor ax,ax ; xor ax,ax
xor dx,dx ; xor dx,dx
again: add ax,[bx] ;again: add ax,[bx]
adc dx,0 ; adc dx,0
inc bx ; inc bx
inc bx ; inc bx
loop again ; loop again
ret ; ret
ENDP crazy ; crazy ENDP
4.25;子程序中又调用子程序就形成子程序嵌套。
子程序中直接或间接调用该子程序本身就形成子程序递归。
4.26; .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
chan proc ;大写转换为小写字母的过程
or al, al
jz don