assemblyx86-16dosdosbox

DOSbox automatically freezes and crashes without any prompt warnings


I was trying to run my assembly language program and it is when i try to enter the 2nd input, the cursor freezes and the DOSbox emulator would crash after a few seconds of delay.

I've tried running other assembly language programs and they seem to be working fine. Im not sure of the reason behind this, could it be an error in my code (MASM format) / not enough RAM to run the program? My code is attached below and I had 1.5GB of RAM available while I was running the program.

.MODEL SMALL
.STACK
.DATA
    msg1 DB "Quantity (unit): $"
    msg2 DB 13,10,"Unit price (RM): $"
    msg3 DB 13,10,"Total amount is RM$"
    Quantity DB 0
    Unit_price DB 0
    Total DB 0
    Q DB 0
    R DB 0
    
.CODE
MAIN PROC
    MOV AX, @DATA
    MOV DS, AX
    
    MOV AH, 09H
    LEA DX, msg1
    INT 21H
    
    MOV AH, 01H
    INT 21H
    MOV Quantity, AL
    
    MOV AH, 09H
    LEA DX, msg2
    INT 21H
    
    MOV AH, 01H
    INT 21H
    MOV Unit_price, AL
    
    MOV AH, 09H
    LEA AX, msg3
    INT 21H
    
    XOR AX, AX
    SUB Quantity, '0'
    SUB Unit_price, '0'
    
    MOV AL, Quantity
    MUL Unit_price
    MOV Total, AL
    
    XOR AX, AX
    MOV DX, 10H
    DIV DX
    MOV Q, AL
    MOV R, AH
    
    MOV AH, 02H
    MOV DL, Q
    INT 21H
    
    MOV AH, 02H
    MOV DL, R
    INT 21H
    
    MOV AH, 4CH
    INT 21H
    
MAIN ENDP
END MAIN
    

Solution

  • Three bugs that I can see, including some spotted in comments.


        MOV AH, 09H
        LEA AX, msg3
        INT 21H
    

    Looks like a typo for LEA DX, msg3. As it stands you will have a random value in AH (the high byte of the address of msg3 and will be executing some random DOS function. That might be what crashes DosBox.

    Also, more efficient than LEA here (and in the other similar instances) would be MOV DX, OFFSET msg3 which has the same effect and saves one byte.


        XOR AX, AX
        MOV DX, 10H
        DIV DX
    

    First, you zeroed out AX thus discarding the total value you so carefully computed (remember, AX emcompasses both AH and AL). Second, DIV r/m16 is a 32 by 16 bit division: it divides the 32-bit unsigned value in DX:AX by the value in r/m16, with the quotient placed in AX and the remainder in DX. So here you are dividing 100000H by 10H; the quotient is 10000h which overflows 16 bits, and so you will get a divide overflow exception.

    This could also be the cause of the crash, though I seem to recall that real MS-DOS had a handler for the divide overflow interrupt that would print a message and terminate the program, without crashing the system. I'm not sure if DosBox provides that, however.

    Also, 10H is hex, so you're dividing by sixteen. I'm assuming you probably wanted decimal output, so you want to divide by ten (10) instead.

    Thus, I think you probably meant

        XOR AH, AH    ; zero-extend AL into AX
        MOV DL, 10
        DIV DL
    

    to do a 16 by 8 bit divide of the number from AL (extended with zeros to produce a 16-bit value in AX) by 10, placing the quotient in AL and the remainder in AH.


        MOV AH, 02H
        MOV DL, Q
        INT 21H
    

    You need to add '0' to the values Q and R to create printable ASCII characters for output.