资源描述
. .
汇编语言程序设计(第二版) 钱晓捷 习题答案
第二章〔01〕
2.1
〔1〕AX=1200h
〔2〕AX=0100h
〔3〕AX=4C2Ah
〔4〕AX=3412h
〔5〕AX=4C2Ah
〔6〕AX=7856h
〔7〕AX=65B7h
2.2(1) 两操作数类型不匹配
(2) IP指令指针制止用户访问
(3) 立即数不允许传给段存放器
(4) 段存放器之间不允许传送
(5) 两操作数类型不匹配
(6) 目的操作数应为[ BP ]
(7) 源操作数应为 [BX+DI]
(8) 立即数不能作目的操作数
2.3
lea bx,table ;获取table的首地址,BX=200H
mov al,8 ;传送欲转换的数字,AL=8
xlat ;转换为格雷码,AL=12H
2.4
堆栈是一种按“先进后出〞原那么存取数据的存储区域。
堆栈的两种根本操作是压栈和出栈,对应的指令是PUSH和POP。
2.5
mov ax,8057h
push ax
mov ax,0f79h
push ax
pop bx ;bx=0f79h
pop [bx] ;DS:[0f79h]=8057h
2.6
AL=89h CF ZF SF OF PF
AL=12h 1 0 0 1 1
AL=0afh 0 0 1 0 1
AL=0afh 1 0 1 0 1
AL=00h 0 1 0 0 1
AL=0ffh 0 0 1 0 1 AL=00h 0 1 0 0 1
2.7W=X+Y+24-Z
2.8
〔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 字操作数改为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的操作数不能是立即数
〔2不能对CS直接赋值
〔3〕两个操作数不能都是存储单元
〔4〕堆栈的操作数不能是字节量
〔5〕adc的操作数不能是段存放器
〔6〕没有确定是字节还是字操作
〔7〕in不支持超过FFH的直接寻址
〔8〕out只能以AL/AX为源操作数
第二章(02)
2.11;
指令
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章〔03〕
2.12;
指令 注释 执行结果 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)
;不考虑进位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码是: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
2.14; 〔1〕用sar编写
2.20; 8086的条件转移的转移X围:在当前指令地址的 +127---- -128之内。
如条件转移的转移X围超出此X围,可在此X围内安排一条无条件转移,再转移到X围外的目标地址。
2.21; (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
there
;CX〔无符号数〕< 64h
2.23;
mov cx,0 不循环,因为一进入循环就判 cx=0? 如cx=0 就退出循环
delay:loop delay
2.24; 〔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
e below_eq
jae below_eq
2.25; 答:将首地址为array得20个字的数组求和,并将结果存入 total 单元中。
2.26; (1)
mov si,0
mov dl,string[si] ;第1个字符送dl存放器
mov si,5
mov dh,string[si] ;第6个字符送dh存放器
(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寄..
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
jz zero
mov ax,-1
jmp done
zero: mov ax,0
done: ret
(4)
lea bx,buffer1
lea dx,buffer2
mov cx,8 ;8个字节
xor si,si ;si=0
clc ;CF=0
(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继续加
ret
(6)
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)
xor si,si ;si<--0
mov cx,100 ;循环次数
again: dec array[si]
dec cx
jnz again
(8)
xor si,si ;si<--0
coun: cmp string[si],’$’
je done
inc si
jmp coun
done: ret
2..27; (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.29; 压缩BCD码加法:AX←AX+BX
出口参数:AX=BCD码和
2.34; 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; ;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的字符不是小写字母
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
第三章(01)
3.1; 硬指令:每个硬指令就是一个处理器指令,在CPU执行时产生相应功能;
伪指令:伪指令并不产生处理器指令,它通常用于辅助汇编程序对源程序进展汇编。
3.2;
3.5; ⒈ 编辑 文本编辑程序 汇编语言源程序.asm
⒉ 汇编 汇编程序 目标模块文件.obj
⒊ 连接 连接程序 可执行文件.exe或.
⒋ 调试 调试程序 应用程序
3.6; ;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’比拟
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; ;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的字符不是小写字母
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; 〔1〕 mov byte ptr [bx],1000 ;1000超出了一个字节X围
〔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; 前者为“与〞操作硬指令助记符,可汇编成机器代码。
后者为逻辑运算符,在汇编时进展“与〞运算,产生具体数值。
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; 假设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 segment
my1b db ‘Personal puter’
my2b db 20
my3b db 14h ;20h
my4b db 00010100b
my5w dw 20 dup(?)
my6c equ 100 ;my6c = 100
my7c equ <Personal puter>
mydataseg ends
3.18; 段地址:表示标号所在代码段的段地址;
偏移地址:表示标号所在代码段的段内偏移地址;
类型:引用该标号时,表示它所在同一个段――near类型,还是另外一个段――far类型。
3.19; 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; 段定义伪指令 段名 定位 组合 类别 组名
.CODE _TEXT WORD PUBLIC ’CODE’
.DATA _DATA WORD PUBLIC ’DATA’ DGROUP
.STACK STACK PARA STACK ’STACK’ DGROUP
3.25; .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; 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;
解答
;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; .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’ ;判键值是小写字母?
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; .
展开阅读全文