王爽《汇编语言》第十六章的实验,我做了一些改动。
;
21
:
02
2007
-
7
-
5
assume cs:codesg
datasg segment
endl EQU < 0dh,0ah >
function0 db endl, " This Int 7ch function is:$ "
function1 db endl, " (1) Cls $ "
function2 db endl, " (2) Set FrontColor$ "
function3 db endl, " (3) Set BackColor$ "
function4 db endl, " (4) Scroll Up$ "
function5 db endl, " (5) Exit$ "
inputf db endl,endl, " Please Input function number:$ "
inputc db endl,endl, " Please Input color(0-8):$ "
errors db endl,endl, " Input Error!Please Input the number(1-5),color(0-8) " ,endl,endl, ' $ '
datasg ends
stack segment
dw 16 dup ( 0 )
stack ends
codesg segment
start:
mov ax,stack
mov ss,ax
mov sp, 32
mov ax,datasg
mov ds,ax
; /**/ ///
;安装int 7ch中断处理程序
mov ax, 0
mov es,ax
cli
mov word ptr es:[7ch * 4 ],offset setscreen
mov es:[7ch * 4 + 2 ],cs
sti
; /**/
int 7ch
mov ax,4c00h
int 21h
; /**/
; int 7ch中断处理程序代码
setscreen:
jmp short showfc
table:
dw 0 ,sub1,sub2,sub3,sub4 ;直接定值表,第一个0为补充地址,使得输入1调用sub1。
showfc:
push ax
push dx
push bx
push cx
;显示功能提示
showfc1:
mov ah, 9 ; int 21h 9号功能为在标准输出上显示以$结尾的字符串,DS:DX指向字符串偏移地址。
mov dx,offset function0
int 21h
mov dx,offset function1
int 21h
mov dx,offset function2
int 21h
mov dx,offset function3
int 21h
mov dx,offset function4
int 21h
mov dx,offset function5
int 21h
mov dx,offset inputf
int 21h
;提示输入功能号码
inputfc:
mov ah, 1
int 21h ; int 21h 1号功能为从标准输入(键盘)读取一个字符的ASCII码到al,无输入时等
;待,回显输入字符。
sub al,30h ;输入数字ASCII码减30h转换为十进制值。
mov bh,al
cmp bh, 5 ;范围判断
ja error
cmp bh, 5 ;5号功能为退出。
je sret
cmp bh, 0 ;范围判断
jb error
cmp bh, 2 ;如果是2 3号功能则提示输入颜色值。
je inputcolor
cmp bh, 3
je inputcolor
jmp short set
inputcolor:
mov ah, 9
mov dx,offset inputc
int 21h
mov ah, 1
int 21h
sub al,30h
cmp al, 8 ;范围判断
ja error
cmp al, 0
jb error ;范围判断
set :
assume cs:codesg
datasg segment
endl EQU < 0dh,0ah >
function0 db endl, " This Int 7ch function is:$ "
function1 db endl, " (1) Cls $ "
function2 db endl, " (2) Set FrontColor$ "
function3 db endl, " (3) Set BackColor$ "
function4 db endl, " (4) Scroll Up$ "
function5 db endl, " (5) Exit$ "
inputf db endl,endl, " Please Input function number:$ "
inputc db endl,endl, " Please Input color(0-8):$ "
errors db endl,endl, " Input Error!Please Input the number(1-5),color(0-8) " ,endl,endl, ' $ '
datasg ends
stack segment
dw 16 dup ( 0 )
stack ends
codesg segment
start:
mov ax,stack
mov ss,ax
mov sp, 32
mov ax,datasg
mov ds,ax
; /**/ ///
;安装int 7ch中断处理程序
mov ax, 0
mov es,ax
cli
mov word ptr es:[7ch * 4 ],offset setscreen
mov es:[7ch * 4 + 2 ],cs
sti
; /**/
int 7ch
mov ax,4c00h
int 21h
; /**/
; int 7ch中断处理程序代码
setscreen:
jmp short showfc
table:
dw 0 ,sub1,sub2,sub3,sub4 ;直接定值表,第一个0为补充地址,使得输入1调用sub1。
showfc:
push ax
push dx
push bx
push cx
;显示功能提示
showfc1:
mov ah, 9 ; int 21h 9号功能为在标准输出上显示以$结尾的字符串,DS:DX指向字符串偏移地址。
mov dx,offset function0
int 21h
mov dx,offset function1
int 21h
mov dx,offset function2
int 21h
mov dx,offset function3
int 21h
mov dx,offset function4
int 21h
mov dx,offset function5
int 21h
mov dx,offset inputf
int 21h
;提示输入功能号码
inputfc:
mov ah, 1
int 21h ; int 21h 1号功能为从标准输入(键盘)读取一个字符的ASCII码到al,无输入时等
;待,回显输入字符。
sub al,30h ;输入数字ASCII码减30h转换为十进制值。
mov bh,al
cmp bh, 5 ;范围判断
ja error
cmp bh, 5 ;5号功能为退出。
je sret
cmp bh, 0 ;范围判断
jb error
cmp bh, 2 ;如果是2 3号功能则提示输入颜色值。
je inputcolor
cmp bh, 3
je inputcolor
jmp short set
inputcolor:
mov ah, 9
mov dx,offset inputc
int 21h
mov ah, 1
int 21h
sub al,30h
cmp al, 8 ;范围判断
ja error
cmp al, 0
jb error ;范围判断
set :
mov ah,bh
mov bl,ah
mov bh, 0
add bx,bx ;根据输入的功能号码来确定TABLE中子程序的偏移地址。
call word ptr table[bx] ;调用子程序
jmp short showfc1 ;功能循环
sret:
pop cx
pop bx
pop dx
pop ax
iret
error:
mov bl,ah
mov bh, 0
add bx,bx ;根据输入的功能号码来确定TABLE中子程序的偏移地址。
call word ptr table[bx] ;调用子程序
jmp short showfc1 ;功能循环
sret:
pop cx
pop bx
pop dx
pop ax
iret
error:
call sub1
mov ah, 9
mov dx,offset errors
int 21h
jmp short showfc1
sub1:
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx, 0 ;显存偶数地址为字符。
mov cx, 2000 ;显存一页4000字节,偶数字节为2000个。
sub1s:
mov byte ptr es:[bx], ' ' ;用空格代替原先字符,相当于清除原字符。
add bx, 2
loop sub1s
pop es
pop cx
pop bx
ret
sub2:
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx, 1 ;显存奇数地址为颜色值。
mov cx, 2000 ;显存一页4000字节,奇数字节为2000个。
sub2s:
and byte ptr es:[bx],11111000b ;颜色值中0 1 2位为前景色RGB,先清除掉。
or es:[bx],al ;再or上我们输入的al值,则得到我们需要的前景色。
add bx, 2
loop sub2s
pop es
pop cx
pop bx
ret
sub3:
push bx
push cx
push es
mov cl, 4
shl al,cl
mov bx,0b800h
mov es,bx
mov bx, 1
mov cx, 2000
sub3s:
and byte ptr es:[bx],10001111b ;颜色值中7 6 5位为背景色RGB。
or es:[bx],al
add bx, 2
loop sub3s
pop es
pop cx
pop bx
ret
sub4:
push cx
push si
push di
push es
push ds
mov si,0b800h
mov es,si
mov ds,si
mov si, 160 ;显存一页25行( 0 - 24 ),160列( 0 - 159 ),这里的160为下一行开头的第一列。
mov di, 0 ;上一行开头。SI,DI顺序递增~
cld
mov cx, 24 ;只需要复制后面的24行,开头第一行不要了。
sub4s:
push cx
mov cx, 160 ;列数还是要够160的,这里是循环次数,注意和上面的区别。
rep movsb
pop cx
loop sub4s
mov cx, 80 ;一行160列,偶数列为80,偶数列也即是字符所在列。
mov si, 0
sub4s1:
mov byte ptr [ 160 * 24 + si], ' ' ;最后一行上移了,原来行的字符要清除掉。
add si, 2
loop sub4s1
pop ds
pop es
pop di
pop si
pop cx
ret
codesg ends
end start
mov ah, 9
mov dx,offset errors
int 21h
jmp short showfc1
sub1:
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx, 0 ;显存偶数地址为字符。
mov cx, 2000 ;显存一页4000字节,偶数字节为2000个。
sub1s:
mov byte ptr es:[bx], ' ' ;用空格代替原先字符,相当于清除原字符。
add bx, 2
loop sub1s
pop es
pop cx
pop bx
ret
sub2:
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx, 1 ;显存奇数地址为颜色值。
mov cx, 2000 ;显存一页4000字节,奇数字节为2000个。
sub2s:
and byte ptr es:[bx],11111000b ;颜色值中0 1 2位为前景色RGB,先清除掉。
or es:[bx],al ;再or上我们输入的al值,则得到我们需要的前景色。
add bx, 2
loop sub2s
pop es
pop cx
pop bx
ret
sub3:
push bx
push cx
push es
mov cl, 4
shl al,cl
mov bx,0b800h
mov es,bx
mov bx, 1
mov cx, 2000
sub3s:
and byte ptr es:[bx],10001111b ;颜色值中7 6 5位为背景色RGB。
or es:[bx],al
add bx, 2
loop sub3s
pop es
pop cx
pop bx
ret
sub4:
push cx
push si
push di
push es
push ds
mov si,0b800h
mov es,si
mov ds,si
mov si, 160 ;显存一页25行( 0 - 24 ),160列( 0 - 159 ),这里的160为下一行开头的第一列。
mov di, 0 ;上一行开头。SI,DI顺序递增~
cld
mov cx, 24 ;只需要复制后面的24行,开头第一行不要了。
sub4s:
push cx
mov cx, 160 ;列数还是要够160的,这里是循环次数,注意和上面的区别。
rep movsb
pop cx
loop sub4s
mov cx, 80 ;一行160列,偶数列为80,偶数列也即是字符所在列。
mov si, 0
sub4s1:
mov byte ptr [ 160 * 24 + si], ' ' ;最后一行上移了,原来行的字符要清除掉。
add si, 2
loop sub4s1
pop ds
pop es
pop di
pop si
pop cx
ret
codesg ends
end start
唉,做个这么简单的东西都要花这么长时间,年轻人的话估计有45分钟也就搞定调试完了。