我的任务是用C语言为VM编写代码。它可以读入文件并根据文件输入执行操作。从我所给出的例子中,似乎每条指令的第一个数字与命令(1 - load,2 - add,3 - store等)有关,第二个数字是地址位置。
到目前为止,我对玛丽和我编写的程序感到很满意,例如,下面的代码用于将2个数字相乘。它还检查输入的数字是否大于0。这很重要
negloop1, clear
store a
input
store a
skipcond 800
jump negloop1
load a
output
negloop2, clear
store b
input
store b
skipcond 800
jump negloop2
output
load result
clear
store result
load result
add a
store result
load b
subt one
store b
skipcond 400
jump 012
load result
output
halt
a, dec 0
b, dec 0
one, dec 1
result, dec 0
字符串
我需要写一个程序,用一种语言做同样的事情,这种语言可以被一个用c语言写的微型虚拟机读懂。它具有由数字1 - 11中的操作码表示的以下指令(加载、添加、存储、子、输入、输出、停止、jmp、skipz、skipg、skipl)。所以指令应该是这样的。
5 5 //in 5
6 7 // out 7
3 0 // store 0
7 0 // halt
型
我不知道我该如何把我的程序翻译成这种类型的指令。我需要实现跳转命令,但无法引用要跳转到的行。另外,似乎没有一个与“clear”等效的命令。
1条答案
按热度按时间xienkqul1#
首先,从逻辑上讲,一些最有用和最复杂的运算是二元运算符,它们是三个操作数,在某种意义上它们使用两个源和一个目的地;它们像加法一样有用,并且由于所需的操作数的数量而复杂。
像玛丽这样的单操作数机器几乎肯定有累加器。它可以指定其中一个源,然后将累加器用于第二个源操作数,也可以用于目的操作数以捕获结果.(正如@Peter所指出的,一个操作数机器也可以是一个堆栈机器。)
玛丽已经是这样一台机器:我们来看看二元运算符是如何执行的,在玛丽中,它们是
add
和subt
-这些指令指定一个(源)内存操作数,另一个源操作数用作累加器,而结果则被捕获回累加器。玛丽也有“一元”操作,即加载和存储,提供一个内存操作数(分别作为源或目标),也与累加器一起工作。
我不知道我该如何将我的程序翻译成这种类型的指令。
当我们将C代码转换为程序集,或者将一个程序集转换为另一个程序集时,需要确定三种逻辑构造来进行转换:
首先,我建议您将注意力集中在如下代码序列上:
字符串
对于上述内容,您需要将
a
和result
Map到存储,这涉及到变量的转换。因此,例如,您可以选择将a
放入位置0,(将b
放入位置1),并将result
放入位置2。(We我不能告诉您这些位置是否可以免费使用,但由于您指定了哈佛Architecture,因此我们假定您可以使用从0开始的数据位置。)
接下来,您将需要使用已经完成的变量Map来翻译执行完整加法赋值语句的指令。比如说:
| 已Map的变量|您的虚拟机| Your VM |
| --|--| ------------ |
| 负载2| 1个2个| 1 2 |
| 添加0|二0| 2 0 |
| 商店2| 3个2| 3 2 |
最后,由于这是一个简单的赋值语句,因此通常将它放在与其他代码相对的位置,就像它在玛丽程序集中一样。
循环要求您更仔细地查看控制流构造,但玛丽已经具有反映在VM中的相对原始的控制结构。
型
此循环执行以下操作(在C语言中):
型
目的是重复加法,直到
b
(向下计数)变为零。转换到您的虚拟机应该很简单。由于玛丽代码使用
SkipCond 400
,它在零上跳过-而被跳过的是jump
,那么从语义上讲,它意味着在非零上的jump
。但是,由于玛丽使用的汇编程序带有我认为您没有的标签,因此您需要为
jump
指令的操作数提供一个计数或值,而不是标签。对于jump
的操作数有两种基本的体系结构选择,一种是绝对地址(这是玛丽所做的),另一种是pc相对偏移量(大多数其他机器都会做)。一旦您决定了操作数的含义(操作数如何标识目标),那么您就需要一个编码(即如果是相对于PC,则如何对反向分支的负数进行编码)。您可以稍微考虑一下您希望
in
(和out
)执行的操作。玛丽对此不接受操作数;它使用累加器作为目标input
和源output
。当然,您可以让in
&out
使用操作数来代替,因此在玛丽中我们可以说两条指令:in; store a
,则只有一条指令,即in a
,或5个0。