|
主题 : : 实验16的事情——无法通过测试就是错的? [待解决] |
回复[ 2次 ]
点击[ 709次 ] | |
|
|
|
|
[帖 主]
[ 发表时间:2009-10-12 08:21 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-10-05 23:09 |
下面是我的实验16的程序。我测试的环境是用虚拟机VPC2007版所模拟的一个实模式DOS系统。这个中断安装例程是可以执行的。但是,我又写了一个对新安装的int 7c例程进行测试的小程序,发现无法通过测试,不是CPU Error:opcode incorrect,就是突然死机。这个情况连续困扰我几个小时。我用debug不断地调试,直到确信我的两个程序在逻辑上是正确的,寻址也没有出错。我开始怀疑我的测试环境有问题。有好几次报错都提示是一个叫emm386.exe的程序检测到的。于是我试着重新在虚拟机内装一个DOS,这一次不装载EMM386和UMB内存管理程序。装完后重新测试我的中断例程,发现完全正常。有时候不一定是程序的错,很可能是你的测试环境出了问题。这是我花了几个小时的时间买到的一个教训,希望对遇到过类似问题的同学们能够有帮助。
************************************************************************************
;实验16 编写包含多个功能子程序的中断例程
;安装一个新的int 7ch中断例程,为显示输出提供如下功能子程序。
;(1) 清屏;
;(2) 设置前景色;
;(3) 设置背景色;
;(4) 向上滚动一行。
;入口参数说明如下:
;(1)用ah寄存器传递功能号:0表示清屏,1表示设置前景色,2表示设置背景色,3表示向上滚动一行。
;(2)对于2、3号功能,用al传送颜色值,(al)∈{0,1,2,3,4,5,6,7} 。
assume cs:code,ss:stack
stack segment
db 128 dup(0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,128
mov ax,code
mov ds,ax
mov si,offset setscreen
mov ax,0
mov es,ax
mov di,200h
mov cx,offset setscreenend-offset setscreen
cld
rep movsb
cli
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0
sti
mov ax,4c00h
int 21h
;===========================以下为新7ch中断=============================================
setscreen:
jmp short set
dw sub1-setscreen,sub2-setscreen,sub3-setscreen,sub4-setscreen
set:
push bx
cmp ah,3 ;判断功能号是否大于3
ja sret
mov bl,ah
mov bh,0
add bx,bx ;根据ah中的功能号计算对应子程序在table表中的偏移
push cs
pop ds
add word ptr [bx+202h],200h
call word ptr [bx+202h] ;调用对应的功能子程序
sret:
pop bx
iret
;入口址:sub1
;功能:清屏。一屏有25行X80个字符(2B/字节)=2000个字符(4000B)。
;字符存于偶字节处(0,2,4,6,8...),颜色属性存于奇字节处(1,3,5,7,9...)。
;技巧:清屏的技巧就是把显示缓冲区中当前屏的2000个字符(即所有偶字节上的数据)全部替换为空格符。
;作为一个子程序,必须做好寄存器的保护和恢复工作。一个替代性的办法就是使用BIOS的int 10h中断和
;DOS的int 21h中断例程。但这个办法的缺点是需要使用一块大小为2000个字节的缓冲区。它的空间开销
;增大了。
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
;功能:设置前景色
;前景色属性在奇字节处
;技巧:前景色的属性值是由al传送的。但在传送之前必须将原来的前景色属性值置为0,否则达不到预期目的。
;这不像寄存器赋值。寄存器赋值是自动以新值代替旧值的。颜色属性值是以位的形式存在的,因此必须使用逻辑位操作
;来清除原来的属性值,再赋予新的属性值。颜色属性赋值是以or罗辑指令加上新值的,旧值如果不用and指令清除掉的
;话,结果的属性值会是新值加上旧值的一个和,而不是纯粹的新值。
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 ;闪烁,高亮,红+蓝+绿
or es:[bx],al
add bx,2
loop sub2s
pop es
pop cx
pop bx
ret
;入口址:sub3
;功能:设置背景色。
;参数:al传送颜色值,左移4位,设置背景色。
;技巧:同上。不同之处在于前景色是对所有奇字节上的数据的第0、1、2位的值进行替换;
;而背景色的赋值是对所有奇字节上的数据的第4、5、6位的值进行替换。所以要将al的值
;左移4位,与目的数据的比特位置相符。
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
or es:[bx],al
add bx,2
loop sub3s
pop es
pop cx
pop bx
ret
;入口址:sub4
;功能:向前滚动一行。
;参数:
sub4:
push cx
push si
push di
push es
push ds
mov si,0b800h
mov es,si
mov ds,si
mov si,160 ;ds:si指向n+1行
mov di,0 ;es:di指向第n行
cld
mov cx,24 ;共复制24行
sub4s:
push cx
mov cx,160
rep movsb ;si,di在这一句执行完成后,各递增160;每次递增1,循环160次共递增160.
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
setscreenend:nop
code ends
end start | | |
|
|
|
|
[第1楼]
[ 回复时间:2010-03-12 10:02 ]
[引用]
[回复]
[ top ] | |
荣誉值:6
信誉值:0
注册日期:2009-12-18 19:53 |
dw sub1-setscreen,sub2-setscreen,sub3-setscreen,sub4-setscreen 这一段有意思
我也是考虑了一晚上,才想到这点,开始都糊涂了 | | |
|
|
|
|
[第2楼]
[ 回复时间:2012-03-09 13:21 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2012-01-05 18:58 |
dw sub1-setscreen,sub2-setscreen,sub3-setscreen,sub4-setscreen 这一段有意思
我也是考虑了一晚上,才想到这点,开始都糊涂了
------------------
回复:这一段是什么意思 求赐教,我各种想不通。。。sub1和setscreen标号的位置都是相对起始偏移量,相减应该是中箭代码长度 怎么会是偏移地址呢。 | | |
|