华北电力大学
实验报告
|
|
实验名称汇编语言程序设计课程实验
课程名称 汇编语言程序设计
|
|
专业班级:网络1002 学生姓名:
学 号: 成 绩:
指导教师:王保义 实验日期:2013.1
附表1
表格形式显示字符源代码:
csegment segment
assume cs:csegment
START:
main proc far
mov ah, 02h
mov dl, 10h ;设置初始输出为ASCII的10h
mov bl, 15 ;输出显示为15行
hang:
mov cx, 16;设置循环次数,16,表示输出显示为16列
lie:
int 21h ;显示输出
push dx ;推入堆栈
mov ah, 02h
mov dl, 0
int 21h
mov ah, 02h
mov dl, 0
int 21h ;显示空白符
pop dx ;将栈顶元素推出
inc dl ;设置下一个元素
loop lie ;循环输出每行的16个ASCII元素
push dx ;将下一行的首元素推入堆栈
mov ah, 02h
mov dl, 0dh
int 21h
mov ah, 02h
mov dl, 0ah
int 21h ;输出换行
pop dx ;将栈顶元素推出
dec bl
cmp bl, 0 ;比较确定是否已经输出15行元素
jne hang ;若还未完成输出,则跳转至e,继续进行下一行元素的输出
je exit ;否则退出程序
exit:
mov ax, 4c00h
int 21h
main endp
csegment ends
end start
附表2
查找匹配字符串源代码:
DATA SEGMENT
mess1 DB 'Enter keyword:','$'
mess2 DB 'Enter Sentence:','$'
mess3 DB 'Match at location:','$'
mess4 DB 'NOT MATCH.',13,10,'$'
mess5 DB 'H if the sentence',13,10,'$'
change DB 13,10,'$'
stoknin1 label byte
max1 db 10
act1 db ?
stokn1 db 10 dup(?)
stoknin2 label byte
max2 db 50
act2 db ?
stokn2 db 50 dup(?)
DATA ENDS
STACKS SEGMENT
;此处输入堆栈段代码
STACKS ENDS
CODE SEGMENT
;*************************************代码段
assume cs:code,ds:data,es:data
START:
main proc far
push ds
sub AX,AX
sub BX,BX
sub DI,DI
sub SI,SI
push AX ;为返回dos并清空后面要用到的寄存器
MOV AX,DATA
MOV DS,AX
LEA DX,mess1
MOV ah,09
INT 21h ;输出Enter keyword
LEA DX,stoknin1
MOV ah,0ah ;用21号中段的0ah号功能获取关键字
INT 21h
cmp act1,0
je exit ;如果为空直接退出程序
a10:
;********************************输入Sentence并判断
LEA DX,change
MOV ah,09
INT 21h ;输出回程,换行
LEA DX,mess2
MOV ah,09
INT 21h ;输出Enter Sentence:
LEA DX,stoknin2
MOV ah,0ah
INT 21h ;用21号中段的0ah号功能获取句子
MOV AL,act1
CBW
MOV CX,AX ;保存关键字长度到cx
PUSH CX ;cx入栈
MOV AL,act2
cmp AL,0
je a50 ;保存句子长度到al,若句子为空则跳转显示not match
SUB AL,act1
js a50 ;若句子长度小于关键字长度,则跳转显示not match
INC AL
CBW
LEA BX,stokn2 ;将句子的首地址放进BX
MOV DI,0
MOV SI,0
a20:
;****************************************比较,内循环
MOV AH,[BX+DI]
CMP AH,stokn1[SI] ;遇见字符不相等就跳转到a30
jne a30
INC DI
INC SI
DEC CX ;没遇到一个相等的字符,cx-1,cx不为0则比较下一个字符,当cx为0是说明关键字比较完
CMP CX,0
je a40
jmp a20
a30:
;*****************************************外循环,BX+1,清空si,di继续内循环比较
INC BX
DEC AL
cmp AL,0
je a50
MOV DI,0
MOV SI,0
POP CX
push CX
jmp a20
a40:
;*****************************************match,将bx减去句子的首地址加一得到关键字所在位置,调用二进制转十六进制子函数将位置输出
SUB BX,offset stokn2
INC BX
LEA DX,change
MOV ah,09
INT 21h
LEA DX,mess3
MOV ah,09
INT 21h
CALL btoh
LEA DX,mess5
MOV ah,09
INT 21h
jmp a10
;****************************************二进制转换十六进制
btoh PROC NEAR
MOV CH,4
rotate: MOV CL,4
ROL BX,CL
MOV AL,BL
and AL,0fh
add AL,30h
cmp al,3ah
jl printit
add al,7h
btoh endp
a50:
exit:
ret
main endp
CODE ENDS
END START
附表3
分类统计字符个数源代码:
datarea segment
string db 80
db ?
db 80 dup(?);定义字符串string,长度为80
letter db 0 ;定义存储单元letter
digit db 0 ;定义存储单元digit
other db 0 ;定义存储单元other
datarea ends
case segment
assume cs:case, ds:datarea
start:
main proc far
mov ax, datarea
mov ds, ax
lea dx, string
mov ah, 0ah
int 21h
lea di, string + 2 ;输入一行字符,依次将每个字符存入字符串string中
sub ch,ch
mov cl, string + 1
add dx, 2
check: ;将每个字符进行分类
mov al, [di]
cmp al, 0dh
je exit ;字符串以回车符结束,若进行分类的字符是回车符,则跳转至exit,退出程序
cmp al, 30h ;与ASCII码中的0,即30h比较
jb o ;小于30h的,为其他类型字符,则跳转至o,在other块进行操作
cmp al, 39h ;与ASCII码中的9,即39h比较
jna d ;不大于39h的,结合不小于30h的,则跳转至d,在digit块进行操作
ja loro ;剩下的为字母或者其他类型
loro:
cmp al, 41h ;与ASCII码中的A,即41h比较
jb o ;小于41h的,结合大于39h的,则跳转至o,在other块进行操作
cmp al, 7ah ;与ASCII码中的z,即7ah比较
ja o ;大于7ah的,则条钻至o,在other块进行操作
cmp al, 5ah ;与ASCII码中的Z,即5ah比较
jna l ;不大于5ah的,结合大于41h的,则跳转至l,在letter块进行操作
cmp al, 61h ;与ASCII码中的a,即61h比较
jnb l ;不小于61h的,结合不大于7ah的,则跳转至l,在letter块进行操作
jb o ;小于61h的,结合大于5ah的,则跳转至o,在other块进行操作
l:
inc letter ;属于letter类型,则letter增1
inc di
jmp check ;返回继续比较下一个字符
d:
inc digit ;属于digit类型,则digit增1
inc di
jmp check
o:
inc other ;属于other类型,则other增1
inc di
jmp check
exit: ;输出letter,digit,other类型的计数结果
mov ah, 02
mov dl, 0dh
int 21h
mov dl, 0ah
int 21h
mov dl, 4ch
int 21h
mov dl, 3ah
int 21h
mov dl, 0
int 21h
xor ax, ax
mov al, letter
call display ;调用子程序display,输出
mov ah, 02
mov dl, 0dh
int 21h
mov dl, 0ah
int 21h
mov dl, 44h
int 21h
mov dl, 3ah
int 21h
mov dl, 0
int 21h
xor ax, ax
mov al, digit
call display
mov ah, 02
mov dl, 0dh
int 21h
mov dl, 0ah
int 21h
mov dl, 4fh
int 21h
mov dl, 3ah
int 21h
mov dl, 0
int 21h
xor ax, ax
mov al, other
call display
mov ax, 4c00h
int 21h
main endp
display proc near ;子程序display,用于将二进制数转换成十进制数
mov bl, 10
div bl
push ax
mov dl, al
add dl, 30h
mov ah, 2
int 21h
pop ax
mov dl, ah
add dl, 30h
mov ah, 2
int 21h
ret
display endp
case ends
end start
附表4
查找电话号码源代码:
DATAS SEGMENT
COUNT DW 0
TEMP DW 0
TELBOOK DB 50 DUP(32 DUP(' '))
WINDOW1 DB 13,10,13,10,' /************| MENU |***********\',13,10,13,10
DB '| 1---INSER |',13,10
DB '| 2---SEARCH |',13,10
DB '| 3---LIST |',13,10
DB '| 4---QUIT |',13,10,13,10
DB ' \*******************************/',13,10,' SELET:','$'
WINDOW2 DB 13,10,13,10,'|-----------| SEARCH |------------|',13,10,13,10
DB '| 1--- NAME |',13,10
DB '| 2--- TELEPHONE |',13,10
DB '| 3--- QUIT |',13,10,13,10
DB '|---------------------------------|',13,10,' SELET:','$'
STR1 DB 13,10,13,10,'1>INPUT NAME:','$'
STR2 DB 13,10,'2>INPUT TEL:','$'
STR3 DB 13,10,13,10,'|---NAME---*^_^*---TELEPHONE---|' ,13,10,13,10,'$'
STR5 DB 13,10,13,10,'|------------------------------|' ,13,10,13,10,'$'
STR4 DB 13,10,13,10,'WHAT YOU SEARCHED IS NOT EXIST ! ! !',13,10,'$'
STR6 DB 13,10,13,10,'THERE IS NO RECORD ! ! !',13,10,'$'
ERROR DB 13,10,13,10,'ERROR!YOU SHOULD INPUT (1-4) !',13,10,'$'
ERROR1 DB 13,10,13,10,'ERROR!YOU SHOULD INPUT (1-3) !',13,10,'$'
N_TEMP DB 21,?
N_T DB 20 DUP(' '),' '
T_TEMP DB 9,?
T_T DB 8 DUP(' '),' ',13,10,'$'
DATAS ENDS ;------------------------数据段
PRINT MACRO X1
LEA DX,X1
MOV AH,9
INT 21H
ENDM ;--------------宏显示字符串
INPUT MACRO X1
LEA DX,X1
MOV AH,10
INT 21H
ENDM ;--------------宏输入字符串
RENEW MACRO MING,WEI
LOCAL NEXT
MOV CX,WEI
LEA SI,MING
NEXT:MOV BYTE PTR [SI],' '
INC SI
LOOP NEXT
ENDM ;宏定义将输入缓冲区还原
QUHC MACRO TEMP,T
XOR DX,DX
MOV DL,TEMP+1
LEA SI,T
ADD SI,DX
MOV BYTE PTR [SI],' '
ENDM ;宏定义去除回车符号
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS
START:
MOV AX,DATAS
MOV DS,AX
MOV ES,AX
LEA DI,TELBOOK
L1:PRINT WINDOW1
MOV AH,1
INT 21H
CMP AL,'1'
JNE L2
CALL INSER ;输入
CALL ORDER ;排序
JMP L1
L2:CMP AL,'2'
JNE L3
CALL SEARCH ;查找
JMP L1
L3:CMP AL,'3'
JNE L4
CALL LIST ;列表
JMP L1
L4:CMP AL,'4'
JE L5 ;退出
PRINT ERROR ;输入错误,返回初始界面
JMP L1 ;--------------------------------------
INSER PROC;*****************输入记录 INSER ***************************
RENEW N_T,20
RENEW T_T,8
PRINT STR1
INPUT N_TEMP
QUHC N_TEMP,N_T
PRINT STR2
INPUT T_TEMP
QUHC T_TEMP,T_T ;输入到缓冲区
LEA SI,N_T
MOV CX,20
CLD
REP MOVSB
LEA SI,T_T
MOV CX,12
CLD
REP MOVSB
INC COUNT
RET
INSER ENDP ;***********************
ORDER PROC;*******************记录排序 ORDER ***************************
PUSH DI
MOV CX,COUNT
CMP CX,1
JBE N4
DEC CX
N5:PUSH CX
SUB DI,32
MOV DX,DI
MOV SI,DI
SUB SI,32
MOV CX,20
N1:MOV BL,[SI]
CMP BL,[DI]
JA N2
JB N6
INC SI
INC DI
LOOP N1
N6:POP CX
JMP N4
N2:MOV DI,DX
MOV SI,DI
SUB SI,32
MOV CX,32
N3:MOV BL,[SI]
XCHG BL,[DI]
XCHG BL,[SI]
INC SI
INC DI
LOOP N3
SUB DI,32
POP CX
LOOP N5
N4:POP DI
RET
ORDER ENDP ;***************************
SEARCH PROC;*******************查找记录 SEARCH ****************************
T0:PRINT WINDOW2
MOV AH,1
INT 21H
CMP AL,'1' ;按名字查找
JNE T1
PRINT STR1
RENEW N_TEMP,20
INPUT N_TEMP
QUHC N_TEMP,N_T
MOV CX,COUNT
MOV TEMP,OFFSET TELBOOK
F3:PUSH CX
MOV SI,TEMP
LEA BX,N_T
MOV CX,20
F2:MOV DL,[SI]
CMP DL,[BX]
JNE F1
INC SI
INC BX
LOOP F2
PRINT STR3
MOV DX,TEMP
MOV AH,9
INT 21H
PRINT STR5
POP CX
JMP F0
F1:ADD TEMP,32
POP CX
LOOP F3
PRINT STR4
JMP F0
T1:CMP AL,'2' ;按号码查找
JNE T2
PRINT STR2
RENEW T_TEMP,8
INPUT T_TEMP
QUHC T_TEMP,T_T
MOV CX,COUNT
MOV TEMP,OFFSET TELBOOK
K3:PUSH CX
MOV SI,TEMP
ADD SI,20
LEA BX,T_T
MOV CX,8
K2:MOV DL,[SI]
CMP DL,[BX]
JNE K1
INC SI
INC BX
LOOP K2
PRINT STR3
MOV DX,TEMP
MOV AH,9
INT 21H
PRINT STR5
POP CX
JMP F0
K1:ADD TEMP,32
POP CX
LOOP K3
PRINT STR4
JMP F0
T2:CMP AL,'3'
JE F0
PRINT ERROR1
JMP T0
F0:RET
SEARCH ENDP ;*************************
LIST PROC;*****************显示电话表 LIST *****************************
PRINT STR3
CMP COUNT,0
JE Z2
MOV CX,COUNT
LEA SI,TELBOOK
Z1:mov DX,SI
MOV AH,9
INT 21H
ADD SI,32
LOOP Z1
JMP Z3
Z2:PRINT STR6
Z3:PRINT STR5
附表5
窗口空中程序代码:
dseg segment
cury db 15
curx db 50
ly db 15
lx db 10
ry db 15
rx db 50
dwy db 22
dwx db 15
dseg ends
;.............................................
clear macro a,b,c,d ;清屏
mov ah,6
mov al,0
mov ch,a
mov cl,b
mov dh,c
mov dl,d
mov bh,7
int 10h
endm
;................................................
scroll macro a,b,c,d,e,f;上卷窗口
mov ah,6
mov al,a
mov ch,b
mov cl,c
mov dh,d
mov dl,e
mov bh,f
int 10h
endm
;................................................
postc macro y,x ;置光标位
mov ah,2
mov dh,y
mov dl,x
mov bh,0
int 10h
endm
;.................................................
cseg segment
assume cs:cseg,ds:dseg
main proc far
push ds
sub ax,ax
push ax
mov ax,dseg
mov ds,ax
clear 0,0,23,71 ;清屏
scroll 10,5,10,15,30,70h ;开出三个窗口
scroll 10,5,50,15,70,70h
scroll 4,18,15,22,65,70h
postc cury,curx
input:
postc cury,curx
mov ah,0 ;从键盘读入
int 16h
cmp ah,4bh ;is left?
jnz no_left
push ax ;保存ax
MOV aL,cury ;改动各光标位
mov ry,al
mov al,curx
mov rx,al ;保存右边光标值
mov al,ly
mov cury,al
mov al,lx
mov curx,al ;把左边坐标给当前光标
pop ax
postc cury,curx
jmp input
no_left:
cmp ah,4dh ;is right?
jnz no_right
push ax ;保存光标位
mov al,cury
mov ly,al
mov al,curx
mov lx,al ;保存右边光标值
mov al,ry
mov cury,al
mov al,rx
mov curx,al ;把左边坐标给当前光标
pop ax
postc cury,curx
jmp input
no_right:
cmp ah,01 ;is ESC
jnz display ;if no then display
ret ;if yes then exit
display: mov ah,0ah ;在光标位显示字符
mov bh,0
mov cx,1
int 10h
inc curx
postc dwy,dwx ;置下窗口光标
mov ah,0ah ;在光标位显示字符
mov bh,0
mov cx,1
int 10h
inc dwx
cmp dwx,65
ja down
mov al,curx;查看是否满行
cmp al,30
jle next
cmp al,50
jle next2
cmp al,70
jle next
ja next3
next2:
scroll 1,5,10,15,30 ,70h
mov cury,15
mov curx,10
jmp next
next3:
scroll 1,5,50,15,70,70h
mov cury,15
mov curx,50
jmp next
down:
scroll 1,18,15,22,65,70h
mov dwx,15
next:
jmp input
main endp
cseg ends
end main
附表六
键盘扩展程序代码:
stack segment para stack 'stack'
db 256 dup(0)
stack ends
data segment para public 'data'
buffer db 16h dup(0)
bufpt1 dw 0 ;缓冲循环队列的头指针
bufpt2 dw 0 ; 尾指针
kbflag db 0 ;按其他键时,置为80H,结束
kbflag1 db 0 ;shift键是否松开,松开为1
prompt db '---kbd_io program begin---',0dh,0ah,'$'
scantab db 0,0,'1234567890-=',8,0
db 'qwertyuiop[]',0dh,0
db 'asdfghjkl;',0,0,0
db 'zxcvbnm,./',0,0,0
db ' ',0,0,0,0,0,0,0,0,0,0,0,0,0
db '789-456+1230.'
shiftab db 0,0,'!@#$%^&*()_+',0,0
db 'QWERTYUIOP{}',0DH,0
db 'ASDFGHJKL:"',0,0,0
db 'ZXCVBNM<>?',0,0,0
db ' ',26 dup(0)
even
oldcs9 dw ?
oldip9 dw ?
data ends
;................................................
code segment para public 'code'
start proc far
assume cs:code,ds:data
push ds
mov ax,0
push ax
mov ax,data
mov ds,ax
cli ;关中断IF=0
mov al,09 ;中断类型号
mov ah,35h;DOS调用,取中断向量
int 21h ;取中断向量
mov oldcs9,es;ES:BX=中断向量
mov oldip9,bx
;...................................................设置新中断向量
push ds
mov dx,offset kbint
mov ax,seg kbint
mov ds,ax;DS:DX=中断向量放在中断向量表
mov al,09 ;中断类型号
mov ah,25h ;DOS调用,设置中断向量
int 21h
pop ds
in al,21h ;中断屏蔽寄存器端口号21H
and al,0fdh ;设置中断屏蔽字,允许键盘中断
out 21h,al
mov dx,offset prompt;9#DOS调用
mov ah,9
int 21h
sti ;开中断
forever:
call kbget
test kbflag,80h;判断是否为80H
jnz endint ;是则结束
push ax
call dispchar ;清屏
pop ax
cmp al,0dh
jnz forever
mov al,0ah
call dispchar
jmp forever
endint:
mov dx,oldip9
mov ax,oldcs9
mov ds,ax
mov al,09h
mov ah,25h
int 21h ;执行9#键盘中断
ret
start endp
;........................................检测并等待键盘中断
kbget proc near
push bx
cli ;关中断
mov bx,bufpt1
cmp bx,bufpt2
jnz kbget2
cmp kbflag,0
jnz kbget3
sti ;开中断
pop bx
jmp kbget
kbget2:
mov al,[buffer+bx]
inc bx
cmp bx,16
jB kbget3
mov bx,0
kbget3:
mov bufpt1,bx
pop bx
ret
kbget endp
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!键盘中断程序
kbint proc far
push bx
push ax
in al,60h;从PA口读扫描码
push ax
in al,61h ;从PB口读信息
or al,80h ;选通
out 61h,al;置键盘应答位
and al,7fh
out 61h,al;复位键盘应答位
pop ax
test al,80h;检测AL第8位是否为1,判断键位是按下(1)还是放开
jnz kbint2
cmp al,2ah ;判断是否为左Shift键
jnz shift5
cmp kbflag1,1
jz shift1
mov kbflag1,1 ;标志位置1
jmp shift1
shift5:
cmp al,36h ;判断是否为右Shift键
jnz shift2
cmp kbflag1,1
jz shift1
mov kbflag1,1
jmp shift1
shift2:
cmp kbflag1,1
jnz shift3
lea bx,shiftab ;shifttab换码
xlat ;(AL)<--((BX)+(AL))
jmp shift4
shift3:
lea bx,scantab ;santab换码
xlat ;(AL)<--((BX)+(AL))
shift4:
cmp al,0 ;判断是否为其他控制符
jnz kbint4
mov kbflag,80h;置退出标志
jmp kbint2
kbint4:
mov bx,bufpt2
mov [buffer+bx],al
inc bx
cmp bx,16
jb kbint3
mov bx,0
kbint3:
cmp bx,bufpt1
jz kbint2
mov bufpt2,bx
kbint2:
cmp al,0aah ;判断左shift键是否松开
jnz shift6
mov kbflag1,0
shift6:
cmp al,0b6h ;判断右shift键是否松开
jnz shift1 ;
mov kbflag1,0
shift1:
cli ;关中断
mov al,20h ;结束键盘中断
out 20h,al
pop ax
pop bx
sti ;开中断
iret
kbint endp
;.....................................
dispchar proc near ;BIOS,10H:0E#显示字符
push bx
mov bx,0 ;AL=字符 BL= 前景颜色
mov ah,0eh
int 10h
pop bx
ret
dispchar endp
code ends
end start