Code Snippets
Code Samples

The Blog
Our Projects

::Add RageStorm to Favorites!::

The Blog | Our Projects | Guest Book | About | Contact

Tutorial - Calling Win32 from DOS
Uploaded at:17-Sep-05
A hacky mechanism to call forth 32 bits userland DLL's from 16 bits applications
which execute under the NTVDM is supported in Windows in order to let DOS
applications extend their environment, whatever it is (video, sound, serial port
or any other peripheral). It is called BOP(-Instructions). And I guess no one really
knows what it stands for, but who cares. This mechanism let you register a DLL
and then call it and later on unregister the DLL. Luckily, it is easily used,
with an interesting trick. In order to invoke those BOP's you have to use an invalid
instruction (0xc4, 0xc4 - sort of LEA but with register-register operands which is
invalid form). Then an Invalid Instruction exception, interrupt #6, is generated
by the processor and the KiTrap06 is executed. The KiTrap quickly tries to determine
the reason of the exception, whether it was a misuse of the LOCK prefix or maybe just
a BOP instruction. It then checks for two specific BOP's instructions, for fast IO.
The BOP instructions we have to use are for 3rd party services, I guess letting DOS
applications communicate with userland applications or VDD's. There are many kinds of
BOP's, but we will simply use a specific one, 0x58, and passing parameters to it as
well. KiTrap06 transfers control to NTVDM which does the real job for handling the
BOP's instructions. The DLL file should be in the DOS application directory, or in
the default paths. When invoking the dispatcher NTVDM guarantees to not change the
values of the registers, thus using the DDK with the VDD functions you could be able
to read and write memory to and fro userland DLL. But in the example I use NTVDM.EXE
directly, in order to spare the library and header files.

Register Module: Register a third party DLL with the BOP manager.
DS:SI - Null terminated string with the userland DLL name.
ES:DI - Null terminated string with the initialization routine (Optional, ES=DI=0).
DS:BX - Null terminated string with the dispatch routine (for later use by dispatcher).
If Carry is set:
AX = 1 - DLL file was not found.
AX = 2 - Dispatch routine wasn't found (GetProcAddress failed).
AX = 3 - Initialization routine wasn't found (GetProcAddress faild).
AX = 4 - Insufficient memory.
AX contains the handle of the registered DLL.
BOP Instruction: 0xc4, 0xc4, 0x58, 0x00

DispatchCall: Call the registered DLL function.
Input: AX - Handle to a registered DLL.
[It depends on you how to pass info to the DLL]
Return: Depends on dispatch routine.
BOP Instruction: 0xc4, 0xc4, 0x58, 0x02

Unregister Module: Unregister a module from the BOP manager.
Input: AX - Handle to a registered DLL.
Return: None
BOP Instruction: 0xc4, 0xc4, 0x58, 0x01

The userland DLL side (using VS):
File galaxy.dll:

__declspec(dllexport) void MyRoutine()
 MessageBox(NULL, "Hey there", "BOPs", MB_OK);

The DOS side (using NASM):
bits 16
mov si, DLL_NAME
;mov di, INIT_PROC
xor di, di
push di
pop es
db 0xc4, 0xc4, 0x58, 0x0
jc error:
; Store the DLL's handle
mov [DLL_HANDLE], ax
;... In the sample, a string is being passed to the userland DLL!
DLL_NAME: db "galaxy.dll", 0
INIT_PROC: db "InitProc", 0
DISPATCHER: db "MyRoutine", 0

Here's a full sample code: galaxy.zip
That took a few hours of researching, I think it's really kewl,
not sure if it's handy though. Oh well. ;)
User Contributed Comments(15)
 [1] Mike Ehlert | 2006-06-10 23:36:14

It seems that the BOP function fails to load a DLL under Windows Vista (beta 2).
Has anyone found a work-around for this?

Regards, Mike
 [2] arkon | 2006-08-06 21:43:42

"AIRC BOP meant "BIOS Operation". It was the mechanism used in SoftPC
to transfer control from the emulated Intel world to the native world
on which the emulator was running. Most of the BIOS in the early
SoftPC versions consisted of very short sequences of Intel code ending
in a BOP. It was originally a different opcode but when we switched
from emulating an 8086 to an 80286 that was no longer an illegal
instruction so we changed it to C4C4.

jim hatfield " (found on news groups)

i guess he was one of the developers in insignia or something.
that's cool ;)
 [3] Mike Ehlert | 2006-09-03 00:59:21

I think I found a reason wy Microsoft has disabled the BOP calls in Windows Vista:
It is an easy exploit for hackers.
 [4] arkon | 2006-09-05 08:07:45

well, this is old news, and it was already fixed.
so i don't think this is the reason why they would go and remove support for BOPs.
 [5] Mike Ehlert | 2006-10-02 07:30:15

MS has fixed the issue in Vista RC1 :)

 [6] senk1 | 2006-12-02 19:17:55

With this method I can execute DLL functions with stack-like parameters, but how can I pass the parameters, or I can't do it in this way?

ps.: I Want to execute DLL-functions within *.COM files, but without any own DLL support, can I do it else? Or it's only a Dream?
 [7] senk1 | 2006-12-02 19:23:59

And one another thing! Where can I get other BOP commands?

ps.: The tutorial was very good!
 [8] arkon | 2006-12-02 22:04:20

That's why you have to write the dll's on your own, so you can pass parameters.
check VDDSVC.H for more info.
You will have to reverse NTVDM.EXE.
 [9] venkatesh | 2007-05-24 09:35:05


this is venkatesh, I create one dll file using VC++. now iam able to get the functions declared in dll, but i have a small problem, i face a problem while iam passing some parameters to that functions from my scripting.

If anybody knows about this problem please help me as soon as possible.

 [10] Nicolas | 2007-07-04 14:26:16

My question is if with this code I can use the windows API if i programing with a 16 bit DOS compiler like Quick Basic 4.5. I want to use the windows framework to do checks, textbox, etc in a qbasic program.
If this is possible, how is the way to do this?


sorry for my poor english, i'm from argentina
 [11] arkon | 2007-07-07 19:33:28

this is not really possible, unless you write another dll which will do your work in the win32 world. and i'm not really sure if you can use assembly in basic, so it's out of question. i suggest you to move to windows and start using visual basic so you enjoy windows' features as well.
good luck.
 [12] Styx | 2008-01-02 19:02:31

you can use assembly in qb 4.5, ive seen it done before. i believe you compile the code then put the hex into an executable section of your qb program using DATA statements.
 [13] senki | 2008-01-23 02:54:00

I have found some intresting...
If you do not register any module, but you use "dispatchcall" with ax=1 then the NTVDM is called and the instruction at 0:0 (segment:offset) is called. But in flat, 32bit protected mode, not in an emulated environment. So if you put one "jmp a32" instruction at 0:0(where a32 is the 32bit address of your routine that you are wanting to run) and enjoy the thing...
 [14] arkon | 2009-07-13 19:46:03

more information about the subject from 29A, the vx zine.
 [15] Glidos | 2009-08-15 12:14:16

When I first used BOPs, I tried from protected mode and found it not to work. I ended up having to use a DPMI realmode call. Is use from realmode a known restriction, or may I have just made a mistake in the way I set thing up under protected mode?
Comments that will hurt anyone in any way will be deleted.
Don't ask for features, advertise or curse.
If you want to leave a message to the author use the contacts,
if you have any question in relation to your comments please use the forum.
Comments which violate any of these requests will be deleted without further
notice. Use the comment system decently.

Post your comment:
::Top 5 Tutorials::
Embedded Python[119194]
2D Rotated Rectangles Collision Detection[90098]
Keyboard Hook[78635]
HTTP Proxy[41966]

::Top 5 Samples::
2D ColDet Rotated Rectangles[11602]
PS2 Mouse Driver[7002]
Wave Format Player[5828]
Reading FAT12[5652]

All rights reserved to RageStorm © 2009