汇编语言程序设计(合工大版)习题参考答案
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
5.13 字数组ARRAY,第一个单元为元素个数N,后面为N个元素,编写程序,把零元素从数组中清除,移动元素位置并修改第一个单元(元素个数)。
;delete the 0 from array
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+1
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
5.14 下表为奥运会获金牌前十名国家的成绩统计表,请编写程序,统计并填写表中的合计栏数据。
;先逐行求小计,再按列求合计。
data segment
array db 1,0,1,? ;设简单数据
db 1,1,0,?
db 1,1,0,?
db 1,1,1,?
db 1,1,1,?
db 1,1,1,?
db 1,1,1,?
db 1,1,1,?
db 1,1,1,?
db 1,1,1,?
org 30h
sumvd db ?,?,?,? ;存放按列求的合计数
org 40h
loca dw ? ;存放array的第一行地址data ends
code segment
assume cs:code,ds:data
start:
mov ax, data
mov ds, ax
mov ax, 0
mov cx, 10
lea bx, array
sumh: mov di, 3
sum3: add al, [bx]
inc bx
dec di
jnz sum3
mov [bx],al ; 存放行的小计
mov ax,0
inc bx
loop sumh
; 下面按列求合计
lea bx, array
mov loca,bx
lea si, sumvd
mov cx,10
mov di,4
sumv3:
mov ax,0
mov bx,loca
sumv: add al, [bx]
add bx,4
loop sumv
mov [si],al
mov cx,10
inc si
inc loca
dec di
jnz sumv3
exit: mov ah,4ch
int 21h
code ends
end start
6.1过程定义如下,补充括号中的指令。
code segment
assume cs:code
main proc far
( PUSH DS )
( XOR AX,AX )
( PUSH AX )
…
…
…
ret
main endp
code ends
end main
6.2 补充下列程序括号中的指令,使得程序对堆栈的操作全部利用程序中定义的TOS堆栈,并画出程序执行后堆栈TOS中的数据。
data segment
dw 100 dup(?)
tos label word
data ends
code segment
assume cs:code,ss:data
main proc far
( MOV AX,DATA )
( MOV SS,AX )
( LEA SP,TOS )
push ds
xor ax, ax
push ax
call far ptr suba
…;假定此处指令的地址为cs=3400h,ip=30h
…
…
code ends
end main
6.3以下两个独立程序模块,互相用到对方的变量和标号,你认为哪一个是主模
块?程序有没有错误?应该如何修改?
答:m1.asm是主模块,因为它有call m2,但没有说明外部符号,而m2必须是过程名,var4,lab2也没有说明外部符号。
var1 ,var2没有说明为PUBLIC。
应加上:
EXTRN m2:FAR,var4:WORD
PUBLIC var1, var2,lab1
并修改data segment为data segment PUBLIC
同理M2.asm应加上:
EXTRN var1:byte,var2:word
extrn lab1:FAR
PUBLIC t603b, var4
并修改data segment为data segment PUBLIC
以上完成主要修改,但程序依然有错,请仔细检查操作数类型是否匹配。
;m1.asm 如下:
data segment
var1 db ?
var2 dw ?
var3 dw ?
data ends
code1 segment
assume cs:code1,ds:data
main proc far
start: …
mov ax, data
mov ds, ax
…
call m2
lab1: mov ax, var4
…
jmp lab2 ;去掉此指令
…
main endp
code1 ends
end start
;m2.asm 如下:
data segment
var4 dw ?
var5 dw ?
data ends
code2 segment
assume cs:code2,ds:data
m2 proc far
…
add dx,var1 ;var1为字节类型
add dx,var2
jmp lab1
…
M2 endp
code2 ends
end
6.4 主程序从键盘输入N位二进制数到缓冲区,用子程序将其转换为二进制数串显示。
主程序和子程序共用数据缓冲区。
data segment
buff db 9,?,9 dup (?)
data ends
code segment
assume cs:code,ds:data
main proc far
start:
mov ax, data
mov ds, ax
lea dx, buff
mov ah, 10
int 21h
call outp
exit: mov ah,4ch
int 21h
main endp
outp proc near
mov ah,2
mov dl,10
int 21h
mov cl, buff+1
mov ch,0
lea bx, buff+2
out1: mov dl, [bx]
mov ah, 2
int 21h
inc bx
loop out1
ret
outp endp
code ends
end start
6.5主程序从键盘输入一个字符串到BUFF,再输入一个字符到AL,用子程序在字符串BUFF中查找是否存在该字符,如果找到,显示发现的字符位置。
用寄存器传递要查找的字符。
;search
data segment
mess1 db 13,10, 'input string:$'
mess2 db 13,10, 'input a char:$'
mess3 db 13,10, 'not found! $'
mess4 db 13,10, 'found at: $'
org 40h
buff label byte
max1 db 9
act1 db ?
stok1 db 9 dup(?)
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
mov es,ax
lea dx,mess1
mov ah,09
int 21h ;qust1?
lea dx,buff
mov ah,0ah
int 21h ;ans1
lea dx,mess2
mov ah,09
int 21h ;qust2?
mov ah,1
int 21h ;ans2
call near ptr scan
ret
main endp
scan proc near
mov cl,act1
mov ch,0
lea di,stok1
repne scasb
je found
nofd: lea dx,mess3
mov ah,9
int 21h
jmp exit
found:
lea dx,mess4
mov ah,9
int 21h
sub act1, cl
mov dl,act1
add dl,30h
mov ah,2
int 21h
exit: ret
scan endp
code ends
end main
6.6编写程序,从键盘输入一个字符串到BUFF,用子程序统计各字符出现的次数。
错误!
;numbers of every char to be found
;ababc
;0b0bc
;0000c
;00000
data segment
mess1 db 13,10, 'input string:$' mess2 db 13,10, 'input a char:$' mess3 db 13,10, 'not found! $' mess4 db 13,10, 'found at: $'
org 40h
buff label byte
max1 db 9
act1 db ?
stok1 db 9 dup(?)
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
lea dx,mess1
mov ah,09
int 21h ;qust1?
lea dx,buff
mov ah,0ah
int 21h ;ans1
call near ptr scan
ret
main endp
scan proc near
mov cl,act1
mov ch,0
mov dl,30h
send: lea di,stok1
k1: cmp byte ptr[di],20h
je kong
cmp byte ptr[di],13
je ones
mov bl,[di]
mov byte ptr[di],20h
k2:
inc dl
inc di
cmp bl,[di]
je cnum
cnum:
mov byte ptr[di],0 ones:
mov ah,2
int 21h
loop send
kong: inc di
jmp k1
mov si,di
mov al,[si]
cmp al,20h
je next
cmp al,[di]
jne next
inc dl
next: inc di
loop
next cmp
repne scasb
je found
nofd: lea dx,mess3
mov ah,9
int 21h
jmp exit
found:
lea dx,mess4
mov ah,9
int 21h
sub act1, cl
mov dl,act1
add dl,30h
mov ah,2
int 21h
exit: ret
scan endp
code ends
end main
6.7主程序从键盘输入一个八位的二进制数,对其作求补操作,用子程序对求补后的值以二进制形式显示。
code segment
assume cs:code
main proc far
start:
mov bx,0
mov cx,8
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
neg bl
call outp
exit: mov ah,4ch
int 21h
main endp
outp proc near
mov ah,2
mov dl,10
int 21h
mov cx,8
kp: shl bl,1
jc k1
mov dl,30h
jmp kk
k1: mov dl,31h
kk: mov ah,2
int 21h
loop kp
ret
outp endp
code ends
end start
6.8主程序从键盘输入两个四位的十六进制数A和B,用子程序作十六进制计算A+B,并显示计算结果。
;only accept print char: 0~9,A~F code segment
assume cs:code
main proc far
start:
mov ax,cs
mov ds,ax
lea dx,mess
mov ah,9
int 21h
mov si,2
inone: mov dx,0
mov bx,0
mov ch,4
mov cl,4
next: mov ah, 1
int 21h
sub al,30h
cmp al,0
jb exit
cmp al,9
ja char
jmp k1
char: sub al,7
cmp al,0ah
jb exit
cmp al,0fh
ja exit
k1: mov dl,al
shl bx,cl
add bx,dx
dec ch
jnz next
push bx
mov ah,2
mov dl,13
int 21h
mov ah,2
mov dl,10
int 21h
dec si
jnz inone
call outp
exit: mov ah,4ch
main endp
outp proc near
mov bp,sp
mov ax,[bp+2]
mov bx,[bp+4]
add bx,ax
mov ch,4
mov cl,4
out1: rol bx,cl
mov dx,bx
and dl,0fh
add dl,30h
cmp dl,39h
ja ad7
jmp kp
ad7: add dl,7
kp: mov ah,2
int 21h
dec ch
jnz out1
ret
outp endp
mess db 'only accept 0-9,A-F,input:',13,10,'$'
code ends
end start
6.9 某字数组为有符号数,第一个单元为元素个数N,后面为N个元素,编写通用子程序,求数组元素中的最大值,并把它放入MAX单元。
;put the big to max location
data segment
array dw 5,9,4,5,15,3
max dw ?
data ends
code segment
assume cs:code,ds:data
main proc far
mov ax, data
mov ds, ax
mov cx, array
lea bx, array+1
call near ptr getmax
mov ah,4ch
main endp
getmax proc near
mov ax, [bx]
mov max, ax
k1: mov ax, [bx]
cmp ax, max
jl next
mov max,ax
next: add bx,2
loop k1
ret
getmax endp
code ends
end main
6.10 某字数组,第一个单元为元素个数N,后面为N个元素,编写通用子程序,把零元素从数组中清除,移动元素位置并修改第一个单元(元素个数)。
;delete the 0 from array
data segment
array dw 6,3,4,0,1,0,5
loca dw 999
data ends
code segment
assume cs:code,ds:data
main proc far
mov ax, data
mov ds, ax
mov cx, array
lea si,array
lea bx, array+1
call near ptr dele0
mov ah,4ch
int 21h
main endp
dele0 proc near
next: cmp word ptr[bx],0
jz move
add bx,2
dec cx
cmp cx,0
jnz next
jmp exit
move: dec word ptr[si]
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: ret
dele0 endp
code ends
end main
部分习题参考答案
1.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, CF=0,OF=1
(2)85+(-69)=55H+BBH=110H,CF=1,OF=0
其余略
1.6实模式下,写出段地址和偏移地址为1234:2002、1430:0042、
FF00:0FFF的物理地址。
1234:2002=12340+2002=14342
1430:0042=14300+0042=14342
FF00:0FFF=FF000+0FFF=FFFFF
1.7已知8086系统某存储单元物理地址为:52506H,你认为段基址的最
大值、最小值分别是多少? 8086微机最多可以有多少个不同的段基址?
52506=5250:0006, 段基址的最大值=5250
52506=4251:FFF6, 段基址的最小值=4251
1.8从物理地址为00100H开始到00103H单元中顺序存放的数据为:12H,
34H,56H,78H。
请画出数据存放示意图,并回答以下问题:
(1)写出00101H字节单元的内容
(00101)= 34H
(2)写出00102H字单元的内容
(00102)= 7856H
习题3
3.1 分别说明8086处理器中各寄存器的名称和作用是什么?
3.2 溢出标志OF与进位标志CF有何作用和区别?
3.3 何为段地址?何为有效地址?何为物理地址?用指令举例说明。
3.4 带符号数比较大小,当AX < BX时程序转向标号L1,若前导指令为CMP AX, BX
后续指令应为什么?若视为二个无符号数比较大小, 后续指令应为什么?
带符号数:JL L1, 无符号数:JB L1
3.5 ADD指令和ADC指令在什么情况下是一样的结果?
CF=0
3.6 说出CALL指令和INT 21H指令的操作,有何异同?
CALL把断点压入堆栈,不一定是远调,INT 21H还要把FLAGS压入堆栈,且是远调,总入口地址为84H内存中的两个字。
3.7 除了用4CH号系统功能调用结束程序的执行并退出,还有哪些办法?
RET指令,INT 20H
3.8指出下列错误的指令,说出错误原因,并给出合适的修改。
(1) MOV AX,[DX] / MOV AX,[BX]
(2) MOV DS,DATA / MOV DS,BX
(3) MOV CS,AX / MOV ES,AX
(4) MOV AX,DL / MOV AL,DL
(5) PUSH AL / PUSH AX
(6) ADD [BX],[DI] / ADD [BX],DI
(7) LEA [BX],[2000H] / LEA BX,[2000H]
(8) MOV [BX],OFFSET [2000H]
(9) MOV [SI],2 / MOV BYTE PTR [SI],2
(10) MUL BX,CX / MUL BX
(11) DIV 5 / DIV BX
(12) MOV BYTE[SI],2 / MOV BYTE PTR [SI],2
(13) MOV AX,[SI+DI] / MOV AX,[BX+SI]
(14) SHR AX,4 / SHR AX,1
(15) CMP 6,AX / CMP AX,6
(16) MOV [FFFF],AX / MOV [FFFE],AX
(17) MOV AX,BX+4 / MOV AX,[BX+4]
(18) JMP FAR PRO / JMP FAR PTR PRO
3.9假定(DS)=1200H,(SS)=4400H, (BX)=463DH,(BP)=2006H, (SI)=6A00H,位移量D=4524H,以AX寄存器为目的操作数,试写出以下各种寻址方式下的传送指令,并确定源操作数的有效地址EA和物理地址。
(1)立即寻址;操作数的EA就是指令的EA/操作数在指令中
/无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
3.10用一条指令完成以下操作。
(1)把BX寄存器和DX寄存器的内容相加,结果存人DX寄存器中。
ADD DX,BX
(2)用寄存器BX和SI的基址变址寻址方式把存储器中的一个字节与AL寄存器的内容相加,并把结果送到AL寄存器中。
ADD AL,[BX+SI]
(3)用寄存器BX和位移量0B2H的寄存器相对寻址方式把存储器中的一个字和AX寄存器的内容互换。
XCHG AX,[BX+0B2]
(4)用位移量为0524H的直接寻址方式把存储器中的一个字与数2A59H相加,并把结果送回该存储单元中。
ADD WORD PTR [524], 2A59H
3.11在数据段定义了ARRAY数组,其中依次存储了五个字数据,请用以下寻址方式的指令把第4个字送AX寄存器。
(1)直接寻址
MOV AX,ARRAY+6 或MOV AX,[ARRAY+6]
(2)使用BX的间接寻址
LEA BX,ARRAY+6 ;MOV AX,[BX]
(3)使用BX的寄存器相对寻址
LEA BX,ARRAY ;MOV AX,[BX+6]
(4)基址变址寻址
LEA BX,ARRAY ; MOV SI,6 ; MOV AX,[BX+SI]
3.12画出数据在数据段中的存放情况,程序执行后,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
1E,00,00,00,20,00,00,64
3.13在DEBUG下设置(SP)=20H,设置AX、BX、CX、DX为不同值,把这四个
寄存器内容依次压入堆栈,再从堆栈中依次弹出到SI、DI、BP、BX寄存器。
写
出一段程序实现上述操作,并画出每条入栈指令执行后SP和堆栈中数据的变化。
3.14求出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
3.15 在数据段有如下定义:
DATAX DW ?,?
DATAY DW ?,?
SUM DW ?,?,?,?
请用16位指令按下列要求写出指令序列:
(1)DATAX和DATAY两个字数据相加,和存放在SUM中。
MOV AX,DATAX
ADD AX,DATAY
MOV SUM AX
(2)DATAX和DATAY两个双字数据相加,和存放在SUM开始的字单元中。
MOV AX,DATAX
MOV DX,DATAX+2
ADD AX,DATAY
ADC DX,DATAY+2
MOV SUM,AX
MOV SUM+2,DX
(3)DATAX和DATAY两个字数据相乘(用MUL),积存放在SUM开始的字单
元中。
(4)DATAX和DATAY两个双字数据相乘(用MUL),积存放在SUM开始的字
单元中。
(5)DATAX双字除以字DATAY(用DIV),商和余数存放在SUM开始的字单
元中。
(6)DATAX和DATAY两个压缩BCD码数据相加,和存放在SUM中。
3.16双字长数X存放在DX和AX中,设(DX)=1004H,(AX)=1002H,要求用
16位指令写出:
(1) 对存放在DX和AX中的双字长数求补的指令序列,并验证结果。
NOT AX
NOT DX
ADD AX,1
ADC DX,0
(2) 用减法指令求0-X的指令序列,并验证结果。
MOV BX,0
MOV CX,0
SUB BX,AX
SBB CX,DX ;结果在CX,BX
3.17试编写一个程序求出双字长数的绝对值。
双字长数在A开始的字单元中,结果存放在B开始的字单元中。
A DW ?,?
B DW ?,?。
MOV AX,A
MOV DX,A+2
TEST DX,8000H
JZ ZS
NOT AX
NOT DX
ADD AX,1
ADC DX,0
ZS:MOV B,AX
MOV B+2,DX
3.18 用移位指令为主实现对AX中的无符号数乘以5,不考虑乘积可能超出16位。
MOV DX,AX
MOV CL,2
SHL AX,CL
ADD AX,DX
3.19用移位指令为主实现对AX中的无符号数乘以5,考虑乘积可能超出16位的情况。
提示:用DX接AX左移的位,32位操作。
3.20把AX中的内容依次倒排序,即第0位移到第15位,第1位移到第14位,…。
3.21在数据段有如下定义:
BUFF DB ‘ABCD$EFGHIJK$’
STR1 DB 12 DUP(?)
LEN DB ?
用串指令编写程序完成以下操作:
(1) 对字符串STR1全部置空格符。
MOV AX,DATA
MOV DS,AX
MOV AL,20H
LEA DI,STR1
MOV CX,STR1-BUFF
CLD
REP STOSB
(2) 从左到右把BUFF中的字符串传送到STR1。
MOV AX,DATA
MOV DS,AX
MOV ES,AX
CLD
LEA SI,BUFF
LEA DI,STR1
MOV CX,STR1-BUFF
REP MOVSB
(3) 从右到左把BUFF中的字符串传送到STR1。
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) 比较BUFF与STR1两个字符串是否相等,如相等则DX=1,否则DX=0。
MOV AX,DATA
MOV DS,AX
MOV ES,AX
CLD
LEA SI,BUFF
LEA DI,STR1
MOV CX,STR1-BUFF
REPE CMPSB
(5) 查找BUFF中有无字符$,把字符$出现的次数计入BX寄存器。
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
3.22对于给定的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=9200H, BX=4000H
(3) AX=420EH, BX=8031H
(4) AX=E002H, BX=8086H
L1,L1,L1,L5
3.23下面不完整的程序段是比较AX和BX的值,把其中大的数送MAX变量。
如果是无符号数,应如何填写指令?如果是有符号数,应如何填写指令?
CMP AX,BX
( JB L1 ) 有符号数:JL L1
MOV MAX,AX
( JMP L2 )
L1:MOV MAX,BX
L2:HLT
3.24在下列程序段的括号中分别填入如下指令,程序执行完后,AX、CX的内容是什么?
(1) LOOP
(2) LOOPE
(3) LOOPNZ
MOV AX, 8
MOV CX,5
L1:SHL AX,CL
( )
提示:上机,SHL指令使ZF=0,LOOPE指令不可能循环。
3.25测试AL寄存器,如果最高位和最低位同时为0,则转L0,如果最高位和最低位只有一位为1,则转L1,如果最高位和最低位同时为1,则转L2。
画出流程图,并编写程序段。
ROL AL,1
AND AL,3
JZ L0
SUB AL,3
JZ L3
JMP L2
3.26从键盘输入一个英文字母,显示输出其大写。
画出流程图,并编写程序段。
3.27从键盘输入一位数字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
3.28 寄存器中为压缩的BCD码表示的十进制数,写出指令完成十进制加减计算,即计算AL+BL;AL-BL。
并在DEBUG下上机验证。
(1) AL=65H,BL=37H
(2) AL=98H,BL=69H
3.29 寄存器中为非压缩的BCD码表示的十进制数,写出指令完成十进制加减计算,即计算AL+BL;AL-BL。
并在DEBUG下上机验证。
(1) AX=235H,BL=37H
(2) AL=238H,BL=39H
3.30 用相对基址比例变址寻址方法求ARRAY行列式的值。
ARRAY DW 2,3,5
DW 1,4,6
DW 2,7,9
习题4
4.1假设VAR1为字节变量,VAR2为字变量,LAB为标号,VAL为常量,指出下列有错误的指令,说出原因,并予纠正。
(1) ADD AX,VAR1 / ADD AL,VAR1
(2) MOV VAR2,VAR1 / MOV VAR2,AX
(3) MOV VAR1,BYTE PTR VAR2 / MOV VAR1,AL
(4) MOV VAR1,OFFSET VAR2 / MOV VAR2,OFFSET VAR1
(5) MOV VAR2,OFFSET VAR1
(6) MOV VAR1,VAR2+VAR1 / MOV VAR2,VAR2-VAR1
(7) MOV VAR1,VAR2-VAR1 / MOV VAR2,VAR2-VAR1
(8) MOV VAR2,VAR2-VAR1
(9) MOV BX,VAR2+VAL-4*5
(10) MOV BX,TYPE VAL
(11) MOV BX,LAB
(12) JMP VAR1 /JMP WORD PTR VAR1
(13) JMP VAR2
(14) JMP [VAL] /仅在DEBUG下可以
(15) MOV BL, VAR1 AND VAL / VAR1 AND VAL须用指令实现
(16) MOV BX, VAL AND 0FH
(17) MOV BX, VAL LT 0FH
(18) MOV BL,LAB+VAR1 / MOV BL,VAR1
4.2画图说明下列数据定义语句所示内存空间的数据,并回答寄存器的值。
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
4.3 变量和标号有哪些区别?变量和标号有哪些属性?如何获取属性值?写
出指令。
变量是为指令提供的操作数,标号是为指令提供标识,都是为了在指令中引用。
它们最主要的属性有:偏移属性,段属性,类型属性。
例如:
MOV BX, OFFSET VAL ;取偏移属性
MOV BX, SEG VAL ;取段属性
MOV BX, TYPE VAL ;取类型属性
4.4 指令和伪指令的区别在哪里?伪指令可以出现在代码段吗?指令可以在数据段吗?
指令只能出现在代码段,定义数据的伪指令通常在数据段。
伪指令不会生成指令。
4.5 下面的程序是否有错?能否通过汇编?程序运行的结果如何?程序的真正意图是什么?应如何修改程序才能实现真正意图?
答:通过汇编和连接可以运行,但程序真正意图是输出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
4.6 用32位指令编写完整程序,并上机调试,计算V=(X+Y)*R,其中所有变
量均为64位变量,X、Y、R的具体数值由你自己确定,变量定义格式如
下:
X DD ?,?
Y DD ?,?
R DD ?,?
V DD ?,?
data segment
x dd 1
y dd 2
r dd 3
v dd ?,?
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
习题5
5.1下列程序是在3个数中找出最小的数并放入AL,在括号中填入指令使其完整。
mov al,x
mov bl,y
mov cl,z
cmp al,bl
( jl l1 )
xchg al,bl
l1: cmp al, cl
jle l2
( xchg al,cl )
l2: ret
5.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,( AX )
mov cx,( COUNT )
mov si, ( OFFSET DA1 )
( MOV DI, OFFSET DA2 )
( REP MOVSB )
5.3以下程序对无符号数组ARRAY的6个元素从小到大排序,补充括号处的指令。
data segment
array dw 4,3,12,56,5,8
data ends
code segment
assume cs:code,ds:data
start: ( mov ax,data )
( mov ds, data )
mov cx, 5
l1: mov di, cx
mov bx, 0
l2: mov ax, array[bx]
cmp ax, array[bx+2]
( jl l3 )
xchg ax, array[bx+2]
mov array[bx], ax
l3: add bx, 2
( loop l2 )
mov cx, di
loop l1
mov ah, 4ch
int 21h
code segment
end start
5.4编写程序,实现从键盘输入的小写字母用大写字母显示出来。
对输入须合法性检查。
code segment
assume cs:code
start: push ds
sub ax,ax
push ax
mov ah,1
int 21h
cmp al,61h
jb exit
cmp al,7ah
ja exit
sub al,20h
mov dl,al
mov ah,2
int 21h
exit:ret
code ends
end start
5.5编写程序,比较两个字符串是否相同,如果相同,则显示两个字符串,如果
不同,则显示发现不同的字符位置。
datasg segment
mess1 db 13,10, 'input string1:$'
mess2 db 13,10, 'input string2:$'
mess3 db 13,10, 'match!$'
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(?)
datasg ends
codesg segment
assume cs:codesg, ds:datasg,es:datasg main proc far
push ds
sub ax,ax
push ax
mov ax,datasg
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
lea si,stok1
lea di,stok2
inc cl
repe cmpsb
cmp cl,0
jz match
nomatch:
lea dx,mess4
jmp exit
match: lea dx,mess3
exit:
mov ah,09
int 21h
sub di,offset stok2
mov dx,di
and dx,0fh
add dl,30h
mov ah,2
int 21h
ret
main endp
codesg ends
end main
5.6 编写程序,从键盘输入一个个位数N,响铃N次(响铃ASCII码为07H)。
code segment
assume cs:code
start: push ds
sub ax,ax
push ax
mov ah,1
int 21h
cmp al,31h
jb exit
cmp al,39h
ja exit
sub al,30h
mov cl,al
mov ch,0
k: mov ah,2
mov dl,7
int 21h
loop k
exit:ret
code ends
end start
5.7编写程序,从键盘输入一个字符串到BUFF,再输入一个字符到AL,在字
符串BUFF中查找是否存在该字符,如果找到,显示发现的字符位置。
;search
datasg segment para'data'
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(?)
datasg ends
codesg segment para'code'
assume cs:codesg, ds:datasg,es:datasg
main proc far
push ds
sub ax,ax
push ax
mov ax,datasg
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
ret
main endp
codesg ends
end main
5.8编写程序,从键盘输入一个N位二进制数,统计1出现的次数。
code segment
assume cs:code
start: mov cx,9 ;N<10
mov dl,30H
next: mov ah,1
int 21h
cmp al,13
jz write
cmp al,30h
jb exit
cmp al,31h
ja exit
sub al,30h
add dl,al
dec cx
jnz next
write:
push dx
mov dl,10
mov ah,2
int 21h
pop dx
mov ah,2
int 21h
exit: mov ah,4ch
int 21h
code ends
end start
5.9编写程序,从键盘输入一个字符串到BUFF,并按相反顺序显示输出。
datasg segment
mess1 db 13,10, 'input string:$'
mess2 db 13,10,'$'
st1 label byte
max1 db 6
act1 db ?
stok1 db 6 dup(?)
datasg ends
codesg segment
assume cs:codesg, ds:datasg
main proc far
push ds
sub ax,ax
push ax
mov ax,datasg
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
ret
main endp
codesg ends
end main
5.10编写程序,从键盘输入一个八位的二进制数,显示其十六进制数。
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
5.11编写程序,从键盘输入某个字符的ASCII码(作为起点)和个数N,显示输出这N个ASCII码和字符。
5.12 字数组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+1
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
6.11 从键盘输入姓名和电话号码,建立通讯录,通讯录的最大容量为9条记录,程序结束时无须保留通讯录,但程序运行时要保留通讯录信息。
程序的人机界面和顺序要求如下:
(1)提示信息INPUT NAME:(调用子程序INNAME录入姓名,序号自动产生)
(2)提示信息INPUT TELEPHONE NUMBER:(调用子程序INTELE录入电话号码)
(3)提示信息INPUT 序号:(调用子程序PRINT显示某人的姓名和电话号码,如果序号不存在,则提示信息 NO THIS NUMB )。
;telephone number list
phone struc
serial db 20h
tname db 3 dup (20h)
tnumb db 11 dup (20h), '$'
phone ends
data segment
num db 0
mess1 db 13,10, 'input name(3):$'
mess2 db 13,10, 'phone number(11):$'
mess3 db 13,10, 'serial number(1):$'
mess4 db 13,10, 'no this number!$'
org 50h
plist phone 9 dup (<>)
org 100h
pname db 4,?,4 dup (?)
pnumb db 12,?,12 dup (?)
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
mov es,ax
next1:
call inname
call intele
mov al,num
dec al
mov bl,16
mul bl
lea di,plist
add di,ax
mov dl,num
add dl,30h
mov byte ptr[di],dl
mov cx,3
lea si,pname+2
rep movsb
mov cx,11
lea si,pnumb+2
rep movsb
cmp byte ptr num,9
jb next1
next2:
call print
ret
main endp
inname proc near
lea dx,mess1
mov ah,09
int 21h ;input name(XXX) lea dx,pname
mov ah,10
int 21h ;get name
inc byte ptr num
ret
inname endp
intele proc near
lea dx,mess2
mov ah,09
int 21h ;input phone(11)
lea dx,pnumb
mov ah,10
int 21h ;get phone numb
ret
intele endp
print proc near
next3: lea dx,mess3
mov ah,09
int 21h ;input serial:(X)
mov ah,1
int 21h
cmp al,30h
jle exit
cmp al,39h
jg exit
sub al,30h
cmp al,num
jg exit
pdisp: dec al
mov bl,16
mul bl
lea dx,plist
add dx,ax
mov ah,9
int 21h
jmp next3
exit: lea dx,mess4
mov ah,9
int 21h
ret
print endp
code ends
end main
6.12对十名同学的期末考试成绩进行统计,使用结构变量定义学生成绩记录并预赋值,使用子程序A统计每个学生的总分,使用子程序B显示输出每个学生的
姓名和总分,对于总分应使用子程序C把总分的数值转为字符显示。
学生成绩记录格式:
字段类型长度
学号,字符型, 8字节
姓名,字符型, 3字节
数学,数值型, 2字节
物理,数值型, 2字节
化学,数值型, 2字节
语文,数值型, 2字节
英语,数值型, 2字节
总分,数值型, 2字节
备用,字符型, 3字节
为便于显示输出,问题简化为:学生成绩只设2门课,每门课分值最高为5分参考程序:
data segment
stm struc
bname db 'aaaaaa$'
c1 db ?
c2 db ?
c3 db 0
stm ends
st1 stm <'aaaaaa$',5,3,0>
st2 stm <'bbb $',2,4,0>
st3 stm <'ccc $',2,3,0>
st4 stm <'ddd $',5,3,0>
st5 stm <'eeeee $',2,4,0>
st6 stm <'ffff $',2,4,0>
st7 stm <'gg $',5,3,0>
st8 stm <'hhh $',3,4,0>
st9 stm <'iiii $',3,4,0>
st10 stm <'kkk $',2,3,0>
data ends
code segment
assume cs:code,ds:data
main proc far
mov ax,data
mov ds,ax
call aa
call bb
mov ah,4ch
int 21h
main endp
aa proc near
mov cx,10
mov bx,offset st1 k: mov al,[bx].c1
add al,[bx].c2
mov [bx].c3,al
add bx,10
loop k
ret
aa endp
bb proc near
mov cx,10
mov bx,offset st1 j: mov dx,bx
mov ah,9
int 21h
mov dl,','
mov ah,2
int 21h
mov dl,[bx].c3
add dl,30h
mov ah,2
int 21h
add bx,10
call hh
loop j
ret
bb endp
hh proc near
mov ah,2
mov dl,13
int 21h
mov ah,2
mov dl,10
int 21h
ret
hh endp
code ends
end main
部分习题参考答案
1.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, CF=0,OF=1
(2)85+(-69)=55H+BBH=110H,CF=1,OF=0
其余略
1.6实模式下,写出段地址和偏移地址为1234:2002、1430:0042、
FF00:0FFF的物理地址。
1234:2002=12340+2002=14342
1430:0042=14300+0042=14342
FF00:0FFF=FF000+0FFF=FFFFF
1.7已知8086系统某存储单元物理地址为:52506H,你认为段基址的最
大值、最小值分别是多少? 8086微机最多可以有多少个不同的段基
址?
52506=5250:0006, 段基址的最大值=5250
52506=4251:FFF6, 段基址的最小值=4251
1.8从物理地址为00100H开始到00103H单元中顺序存放的数据为:12H,
34H,56H,78H。
请画出数据存放示意图,并回答以下问题:
(3)写出00101H字节单元的内容
(00101)= 34H
(4)写出00102H字单元的内容
(00102)= 7856H
习题3
3.1 分别说明8086处理器中各寄存器的名称和作用是什么?
3.2 溢出标志OF与进位标志CF有何作用和区别?
3.3 何为段地址?何为有效地址?何为物理地址?用指令举例说明。
3.4 带符号数比较大小,当AX < BX时程序转向标号L1,若前导指令为CMP AX, BX
后续指令应为什么?若视为二个无符号数比较大小, 后续指令应为什么?
带符号数:JL L1, 无符号数:JB L1
3.5 ADD指令和ADC指令在什么情况下是一样的结果?
CF=0
3.6 说出CALL指令和INT 21H指令的操作,有何异同?
CALL把断点压入堆栈,不一定是远调,INT 21H还要把FLAGS压入堆栈,
且是远调,总入口地址为84H内存中的两个字。
3.7 除了用4CH号系统功能调用结束程序的执行并退出,还有哪些办法?
RET指令,INT 20H
3.8指出下列错误的指令,说出错误原因,并给出合适的修改。
(1) MOV AX,[DX] / MOV AX,[BX]
(2) MOV DS,DATA / MOV DS,BX
(3) MOV CS,AX / MOV ES,AX
(4) MOV AX,DL / MOV AL,DL
(5) PUSH AL / PUSH AX
(6) ADD [BX],[DI] / ADD [BX],DI
(7) LEA [BX],[2000H] / LEA BX,[2000H]
(8) MOV [BX],OFFSET [2000H]
(9) MOV [SI],2 / MOV BYTE PTR [SI],2
(10) MUL BX,CX / MUL BX
(11) DIV 5 / DIV BX
(12) MOV BYTE[SI],2 / MOV BYTE PTR [SI],2
(13) MOV AX,[SI+DI] / MOV AX,[BX+SI]
(14) SHR AX,4 / SHR AX,1
(15) CMP 6,AX / CMP AX,6
(16) MOV [FFFF],AX / MOV [FFFE],AX
(17) MOV AX,BX+4 / MOV AX,[BX+4]
(18) JMP FAR PRO / JMP FAR PTR PRO
3.9假定(DS)=1200H,(SS)=4400H, (BX)=463DH,(BP)=2006H, (SI)=6A00H,位移量D=4524H,以AX寄存器为目的操作数,试写出以下各种寻址方式下的传送指令,并确定源操作数的有效地址EA和物理地址。
(1)立即寻址;操作数的EA就是指令的EA/操作数在指令中
/无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
3.10用一条指令完成以下操作。
(1)把BX寄存器和DX寄存器的内容相加,结果存人DX寄存器中。
ADD DX,BX
(2)用寄存器BX和SI的基址变址寻址方式把存储器中的一个字节与AL寄存器的内容相加,并把结果送到AL寄存器中。
ADD AL,[BX+SI]
(3)用寄存器BX和位移量0B2H的寄存器相对寻址方式把存储器中的一个字和AX寄存器的内容互换。
XCHG AX,[BX+0B2]。