Call Absolute, Version 1.01
Copyright (c) 1996-97 SoftCircuits Programming
Redistributed by Permission.

SoftCircuits Programming
http://www.softcircuits.com
P.O. Box 16262
Irvine, CA 92623

CALLABS.DLL was designed to assist in duplicating the
functionality of the Call Absolute statment in earlier DOS
versions of Microsoft BASIC. It allows you to call any memory
address under Win32.

To use this technique, allocate memory that has execute
access. Many variables allocated in VB can be executed.
Memory allocated with GlobalAlloc can also be executed.
Next, write the machine code bytes to that memory. This step
requires knowledge of Intel 32-bit processor instructions.
The last instruction should be RET (&HC3) which causes the
processor to return to the code that called the memory.

There are two advantages to this technique. One, you can
write small custom assembly language routines without an
assembler, and two, you can modify the code at run-time to
create special purpose routines based on run-time conditions.

Much of this technique requires only Visual Basic. However,
Visual Basic provides no direct means to call the memory.
This DLL provides this link. Use CallAbsolute to call a
memory location that contains instructions. Use
CallAbsoluteRegs to do the same thing except this version
lets you use the CALLREGS UDT to set register values before
the memory is called, and to return register values after the
memory is called. The VarPtr function offers support if you
need to obtain an address of a variable. Note that Visual
Basic passes a copy of some variable types when calling a DLL
function. For example, this is the case with strings and UDTs
that contain strings. In these instances, VarPtr returns the
address of the copy which would not normally be of any value.

If you run into problems using this technique on some
platforms, you might instead try calling GlobalAlloc() to
allocate the memory block that you execute. If you plan to
implement this technique in a commercial application, you
should also consider some other issues that may make your
program more reliable. The Microsoft Knowledge Base article
Q127904 addresses these issues. Basically, the article
recommends you call VirtualProtect() before and after you
modify the block of memory to change the memory's protection
level. The article also recommends you call
FlushInstructionCache() under NT to prevent high-performance
processors from executing cached instructions instead of
the instructions you just modiified.

Declarations:
=============

Type CALLREGS
    EAX As Long
    EBX As Long
    ECX As Long
    EDX As Long
    ESI As Long
    EDI As Long
    Flags As Long
End Type

'CALLREGS Flags bit values
Public Const FLAGS_CARRY = &H1
Public Const FLAGS_PARITY = &H4
Public Const FLAGS_AUX = &H10
Public Const FLAGS_ZERO = &H40
Public Const FLAGS_SIGN = &H80

Declare Function CallAbsolute Lib "CALLABS.DLL" (Mem As Any) As Long
Declare Function CallAbsoluteRegs Lib "CALLABS.DLL" (Mem As Any, Regs As CALLREGS) As Long
Declare Function VarPtr Lib "CALLABS.DLL" (Mem As Any) As Long
