虚拟并行端口仿真器

发布于 2024-12-10 02:04:13 字数 226 浏览 0 评论 0原文

在我的计算机网络课程中,我们应该通过使用本机寄存器(例如使用 outportb 等命令)来学习并行端口编程。我没有并行端口(因为我住在 2011 年),但想练习这些程序(我使用 dosbox 安装了旧的 Turboc 3 IDE)。是否有一个模拟并行端口的程序,例如 这个 程序模拟串行端口?

In my computer networks course we are supposed to learn parallel port programming by using the native registers (like using outportb like commands). I don't have a parallel port (because I live in 2011) but want to practice the programs (I installed the old turboc 3 IDE using dosbox). Is there a program which emulates parallel ports like this program emulates serial ports?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

眸中客 2024-12-17 02:04:13

由于环境无论如何都是假的,即您没有实际的端口可以使用,因此您也可以在程序中模拟端口功能。

以下是如何在 Windows 中使用结构化异常处理< /strong> (SEH):

// 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;
}

输出:

C:\>PortEmu.exe
portb=0x0
portb=0x55
portb=0xFF
portw=0xAAAA
portd=0x12345678
portd=0x1234AA55

只需更改 ReadPort()WritePort() 的实现即可执行更有用或更符合打印机端口操作的操作。

Since the environment is fake anyway, i.e. you don't have an actual port to play with, you could just as well emulate the port functionality in your program.

Here's how to do it in Windows using Structured Exception Handling (SEH):

// 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;
}

Output:

C:\>PortEmu.exe
portb=0x0
portb=0x55
portb=0xFF
portw=0xAAAA
portd=0x12345678
portd=0x1234AA55

Just alter the implementation of ReadPort() and WritePort() to do something more useful or more in line with the printer port operation.

暮色兮凉城 2024-12-17 02:04:13

如果没有补丁,dosbox 可能不支持并行端口。似乎 virtualbox尚不支持并行端口。但即使它们确实支持并行端口,您在另一端仍然需要一些东西 - 要么是主机操作系统上的调试驱动程序,要么是 USB 转并行适配器(可在通常的零售商处购买)之类的东西。

您能否详细说明一下为什么要了解并行端口?正如您所建议的,它在 2011 年基本上已经死了。如果您确实想使用低级并行式 I/O,您可能需要查看 Arduino< /a> 平台。

It looks like dosbox may not support parallel ports without patches. It also appears that virtualbox also doesn't yet support parallel ports. But even if they did support parallel ports, you'd still need something on the other end - either a debug-driver on your host operating system, or something like a USB to Parallel adapter (available at the usual retailers).

Can you say more about why you want to learn about the parallel port? It is a mostly dead interface in 2011, as you suggest. If you really want to play with low-level parallel-style I/O, you may want to look in to the Arduino platform.

月亮是我掰弯的 2024-12-17 02:04:13

我不知道任何软件,但如果 Linux Wine 做得很好,我不会感到惊讶支持并口,不过不知道在没有物理LPT的情况下是否可以完全虚拟化。

当必须进行旧版兼容性测试时,我总是惊讶地发现找到一台便宜的旧电脑是多么容易。

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

I don't know of any software offhand, though I would not be surprised if Linux Wine did a good job of supporting a parallel port, though I don't know if it can be completely virtualized when lacking a physical LPT.

When having to do legacy compatibility testing, I'm always amazed out how easy it is to find a cheap old PC.

Alas, this is highly regionally-centric, but visit a local resale store or computer recycling operation. For example, in Portland, I would visit Free Geek and Goodwill and not expect to pay more than $15. If your time is worth much, this is probably more affordable than messing around with emulators and then wondering how good they are.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文