【问题标题】:Beginner bare-metal pdp11 console output初学者裸机 pdp11 控制台输出
【发布时间】:2016-11-18 03:14:58
【问题描述】:

我正在尝试了解使用 pdp-11 的基本知识(在大学学习了指令集,想重温一下),想将一些字符作为第一个程序从 TTO/DL11 中射出(除非那也是复杂的第一个程序)。

在 simh 上运行。显示开发有

TTO, address=17777564-17777567, vector=64

阅读文档时,tx 缓冲区的偏移量为 566。在 stackoverflow 和其他一些页面上看到其他代码有/可能在高位地址空间中有一个 mmu,说 177566(八进制)可能会将您放在那里,因为寄存器不是 16 位22 位,正如 show dev 所暗示的那样。

mov $0x32,r1
movb r1, @$0177566
mov $0177566,r2
mov $0x30,r3
movb r3,(r2)
mov $0x31,r3
movb r3,(r2)
halt

什么都没有出来。

load test.bin
go

可以使用 set console telnet=4444 和 telnet 到那个,没有变化。毫无疑问,我无法解决超过 16 位的问题,但不太确定去哪里解决这个问题。

基本上我想,除非它是很多代码(数千行 asm)才能让一些字符从控制台中出来,否则我想从那里开始“看到”一些东西,然后在此基础上进行构建.所以如果我很接近但不是很接近,或者如果这不是最好的外围设备,那么去哪里,它们都在那个上层地址空间中。

我正在使用 gnu 工具

pdp11-aout-as --version
GNU assembler (GNU Binutils) 2.26.20160125
Copyright (C) 2015 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `pdp11-aout'.

所以语法有点傻/不标准。 binutils 至少现在已经支持 pdp11 的几个版本,希望也能利用这一点。 simh 的二进制文件格式并不难弄清楚,单步执行它与我想要的指令相匹配并提供 gnu 汇编器。

在 apt-got v3.8-1 版本的 simh pdp11 以及 github 上都尝试了 4.0 版本,结果相同。使用 pdp11 模拟器/可执行文件。

sim> show config
PDP-11 simulator configuration

CPU, 11/73, NOCIS, idle disabled, autoconfiguration enabled, 256KB
SYSTEM
RHA, address=17776700-17776753, vector=254
RHB, disabled
CLK, 60Hz, address=17777546-17777547, vector=100
PCLK, disabled
PTR, address=17777550-17777553, vector=70, not attached
PTP, address=17777554-17777557, vector=74, not attached
TTI, address=17777560-17777563, vector=60, 7b
TTO, address=17777564-17777567, vector=64, 7p
CR, address=17777160-17777167, vector=230, 285 cards per minute, translation 029, not attached, CR11, auto EOF, unknown format
LPT, address=17777514-17777517, vector=200, not attached
DLI, disabled
DLO, disabled
...

编辑

#define TKS (*((volatile unsigned *)0177560))
#define TKB (*((volatile unsigned *)0177562))
#define TPS (*((volatile unsigned *)0177564))
#define TPB (*((volatile unsigned *)0177566))

void punch ( unsigned x )
{
    while((TPS&0x80)==0) continue;
    TPB=x;
}

void notmain ( void )
{
    //unsigned ra;
    //for(ra=0x30;ra<0x37;ra++) punch(ra);
    punch(0x30);
    while((TPS&0x80)==0) continue;
    return;
}

这让

Disassembly of section .text:

00000000 <start.o>:
   0:   15c6 2000       mov $20000, sp
   4:   09f7 001a       jsr pc, 22 <_punch+0x18>
    ...

0000000a <_punch>:
   a:   1166            mov r5, -(sp)
   c:   1185            mov sp, r5
   e:   17c0 ff74       mov *$177564, r0
  12:   45c0 ff7f       bic $-201, r0
  16:   03fb            beq e <_punch+0x4>
  18:   1d5f 0004 ff76  mov 4(r5), *$177566
  1e:   1585            mov (sp)+, r5
  20:   0087            rts pc
  22:   1166            mov r5, -(sp)
  24:   1185            mov sp, r5
  26:   17c0 ff74       mov *$177564, r0
  2a:   45c0 ff7f       bic $-201, r0
  2e:   03fb            beq 26 <_punch+0x1c>
  30:   15df 0030 ff76  mov $60, *$177566
  36:   17c0 ff74       mov *$177564, r0
  3a:   45c0 ff7f       bic $-201, r0
  3e:   03fb            beq 36 <_punch+0x2c>
  40:   1585            mov (sp)+, r5
  42:   0087            rts pc

两个问题,一个是我没等到忙。在初始化/重置时没关系,它不忙。我认为踢球者是我在它吐出角色之前就停下来了。当我有循环时,它吐出了大部分字符。如果我发送一个字符并停止它不会出现,但是如果我将等待忙到零之后(notmain() 中的最后一件事),那么该字符就会出现。

如果我把它改成这个

#define TKS (*((volatile unsigned *)0177560))
#define TKB (*((volatile unsigned *)0177562))
#define TPS (*((volatile unsigned *)0177564))
#define TPB (*((volatile unsigned *)0177566))

void punch ( unsigned x )
{
    TPB=x;
    while((TPS&0x80)==0) continue;
}

void notmain ( void )
{
    unsigned ra;
    for(ra=0x30;ra<0x37;ra++) punch(ra);
    return;
}

效果很好...感谢您让我开始工作。

手册中的注释:

In addition to the word length constraint on basic memory addressing
space, the uppermost 4K words of address space is always reserved for
UNIBUS 1/0 device registers. In a basic PDP-11/40 memory configura·
tion (without Management) all address references to the uppermost 4K
words of 16-bit address space (170000-177777) are converted to full
18-bit reference5 with bits 17 and 16 always set to 1. Thus, a 16·bit
reference to the 1/0 device register at address 173224 is automatically
internally converted to a full 18-bit reference to the register at address
773224. Accordingly, the basic PDP-11/40 configuration can directly
address up to 28K words of true memory, and 4K words of UNIBUS 1/0
device registers.

所以答案就在那里,我没看对地方。

EDIT2:

在汇编中,为了达到将字符发送到 tty 的目的,使用 gnu 汇编语法(* 代替 @ 和 $ 代替 #)

movb $0x32,*$0177566
pwait:
   tstb *$0177564
   bpl pwait
halt

【问题讨论】:

  • 生成的 PDP-11 代码实际上效率很低。就绪位故意是低字节的高位,这样可以很容易地用TSTB @#0177564然后BLT .-6进行测试以完成循环。只是想你可能想知道。
  • 它是一个 C 编译器。我不会非常使用这个词,它确实会烧录一个寄存器并添加几个词,我可以关闭优化并可能使它变得更糟。将操作系统放在它前面,它会变得更糟。如果我将指针设为 char,那么编译器会生成 movb *$177564, r0; bge ...,它会烧录一个寄存器,但大小与 tstb/bpl 相同。打孔状态和打孔缓冲区被定义为带有未使用位的 16 位寄存器,因此这样定义它们并没有错,必须知道将 16 位寄存器作为字节访问是安全的。
  • 如果我们想争论速度,编译器可以展开循环,不使用寄存器来提供 tty 缓冲区,只是将字节推入 movb $060,*$0177566,总体上会消耗更多指令空间但速度更快.它是一个 C 编译器,实际上它在 C 编译器中做得很好。对于高级语言的任何应用程序也是如此,您总是可以找到“改进”输出的调整。
  • 但是,OQ 正在谈论学习用汇编程序编程。我只是指出了一种更好的方法。
  • 明白,汇编程序暗示是的,裸机是真正的目标。

标签: assembly emulation simulator bare-metal pdp-11


【解决方案1】:

我认为问题在于没有正确使用 DL11。你不能在任何时候给它一个角色。您必须测试控制寄存器中的“就绪”标志。然后,当它准备好发送字符。此外,您无法可靠地从数据寄存器中读回值。然后您将该字符用作内存指针(那里肯定会有内存,但写入它可能不是您想要的)。

您可能也有兴趣查看Retrocomputing Stack Exchange 站点。我可能不是唯一一个有 PDP-11 经验的人,但我可能在这里。

【讨论】:

  • 明白了,有些模拟器可以绕过init直接进入tx缓冲区。更大的问题是我是否甚至在正确的路径上远程,我是否可以在 64K 地址空间内寻址并点击这些声称具有大于 16 位地址的外围设备,或者是否有一些其他硬件我必须先痒/设置进行这些访问以生成额外的地址位?
  • 有没有一种简单的方法来确定我是使用 177xxx 类型的地址来寻址外围空间还是内存空间?
  • 裸机上高于(或等于)176000 的所有正常引用都引用了 I/O 页面。唯一的情况是,如果您打开了内存管理。
  • 搞定了!谢谢!只需要一个启动或信心我大致在正确的方向。现在可以将字符打印到控制台。
  • 你应该做的是将结果写下来作为未来寻求者寻找的问题的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多