本文写于 2018年11月02日,距今已超过 1 年,距 2020年03月27日 的最后一次修改也已超过 3 个月,部分内容可能已经过时,您可以按需阅读。如果图片无法显示或者下载链接失效,请给我反馈,谢谢!


5 3 投票数
评分

一开始其实我是一头雾水的,完全不知道要干什么,不过看了几个Example之后,也自己能猜的大概,然后试试,果真如此,非常开心。

下面就来一句句地实现。

首先指令是这样的格式:

1541157879294

现在是我来设计指令,那一切都是听我的,OP-CODE就完全是我自己定义的了,我想让他是多少就是多少。

第一条指令是INL,就是INPUT的低 $8$ 位送到寄存器DR,我想让这句话的OP-CODE是 $001$。

RS在这里是不适用的,因为没有源寄存器,就是从I/O获得的数据,我用 $XX$ 表示。

RD是目标寄存器,是编码的时候确定的,我用 $YY$ 表示。

$0010XXYY$ 就是这条指令。

由于 $XXYY$ 是不确定的,所以显然不能用来散转,那么散转的指令就应该是 $0010$,是 $4$ 位操作码,因此,运用散转规则,得到的散转地址是 $11001000000$。

1541161049500

散转地址用 $16​$ 进制表示,就是 $640​$。

这意味着,我第一句指令,应该写在散转地址为 $640$ 的地方。

这之前的都不需要动,程序复位以后这两句话是没错的。

1541161146438

找到微地址为 $640$ 的地方。

这里要执行一句话,是从I/O到寄存器,取低 $8$ 位,也就是可以认为是偶字节传递。

目的编码应该是通用寄存器。

1541161258994

原编码应该是I/O

1541161277621

因为是取第 $8$ 位,所以可以认为是偶字节传递。

1541161303841

这条指令到这里就执行完了,是一条长度为 $1$ 的指令。

因此,执行完以后,$\mu PC$ 需要做结尾变址,且 $PC = PC+1$。

1541161359338

1541161390448

单击“修改”,这条指令就被录入了,是在 $640$ 的地方。

1541161444093

接下来去指令系统定义这条指令。

这条指令的助记码是INL,需要的操作数只有一个寄存器R0,长度为 $1$。

指令码的话,如上所言,我定义的是 $0010XXYY$,用 $16$ 进制表示就是 $2X$,不妨就设置为 $20$。

那么,这条指令就应该被定义为:

INL R0 20 1

事实上,正如上面说的,指令码是 $2X$,所以其实定义为 $22$ 或者 $29$ 或者其他的形式都是可以的,最后程序装载、运行得到的散转地址都是 $640$,都能够正常运行。

为此,我还特意尝试过,确实是可以的。

15411618102721541161834356

但是定义操作码为 $30$ 显然不行,那就散转到 $660$ 去了。

类似地,定义第二条指令。

OUTL SR,是将源寄存器的低 $8$ 位取出,输出到I/O区域。

上面我用掉了 $001$,现在我想用 $010$。

那么这条指令就是 $0100XXYY$,取 $0100$ 进行散转,得到的散转地址是 $11010000000$,用 $16$ 进制表示就是 $680$,所以这一条指令应该写在散转地址为 $680$ 的地方。

是将寄存器的值输出到I/O,所以源地址是寄存器,目的地址是准双向输入输出,取的是低 $8$ 位,所以总线规则是偶字节传递,这是单条指令,执行完就好了,所以 $PC++$ 且 $\mu PC$ 是结尾变址回到 $0001$。

1541162560465

1541162576951

类似地,定义指令系统。

指令码应该是 $0100XXYY$,所以就是 $4X$,我定义的是 $40$。

OUTL R0 40 1

第三条指令,JMP

下面轮到 $011$ 了,那就是 $11011000000$,换成 $16$ 进制是 $6C0$。

因为地址是 $16$ 位的,所以势必需要分批次将数据读入。

且,这条指令的长度为 $3$,其中第 $1$ 个字节是指令,后面 $2$ 个字节都是数据,因此,应该要做 $PC=PC+3$。

第 $1$ 步,由于要读内存,所以要先取出 $PC$ 的值放到 $AR$,这时候 $PC$ 做第 $1$ 次递增,微地址递增。

因此,指令是 $4307C0$。

第 $2$ 步,将内存里面的值取出一个字节来,放到低位,那就相当于是奇字节到偶字节,我放到了寄存器BX里面。

这时候,源地址就是内存,注意是RAM而不是ROM,所以选择了源是MRD以后,需要选上E/M,目的地址是我选择了BX, 都无所谓,总线规则是奇字节到偶字节。

因此,指令是 $850400$。

第 $3$ 步,和第 $1$ 步是一样的,指令是 $4307C0$。

第 $4$ 步,要读内存里面的下一个字节了,放到高位,那就相当于是奇字节到奇字节,与第 $2$ 步是类似的,只要稍微改动一点,指令是 $840400$。

第 $5$ 步,数据准备完毕就可以跳了,跳的本质上就是用跳转到的地址覆盖掉 $PC$ 里面的值,这样的话下一次 $PC$ 取指取出来的就是跳过去那个地方的下一条指令了。

所以,执行的是,$PC$ 装载。

我是把数据放在BX的,所以应该是源地址选择ALU

1541164023950

ALU是算数逻辑单元,现在我不需要计算 $A+B$ 或者 $A \& B$之类的东西,我只想要BX的值,所以选择的是

1541164042090

目的地址应该是选择 $PC$ 装载。

1541164088433

微变址是结尾变址,因为已经执行完了。

$PC$ 装载了,自然也不存在保持还是增量这一说。

1541165207171

因此,指令是 $C039F2$。

1541165227107

回去定义指令系统。

操作数是内存,所以是*,指令的长度是 $3$,操作码我刚才定义的是 $0110$,也就是$6X$,所以我写的是 $60$。

JMP * 60 3

指令全部设计好了,回过头看一眼,所有的微地址都是唯一的,不冲突,所以满足要求。

下面就可以编写汇编代码了。

这个就非常简单了。

data    segment         ;将程序装载到数据存储器
        assume ds:data
        org   0
start:  INL    r0
        OUTL   r0
        JMP   start
data    ends
        end   start

装载,看一眼,好像还挺正常。

1541164364136

1541164373625

微单步执行,正常取出第 $1$ 条指令 $20$,散转,得到 $640$,跳过去了。

1541164434840

然后执行INL,我输入的是 $5936$,取低 $8$ 位,放到了寄存器。

1541164507863

然后正常回去,取下一条指令,并产生下址。

15411645549851541164563465

我重置I/O为 $0000$,观察得到低 $8$ 位输出成功。

1541164600366

然后是JMP

15411647089741541164725499

这时候BX的值已经是要回去的地址了,$0000$,然后ALUBX的值存放到PC

1541165285804

然后就跳回去了,回到起点了,$0000$。实现了循环往复。

1541165305454

程序到此就结束了。

最后完整的代码附于本文文末。

下面就是画指令流程图。

20181102214508

机器指令格式在上面已经解释过了。

INL是 $XXX0YYZZ$,OUTL是 $XXX0YYZZ$,JMP是 $XXX0YYYY[ADDR][ADDR]$。

至此,作业就写完了。

下面玩一些好玩的。

例如,我想从输入获得一个数,放到AX,从输入获得一个数,放到BX,然后执行 $AX+BX$,结果存到SP

1541166994002

15411669433391541166960827

1541166973579

也是完全可以的。

最后附上代码:

data    segment         ;将程序装载到数据存储器
        assume ds:data
        org   0
start:  INL    r0
        OUTL   r0
        JMP   start
data    ends
        end   start
INL      R0                  20     1
OUTL     R0                  40     1
JMP      *                   60     3
微地址 微指令 表达式 μPC
0000 000000 +1
0001 0307C0 AR=PC +1
0002 800405 IR=RAM 0600
0640 4F0392 REG=IO, PC++ 0001
0680 4B0692 IO=REG, PC++ 0001
06C0 4307C0 AR=PC, PC++ +1
06C1 850400 BX=RAM +1
06C2 4307C0 AR=PC, PC++ +1
06C3 840400 BX=RAM +1
06C4 C039F2 PC=B 0001
5 3 投票数
评分
17条留言
订阅评论
提醒
guest

在点击发表评论按钮时,网络请求的数据包含浏览器版本、操作系统版本和 IP 地址;您的网络服务提供商、雇主或学校、政府机构可能会看到您的访问活动;根据浏览器默认行为、操作系统设置和安全防护软件的设置不同,您的浏览器可能会也可能不会在本地 Cookies 缓存您输入的用户名、邮箱以便下次评论使用。

请对自己的言行负责。

您想以什么身份发表评论
邮箱将在您的评论被回复时给您通知
(可选)如果您也有个人网站,不妨分享一下
我对这篇文章的评分
这篇文章给您带来多大帮助
17 评论
内联反馈
查看所有评论
hhh
hhh (@guest_2949) Chrome 87.0.4280.88 Mac OS X Lion 10_15_7
游客
2021年1月7日 16:23
我对这篇文章的评分 :
     

ROM和RAM的区别是什么啊 是指令放在ROM中 数据放在RAM中吗

hhh
hhh (@guest_2917) Chrome 87.0.4280.88 Mac OS X Lion 10_15_7
游客
2021年1月5日 11:04
我对这篇文章的评分 :
     

不太理解为什么 JMP addr是从内存中读地址 为什么不是直接把addr赋值给PC