1

将 DOSBOX 与 TASM 一起使用

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

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

发生的问题是在 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
4

1 回答 1

1

(把我的评论变成答案,所以这个 Q 得到了正确的“回答”)

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

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

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

当你int 21h, 3D用来打开文件时,你应该int 21h, 3E用来关闭它们。

所以第一个快速修复是创建“closeFile”过程并在加载一个图像后调用它。

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

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

于 2017-08-21T09:10:45.660 回答