6

I am currently working on an assembly program, but I need to make the program wait every once in a while.

So, I have been using int 15h/ah = 86h, but for some reason DosBox is giving me a hard time, and the program either gets confused with pixels (wierd colors) or in the worse case; crash.

Can someone please help me?

elyking2001
  • 113
  • 9
  • Are you **preserving** registers before the delay and **restoring** them right after? – Jose Manuel Abarca Rodríguez Apr 03 '17 at 22:10
  • Maybe [Ralph Brown's interrupt list](http://www.ctyme.com/intr/rb-1526.htm) can help you on this issue. – zx485 Apr 04 '17 at 00:20
  • 1
    I believe this function is buggy in DOSBox. – Ross Ridge Apr 04 '17 at 03:06
  • I can't reproduce any weird behaviour on DOSBox 0.74 (Windows 64-bit). The source code seems fine too, at first glance (IRQ 8 must not be impeded, the RTC timing must be the default one) Can you be more specific about the nature of the problem? I cannot imagine how a wait function could drive a program "confused with pixels" or to a crash. – Margaret Bloom Apr 04 '17 at 12:54
  • @MargaretBloom: Does the program in http://stackoverflow.com/q/27877996/3512216 finish in DOSBox? My DOSBox hangs after a while and shows in the status window a lot of messages like "Illegal read from 20202000, CS:IP f000:11c4". – rkhb Apr 04 '17 at 15:26
  • @rkhb I don't know. I've tested with a very simple program that does nothing but calls the wait function. I also have the warning messages in the console but they don't seem to affect the program as it ultimately works (i.e. it waits and exits). The INT15/AH=86 uses the IRQ 8 and the RTC, so playing with the interrupts and related hardware may break that function. IIRC Ralf Brown also warn about it. BTW, I didn't downvote your answer. – Margaret Bloom Apr 04 '17 at 16:03

3 Answers3

5

This is a bug in DOSBox through release 0.74.3. There is a missing break in the switch of their int 15h handler function, so the ah=86h handler falls through into ah=87h, Copy Extended Memory which copies memory around from some random addresses. See bios.cpp around line 663-681. (If they'd turned on -Wextra they'd have got a compiler warning!)

This seems to have been fixed in trunk back in 2011 but somehow never made it into releases, I guess.

I have filed bug #548 to report this.

The region to be copied by ah=87h is specified by a count in cx and addresses in a descriptor table pointed to by es:si. If those addresses are out of range, you should just get the Illegal read/write warnings and no other harmful behavior, but if they happen to point to actual memory, something important may be overwritten. I suspect in OP's test the destination happened to point into video memory, explaining the "weird colors"

By the same token, if cx = 0 then nothing is copied and the bug won't appear. That justifies the workaround in rkhb's deleted answer, of executing delays of less than 65 ms in a loop.

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
  • 1
    I have been wondering for so long why this behaviour in DOSBox exists. Now I know. Let's hope the developers respond to the bug report that you filed. – Sep Roland Apr 04 '21 at 21:22
1

I had this issue as well. Based on the answer at Problems with BIOS delay function (INT 15h / AH = 86h), I was able to get it working by making sure to set AL to zero before calling the interrupt:

    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

(the program prints 10 *'s, pausing for 1 second between each.) With out the 'mov al, 0', the program would hang or give other undefined behavior while DOSBox spews illegal read/write messages. By setting al to zero, the program works correctly but, strangely, error messages still appear on the DOSBox log.

Community
  • 1
  • 1
ttb
  • 229
  • 3
  • 12
  • 1
    I don't think this really helps, except maybe by chance. DOSBox doesn't look at the contents of `al`, and the errors and misbehavior are caused by the bug mentioned in my answer, which tries to access memory based on the contents of other registers and the memory where they point. – Nate Eldredge Mar 28 '21 at 19:06
0

Replace int 15h by something else, for example a procedure that waits "n" seconds:

.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
  • 1
    Doesn't the code assume that `mov ah, 2ch / int 21h` completes in no more than 1us? For, suppose the microseconds part of time crosses the *seconds* value between the call to the DOS service, then the function will keep jumping. E.g. Suppose *seconds*=99 and `dh` is returned as 12, 78, 30, 90, 02, 65, 20, 80, ... and similar. 3 seconds have elapsed but the function didn't detect that. – Margaret Bloom Apr 04 '17 at 16:15
  • 1
    @MargaretBloom, I understand your point and you are right (as usual :). My answer is a blind suggestion because the OP didn't share their code, so the behavior of the seconds might be uniform (0,1,2,...) or irregular (12,38,...) depending on many factors. – Jose Manuel Abarca Rodríguez Apr 04 '17 at 16:43