开发dos虚拟机程序

        有过dos编程经历的老鸟们一定都很怀念在dos平台上写程序的随心所欲的日子。前几天看到一篇开发dos虚拟机程序的技术文章,说是可以在不修改16位dos程序的情况下,让dos程序在win32上跑起来,我一下来了兴趣,可写出来的东西怎么也没法加载。最后我在苏联老大哥的一个偏僻的网站上找到几段代码,虽说俄文我一点不懂,可那几段代码经过我稍加修改,居然编译通过并加载成功了。为了感谢苏联老大哥对我国社会主义建设事业的无私援助,我将我修改编译成功的代码贴在下面,希望对想写dos虚拟机程序的朋友有所帮助。代码由六个文件组成,就像发现远古时期的藏宝图总会残缺不全一样,应该有一些文件遗失了,不过这对由一定功底的朋友应该不是问题了。我至今没搞懂这些代码是一个什么东西的驱动程序。以下是六个程序的源代码:

1,sources文件:

TARGETNAME=mi1201
TARGETPATH=obj
TARGETTYPE=DYNLINK

TARGETLIBS=$(BASEDIR)/lib/*/$(DDKBUILDENV)/kernel32.lib     /
           $(BASEDIR)/lib/*/$(DDKBUILDENV)/ntvdm.lib

DLLENTRY=VDDInitialize
DLLBASE=0x2000000

SOURCES=vdd.c

INDENTED_DIRECTIVES=1

C_DEFINES=-DWIN_32 -DDEBUG

2,makefile文件:

#
# DO NOT EDIT THIS FILE!!!  Edit ./sources. if you want to add a new source
# file to this component.  This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#

!INCLUDE $(NTMAKEENV)/makefile.def

3,mi1201.def文件:

LIBRARY VDD

EXPORTS
        VDDInitialize

4,gpioctl.h文件:

// Device type           -- in the "User Defined" range."
#define GPD_TYPE 40000

// The IOCTL function codes from 0x800 to 0xFFF are for customer use.

#define IOCTL_GPD_READ_PORT_UCHAR /
    CTL_CODE( GPD_TYPE, 0x900, METHOD_BUFFERED, FILE_READ_ACCESS )

#define IOCTL_GPD_READ_PORT_USHORT /
    CTL_CODE( GPD_TYPE, 0x901, METHOD_BUFFERED, FILE_READ_ACCESS )

#define IOCTL_GPD_READ_PORT_ULONG /
    CTL_CODE( GPD_TYPE, 0x902, METHOD_BUFFERED, FILE_READ_ACCESS )

#define IOCTL_GPD_WRITE_PORT_UCHAR /
    CTL_CODE(GPD_TYPE,  0x910, METHOD_BUFFERED, FILE_WRITE_ACCESS)

#define IOCTL_GPD_WRITE_PORT_USHORT /
    CTL_CODE(GPD_TYPE,  0x911, METHOD_BUFFERED, FILE_WRITE_ACCESS)

#define IOCTL_GPD_WRITE_PORT_ULONG /
    CTL_CODE(GPD_TYPE,  0x912, METHOD_BUFFERED, FILE_WRITE_ACCESS)

typedef struct  _GENPORT_WRITE_INPUT {
    ULONG   PortNumber;     // Port # to write to
    union   {               // Data to be output to port
        ULONG   LongData;
        USHORT  ShortData;
        UCHAR   CharData;
    };
}   GENPORT_WRITE_INPUT;

5,vdd.h文件:

#include "windows.h"

// VDD services header
#include <vddsvc.h>

// private macro definitions


#define PAGE_SIZE  0x1000
/*disconnected I/O value */
#define FLOATING_IO  0xFF
#define FLOATING_MIO  0xFF

// I/O mapped I/O
#define IO_PORT_FIRST1  0xED00
#define IO_PORT_LAST1  0xEE00

#define IO_PORT_FIRST2  0x120
#define IO_PORT_LAST2  0x127

#define IO_PORT_FIRE_DMA_SLOW IO_PORT_FIRST
#define IO_PORT_FIRE_DMA_FAST IO_PORT_FIRST + 1
#define IO_PORT_DMA  IO_PORT_FIRST + 2
#define IO_PORT_RANGE  IO_PORT_LAST - IO_PORT_FIRST + 1

// memory mapped I/O
#define MIO_SEGMENT  0xC000
#define MIO_PORT_FIRST  0
#define MIO_PORT_LAST  7
#define MIO_PORT_FIRE_DMA MIO_PORT_FIRST
#define MIO_PORT_DMA  MIO_PORT_FIRST + 1
#define MIO_PORT_RANGE  MIO_PORT_LAST - MIO_PORT_FIRST + 1
#define MIO_ADDRESS  ((((ULONG)MIO_SEGMENT) << 16) | MIO_PORT_FIRST)

// DMA
#define DMA_CHANNEL  1
#define DMA_PORT_BASE  0
#define DMA_SHIFT_COUNT  0
#define DMA_INTERRUPT_LINE 2
#define DMA_INTERRUPT_PIC ICA_SLAVE
#define DMA_PORT_PAGE  0x83
#define DMA_PORT_ADDR  DMA_PORT_BASE + 2
#define DMA_PORT_COUNT  DMA_PORT_BASE + 3
#define DMA_PORT_CMD  DMA_PORT_BASE + 8
#define DMA_PORT_REQUEST DMA_PORT_BASE + 9
#define DMA_PORT_SNGLE_MASK DMA_PORT_BASE + 10
#define DMA_PORT_MODE  DMA_PORT_BASE + 11
#define DMA_PORT_FLIPFLOP DMA_PORT_BASE + 12
#define DMA_PORT_TEMP  DMA_PORT_BASE + 13
#define DMA_PORT_CLEARMASK DMA_PORT_BASE + 14
#define DMA_PORT_WRTEMASK DMA_PORT_BASE + 15


/* function prototype definitions */

/* entry function of VDD */
BOOL VddDllEntry(HANDLE hVdd, DWORD dwReason, LPVOID lpReserved);

/* private functions */
VOID MyInB(WORD, PBYTE);
VOID MyOutB(WORD, BYTE);
VOID MyMIOHandler(ULONG, ULONG);
WORD FakeDD_DMARead(PBYTE, WORD);
WORD FakeDD_DMAWrite(PBYTE, WORD);
BOOLEAN SlowDMA();
BOOLEAN FastDMA();

6,vdd.c文件:

#include "vdd.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <winioctl.h>
#include "gpioctl.h"

/** Global variables **/
    HANDLE  hndFile;
    HANDLE  hVDD;  /* VDD module handle */
 BOOL IOHook;  /* true if we installed a I/O hooked */
//    BOOLEAN IOHook;  /* true if we installed a I/O hooked */
    static VDD_IO_PORTRANGE PortRange[2];

BOOL
VDDInitialize(
    HANDLE   hVdd,
    DWORD    dwReason,
    LPVOID   lpReserved)
{
    VDD_IO_HANDLERS  IOHandlers[2];

    hVDD = hVdd;

    switch ( dwReason ) {

    case DLL_PROCESS_ATTACH:
        hndFile = CreateFile(
                ".//PortIODev",                    // Open the Device "file"
                GENERIC_WRITE | GENERIC_READ,
                FILE_SHARE_READ,
                NULL,
                OPEN_EXISTING,
                0,
                NULL
                );
 IOHandlers[0].inb_handler = MyInB;
 IOHandlers[0].inw_handler = NULL;
 IOHandlers[0].insb_handler = NULL;
 IOHandlers[0].insw_handler = NULL;
 IOHandlers[0].outb_handler = MyOutB;
 IOHandlers[0].outw_handler = NULL;
 IOHandlers[0].outsb_handler = NULL;
 IOHandlers[0].outsw_handler = NULL;
 PortRange[0].First = IO_PORT_FIRST1;
 PortRange[0].Last = IO_PORT_LAST1;

// 呩忪 ぅ?イΕ?
//     IOHandlers[1]=IOHandlers[0]
 IOHandlers[1].inb_handler = MyInB;
 IOHandlers[1].inw_handler = NULL;
 IOHandlers[1].insb_handler = NULL;
 IOHandlers[1].insw_handler = NULL;
 IOHandlers[1].outb_handler = MyOutB;
 IOHandlers[1].outw_handler = NULL;
 IOHandlers[1].outsb_handler = NULL;
 IOHandlers[1].outsw_handler = NULL;
 PortRange[1].First = IO_PORT_FIRST2;
 PortRange[1].Last = IO_PORT_LAST2;

 // hook I/O mapped I/O
 IOHook = VDDInstallIOHook(hVDD, (WORD)2, PortRange, IOHandlers);
 break;

    case DLL_PROCESS_DETACH:
        // communicate to appropriate Device driver about your departure
 if (IOHook)
     VDDDeInstallIOHook(hVDD, 2, PortRange);
        CloseHandle(hndFile);
        break;

    default:
        break;
    }

    return TRUE;
}


VOID
MyInB(
WORD Port,
PBYTE Buffer
)
{
ULONG PortNumber = Port;
DWORD   ReturnedLength;
DeviceIoControl(
                            hndFile,            // Handle to device
                            IOCTL_GPD_READ_PORT_UCHAR,          // IO Control code for Read
                            &PortNumber,        // Buffer to driver.
                            sizeof(PortNumber), // Length of buffer in bytes.
                            Buffer,        // Buffer from driver.
                            1,         // Length of buffer in bytes.
                            &ReturnedLength,    // Bytes placed in DataBuffer.
                            NULL                // NULL means wait till op. completes.
                            );
}

VOID
MyOutB(
WORD Port,
BYTE Data
)
{
GENPORT_WRITE_INPUT InputBuffer;
DWORD   ReturnedLength;
InputBuffer.PortNumber = Port;
InputBuffer.CharData = Data;
DeviceIoControl(
                        hndFile,                // Handle to device
                        IOCTL_GPD_WRITE_PORT_UCHAR,              // IO Control code for Write
                        &InputBuffer,           // Buffer to driver.  Holds port & data.
                        5,             // Length of buffer in bytes.
                        NULL,                   // Buffer from driver.   Not used.
                        0,                      // Length of buffer in bytes.
                        &ReturnedLength,        // Bytes placed in outbuf.  Should be 0.
                        NULL                    // NULL means wait till I/O completes.
                        );
Data = InputBuffer.CharData;
}

        我在此基础上开发了一个dos虚拟机程序,16位的串口程序可以不用修改在上面运行,考虑到现在搞这些古怪玩意儿的人不多,程序的代码又不少,就不想贴出来了,有感兴趣的朋友可以在下面留言,我发现有知音就贴出来。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值