王爽《汇编语言》(第二版)实验题、课程设计 代码参考
本人将根据汇编代码规范以及尽量简洁和优化使用寻址方式进行编写,给新人们一个参考和互相学习。实验3:编程、编译、链接、跟踪
该实验因没有自己编写代码,故在此省略。
实验4和loop的使用
(1)
assume cs:cseg
cseg segment
start:
mov ax,0h
mov ds,ax
mov bx,200h
mov cx,64 ;因是传送0-63,故实际数据有64个
s:
mov ,al ;因前面有mov ax,0,故初始(al)=0
inc bx
inc al
loop s
mov ax,4c00h
int 21h
cseg ends
end start
(2)这个,我只能写出上面那个10条指令的写法(根据到第五章的知识)
(3)略。 (2)
assume cs:cseg
cseg segment
start:
mov ax,200
mov ds,ax
mov bx,0
mov cx,64
s:
mov ,bl
inc bl
loop s
mov ax,4c00h
int 21h
cseg ends
end start 实验5(5)
assume cs:code
a segment
db 1,2,3,4,5,6,7,8
a ends
b segment
db 1,2,3,4,5,6,7,8
b ends
c segment
db 0,0,0,0,0,0,0,0
c ends
code segment
start:
mov ax,a
mov ds,ax
mov ax,b
mov es,ax
sub bx,bx
mov cx,8
s:
mov dl,
add dl,es:
push ds
mov ax,c
mov ds,ax
mov ,dl
inc bx
pop ds
loop s
mov ax,4c00h
int 21h
code ends
end start 实验5(6)
assume cs:code
a segment
dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
a ends
b segment
dw 0,0,0,0,0,0,0,0
b ends
code segment
start:
mov ax,a
mov ds,ax
mov ax,b
mov ss,ax
mov sp,16
sub bx,bx ;bx置0
mov cx,8
s1:
push ;压栈时,sp每次-2,也就是说逆序,因此符合题目要求
add bx,2
loop s1
mov ax,4c00h
int 21h
code ends
end start
看看看看阿 看看了。好不好啊。 实验6(2)
assume cs:codesg,ss:stacksg,ds:datasg
stacksg segment
dw 0,0,0,0,0,0,0,0
stacksg ends
datasg segment
db '1. display '
db '2. brows '
db '3. replace '
db '4. modify '
datasg ends
codesg segment
start:
mov ax,stacksg
mov ss,ax
mov sp,16
mov ax,datasg
mov ds,ax
mov bx,3 ;将ds:bx指向第1字符串的'd'
mov cx,4
s1:
push cx
mov cx,4
s2:
mov al,
sub al,20h ;因小写字母比对应大写字母大20,也可以用and指令来实现
;或用and al,11011111b
mov ,al
inc bx
loop s2
add bx,12 ;转到下一行字符串的首字母
pop cx ;回复外循环的CX计数器
loop s1
mov ax,4c00h
int 21h
codesg ends
end start
实验7:
assume cs:cseg,ds:dseg,ss:sseg
dseg segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
;以上是21个年份
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;以上表示21年公司总收入的21个dword型数据
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
;以上表示21年公司雇员人数的21个word型数据
dseg ends
table segment
db 21 dup ('year summ ne ?? ')
table ends
sseg segment
dw 100 dup (0)
sseg ends
cseg segment
start:
mov ax,sseg ;数据初始化
mov ss,ax
mov sp,200
mov ax,dseg
mov ds,ax
mov ax,table
mov es,ax
mov bx,0
mov si,168 ;定位到雇员数
mov di,0
mov cx,21
s:
push ;复制年份数据
pop es:
push
pop es:
push ;复制总收入数据
pop es:
mov ax,es: ;保存总收入低位留作计算平均收入用
push
pop es:
mov dx,es: ;保存总收入高位留作计算平均收入用
push ;复制雇员人数数据
pop es:
push bx ;保存bx,将bx临时用于保存雇员数以算平均数
mov bx,es:
div bx ;计算人均收入
mov es:,ax
pop bx
add si,2
add bx,4
add di,16
loop s
mov ax,4c00h
int 21h
cseg ends
end start
实验10(1):
assume cs:code
data segment
db 'Welcome to masm!',0
data ends
code segment
start:
mov dh,8
mov dl,3
mov cl,2
mov ax,data
mov ds,ax
mov si,0
call show_str
mov ah,1 ;按任意键退出
int 21h
mov ax,4c00h
int 21h
;名称:show_str(子程序)
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:(dh)=行号(取值范围0-24),(dl)=列号(取值范围0-79),
; (cl)=颜色,ds:si指向字符串的首地址。
;返回:无。
show_str proc
push di ;保护现场
push ax
push es
push si
mov ax,160 ;一行有160字节
mul dh
mov di,ax
mov ax,2 ;一列占2个字节(含一个颜色字节)
mul dl
add di,ax
mov ax,0b800h
mov es,ax
mov al,cl ;用al保存颜色值
sub cx,cx
s_show:
mov cl,
jcxz show_end
inc si
mov es:,cl
inc di
mov es:,al
inc di
jmp s_show
show_end:
pop si
pop es
pop ax
pop di
ret
show_str endp
code ends
end start 实验10(2):
;子程序:divdw
;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; (cx)=除数
;返回:(dx)=结果的高16位,(ax)=结果的低16位
; (cx)=余数
divdw proc
push bx ;保护现场
push ax ;除法运算段
mov ax,dx
sub dx,dx
div cx
mov bx,ax
pop ax
div cx
mov cx,dx
mov dx,bx ;除法运算结束,配置返回值
pop bx ;恢复现场
ret
divdw endp 实验10(3):
说明: 为配合等下的课程设计1,这里这个子程序修改了下
;子程序:dtoc
;功能:将dword型数转变为表示十进制数的字符串,字符串以0为结束符。
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; ds:si指向字符串的首地址
;返回:无
;说明:本子程序需与解决除法溢出的子程序divdw一起使用方可行
dtoc proc
push ax
push cx
push dx
push si
push di
sub di,di ;位数计数器初始为0
dtoc_go:
mov cx,dx
jcxz cha_next
jmp go_on ;不为0则继续除以10
cha_next:
mov cx,ax
jcxz dtoc_over ;以上几行为验证数值是否计算完毕
go_on:
mov cx,10
call divdw
push cx ;保存余数(顺序为从末位到首位)
inc di ;位数计数
jmp dtoc_go
dtoc_over:
mov cx,di
dtoc_s:
pop ax
mov ,al
loop dtoc_s
pop di
pop si
pop dx
pop cx
pop ax
ret
dtoc endp 课程设计1:
说明:在这里代码量虽然有点大,但是主体部分其实很少,其他的都是子程序。在这个课程设计中,本人主要是采用模块化开发,所谓模块化,其实就是多用子程序,将常用功能都做成子程序的形式。如果不用子程序这些,和优化结构,其实这个课程设计的总代码量也可以控制在 150行左右的。
另外,大家也可以利用在实验7中已经做过的TABLE表格,直接拿来用,那样也比较方便的。
assume cs:cseg,ds:dseg,ss:sseg
;常量定义
COLORequ2 ;显示文本的颜色:黑底绿色
HANGequ1 ;文本显示位置:初始显示的行号(从0开始数)
LIEequ 2 ;文本显示位置:初始显示的列号(从0开始数)
;数据段设置
dseg segment
ty:
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
;以上是表示21年的21个字符串
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;以上是表示21年公司总收入的21个dword型数据
tp:
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
;以上是表示21年公司雇员人数的21个word型数据
tsz:
db 12 dup (0)
;以上用于为显示数值字符串变量数组(那个显示字符串的子程序show_str要用到)
dseg ends
;堆栈段设置
sseg segment
db 100 dup (0)
sseg ends
cseg segment
start:
mov ax,sseg ;代码初始化工作
mov ss,ax
mov sp,100
mov ax,dseg
mov ds,ax
mov cx,21 ;21组数据,故循环21次
mov dh,HANG ;设置显示的初始位置
mov dl,LIE
mov bx,offset ty
mov si,offset tp
main_s:
push cx ;显示年份,先保存cx以方便重新赋值
push si
mov cx,4
mov si,offset tsz
ty_s:
mov al,
mov ,al
inc si
inc bx
loop ty_s
mov si,offset tsz
mov cl,COLOR;黑底绿字显示
call show_str
mov si,offset tsz ;变量数组清零
mov cx,12
call zerosz
add dl,6 ;年份和空格总占据6列
pop si
push si
push dx
mov ax,;显示总收入,因前面已经有循环4次的inc bx,故此处只需+80
mov dx,
mov si,offset tsz
call dtoc
mov si,offset tsz
mov cl,2
pop dx
call show_str
mov si,offset tsz
mov cx,12
call zerosz
pop si
push si
add dl,9
push dx
mov ax, ;显示雇员人数
sub dx,dx
mov si,offset tsz
call dtoc
mov si,offset tsz
mov cl,2
pop dx
call show_str
mov si,offset tsz
mov cx,12
call zerosz
pop si
add dl,7
push dx
mov ax,;计算人均收入并显示
mov dx,
mov cx,
add si,2
call divdw
push si
mov si,offset tsz
call dtoc
pop si
pop dx
push si
mov si,offset tsz
mov cl,2
call show_str
mov si,offset tsz
mov cx,12
call zerosz
pop si
pop cx
dec cx
jcxz main_end
inc dh
mov dl,LIE
jmp main_s
main_end:
mov ah,1 ;该代码作用为按任意键后再退出
int 21h
mov ax,4c00h
int 21h
;名称:show_str(子程序)
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:(dh)=行号(取值范围0-24),(dl)=列号(取值范围0-79),
; (cl)=颜色,ds:si指向字符串的首地址。
;返回:es:di指向显示末位下一个。
show_str proc
push ax
push si
push dx
push cx
mov ax,160 ;一行有160字节
mul dh
mov di,ax
mov ax,2 ;一列占2个字节(含一个颜色字节)
mul dl
add di,ax
mov ax,0b800h
mov es,ax
mov al,cl ;用al保存颜色值
sub cx,cx
s_show:
mov cl,
jcxz show_end
inc si
mov es:,cl
inc di
mov es:,al
inc di
jmp s_show
show_end:
pop cx
pop dx
pop si
pop ax
ret
show_str endp
;子程序:dtoc
;功能:将dword型数转变为表示十进制数的字符串,字符串以0为结束符。
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; ds:si指向字符串的首地址
;返回:无
;说明:本子程序需与解决除法溢出的子程序divdw一起使用方可行
dtoc proc
push ax
push cx
push dx
push si
push di
sub di,di ;位数计数器初始为0
dtoc_go:
mov cx,dx
jcxz cha_next
jmp go_on ;不为0则继续除以10
cha_next:
mov cx,ax
jcxz dtoc_over;以上几行为验证数值是否计算完毕
go_on:
mov cx,10
call divdw
add cl,30h
push cx ;保存余数(顺序为从末位到首位)
inc di ;位数计数
jmp dtoc_go
dtoc_over:
mov cx,di
dtoc_s:
pop ax
mov ,al
inc si
loop dtoc_s
pop di
pop si
pop dx
pop cx
pop ax
ret
dtoc endp
;子程序:divdw
;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; (cx)=除数
;返回:(dx)=结果的高16位,(ax)=结果的低16位
; (cx)=余数
divdw proc
push bx ;保护现场
push ax ;除法运算段
mov ax,dx
sub dx,dx
div cx
mov bx,ax
pop ax
div cx
mov cx,dx
mov dx,bx ;除法运算结束,配置返回值
pop bx ;恢复现场
ret
divdw endp
;子程序:zerosz数组内容清零
;参数:ds:si指向数组,cx为清零个数
;返回:无
zerosz proc
zerosz_s:
mov BYTE ptr ,0
inc si
loop zerosz_s
ret
zerosz endp
cseg ends
end start
实验11
assume cs:cseg,ds:dseg
dseg segment
sztext:
db "Beginner's All-purpose Symbolic Instruction Code.",0,'$'
dseg ends
cseg segment
start:
mov ax,dseg
mov ds,ax
mov si,0
doing:
mov al,
cmp al,0 ;判断是否为结束符0
je over ;是则转到显示改变的文本
cmp al,'a'
jb next
cmp al,'z'
ja next
sub al,20h
mov ,al
next:
inc si
jmp doing
over:
mov dx,offset sztext ;显示改变后的文本
mov ah,9h
int 21h
mov ah,1
int 21h
mov ax,4c00h
int 21h
cseg ends
end start
实验12assume cs:cseg
cseg segment
start:
push cs
pop ds ;将CS的值赋给DS
mov si,offset do0 ;将ds:si指向do0程序开始
mov ax,0
mov es,ax
mov di,200h ;将es:di指向0:200h(目的地址)
mov cx,offset do0_end - offset do0 ;设置传输的长度
cli ;关中断
rep movsb ;传输开始
sti ;传输结束,中断打开
mov ax,200h
mov es:,ax
mov ax,0
mov es:,ax ;设置0号中断向量
mov ax,4c00h
int 21h
do0:
jmp do0_begin
db 'divide error!'
do0_begin:
mov ax,cs ;此处也可以直接设置ds=0
mov ds,ax
mov ax,0b800h
mov es,ax
mov di,12*160+2*33 ;显示在中间位置
mov si,202h
mov cx,13
do0_s:
mov al,
mov es:,al
inc si
add di,2
loop do0_s
mov ax,4c00h
int 21h
do0_end:
nop
cseg ends
end start 实验13(1)assume cs:cseg
cseg segment
start:
push cs
pop ds ;设置ds为cs的值
mov si,offset do7ch
mov ax,0
mov es,ax
mov di,200h
mov cx,offset do7ch_end - offset do7ch
cli
rep movsb
sti
mov ax,200h ;设置7ch的中断向量
mov es:,ax
mov ax,0
mov es:,ax
mov ax,4c00h
int 21h
do7ch:
push ax ;保护现场
push cx
push dx
push di
push si
push es
mov ax,0b800h ;配置显示位置
mov es,ax
sub di,di
mov ax,160
mul dh
add di,ax
mov ax,2
mul dl
add di,ax
mov al,cl ;保存显示颜色
sub cx,cx
do7ch_begin:
mov cl,
jcxz do7ch_szend ;遇到结束0则跳出
mov es:,cl
inc di
mov es:,al
inc di
inc si
jmp do7ch_begin
do7ch_szend:
pop es ;恢复现场
pop si
pop di
pop dx
pop cx
pop ax
iret
do7ch_end:
nop
cseg ends
end start 实验13(2):assume cs:code
code segment
s1: db 'Good,better,best,','$'
s2: db 'Never let it rest,','$'
s3: db 'Till good is better,','$'
s4: db 'And better,best.','$'
s : dw offset s1,offset s2,offset s3,offset s4
row: db 2,4,6,8
start:
mov ax,cs
mov ds,ax
mov bx,offset s
mov si,offset row
mov cx,4
ok:
mov bh,0
mov dh,
mov dl,0
mov ah,2
int 10h
mov dx,
mov ah,9
int 21h
inc si
add bx,2
loop ok
mov ah,1
int 21h
mov ax,4c00h
int 21h
code ends
end start 实验14:;程序:显示当前时间,格式“年/月/日 时:分:秒”
assume cs:cseg
;常量定义
HANG EQU 2
LIE EQU 28
COLOR EQU 7 ;显示黑底白色
cseg segment
start:
mov ax,0b800h
mov es,ax
sub di,di
mov ax,160
mov bh,HANG
mov bl,LIE
mul bh
add di,ax
mov ax,2
mul bl
add di,ax
dos1:
; push di
mov cx,3
mov al,9
s1:
push ax
call ttoa
mov es:,ah
add di,2
mov es:,al
add di,2
dec cx
pop ax
jcxz dos2
mov es:,'/'
mov es:,COLOR
add di,2
dec al
jmp s1
dos2:
add di,2
mov cx,3
mov al,4
s2:
push ax
call ttoa
mov es:,ah
add di,2
mov es:,al
add di,2
dec cx
pop ax
jcxz doend
mov es:,':'
mov es:,COLOR
add di,2
sub al,2
jmp s2
doend:
; pop di
; jmp dos1
mov ah,1
int 21h
mov ax,4c00h
int 21h
;子程序:读取时间并转换为ASCII
ttoa proc
push cx
out 70h,al
in al,71h
mov ah,al
mov cl,4
shr ah,cl
and al,0fh
add ax,3030h
pop cx
ret
ttoa endp
cseg ends
end start 实验15:assume cs:cseg,ss:sseg
sseg segment
db 100 dup (0)
sseg ends
cseg segment
start:
mov ax,sseg
mov ss,ax
mov sp,100
push cs ;准备传送新9号中断代码
pop ds
mov ax,0
mov es,ax
mov si,offset int9
mov di,204h
mov cx,offset int9_end - offset int9
cld
rep movsb
push es: ;保存原9号中断入口地址
pop es:
push es:
pop es:
cli ;配置新9号中断入口地址
mov WORD ptr es:,204h
mov WORD ptr es:,0
sti
mov ax,4c00h
int 21h
int9:
push ax
push bx
push cx
push es
in al,60h
pushf
call DWORD ptr cs:
cmp al,9eh
jne int9ret
mov ax,0b800h
mov es,ax
mov bx,0
mov cx,2000
int9_s:
mov BYTE ptr es:,'A'
inc bx
mov BYTE ptr es:,2
inc bx
loop int9_s
int9ret:
pop es
pop cx
pop bx
pop ax
iret
int9_end:
nop
cseg ends
end start
页:
[1]
2