第七章 更灵活的定位内存地址的方法
2.编程,完成问题7.9中的程序
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,0
mov cx,4
s0:push cx
mov si,3
mov cx,4
s:mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s
add bx,16
pop cx
loop s0
mov ax,4c00h
int 21h
codesg ends
end start
第八章 数据处理的两个基本问题
assume cs:codesg, ss:stack,ds:data
data 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'
dd 16, 22, 382, 1356, 2390, 8000, 16000, 24486, 50065, 97479, 140417, 197514
dd 345980, 590827, 803530, 1183000, 1843000, 2759000, 3753000, 4649000, 5937000
dw 3, 7, 9, 13, 28, 38, 130, 220, 476, 778, 1001, 1442, 2258, 2793, 4037, 5635, 8226
dw 11542, 14430, 15257, 17800
data ends
table segment
db 21 dup ('year summ ne ?? ')
table ends
assume cs:codesg, ss:stack
stack segment
dw 8 dup (0) ;存放cx
stack ends
codesg segment
start:mov ax,table
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,16
mov ax,data
mov es,ax
mov cx,21
mov si,0
mov bx,0
year:push cx
mov di,0
mov cx,4
s:mov al,es:[si]
mov [bx+di],al
inc si
inc di
loop s
add bx,16
pop cx
loop s
mov cx,21
mov bx,0
incom:mov ax,es:[si]
mov [5+bx],ax
add si,2
mov ax,es:[si]
mov [7+bx],ax
add si,2
add bx,16
loop incom
mov cx,21
mov bx,0
staff:mov ax,es:[si]
mov [10+bx],ax
add bx,16
loop staff
mov cx,21
mov bx,0
ave:mov ax,[bx+5]
mov dx,[bx+7]
div word ptr [bx+10]
mov [13+bx],ax
add bx,16
loop ave
mov ax,4c00h
int 21h
codesg ends
end start
第九章 转移指令的原理
1.分析下面的程序,在运行前思考,这个程序可以正确返回吗? 运行后再思考:为什么是这种结果? 通过这个程序加深对相关内容的理解。
可以正确返回。通过ax将s2的地址传送到s,jmp short s 实际跳转到s2,而s2中jmp short s1 计算的是s1,s2之间的偏移量,然后加上s的地址,实际跳转到首地址,完成返回
2.编程:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串’welcome to masm!’。
;在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串’welcome to masm!’
assume ds:data, cs:code
data segment
db 'welcome to masm!'
data ends
code segment
start: mov ax,data
mov ds,ax
mov ax,0b800h
mov es,ax
mov bx,0
mov si,1664
mov cx,16
gree:mov al,ds:[bx]
mov ah,10000010B
mov es:[si],ax
add si,2
inc bx
loop gree
mov bx,0
mov si,1824
mov cx,16
rad:mov al,ds:[bx]
mov ah,10100100B
mov es:[si],ax
add si,2
inc bx
loop rad
mov bx,0
mov si,1984
mov cx,16
blue:mov al,ds:[bx]
mov ah,11110001B
mov es:[si],ax
add si,2
inc bx
loop blue
mov ax,4c00h
int 21h
code ends
end start
第十章 CALL和RET指令
1.显示字符串
问题 显示字符串是现实工作中经常要用到的功能,应该编写一个通用的子程序来实现这个功 能。我们应该提供灵活的调用接口,使调用者可以决定显示的位置(行、列、内容和颜色。 子程序描述 名称:show_str 功能:在指定的位置,用指定的颜色,显示一个用口结束的字符串, 参数:(dh)-行号(取值范围 0~24),(d=列号(取值范围 0~79), (c)-颜色,ds:si指向字符串的首地址 返回:无
应用举例:在屏幕的8行3列,用绿色显示data段中的字符串
;在屏幕的8行3列,用绿色显示data段中的字符串
assume cs:code,ds:data,ss:stack ?
data segment ?
? ? db 'welcome to masm!',0 ?
data ends ?
stack segment ?
? ? dw 8 dup (0) ?
stack ends ?
code segment ?
start:mov ax,data
? ? ? mov ds,ax
? ? ? mov ax,stack
? ? ? mov ss,ax
? ? ? mov sp,16
? ? ??
? ? ? mov dh,8
? ? ? mov dl,3
? ? ? mov cl,2
? ? ? call show_str
? ? ??
? ? ? mov ax,4c00h
? ? ? int 21h
? ? ??
?show_str:push dx
? ? ? ? ? push cx
? ? ? ? ? push ax
? ? ? ? ? push ss
? ? ? ? ? push si
? ? ? ? ??
? ? ? ? ? mov ax,0b800h
? ? ? ? ? mov es,ax
? ? ? ? ??
;计算行偏移量 偏移量保存在bx
? ?mov al,0a0h
? ?dec dh
? ?mul dh
? ?mov bx,ax
? ?
? ?mov al,2
? ?dec dl
? ?mul dl
? ?add bx,ax;
? ?
? ?mov di,0
? ?mov si,0
? ?mov al,cl
? ?
? ?s1:
? ?mov ch,0
? ?mov cl,ds:[di]
? ?jcxz ok
? ?mov ch,al
? ?mov es:[bx+si],cx
? ?
? ?add si,2
? ?inc di
? ?jmp short s1
? ?ok:
? ?pop si
? ?pop ss
? ?pop ax
? ?pop cx
? ?pop dx
? ?ret
? ?
code ends
end
2.解决除法溢出的问题
名称:divdw 功能:进行不会产生溢出的除法运算,被除数为 dword 型,除数为 word 型,结果为dword? 参数:(ax)=dword 型数据的低 16位 (dx)=dword型数据的高16位 (cx)=除数 返回:(dx)=结果的高16位,(ax)-结果的低 16位 (cx)=余数 应用举例:计算 1000000/10(F4240H/0A)
assume cs:code, ss:stack
stack segment
dw 16 dup (0)
stack ends
code segment
start: mov ax, stack
mov ss, ax
mov sp, 32
mov ax, 4240h
mov dx, 000fh
mov cx, 0ah
call divdw
mov ax, 4c00h
int 21h
3.数值显示
名称:dtoc 功能:将word 型数据转变为表示十进制数的字符串,宇符串以。为结尾符。 参数:(ax)=word 型数据 dssi指向字符串的首地址 返回:无 应应用举例:编程,将数据 12666 以十进制的形式在屏幕的8行了列,用绿色显示出 来。在显示时我们调用本次实验中的第一个子程序 show str。
assume cs:code, ss:stack
stack segment
dw 16 dup (0)
stack ends
data segment
db 10 dup (0)
data ends
code segment
start: mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 32
mov ax, 12666
mov si, 0
call dtoc
mov dh, 8
mov dl, 3
mov cl, 2
call show_str
mov ax, 4c00h
int 21h
dtoc: push ax
push si
push di
push dx
push bx
push cx
mov di, 0
mov dx, 0
mov bx, 10
devide: mov cx, ax
jcxz stop
div bx
inc di
push dx
mov dx, 0
jmp devide
stop: mov cx, di
string: pop bx
add bx, 30h
mov [si], bl
inc si
loop string
pop cx
pop bx
pop dx
pop di
pop si
pop ax
ret
show_str:
push cx
push bx
push ax
push si
push di
push es
;using cx, bx, ax, si, di, es
mov ax, 0b800h
mov es, ax
mov bx, 0
mov di, 0
mov al, 160
mul dh
add bx, ax
mov al, 2
mul dl
add bx, ax ;bx stores address of start character
mov al, cl ;al stores the color of character
char: mov ch, 0
mov cl, ds:[si]
jcxz zero
mov ch, al
mov es:[bx+di], cx
add di, 2
inc si
jmp char
zero: pop es
pop di
pop si
pop ax
pop bx
pop cx
ret
code ends
end start
第十一章 标志寄存器
编写一个子程序,将包含任意字符,以0结尾的字符串中的小写字母转变成大写字 母,描述如下。 名称:letterc 功能:将以0结尾的字符串中的小写字母转变成大写字母 参数:ds:si指向字符串首地址
assume cs:code
stack segment
dw 8 dup (0)
stack ends
data segment
db "Beginner's All-purpose Symbolic Instruction Code.", 0
data ends
code segment
begin: mov ax, stack
mov ss, ax
mov sp, 16
mov ax, data
mov ds, ax
mov si, 0
call letterc
mov ax, 4c00h
int 21h
letterc: push cx
push si
pushf
mov ch,0
s:mov cl,ds:[si]
jcxz ok
cmp cl,97
jb next
cmp cl,122
ja next
sub cl,20h
mov ds:[si],cl
next:inc si
jmp s
ok: popf
pop si
pop cx
ret
code ends
end begin
第十二章 内中断
1.编写0号中断的程序,使得除法溢出发生时,在屏幕中间显示字符串“divide error!",然后返回到DOS。
;编写0号中断的程序,使得除法溢出发生时,在屏幕中间显示字符串“divide error!",然后返回到DOS。
assume cs:code
code segment
start:mov ax,cs
mov ds,ax
mov si,offset do0
mov ax,0
mov es,ax
mov di,200h
mov cx,offset do0end-offset do0
cld
rep movsb
mov ax,0
mov es,ax
mov word ptr es:[0*0],200h
mov word ptr es:[0*4+2],0
mov ax,1000h
mov bh,1
div bh
mov ax,4c00h
int 21h
do0:jmp short do0start
db"divide error!"
do0start:mov ax,cs
mov ds,ax
mov si,202h
mov ax,0b800h
mov es,ax
mov di,12*160+36*2
mov cx,13
s:mov al,[si]
mov es:[di],al
inc si
add di,2
loop s
mov ax,4c00h
int 21h
do0end:nop
code ends
end start
第十三章 int指令?
-
编写并安装int 7ch中断例程,功能为显示一个用0结束的字符串,中断例程安装在0:200处。
;编写并安装int 7ch中断例程,功能为显示一个用0结束的字符串,中断例程安装在0:200处。
assume cs:code
data segment
db"welcom to maxm!",0
data ends
code segment
start: mov ax,cs
mov ds,ax
mov si,offset view
mov ax,0
mov es,ax
mov di,200h
mov cx,offset viewend-offset view
cld
rep movsb
mov ax,0
mov es,ax
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0
mov dh,10
mov dl,10
mov cl,2
mov ax,data
mov ds,ax
mov si,0
int 7ch
mov ax,4c00h
int 21h
view:push cx
push si
push ax
push es
push di
push dx
copy:mov ax,0b800h
mov es,ax
mov al,160
mov ah,0
mul dh
mov di,ax
add dl,dl
mov dh,0
add di,dx
mov al,cl
s:mov ch,0
mov cl,[si]
jcxz ok
mov ch,al
mov es:[di],cx
inc si
add di,2
loop s
ok:pop dx
pop di
pop es
pop ax
pop si
pop cx
iret
viewend:
nop
code ends
end start
?2.编写并安装int 7ch中断例程,功能为完成loop指令功能。
assume cs:code
code segment
start: mov ax, cs
mov ds, ax
mov si, offset lp
mov ax, 0
mov es, ax
mov di, 200h
mov cx, offset lpend - offset lp
cld
rep movsb
mov ax, 0
mov es, ax
mov word ptr es:[7ch * 4], 200h
mov word ptr es:[7ch * 4 + 2], 0
mov ax, 4c00h
int 21h
lp: push bp
mov bp, sp
dec cx
jcxz lpret
add [bp + 2], bx
lpret: pop bp
iret
lpend: nop
code ends
end start
3.下面的程序,分别在屏幕的第2、4、6、8行显示4句英文诗,补全程序。
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, [si]
mov dl, 0
mov ah, 2
int 10h
mov dx,[bx]
mov ah, 9
int 21h
inc si
add bx,2
loop ok
mov ax, 4c00h
int 21h
code ends
end start
第十四章 端口
编程,以”年/月/日 时:分:秒”的格式,显示当前的日期,时间。 ?
;编程,以”年/月/日 时:分:秒”的格式,显示当前的日期,时间。
assume cs:code,ds:data
data segment
s db 9,8,7,4,2,0
data ends
code segment
start:mov ax,0b800h
mov es,ax
mov di,160*12
mov ax,data
mov ds,ax
mov si,0
mov cx,6
view:mov al,s[si]
out 70h,al
in al,71h
call num
cmp si,2
jb year
je time
cmp si,5
jb kong
next:inc si
loop view
mov ax,4c00h
int 21h
num:push cx
mov ah,al
mov cl,4
shr ah,cl
and al,00001111b
add ah,30h
add al,30h
mov byte ptr es:[di],ah
mov byte ptr es:[di+2],al
add di,4
pop cx
ret
year:mov byte ptr es:[di],'/'
add di,2
jmp next
time:mov byte ptr es:[di],':'
add di,2
jmp next
kong:mov byte ptr es:[di],' '
add di,2
jmp next
code ends
end start
第十五章 外中断
安装一个新的int 9中断例程,功能:在DOS下,按下’A’键后,除非不再松开,如果松开,就显示满屏幕的’A’;其他键照常处理。
;安装一个新的int 9中断例程,功能:在DOS下,按下’A’键后,除非不再松开,如果松开,就显示满屏幕的’A’;其他键照常处理。
assume cs:code
stack segment
db 128 dup (0)
stack ends
code segment
start: mov ax, stack
mov ss, ax
mov sp, 128
push cs
pop ds
mov ax, 0
mov es, ax
mov si, offset int9
mov di, 204h
mov cx, offset int9end - offset int9
cld
rep movsb
push es: [9 * 4]
pop es: [200h]
push es: [9 * 4 + 2]
pop es: [202h]
cli
mov word ptr es: [9 * 4], 204h
mov word ptr es: [9 * 4 + 2], 0
sti
mov ax, 4c00h
int 21h
int9: push ax
push bx
push cx
push es
in al, 60h
pushf
call word ptr cs:[200h]
cmp al, 9eh
jne int9ret
mov ax, 0b800h
mov es, ax
mov bx, 0
mov cx, 2000
s: mov byte ptr es:[bx], 'A'
add bx, 2
loop s
int9ret:pop es
pop cx
pop bx
pop ax
iret
int9end:nop
code ends
end start
|