鱼C论坛

 找回密码
 立即注册
查看: 1831|回复: 0

[汇编作业] 实验16——为了节约内存,拼了。。。

[复制链接]
发表于 2015-6-9 23:26:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-27 16:29

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表