装配 X86 - 如何防止清除标志错误?(JC 命令)



使用 DOSBOX 和 TASM

首先,我想为难以理解的标题感到抱歉,我真的不知道如何称呼它,因为我自己无法定义问题,这就是我需要帮助的原因。

我试图在屏幕上显示一张闪烁的图片,只有 2 张几乎相同的图片,但一个对象在第二张图片中消失,导致它通过"等待"程序闪烁。

出现的问题是在 16 个"等待"程序之后,某些东西导致了与携带标志相关的问题(我无法定义( 我在互联网上搜索了一下,发现当一个位达到其极限时会发生一些事情(0Fh + 1 = 10h = 16( 发生的情况是在"打开文件"过程中遇到JC并显示错误消息。 我发布这个是因为我真的不明白这里的解决方案是什么,甚至无法解决什么

IDEAL
MODEL small
STACK 100h
DATASEG
; --------------------------
; Variables:
imgwelcome1 db 'welcome1.bmp',0
imgwelcome2 db 'welcome2.bmp',0
filename db 'test.bmp',0
filehandle dw 1
Header db 54 dup (0)
Palette db 256*4 dup (0)
ScrLine db 320 dup (0)
ErrorMsg db 'Error', 13, 10,'$'
counter db 0
; --------------------------
CODESEG
; --------------------------
; Procedures:
proc OpenFile1
mov ah, 3Dh
xor al, al
mov dx, offset imgwelcome1
int 21h
jc openerror1
mov [filehandle], ax
ret
openerror1:
mov dx, offset ErrorMsg
mov ah, 9h
int 21h
ret
endp
proc OpenFile2
mov ah, 3Dh
xor al, al
mov dx, offset imgwelcome2
int 21h
jc openerror2
mov [filehandle], ax
ret
openerror2:
mov dx, offset ErrorMsg
mov ah, 9h
int 21h
ret
endp
proc ReadHeader
mov ah,3fh
mov bx, [filehandle]
mov cx,54
mov dx, offset Header
int 21h
ret
endp ReadHeader
proc ReadPalette
mov ah,3fh
mov cx,400h
mov dx,offset Palette
int 21h
ret
endp
proc CopyPal
mov si, offset Palette
mov cx,256
mov dx,3C8h
mov al,0
out dx,al
inc dx
PalLoop:
mov al,[si+2] ; Get red value.
shr al,2 ; Max. is 255, but video palette maximal
out dx,al ; Send it.
mov al,[si+1] ; Get green value.
shr al,2
out dx,al ; Send it.
mov al,[si] ; Get blue value.
shr al,2
out dx,al ; Send it.
add si,4 ; Point to next color.
loop PalLoop
ret
endp
proc CopyBitmap
mov ax, 0A000h
mov es, ax
mov cx,200
PrintBMPLoop:
push cx
mov di,cx
shl cx,6
shl di,8
add di,cx
mov ah,3fh
mov cx,320
mov dx,offset ScrLine
int 21h
cld 
mov cx,320
mov si,offset ScrLine
rep movsb 
pop cx
loop PrintBMPLoop
ret
endp
proc time
push ax
push cx
push dx
mov cx, 0001h
mov dx, 9999h
mov ah, 86h
int 15h 
pop dx
pop cx
pop ax
ret
endp
; --------------------------
start:
mov ax, @data
mov ds, ax
; --------------------------
; Code:
mov ax, 13h
int 10h
again:
mov ah, 01h
int 16h
jnz skip
call OpenFile1
call ReadHeader
call ReadPalette
call CopyPal
call CopyBitmap
call time
call OpenFile2
call ReadHeader
call ReadPalette
call CopyPal
call CopyBitmap
call time
inc counter
jmp again
skip:
mov ax, 03h
int 10h
; --------------------------
exit:
mov ax, 4c00h
int 21h
END start

(将我的评论变成答案,因此此Q被正确"回答"(

只是一个猜测。我在代码中只看到"打开",但没有看到"关闭",所以如果你反复打开新文件和新文件,你会得到新的和新的文件句柄,直到你导致DOS内部的文件句柄不足,然后下一次打开失败。

您可以只打开这两个文件一次,并保持句柄存储(并在下次重新读取图像之前将文件指针重置为 0 偏移量(,也可以尝试在每次读取后关闭文件,以验证这是问题的原因(写入关闭比修复代码以仅打开文件一次(。

您仍然应该在以任何方式退出之前关闭所有打开的文件,即使您更改整个代码以保持两个文件始终打开,然后重新读取它们(尽管现代DOS和dosbox将在您通过4Ch服务正确退出时恢复,并在您之后清理,IIRC(。

使用int 21h, 3D打开文件时,应使用int 21h, 3E关闭文件。

因此,第一个快速修复方法是创建"closeFile"过程并在加载一个图像后调用它。

更高级的修复将涉及在开始时打开两个文件,存储两个句柄,并通过每次通过int 21h, 42将文件指针重置为零来重新读取它们,而无需再次打开它们。然后在退出前关闭它们一次。

更高级的修复方法是分配更多内存(如果可用内存(,首先将两个图像加载到可用内存中,关闭文件,然后仅从内存中已解码的图像进行动画处理,而无需任何文件读取(如果您感到无聊并想尝试将原始代码推向新的方向,这只是一个建议。由于它看起来像一些"欢迎"消息,因此每次重新读取文件实际上都可以,如果您从软盘运行它,那么在原始PC上只会非常嘈杂和缓慢。如果你在dosbox下测试,也许你可以试试MOUNT A <your dir with executable> -t floppy,我认为它可以模拟软盘速度,但我不确定,从来没有那样使用dosbox......仍然没有来自驱动器本身的实际*痛苦的声音*,很难解释您,每次在DOS中重新读取文件是多么糟糕:) ;)(。

最新更新