花了几个钟头才写好一个利用直接定址表的中断处理程序

来源:互联网 发布:office办公软件难学吗 编辑:程序博客网 时间:2024/06/11 01:43

王爽《汇编语言》第十六章的实验,我做了一些改动。

 

;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:    
        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:    
        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

 

唉,做个这么简单的东西都要花这么长时间,年轻人的话估计有45分钟也就搞定调试完了。

原创粉丝点击