Article: Q42465
Product(s): See article
Version(s): 4.00 4.00b 4.50
Operating System(s): MS-DOS
Keyword(s): ENDUSER | SR# S890222-47 B_BasicCom | mspl13_basic
Last Modified: 12-DEC-1989
An assembly-language routine accessed with CALL ABSOLUTE must use a
machine-language return instruction of CB hex (a far return), instead
of C3 hex (a near return).
The two programs shown below demonstrate that a program hangs if it
uses CALL ABSOLUTE on an assembly-language routine that returns with a
return instruction of C3 (Hex). To correct this problem, you must use
a return instruction of CB (hex).
This information applies to QuickBASIC Versions 4.00, 4.00b, and 4.50
for MS-DOS, Microsoft BASIC Compiler Versions 6.00 and 6.00b for
MS-DOS and MS OS/2, and Microsoft BASIC PDS Version 7.00 for MS-DOS
and MS OS/2.
The far-return instruction CB (hex) correctly pops 4 bytes off the
stack for a segment and offset to return. Near-return C3 (hex) pops
only 2 bytes off the stack for an offset, which is inappropriate.
The following is a good reference for the machine instructions in the
Intel 8086 family of microprocessors: "The 80386 Book: Assembly
Language Programmer's Guide for the 80386," by Ross Nelson (published
by Microsoft Press, 1988).
The following program is TEST1.BAS. It calls an assembly-language
routine that prints an "A" on the screen. It uses the correct return
code of CB.
DIM ASMROUTINE(1 TO 6) AS INTEGER
DATA &H55 : ' PUSH BP Save base pointer
DATA &H8B,&HEC : ' MOV BP,SP Get our own
DATA &HB4,2 : ' MOV AH,2 Function 2 - print to screen
DATA &HB2,65 : ' MOV DL,65 Character 'A'
DATA &HCD,&H21 : ' INT 21H Make ROM BIOS call
DATA &H5D : ' POP BP Restore base pointer
DATA &HCB,0 : ' RET Far Return (correct) <-----
OFFSET = VARPTR(ASMROUTINE(1))
DEF SEG = VARSEG(ASMROUTINE(1))
' Poke assembly routine into memory:
FOR I = 0 TO 11
READ ASMCODE
POKE (OFFSET + I), ASMCODE
NEXT I
CALL ABSOLUTE(VARPTR(ASMROUTINE(1))) ' call routine we poked in
DEF SEG
END
The following program, TESTS.BAS, uses the incorrect return code and
hangs the machine:
DIM ASMROUTINE(1 TO 6) AS INTEGER
DATA &H55 : ' PUSH BP Save base pointer
DATA &H8B,&HEC : ' MOV BP,SP Get our own
DATA &HB4,2 : ' MOV AH,2 Function 2 - print to screen
DATA &HB2,65 : ' MOV DL,65 Character 'A'
DATA &HCD,&H21 : ' INT 21H Make ROM-BIOS call
DATA &H5D : ' POP BP Restore base pointer
DATA &HC3,0 : ' RET Near Return (incorrect) <-----
OFFSET = VARPTR(ASMROUTINE(1))
DEF SEG = VARSEG(ASMROUTINE(1))
' Poke assembly routine into memory:
FOR I = 0 TO 11
READ ASMCODE
POKE (OFFSET + I), ASMCODE
NEXT I
CALL ABSOLUTE(VARPTR(ASMROUTINE(1))) ' call routine we poked in
DEF SEG
END