|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
在正式开始做实验16之前,我不知道0:200到0:2ff的空间够不够放得下四个子程序。
在看16.4的时候,我发现子程序2和子程序3的功能基本相同,一个是改前景色,一个是改背景色,代码也基本相同。我想,既然不能确定内存空间够不够,干脆就采用最节约的方式吧,把程序2和程序3做成一个程序
当然了,我遇到了大家初次做实验16应该都会遇到的问题,就是假如采用16.4的思路,直接定址表中的内存地址在安装之后是错的。笨人当然有笨人的策略,于是我就这样做了:
- assume cs:code
- stack segment stack
- dw 32 dup(0)
- stack ends
- code segment
- start: mov ax, cs
- mov ds, ax
- mov si, offset int7ch
-
- xor ax, ax
- mov es, ax
- mov di, 200h
-
- mov cx, offset int7chend - offset int7ch
- cld
- rep movsb
-
- cli
- mov word ptr es:[7ch * 4], 200h
- mov word ptr es:[7ch * 4 + 2], 0h
- sti
-
- mov ax, 4c00h
- int 21h
-
- int7ch: jmp short screenstart
- dw sub1 - int7ch + 200h, sub23 - int7ch + 200h, sub23 - int7ch + 200h, sub4 - int7ch + 200h
-
- screenstart:
- push bx
- cmp ah, 3
- ja quit
-
- mov bl, ah
- xor bh, bh
- add bx, bx
-
- call word ptr cs:[bx + 202h]
-
- quit: pop bx
- iret
-
- sub1: push cx
- push ds
- push si
-
- mov si, 0b800h
- mov ds, si
- mov si, 0
-
- mov cx, 4000h
- sub1s: mov byte ptr [si], 0
- add si, 2
- loop sub1s
-
- pop si
- pop ds
- pop cx
- ret
-
- ; 子程序2和3的功能类似,合并为一了
- sub23: push bx
- push cx
- push ds
- push si
-
- jmp sub23switch
- submask db 11111000b, 10001111b ; 色彩掩码
- bits db 0, 4 ; 移动位数
- sub23switch:
- mov bx, 0b800h
- mov ds, bx
- mov si, 1
-
- mov bl, ah
- xor bh, bh
- shr bx, 1 ; 这里是将1和2对应为0和1
-
- ; 假如修改背景色,al是要左移4位的
- mov cl, cs:[bits - int7ch + 200h][bx]
- shl al, cl
- mov bl, cs:[submask - int7ch + 200h][bx]
-
- mov cx, 2000h
- sub23s: and [si], bl
- or [si], al
- add si, 2
- loop sub23s
-
- pop si
- pop ds
- pop cx
- pop bx
- ret
-
- sub4: push cx
- push ds
- push es
- push si
- push di
-
- mov si, 0b800h
- mov ds, si
- mov es, si
- mov si, 80 * 2
- mov di, 0
-
- cld
- mov cx, 24
- sub4s: push cx
- mov cx, 160
- rep movsb
- pop cx
- loop sub4s
-
- mov cx, 80
- sub4s1: mov byte ptr [di], 0
- add si, 2
- loop sub4s1
-
- pop di
- pop si
- pop es
- pop ds
- pop cx
- ret
-
- int7chend:
- nop
-
- code ends
- end start
复制代码
大约可以节省15字节的空间
定址方法并不算好,只是权宜之计。假如中断程序安装的位置发生了变化,本程序需要修改的地方还是比较多的。
下面总结两种个人认为很有价值的方案:
1、将需要安装的中断程序放在主程序前面。这样的好处在于不论在安装程序中还是在安装后的中断程序中,直接定址表中保存的偏移地址是一致的,不需要像我的程序需要大量换算。此时,中断向量表中的cs和ip就不能是0和200h了,而应该是20h和0,个中妙处实在难以言喻。
2、采用ORG伪指令。依旧是主程序在前中断程序在后,但在中断程序前加ORG 200h指令,规定下面的代码从200h开始,这样一来,直接定址表就会按照200h为基准计算偏移。
以上两种方案的优势均在于思路直观,便于修改
ps:如果采用宏,我的程序也并不是很难改的,只是我还不会 :P |
|