ASSEMBLY X86 - 如何防止Clear Flag错误? (jc命令)

时间:2017-08-20 21:36:03

标签: assembly x86 dos tasm carryflag

使用带有TASM的DOSBOX

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

我试图在屏幕上显示一张闪烁的图片,只是两张图片几乎相同,但是一张图片在第二张图片中消失,导致它以“等待”程序闪烁。

发生的问题是在16'等待'程序之后导致与进位标志相关的问题(我无法定义) 我在互联网上搜索了一下,发现当有一点达到极限时会发生一些事情(0Fh + 1 = 10h = 16) 最新发生的是在'openfile'过程中遇到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

1 个答案:

答案 0 :(得分:1)

(将我的评论转为答案,所以这个Q“正确”回答“

只是一个猜测。我看到代码中只有“open”,但没有“关闭”,所以如果你反复打开新的和新的文件,你会得到新的和新的文件句柄,直到你导致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下重新读取文件有多糟糕:);))。