KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q42465: CALL ABSOLUTE Hang; Assembly Must Use CB Return Instruction

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

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.