- [游客] 课程设计二能做出来最好了。不过,对于以后的学习也没什么大影响。呵呵 04/29 11:19
- [sbx2000_0] 还是没有学习到家呀! 11/02 14:26
- [wushuai59] 谢谢了,这个对我帮助很大,我说我怎么老是出现问题呢,看完你的总结,我明白了。 06/02 23:13
- [游客] 你在香港!我在台灣 01/24 10:51
- [游客] 是循环数cx,嘿嘿 12/09 18:57
- [游客] 看有人用10这个乘数当循环用,挺不错的 12/09 18:57
- [happyxulingli] 对于3:其实,可以给一过内存空间,用来保护ax,cx,dx的值,就可以避免栈带来的麻烦了。 呵呵. 11/24 12:31
- [游客] 好文,顶阿~ 11/14 13:18
- [Wednesday] 收藏之,加顶一下!!! 11/09 17:33
- [Wednesday] 说得对, 可以参考 王爽《汇编语言》论坛 勘误区的帖子! 11/09 17:03
- [wubizao] 多谢bloom的提醒 我也是有些松懈了 在学习上是不能找任何理由的 现在虽然不能每天花很多时间 11/17 22:51
- [bloom] 博主,继续加油啊!行百里者半九十,越到最后越需要坚持,还有课程设计二呢,努力吧! 11/17 15:10
- [happyxulingli] 呵呵 你学的不错,挺深刻的 继续努力,我会一直支持你for ever 呵呵 我还得向你学习呢 11/09 21:22
- [playboy] 有望成为number one! 10/29 09:33
- [wubizao] 不好意思,冒得 10/23 15:02
- [lijiangwei] 哥们儿,有没有CHM的电子书啊,有的话给我发一个,824956294 10/22 16:15
[2007-11-04 19:57] 实验16--多个功能的子程序的中断例程
代码如下:
assume cs:code,ss:stack
stack segment
db 128 dup (0)
stack ends
code segment
/*程序setscreen部分*/
setscreen: jmp short set
table dw sub1,sub2,sub3,sub4;将各子程序偏移地址存在table中
set: push bx
cmp ah,3 ;比较功能号
ja sret
mov bl,ah
mov bh,0
add bx,bx ;算出相应子程序的地址入口
call word ptr table[bx];调用子程序
sret: pop bx
iret ;中断结束
/*子程序sub1,功能号0,清屏*/
sub1: push bx ;保护现场
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0
mov cx,2000
sub1s: mov byte ptr es:[bx],' ' ;传空格字符
add bx,2
loop sub1s
pop es ;恢复现场
pop cx
pop bx
ret
/*子程序sub2,功能号1,设置前景色*/
sub2: push bx ;保护现场
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,1 ;改变属性的起点
mov cx,2000
sub2s: and byte ptr es:[bx],11111000b ;前景色清0
or es:[bx],al ;al=00000***,正好or可以改变
add bx,2
loop sub2s
pop es ;恢复现场
pop cx
pop bx
ret
/*子程序3,功能号2,改变背景色*/
sub3: push bx ;保护现场
push cx
push es
mov cl,4 ;原al=00000***
shl al,cl ;将al左移4位,变为0***0000
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
sub3s: and byte ptr es:[bx],10001111b
or es:[bx],al ;改变背景色
add bx,2
loop sub3s
pop es ;恢复现场
pop cx
pop bx
ret
/*子程序4,功能号3,向上移动*/
sub4: push cx ;保护现场
push si
push di
push es
push ds
mov si,0b800h
mov es,si
mov ds,si
mov si,160 ;设置n+1行
mov di,0 ;设置n行
cld ;方向
mov cx,24
sub4s: push cx
mov cx,160
rep movsb ;把n+1行的数据传给n行
pop cx
loop sub4s
mov cx,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
mov ax,4c00h
int 21h
setscreenend: nop ;至此新中断int 7ch结束
/*安装程序开始*/
start: mov ax,cs
mov ds,ax
mov si,offset setscreen ;设置si
mov ax,0
mov es,ax
mov di,200h ;设置di
mov cx,offset setscreenend-offset setscreen;设置复制int 7ch的长度
cld
rep movsb
mov ax,0
mov es,ax
mov word ptr es:[7ch*4],0 ;设置中断向量表
mov word ptr es:[7ch*4+2],0020h
mov ah,3 ;测试功能
mov al,5
int 7ch ;调用int 7ch
mov ax,4c00h
int 21h
code ends
end start
分析:
在本次实验中需要注意一些问题
我想前提至少要把书上给出的各个子程序的写法看懂
1.关于安装程序
关键就在设置中断向量表这快,以前的做法通常是
设置cs=0,ip=0200h
可是到了本实验问题就很大,如若这样,debug时候会错误
因为在题目中
setscreen: jmp short set
table dw sub1,sub2,sub3,sub4
set: push bx
............
call word ptr table[bx]
table[bx]=所在段地址:[偏移地址+bx]
如果设置cs=0,ip=0200h
安装成功后
那么table[bx]=0000:[偏移地址+bx]
就有可能会指向错误的地方,并未调用你所想调用的sub
所以应该设置成cs=0020h,ip=0000h
2.新的int 7ch在安装程序中的位置
我在程序中是这样的:
assume cs:code,ss:stack
stack segment
db 128 dup (0)
stack ends
code segment
setscreen: jmp short set ;本指令2个字节
table dw sub1,sub2,sub3,sub4
set: push bx
.........
call word ptr table[bx]
我是把setscreen放在code的最前面
为什么?
因为我一开始放在后面遇到了困难
其实还是标号table惹的祸!
在1中,我说table[bx]=所在段地址:[偏移地址+bx]
关键就在这个偏移地址上
在安装程序中,这个偏移地址是相对安装程序而言的
setscreen: jmp short set ;本指令2个字节
所以如果安装在code的后面,在start的前面
那么其实call word ptr table[bx]=call [bx+0002h]
现在需要考虑的是安装到0020:0000后会成功调用sub吗?
那就要看能不能取到sub1,sub2,sub3,sub4的地址
安装好后,其实这个call word ptr table[bx]=call [bx+0002h]
中的0002h也被"安装"了,这样在执行call指令的时候,会正确的调用sub子程序
我的错误:一开始把int 7ch写在安装程序start的后面
结果安装好后,查看
call word ptr table[bx]=call [bx+0033h]
根本不可能调用正确的sub地址!
所以说我们应该注意的是相对的逻辑地址要正确,这样才能保证程序功能的实现
assume cs:code,ss:stack
stack segment
db 128 dup (0)
stack ends
code segment
/*程序setscreen部分*/
setscreen: jmp short set
table dw sub1,sub2,sub3,sub4;将各子程序偏移地址存在table中
set: push bx
cmp ah,3 ;比较功能号
ja sret
mov bl,ah
mov bh,0
add bx,bx ;算出相应子程序的地址入口
call word ptr table[bx];调用子程序
sret: pop bx
iret ;中断结束
/*子程序sub1,功能号0,清屏*/
sub1: push bx ;保护现场
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0
mov cx,2000
sub1s: mov byte ptr es:[bx],' ' ;传空格字符
add bx,2
loop sub1s
pop es ;恢复现场
pop cx
pop bx
ret
/*子程序sub2,功能号1,设置前景色*/
sub2: push bx ;保护现场
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,1 ;改变属性的起点
mov cx,2000
sub2s: and byte ptr es:[bx],11111000b ;前景色清0
or es:[bx],al ;al=00000***,正好or可以改变
add bx,2
loop sub2s
pop es ;恢复现场
pop cx
pop bx
ret
/*子程序3,功能号2,改变背景色*/
sub3: push bx ;保护现场
push cx
push es
mov cl,4 ;原al=00000***
shl al,cl ;将al左移4位,变为0***0000
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
sub3s: and byte ptr es:[bx],10001111b
or es:[bx],al ;改变背景色
add bx,2
loop sub3s
pop es ;恢复现场
pop cx
pop bx
ret
/*子程序4,功能号3,向上移动*/
sub4: push cx ;保护现场
push si
push di
push es
push ds
mov si,0b800h
mov es,si
mov ds,si
mov si,160 ;设置n+1行
mov di,0 ;设置n行
cld ;方向
mov cx,24
sub4s: push cx
mov cx,160
rep movsb ;把n+1行的数据传给n行
pop cx
loop sub4s
mov cx,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
mov ax,4c00h
int 21h
setscreenend: nop ;至此新中断int 7ch结束
/*安装程序开始*/
start: mov ax,cs
mov ds,ax
mov si,offset setscreen ;设置si
mov ax,0
mov es,ax
mov di,200h ;设置di
mov cx,offset setscreenend-offset setscreen;设置复制int 7ch的长度
cld
rep movsb
mov ax,0
mov es,ax
mov word ptr es:[7ch*4],0 ;设置中断向量表
mov word ptr es:[7ch*4+2],0020h
mov ah,3 ;测试功能
mov al,5
int 7ch ;调用int 7ch
mov ax,4c00h
int 21h
code ends
end start
分析:
在本次实验中需要注意一些问题
我想前提至少要把书上给出的各个子程序的写法看懂
1.关于安装程序
关键就在设置中断向量表这快,以前的做法通常是
设置cs=0,ip=0200h
可是到了本实验问题就很大,如若这样,debug时候会错误
因为在题目中
setscreen: jmp short set
table dw sub1,sub2,sub3,sub4
set: push bx
............
call word ptr table[bx]
table[bx]=所在段地址:[偏移地址+bx]
如果设置cs=0,ip=0200h
安装成功后
那么table[bx]=0000:[偏移地址+bx]
就有可能会指向错误的地方,并未调用你所想调用的sub
所以应该设置成cs=0020h,ip=0000h
2.新的int 7ch在安装程序中的位置
我在程序中是这样的:
assume cs:code,ss:stack
stack segment
db 128 dup (0)
stack ends
code segment
setscreen: jmp short set ;本指令2个字节
table dw sub1,sub2,sub3,sub4
set: push bx
.........
call word ptr table[bx]
我是把setscreen放在code的最前面
为什么?
因为我一开始放在后面遇到了困难
其实还是标号table惹的祸!
在1中,我说table[bx]=所在段地址:[偏移地址+bx]
关键就在这个偏移地址上
在安装程序中,这个偏移地址是相对安装程序而言的
setscreen: jmp short set ;本指令2个字节
所以如果安装在code的后面,在start的前面
那么其实call word ptr table[bx]=call [bx+0002h]
现在需要考虑的是安装到0020:0000后会成功调用sub吗?
那就要看能不能取到sub1,sub2,sub3,sub4的地址
安装好后,其实这个call word ptr table[bx]=call [bx+0002h]
中的0002h也被"安装"了,这样在执行call指令的时候,会正确的调用sub子程序
我的错误:一开始把int 7ch写在安装程序start的后面
结果安装好后,查看
call word ptr table[bx]=call [bx+0033h]
根本不可能调用正确的sub地址!
所以说我们应该注意的是相对的逻辑地址要正确,这样才能保证程序功能的实现
评论次数(3) |
浏览次数(3221) |
类型(汇编作业) |
收藏此文 |