首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >虚拟并行端口仿真器

虚拟并行端口仿真器
EN

Stack Overflow用户
提问于 2011-10-17 23:07:54
回答 3查看 8.3K关注 0票数 9

在我的计算机网络课程中,我们应该通过使用本机寄存器来学习并行端口编程(比如使用类似outportb的命令)。我没有并行端口(因为我住在2011),但我想练习一下这些程序(我使用dosbox安装了旧的turboc 3 IDE )。有没有像this程序模拟串口那样模拟并口的程序?

EN

回答 3

Stack Overflow用户

发布于 2011-10-19 05:47:19

因为环境是假的,也就是说你没有实际的端口,你也可以在你的程序中模拟端口功能。

下面是如何在Windows中使用 (SEH)实现这一点:

代码语言:javascript
复制
// Filename: PortEmu.c
// Compiled with Open Watcom 1.9 as: wcl386 PortEmu.c

#include <windows.h>
#include <stdio.h>
#include <conio.h>

// Port state. Holds the last value written by OUT.
// IN reads from it.
volatile UINT32 PortState = 0;

UINT32 ReadPort(UINT16 PortNumber, UINT OperandSize)
{
  UNREFERENCED_PARAMETER(PortNumber);

  switch (OperandSize)
  {
  default:
  case 8:
    return PortState & 0xFF;

  case 16:
    return PortState & 0xFFFF;

  case 32:
    return PortState;
  }
}

void WritePort(UINT16 PortNumber, UINT OperandSize, UINT32 Value)
{
  UNREFERENCED_PARAMETER(PortNumber);

  switch (OperandSize)
  {
  default:
  case 8:
    PortState = (PortState & ~0xFF) | (Value & 0xFF);
    break;

  case 16:
    PortState = (PortState & ~0xFFFF) | (Value & 0xFFFF);
    break;

  case 32:
    PortState = Value;
    break;
  }
}

// Exception filter to emulate x86 IN and OUT instructions
// in 32-bit Windows application.
int IoExceptionFilter(LPEXCEPTION_POINTERS ep)
{
  CONTEXT* c = ep->ContextRecord;
  UINT8* instr = (UINT8*)c->Eip;
  int OperandSizeIs16Bit = 0;

  switch (ep->ExceptionRecord->ExceptionCode)
  {
  case EXCEPTION_PRIV_INSTRUCTION:
    if (instr[0] == 0x66)
    {
      OperandSizeIs16Bit = 1;
      instr++;
    }

    switch (instr[0])
    {
    case 0xE4: // IN AL, imm8
      *(UINT8*)&c->Eax = ReadPort(instr[1], 8);
      c->Eip += 2 + OperandSizeIs16Bit;
      return EXCEPTION_CONTINUE_EXECUTION;

    case 0xE5: // IN (E)AX, imm8
      if (OperandSizeIs16Bit)
        *(UINT16*)&c->Eax = ReadPort(instr[1], 16);
      else
        c->Eax = ReadPort(instr[1], 32);
      c->Eip += 2 + OperandSizeIs16Bit;
      return EXCEPTION_CONTINUE_EXECUTION;

    case 0xEC: // IN AL, DX
      *(UINT8*)&c->Eax = ReadPort((UINT16)c->Edx, 8);
      c->Eip += 1 + OperandSizeIs16Bit;
      return EXCEPTION_CONTINUE_EXECUTION;

    case 0xED: // IN (E)AX, DX
      if (OperandSizeIs16Bit)
        *(UINT16*)&c->Eax = ReadPort((UINT16)c->Edx, 16);
      else
        c->Eax = ReadPort((UINT16)c->Edx, 32);
      c->Eip += 1 + OperandSizeIs16Bit;
      return EXCEPTION_CONTINUE_EXECUTION;

    case 0xE6: // OUT imm8, AL
      WritePort(instr[1], 8, (UINT8)c->Eax);
      c->Eip += 2 + OperandSizeIs16Bit;
      return EXCEPTION_CONTINUE_EXECUTION;

    case 0xE7: // OUT imm8, (E)AX
      if (OperandSizeIs16Bit)
        WritePort(instr[1], 16, (UINT16)c->Eax);
      else
        WritePort(instr[1], 32, c->Eax);
      c->Eip += 2 + OperandSizeIs16Bit;
      return EXCEPTION_CONTINUE_EXECUTION;

    case 0xEE: // OUT DX, AL
      WritePort((UINT16)c->Edx, 8, (UINT8)c->Eax);
      c->Eip += 1 + OperandSizeIs16Bit;
      return EXCEPTION_CONTINUE_EXECUTION;

    case 0xEF: // OUT DX, (E)AX
      if (OperandSizeIs16Bit)
        WritePort((UINT16)c->Edx, 16, (UINT16)c->Eax);
      else
        WritePort((UINT16)c->Edx, 32, c->Eax);
      c->Eip += 1 + OperandSizeIs16Bit;
      return EXCEPTION_CONTINUE_EXECUTION;

    default:
      return EXCEPTION_CONTINUE_SEARCH;
    }

  default:
    return EXCEPTION_CONTINUE_SEARCH;
  }
}

int main(void)
{
  __try
  {
    outp(0x278, 0x00);
    printf("portb=0x%X\n", inp(0));

    outp(0x278, 0x55);
    printf("portb=0x%X\n", inp(0));

    outp(0x278, 0xFF);
    printf("portb=0x%X\n", inp(0));

    outpw(0x278, 0xAAAA);
    printf("portw=0x%X\n", inpw(0));

    outpd(0x278, 0x12345678);
    printf("portd=0x%X\n", inpd(0));

    outpw(0x278, 0xAAAA);
    outp(0x278, 0x55);
    printf("portd=0x%X\n", inpd(0));
  }
  __except(IoExceptionFilter(GetExceptionInformation()))
  {
  }

  return 0;
}

输出:

代码语言:javascript
复制
C:\>PortEmu.exe
portb=0x0
portb=0x55
portb=0xFF
portw=0xAAAA
portd=0x12345678
portd=0x1234AA55

只需更改ReadPort()WritePort()的实现,以做一些更有用或更符合打印机端口操作的事情。

票数 2
EN

Stack Overflow用户

发布于 2011-10-18 02:25:56

看起来dosbox可能不支持没有patches的并行端口。此外,virtualbox似乎还会doesn't yet support并行端口。但是,即使它们确实支持并行端口,你仍然需要在另一端有一些东西-要么是你主机操作系统上的调试驱动程序,要么是像USB转并行适配器这样的东西(在通常的零售商那里可以买到)。

你能说更多关于你为什么想了解parallel port的原因吗?正如你所说的,它在2011年是一个几乎已经死亡的界面。如果您真的想使用低级并行式I/O,那么您可能需要研究一下Arduino平台。

票数 0
EN

Stack Overflow用户

发布于 2011-10-18 03:19:27

我暂时不知道有什么软件,但如果Linux Wine在支持并行端口方面做得很好,我不会感到惊讶,尽管我不知道在缺乏物理LPT的情况下,它是否可以完全虚拟化。

当不得不做遗留兼容性测试时,我总是惊讶地发现,找到一台便宜的旧PC是多么容易。

遗憾的是,这是高度以地区为中心的,但请访问当地的转售店或计算机回收操作。例如,在波特兰,我会访问Free Geek和Goodwill,不希望花费超过15美元。如果你的时间很有价值,这可能比胡乱摆弄模拟器,然后想知道它们有多好更实惠。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7795739

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档