DosBox 有 int 15h ah = 86h 的错误
DosBox is buggy with int 15h ah = 86h
我目前正在编写一个汇编程序,但我需要让程序每隔一段时间等待一次。
所以,我一直在使用 int 15h/ah = 86h,但出于某种原因,DosBox 给我带来了困难,程序要么与像素(奇怪的颜色)混淆,要么在更糟糕的情况下;崩溃。
有人可以帮我吗?
用其他东西替换 int 15h
,例如等待 "n" 秒的过程:
.stack 100h
.data.
text db 'text$'
seconds db 99
delay db ? ;HOW MANY SECONDS TO WAIT.
.code
mov ax, @data
mov ds, ax ;INITIALIZE DATA SEGMENT.
forever:
mov delay, 5 ;DELAY 5 SECONDS.
call my_delay ;◄■■ CALL PROCEDURE HERE.
;DISPLAY TEXT EVERY 5 SECONDS.
mov ah, 9
mov dx, offset text
int 21h
jmp forever
mov ax, 4c00h
int 21h ;FINISH PROGRAM.
;--------------------------------------------------------
;PROCEDURE TO WAIT "N" SECONDS.
;SECONDS ENTER IN VARIABLE "DELAY".
;VARIABLE "SECONDS" MUST EXIST. USED AS LOCAL COUNTER.
my_delay proc
delaying:
;GET SYSTEM TIME.
mov ah, 2ch
int 21h ;RETURN SECONDS IN DH.
;CHECK IF ONE SECOND HAS PASSED.
cmp dh, seconds
je delaying
;IF NO JUMP, ONE SECOND HAS PASSED. VERY IMPORTANT : PRESERVE
;SECONDS TO USE THEM TO COMPARE WITH NEXT SECONDS. THIS IS HOW
;WE KNOW ONE SECOND HAS PASSED.
mov seconds, dh
dec delay
jnz delaying ;IF DELAY IS NOT ZERO, REPEAT.
ret
my_delay endp
我也有这个问题。根据 Problems with BIOS delay function (INT 15h / AH = 86h) 的回答,我能够通过确保在调用中断之前将 AL 设置为零来使其工作:
mov counter, 10
L1:
mov cx, 0007H
mov dx, 8480H
mov ah, 86h
mov al, 0
int 15h
mov dl, '*'
mov ah, 02h
int 21h
dec counter
jnz L1
(程序打印 10 个 *,每个之间暂停 1 秒。)如果没有 'mov al, 0',程序将挂起或出现其他未定义的行为,而 DOSBox 会发出非法的 read/write 消息.通过将 al 设置为零,程序可以正常运行,但奇怪的是,错误消息仍然出现在 DOSBox 日志中。
这是 DOSBox 0.74.3 版中的错误。他们的 int 15h
处理程序函数的 switch
中缺少 break
,因此 ah=86h
处理程序落入 ah=87h
, Copy Extended Memory which copies memory around from some random addresses. See bios.cpp
around line 663-681。 (如果他们打开 -Wextra
他们会收到编译器警告!)
这似乎是 fixed in trunk back in 2011,但我猜不知何故从未将其发布。
我已提交 bug #548 报告。
ah=87h
要复制的区域由cx
中的计数和es:si
指向的描述符table中的地址指定。如果这些地址超出范围,您应该只会收到 Illegal read/write
警告,而不会出现其他有害行为,但如果它们恰好指向实际内存,则可能会覆盖一些重要的内容。我怀疑在 OP 的测试中目的地恰好指向视频内存,解释了“奇怪的颜色”
同理,如果cx = 0
则什么都没有复制,bug也不会出现。这证明了 rkhb 已删除答案中的解决方法,即在循环中执行小于 65 毫秒的延迟。
我目前正在编写一个汇编程序,但我需要让程序每隔一段时间等待一次。
所以,我一直在使用 int 15h/ah = 86h,但出于某种原因,DosBox 给我带来了困难,程序要么与像素(奇怪的颜色)混淆,要么在更糟糕的情况下;崩溃。
有人可以帮我吗?
用其他东西替换 int 15h
,例如等待 "n" 秒的过程:
.stack 100h
.data.
text db 'text$'
seconds db 99
delay db ? ;HOW MANY SECONDS TO WAIT.
.code
mov ax, @data
mov ds, ax ;INITIALIZE DATA SEGMENT.
forever:
mov delay, 5 ;DELAY 5 SECONDS.
call my_delay ;◄■■ CALL PROCEDURE HERE.
;DISPLAY TEXT EVERY 5 SECONDS.
mov ah, 9
mov dx, offset text
int 21h
jmp forever
mov ax, 4c00h
int 21h ;FINISH PROGRAM.
;--------------------------------------------------------
;PROCEDURE TO WAIT "N" SECONDS.
;SECONDS ENTER IN VARIABLE "DELAY".
;VARIABLE "SECONDS" MUST EXIST. USED AS LOCAL COUNTER.
my_delay proc
delaying:
;GET SYSTEM TIME.
mov ah, 2ch
int 21h ;RETURN SECONDS IN DH.
;CHECK IF ONE SECOND HAS PASSED.
cmp dh, seconds
je delaying
;IF NO JUMP, ONE SECOND HAS PASSED. VERY IMPORTANT : PRESERVE
;SECONDS TO USE THEM TO COMPARE WITH NEXT SECONDS. THIS IS HOW
;WE KNOW ONE SECOND HAS PASSED.
mov seconds, dh
dec delay
jnz delaying ;IF DELAY IS NOT ZERO, REPEAT.
ret
my_delay endp
我也有这个问题。根据 Problems with BIOS delay function (INT 15h / AH = 86h) 的回答,我能够通过确保在调用中断之前将 AL 设置为零来使其工作:
mov counter, 10
L1:
mov cx, 0007H
mov dx, 8480H
mov ah, 86h
mov al, 0
int 15h
mov dl, '*'
mov ah, 02h
int 21h
dec counter
jnz L1
(程序打印 10 个 *,每个之间暂停 1 秒。)如果没有 'mov al, 0',程序将挂起或出现其他未定义的行为,而 DOSBox 会发出非法的 read/write 消息.通过将 al 设置为零,程序可以正常运行,但奇怪的是,错误消息仍然出现在 DOSBox 日志中。
这是 DOSBox 0.74.3 版中的错误。他们的 int 15h
处理程序函数的 switch
中缺少 break
,因此 ah=86h
处理程序落入 ah=87h
, Copy Extended Memory which copies memory around from some random addresses. See bios.cpp
around line 663-681。 (如果他们打开 -Wextra
他们会收到编译器警告!)
这似乎是 fixed in trunk back in 2011,但我猜不知何故从未将其发布。
我已提交 bug #548 报告。
ah=87h
要复制的区域由cx
中的计数和es:si
指向的描述符table中的地址指定。如果这些地址超出范围,您应该只会收到 Illegal read/write
警告,而不会出现其他有害行为,但如果它们恰好指向实际内存,则可能会覆盖一些重要的内容。我怀疑在 OP 的测试中目的地恰好指向视频内存,解释了“奇怪的颜色”
同理,如果cx = 0
则什么都没有复制,bug也不会出现。这证明了 rkhb 已删除答案中的解决方法,即在循环中执行小于 65 毫秒的延迟。