7

I was trying to run some simple machine code programs in QuickBasic (4.5 and QBX 7.1) and QBasic from DosBox-X. The program should output a character "A" (code 65) to the screen using int 21h and AH=2 subroutine.

(A more ambitious goal is to print a whole string with int21h/ah=9, but right now I am stuck here.)

This is an example from qbasic.com:

'Create a machine-language procedure and 
'call it using CALL ABSOLUTE

'Array to store machine code
DIM asmroutine(1 TO 6) AS INTEGER

'Data that makes up machine-code routine
DATA &H55           : ' PUSH BP
DATA &H8B, &HEC     : ' MOV BP, SP
DATA &HB4, 2        : ' MOV AH, 2
DATA &H2, 65        : ' MOV DL, 65
DATA &HCD, &H21     : ' INT 21H
DATA &H5D           : ' POP BP
DATA &HCB, 0        : ' RET

'Get array offset
offset = VARPTR(asmroutine(1))

'Change the segment to the start of the array
DEF SEG = VARSEG(asmroutine(1))

'Fill the array with machine code
FOR i = 0 TO 11
  READ asmcode
  POKE (offset + i), asmcode
NEXT i

'Call the routine and restore the segment
CALL ABSOLUTE(VARPTR(asmroutine(1)))
DEF SEG

Running this program either gives an error "Division by zero" on Windows PC (QBX) or crashes DosBox on Android, as well as in the web-based versions like https://dos.zone/qbasic-1991/

There is no problem executing it in assembly.

I was able however to run the following program using int 10h to print characters on Android-based DosBox, but on my PC it still gives "Division by zero":

CLS
DIM PM%(5)
SegPM% = VARSEG(PM%(0))
OffPM% = VARPTR(PM%(0))
DEF SEG = SegPM%
FOR I% = 0 TO 11
READ Octet$
POKE OffPM% + I%, VAL("&H" + Octet$)
NEXT I%

CALL ABSOLUTE(OffPM%)
DEF SEG
END
'machine code
DATA B4,0A    'MOV AH,0A
DATA B0,61    'MOV AL,61
DATA B7,00    'MOV BH,0
DATA B9,78,00 'MOV CX,78
DATA CD,10    'INT 10
DATA CB       'RETF

How to execute the program above in QB?

New contributor
Glory2Ukraine is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
4
  • 2
    I’m voting to close this question because it's a once-in-a-lifetime trivial typo question Commented 13 hours ago
  • 1
    Typo (&H2) in documentation/CALL-ABSOLUTE.md #1 Commented 7 hours ago
  • I’m voting to close this question because it is a typo that will (hopefully) be corrected at source. Commented 7 hours ago
  • 1
    I am voting to keep this question active. The question and provided answer document a problem with the compiler not having a write-or-read protection feature that limits the memory accessed by the program. In fact, just looking at the code, one might spend hours trying to find this coding error. We can learn something from this answer. I don't care if this is a once in a lifetime typo or coding error... Commented 4 hours ago

1 Answer 1

13

The problem is here:

DATA &H2, 65        : ' MOV DL, 65

Apparently there is a typo in that example, as the MOV DL,65 should be compiled as B2 41. The opcode 02 is totally different from B2, it's not even two-byte command, it's the 02 41 CD now and produces the MOV AH, [BX+DI-35] command.

The beginning of the next opcode CD 21 thus gets consumed as part of previous command, and instead of calling the interrupt 21h you get the command AND [DI-35],BX, which also consumes the RETF opcode as part of this new AND, so the routine continue to execute whatever garbage is located past the allocated array area.

Just edit that basic line, replace &H2 with &HB2

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.