运行环境masmplus
链接:https://pan.baidu.com/s/1jWoLfvxBxQgxd6wq21GK0w
提取码:ih43
1.通过实验了解和熟悉微机系统的配置。
2.学习在DEBUG状态下输入汇编源程序的方法。
3.初步掌握调试(在DEBUG状态下)的过程。
1、本实验要求在DEBUG状态下输入汇编源程序,并用DEBUG命令进行调试。用单步跟踪的方法验证指令的功能。
2、 以下是给定的参考程序,并在实验时在每条指令的“;”符号右边按要求填写指令的执行结果。
注:
⑴ 微机进入DEBUG状态下之后,一切立即数和地址数据均被默认为十六进制数,在输入时数的后面不加后缀“H”;
⑵ 在DEBUG状态下执行程序时,“INT 20H”指令可使系统执行完该指令前的程序时返回到“-”提示符状态,并且恢复CS和IP寄存器原来的值。
微机一台。
1、开机后进入DOS系统,
C > DEBUG↙ (↙回车符)
- (为DEBUG 提示符)
当显示器出现提示符“-”时,说明已进入DEBUG状态,这时,可用DEBUG命令进行操作。
2、 用DEBUG的Register命令检查所有寄存器内容,并作记录。命令格式:
R [寄存器名]
该命令的功能是显示寄存器的内容,或修改某一指定寄存器内容,若[寄存器名]缺省,则显示所有寄存器内容。例如:
-R
3、 用DEBUG的Assemble命令输入汇编源程序。格式:
A [内存地址]
注:用“[ ]”符号括起来的部分表示可以省略。
该命令的功能是从指定的内存地址开始(括号不要输入)逐条输入汇编语言源程序并汇编成机器码存入内存。若地址缺省,则接上一个A命令最后一条指令之后输入汇编语句,若没有用过A命令,则从CS:0100H地址开始输入。例如:
-A
0CD3:0100-
在输入A命令之后,或每输入一条指令之后,显示器的左端给出了内存的段地址和偏移地址。
每条指令均用回车(↙)结束。若输入的指令有语法错误,DEBUG拒绝接收,并给出提示,此时可以重新输入。程序的最后一条指令输入完之后,再按一次回车键(↙),即可结束汇编命令,回到DEBUG提示符“-”状态。
4、 用DEBUG的Unassemble命令反汇编。命令格式:
U [起始地址[终止地址]]
该命令的功能是从起始地址到终止地址反汇编目标码,缺省值是接上一个U命令或从CS:0100H地址开始。例如:
-U
显示器上将显示程序的内存地址、指令机器码的汇编源程序三列对照清单。
5、用DEBUG的Trace命令单步跟踪程序。命令格式:
T 【=起始地址】【指令条数】
该命令的功能是从指定的起始地址开始逐条执行指令,每执行完一条指令,屏幕显示所有寄存器内容和下一条指令地址和指令。若[=起始地址]缺省,则T命令从CS:IP地址开始执行指令。
例如:
-T↙
重复这一过程,即可看到每条指令执行后,所有寄存器和标志寄存器的标志位内容。此时,要检查内存单元的数据,可用DEBUG的D命令。
6. 用DEBUG的Dump命令显示存贮器单元的内容。命令格式:
D[起始地址[终止地址]]
该命令的功能是从起始地址到终止地址,连续显示存贮器单元的内容。若地址缺省,则接上一个D命令或从DS:0100H地址开始显示。例如:
-D↙
参考程序:
MOV AX, 2000 ; AL=00H
MOV DS, AX ; DS=2000H
NOT AX ; AX=0DFFFH
XOR AX, AX ; AX=0000H
DEC AX ; AX=0FFFFH
INC AX ; AX=0000H
MOV BX, 2030 ; BH=20H
MOV SI, BX ; SI=2030H
MOV [SI], BL ; [2030H]=30H
MOV WORD PTR[SI], 10F ; [2030H]=0FH [2031H]=01H
MOV DI, SI ; DI=2030H
MOV [DI+50], BH ; [DI+50H]=20H
MOV BH, [SI] ; BH=0FH
MOV BL, [DI+50] ; BL=20H
MOV SP, 5000
PUSH AX ; AX=0000H [SS:4FFEH]=00H [SS:4FFFH]=00H
PUSH BX ; BX=0F20H [SS:4FFCH]=20H [SS:4FFDH]=0FH
POP AX ; AX=0F20H
POPF ; F=00000000
NEG BX ; BX=F0E0H
XCHG BX, AX ; BX=0F20H
STD ; F=01010001
STI ; F=01110001
CLD ; F=00110001
CLI ; F=00010001
ADC DI, 2050 ; DI=4081H F=00000010
ADC SP, DI ; SP=9081H F=10010010
ADC AX, 1500 ; AX=05E0H F=00000001
SUB AX, BX ; AX=F6C0H BX=0F20H
SHL AH, 1 ; AH=ECH
RCL AX, 1 ; AX=D981H
SHR BH, 1 ; BH=07H
RCR BL, 1 ; BL=90H
MOV CL, 4
MOV DX, 80F0
ROL DX, CL ; DX=0F08H CL=04H
INT 20 ; CS= F000H IP=1480H
1、整理每条指令执行的结果,填到打印清单的右半部分(应注意内存数据检查的正确性)。
结果如上述表格所示。
2. 比较实验记录与理论分析的结果是否相同,若有不同,找出差别及问题所在。
实验记录和理论分析结果是相同的。
3.总结本次实验的体会。
主要学习了在DEBUG状态下输入汇编源程序的方法以及调试过程。当显示器出现提示符“-”时,用 DEBUG 命令进行操作,-r是显示寄存器的内容,输入汇编源程序用-a,单步执行用-t, 显示存贮器单元的内容用-d.
1、继续学习DEBUG命令。
2、验证指令的功能。
在DEBUG状态下,分别输入下面各程序段,每输入完一个程序段,用G命令进行连续方式执行程序,在连续执行时,要记录程序的执行结果。
参考程序:
1. 在内存10000H单元开始,建立00H~0FH~00H 31个数,要求00H~0FH数据逐渐增大,0FH~00H逐渐减小。该程序从内存CS:0100H地址开始输入。
MOV AX, 1000H
MOV DS, AX
MOV SI, 0
MOV CL, 0FH
XOR AX, AX
PPE1: MOV [SI], AL
INC SI
INC AL
DEC CL
JNZ PPE1
MOV CX, 10H
PPE2: MOV [SI], AL
INC SI
DEC AL
LOOP PPE2
INT 20H
注:转移指令的符号地址直接用绝对偏移地址,该地址在用A命令汇编输入时,可以看到程序全部运行完之后,可用DEBUG的Dump命令查看建立的数据块内容。例如:
-D1000:00 1E
2、把上一个程序的执行结果(建立的31个字节数据块,其首地址在10000H),分几种方式传送到以下指定的区域。
(a) 该程序从内存CS:0150H开始输入。把数据块传送到15050H开始的存贮区域中。
参考程序: MOV AX, 1000H
MOV DS, AX
MOV SI, 0
MOV DI, 5050H
MOV CX, 1FH ; 数据块长度是31
PPEA: MOV AL, [SI]
MOV [DI], AL
INC SI
INC DI
LOOP PPEA
INT 20H
检查内存数据块的传送情况,可用“D”命令。
(b) 用串传送指令MOVSB,把数据块传送到15150H开始的区域,该程序从内存CS:0200H开始输入。
检查程序最后的执行结果,可用“D”命令,例如:
-D1000:5150↙
© 用重复串操作指令“REP MOVSB”把数据块传送到15250H开始的区域。该程序从CS:250H地址开始输入。
检查程序的最后执行结果时,可用:
-D1000: 5250H
(d) 用串操作的减量工作方式,把数据块传送到25050H开始的区域。该程序从CS:0300H开始输入。
检查程序的最后执行结果,用D命令:
-D2000:5050↙
微机一台。
参照实验一的步骤,按照本实验程序的内容,分别输入各段程序,连续执行程序,记录每个程序段的最后结果。若想把源数据块重新换一批数据,可以用DEBUG的Fill命令填充新的数据。例如:
-F1000:00 L1F 33↙
从1000:0000H开始的31个字节被替换成33H。
预习要求:
1.认真阅读DEBUG调试程序的命令说明。
2.仔细阅读本实验给出的程序段。
3.写出每个程序段的结果数据(分析结果),并说明结果所在的位置(寄存器或存贮器)。
报告要求:
1、整理每个程序段在实验时的记录内容。
如上图所示。
2、 比较每个程序段的特点。
第一个程序执行完后,即已经存入数据,第二个程序采用了四种方式将它的执行结果传送到了指定的区域,不论是串操作指令,重复串操作指令,串操作的减量工作方式,都精确的传送到了指定的区域。
3、分析本次实验出现的问题,找出问题所在。
本次实验进行时,出现了用g命令运行死掉的情况,int20h 来结束程序有要求的,就时栈顶必须是 psp:0000 向量,最后我直接用 g=100 107 直接在需要的功能后停下来,就解决了问题。
⒈、练习分支程序的编写方法。
⒉、练习汇编语言程序的上机过程。
⒈、通过分支程序设计调试和运行,进一步熟悉掌握汇编程序执行的软件环境。
⒉、通过分支程序的执行过程,熟悉EDIT的使用,建立OBJ文件EXE文件的方法。
⒈、 微机一台。
1.给出三个有符号数,编写一个比较相等关系的程序:
(1)如果这三个数都不相等,则显示0;
(2)如果这三个数中有两个数相等,则显示1;
(3)如果这三个数都相等,则显示2;
源程序如下:
.model small
.stack
.data ;给出三个数据
msgst db 'input three number:',0dh,0ah,'$'
var1 db ?
var2 db ?
var3 db ?
temp db ?
msg0 db '0$'
msg1 db '1$'
msg2 db '2$'
.code
.startup
mov dx,offset msgst
mov ah,9
int 21h ;显示提示信息
call readsiw ;第一个数
mov al,temp
mov var1,al
call readsiw ;第二个数
mov al,temp
mov var2,al
call readsiw ;第三个数
mov al,temp
mov var3,al
mov al,var1
cmp al,var2 ;12
je equal ;如果相等,跳转
jnz again
equal:
cmp al,var3 ;23
je second ;1=2 2=3
jnz first ;1=2 2!=3
again: ;1!=2
mov al,var1
cmp al,var3
je first ;1=3
jnz again1 ;1!=3
again1:
mov al,var2
cmp al,var3
je first
jnz zone
jmp done
zone:
mov dx,offset msg0
jmp done
first:
mov dx,offset msg1
jmp done
second:
mov dx,offset msg2
jmp done
done:
mov ah,9
int 21h
.exit
readsiw proc
push ax ;保护寄存器
push bx
push cx
xor bx,bx ;bx保存结果
xor cx,cx ;cx为正负标志,0为正,-1为负,默认为正
rsiw0: mov ah,1 ;输入第一个字符,正号或者负号
int 21h
cmp al,'+'
jz rsiw1 ;如果是正,cx原本就是0,向下继续输字符,zf=1跳转
cmp al,'-'
jnz rsiw2 ;如果不是负,则输入的不对
mov cx,-1 ;输入的是负数,设置cx=-1
rsiw1:mov ah,1
int 21h
rsiw2:cmp al,'0' ;不是0~9之间数码,结束
jb rsiw3 ;低于0
cmp al,'9'
ja rsiw3 ;高于9
sub al,30h ;是0~9之间的数码,转换,字符0的ascii码是30H
xor ah,ah ;AL零位扩展为AX
shl bx,1
shl bx,1
add bx,dx
add bx,ax ;原数乘10后,与新数码相加
jmp rsiw1 ;继续转换下一个数位
rsiw3:cmp cx,0 ;判断是正数还是负数
jz rsiw4 ;是正数,跳转
neg bx ;是负数,进行求补
rsiw4: mov temp,bl ;设置出口参数
pop cx
pop bx
pop ax
ret ;子程序返回
readsiw endp
end
2.从键盘上输入一串字符到输入缓冲区,找出其中的大写字母和小写字母,并分别统计它们的个数,结果放到变量num1和num2中,要求在屏幕输出显示所有字母及变量num1和num2的值。
源程序如下:
data segment
msg db 'please input string:$' ;缓冲区定义
buf1 db 81 ;缓冲区第零个字节,申请的存放数据的缓冲区的字节数
db ? ;缓冲区第一个字节,实际存放的字符个数
db 81 dup(0) ;存放数据的81个字节初始全为0
;用户从键盘输入的字符从第2个字节开始存放,直到用户输入回车键为止,并将回车键码(0DH)加在刚才输入字符串的末尾上
buf2 db 81 dup(0)
crlf db 0ah,0dh,'$'
msg0 db 'The String is:','$'
msg1 db 'The number of Capital is:','$'
num1 db 30h,0ah,0dh,'$' ;保存大写字母个数
msg2 db 'The number of Lowercase is:','$'
num2 db 30h,'$' ;保存小写字母个数
data ends
stack segment
stack ends
code segment
assume cs:code,ds:data,ss:stack ;code段和cs这个段寄存器相关联
start:
mov ax,data ;初始化数据段寄存器的值
mov ds,ax ;执行完,ds保存的是数据段的段基地址
lea dx,msg ;取msg偏移地址
mov ah,9
int 21h ;输入提示信息
lea dx,buf1 ;接收输入的字符串
mov ah,10
int 21h
lea dx,crlf
mov ah,9
int 21h
mov al,buf1+1 ;buf1+1是输入的字符个数
mov ah,0
mov cx,ax ;cx是循环变量
xor si,si
add si,02h
lea di,buf2 ;DI指向字符串变量BUFB
again:
mov al,buf1[si]
mov [di],al
cmp al,'A' ;A~Z 41h~5Ah a~z 61h~7Ah
jb next1 ;低于A,直接结束,读取下一个字符
cmp al,'Z' ;和Z比较,低于它就是大写字母
ja next2 ;再跳转判断是否是小写字母
inc num1 ;是大写字母
jmp next1
next2:
cmp al,'z' ;低于a或者高于z,直接结束
ja next1
cmp al,'a'
jb next1
inc num2
next1:
inc si
inc di
loop again
lea dx,crlf
mov ah,9
int 21h
lea dx,msg0 ;输出所有字符提示信息
mov ah,9
int 21h
lea dx,buf2 ;输出所有字符
mov ah,9
int 21h
lea dx,msg1 ;大写字符提示信息
mov ah,9
int 21h
lea dx,num1 ;大写字符数
mov ah,9
int 21h
lea dx,crlf
mov ah,9
int 21h
lea dx,msg2 ;小写字符提示信息
mov ah,9
int 21h
lea dx,num2 ;小写字符数
mov ah,9
int 21h
lea dx,crlf
mov ah,9
int 21h
mov ah,4ch
int 21h
code ends
end start
1.该源程序在DEBUG和EDIT两种状态下运行。
2. 实验报告中要有源程序和执行结果。
进一步掌握分支程序和循环程序的编写方法。
设有10个学生的成绩分别为56、69、84、82、73、88、99、63、100和80分。试编制程序分别统计低于60分、60~69分、70~79分、80~89分、90~99分及100分的人数存放到s5、s6、s7、s8、s9及s10单元中。
这一题目的算法很简单,成绩分等部分采用分支结构,统计所有成绩则用循环结构完成。程序框图如下图所示。
1、 微机一台。
参考给的流程图编写源程序,进行调试。
流程图如下:
程序如下:
;PROGRAM TITLE GOES HERE――result
;************************************
DATAREA SEGMENT ;DEFINE DATA SEGMENT
GRADE DW 56,69,84,82,73,88,99,63,100,80
S5 DW 0
S6 DW 0
S7 DW 0
S8 DW 0
S9 DW 0
S10 DW 0
DATAREA ENDS
;************************************
PROGNAM SEGMENT ;DEFINE CODE SEGMENT
;----------------------------
MAIN PROC FAR ; MAIN PART OF PROGRAM
ASSUME CS:PROGNAM, DS:DATAREA
START: ; STARTING EXECUTION ADDRESS
; SET UP STACK FOR RETURN
PUSH DS ; SAVE OLD DATA SEGMENT
SUB AX,AX ; PUT ZERO IN AX
PUSH AX ; SAVE IT ON STACK
; SET DS REGISTER TO CURRENT DATA SEGMENT
MOV AX,DATAREA ; DATAREA SEGMENT ADDR
MOV DS,AX ; INTO DS REGISTER
; MAIN PART OF PROGRAM GOES HERE
MOV S5, 0 ; INITIALIZE COUNTER
MOV S6, 0
MOV S7, 0
MOV S8, 0
MOV S9, 0
MOV S10, 0
MOV CX, 10 ; INITIALIZE LOOP COUNT VALUE
MOV BX, OFFSET GRADE ; INITIALIZE FIRST ADDR
COMPARE:
MOV AX,[BX] ; GET A RESULT
CMP AX, 60 ; <60?
JL FIVE
CMP AX, 70 ; <70?
JL SIX
CMP AX, 80 ; <80?
JL SEVEN
CMP AX, 90 ; <90?
JL EIGHT
CMP AX, 100 ; =100?
JNE NINE
INC S10
JMP SHORT CHANGE_ADDR
NINE: INC S9
JMP SHORT CHANGE_ADDR
EIGHT: INC S8
JMP SHORT CHANGE_ADDR
SEVEN: INC S7
JMP SHORT CHANGE_ADDR
SIX: INC S6
JMP SHORT CHANGE_ADDR
FIVE: INC S5
CHANGE_ADDR:
ADD BX, 2
LOOP COMPARE
RET ; RETURN TO DOS
MAIN ENDP ; END OF MAIN PART OF PROGRAM
; ------------------------------
PROGNAM ENDS
;***************************
END START ; END ASSEMBLY
1.读懂所给的程序。
2.编写将存放于S5、S6、S7、S8、S9及S10单元中的数据在屏幕上显示出来的部分程序。
编写的程序:
在S10与datarea ends之间定义了输出的提示信息:
n1 db 'S5=$'
n2 db 'S6=$'
n3 db 'S7=$'
n4 db 'S8=$'
n5 db 'S9=$'
n6 db 'S10=$'
crlf db 0dh,0ah,'$'
在loop compare与ret之间进行输出:
mov dx,offset n1 ;输出s5
mov ah,9
int 21h
mov dx,s5
add dx,30h
mov ah,2
int 21h
mov dx,offset crlf
mov ah,9
int 21h
mov dx,offset n2 ;输出s6
mov ah,9
int 21h
mov dx,s6
add dx,30h
mov ah,2
int 21h
mov dx,offset crlf
mov ah,9
int 21h
mov dx,offset n3 ;输出s7
mov ah,9
int 21h
mov dx,s7
add dx,30h
mov ah,2
int 21h
mov dx,offset crlf
mov ah,9
int 21h
mov dx,offset n4;输出s8
mov ah,9
int 21h
mov dx,s8
add dx,30h
mov ah,2
int 21h
mov dx,offset crlf
mov ah,9
int 21h
mov dx,offset n5;输出s9
mov ah,9
int 21h
mov dx,s9
add dx,30h
mov ah,2
int 21h
mov dx,offset crlf
mov ah,9
int 21h
mov dx,offset n6;输出s10
mov ah,9
int 21h
mov dx,s10
add dx,30h
mov ah,2
int 21h
进一步熟悉排序方法。
将0~100之间的10个成绩存入首址为1000H的单元中。1000H+i表示学号为i的学生成绩,编写程序能在2000H开始的区域排出名次表。2000H+i为学号i的学生的名次。
参考主程序:
1、微机一台。
1.参考流程图编写实验程序,进行调试。
2.记录实验结果。
3.写出标准实验报告。
源程序如下:
CRLF MACRO
MOV AH, 02H
MOV DL, 0DH
INT 21H
MOV AH, 02H
MOV DL, 0AH
INT 21H
ENDM
DATA SEGMENT
res db 'The sorted result is:',0dh,0ah,'$'
STUNUM EQU 10
MESS DB ' INPUT 10 STUDENTS SCORE: ',0DH,0AH,'$'
ERROR DB ' INPUT ERROR!',0DH,0AH,'$'
ORG 1000H
SCORE DB 10 DUP (?)
ORG 2000H
SEQU DB 10 DUP (?)
DATA ENDS
STACK SEGMENT
STA DW 12 DUP (?)
TOP DW ?
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK
START: MOV AX, DATA
MOV DS, AX
MOV ES, AX
MOV SP, TOP ; 初始化
MOV AH, 09H
MOV DX, OFFSET MESS
INT 21H ; 显示提示信息
MOV SI, OFFSET SCORE ; 成绩表首址
MOV CX, STUNUM ; 学生数送CX
UUU: CALL GETNUM ; 读取键入数值送DX
MOV [SI], DL ; 存入成绩表缓冲区
INC SI ; 指向下一单元
LOOP UUU
MOV CX, STUNUM ; 学生数
MOV DI, OFFSET SEQU ; 名次表首址
mov dx,offset res;输出提示信息
mov ah,9
int 21h
VVV: CALL SCAN ; 扫描子程序
MOV AL, STUNUM ; 学生数
SUB AL, CL
INC AL ; 计算名次
MOV BX, DX
MOV [DI+BX], AL ; 记DX学号对应名次
LOOP VVV
MOV CX, STUNUM ; 学生数
MOV SI, OFFSET SEQU ; 名次表首址
WWW: MOV AL, [SI]
CALL DISP1
CRLF
INC SI
LOOP WWW ; 显示排定的学生名次
MOV AX, 4C00H
INT 21H
SCAN PROC NEAR ; 子程序,每扫描一遍成绩表缓冲区, 找出其中成绩最高者由DX指针指示对应学生 之后将该成绩清除,以便下一次扫描
PUSH CX
MOV CX, STUNUM ;学生数
MOV AL, 00H ;最低成绩
MOV BX, OFFSET SCORE
MOV SI, BX ;指向成绩表首址
CCC: CMP AL, [SI]
JAE JJJ ;AL中的成绩不低于成绩表指针SI所指单元的成绩则转JJJ
MOV AL, [SI] ;AL存放较高的成绩
MOV DX, SI
SUB DX, BX ;DX为对应学号
JJJ: INC SI ;指向下一单元
LOOP CCC
ADD BX, DX
MOV BYTE PTR[BX], 00H ;本次扫描成绩最高者清0
POP CX
RET
SCAN ENDP
DISP1 PROC NEAR
PUSH CX
MOV BL, AL
MOV DL, BL
MOV CL, 04
ROL DL, CL
AND DL, 0FH
CALL DISPL
MOV DL, BL
AND DL, 0FH
CALL DISPL
POP CX
RET
DISP1 ENDP
DISPL PROC NEAR
ADD DL, 30H
CMP DL, 3AH
JB DDD
ADD DL, 27H
DDD:MOV AH, 02H
INT 21H
RET
DISPL ENDP
GETNUM PROC NEAR
PUSH CX
XOR DX, DX
GGG: MOV AH, 01H
INT 21H
CMP AL, 0DH
JZ PPP
CMP AL, 20H
JZ PPP
SUB AL, 30H
JB KKK
CMP AL, 0AH
JB GETS
CMP AL, 11H
JB KKK
SUB AL, 07H
CMP AL, 0FH
JBE GETS
CMP AL, 2AH
JB KKK
CMP AL, 2FH
JA KKK
SUB AL, 20H
GETS: MOV CL, 04
SHL DX, CL
XOR AH, AH
ADD DX, AX
JMP GGG
KKK: MOV AH, 09H
MOV DX, OFFSET ERROR
INT 21H
PPP: PUSH DX
POP DX
POP CX
RET
GETNUM ENDP
CODE ENDS
END START