6

在大学的最后一个学期,我在计算机语言课上的老师教我们一门名为Whitespace的深奥语言。为了在非常繁忙的日程(期中考试)中更好地学习这门语言,我用Python编写了一个解释器汇编器。一种汇编语言旨在方便编写程序,并使用给定的汇编助记符编写了一个示例程序

现在是夏天,一个新项目已经开始,目标是为 Whitespace 0.3 重写解释器和汇编器,之后会有进一步的发展。由于比以前有更多的时间来设计它,因此这里为您提供了一个大纲,该大纲为汇编语言提供了一组经过修改的助记符。这篇文章被标记为 wiki 供他们讨论。

你过去有过汇编语言的经验吗?是否有一些您认为应该重命名为不同的指令?您是否发现自己跳出框框思考并使用与命名助记符不同的范式?如果您对这些问题中的任何一个问题的回答都是肯定的,那么这里非常欢迎您。感谢主观回答!


堆栈操作(IMP:[空格])

堆栈操作是更常见的操作之一,因此 IMP [Space] 很短。有四个堆栈指令。

hold N       Push the number onto the stack
copy         Duplicate the top item on the stack
copy N       Copy the nth item on the stack (given by the argument) onto the top of the stack
swap         Swap the top two items on the stack
drop         Discard the top item on the stack
drop N       Slide n items off the stack, keeping the top item

算术(IMP:[Tab][Space])

算术命令对栈顶的两项进行运算,并用运算结果替换它们。推送的第一个项目被认为是操作员的左侧。

add          Addition
sub          Subtraction
mul          Multiplication
div          Integer Division
mod          Modulo

堆访问(IMP:[Tab][Tab])

堆访问命令查看堆栈以查找要存储或检索的项目的地址。要存储项目,请先推送地址,然后推送值并运行存储命令。要检索项目,请推送地址并运行检索命令,这会将存储的值放置在堆栈顶部的位置。

save         Store
load         Retrieve

流量控制 (IMP: [LF])

流量控制操作也很常见。子程序由标签标记,以及条件和无条件跳转的目标,通过这些标签可以实现循环。程序必须通过 [LF][LF][LF] 结束,这样解释器才能干净地退出。

L:           Mark a location in the program
call L       Call a subroutine
goto L       Jump unconditionally to a label
if=0 L       Jump to a label if the top of the stack is zero
if<0 L       Jump to a label if the top of the stack is negative
return       End a subroutine and transfer control back to the caller
halt         End the program

I/O (IMP: [Tab][LF])

最后,我们需要能够与用户交互。有读写数字和单个字符的 IO 指令。有了这些,可以编写字符串操作例程。读取指令从栈顶获取存储结果的堆地址。

print chr    Output the character at the top of the stack
print int    Output the number at the top of the stack
input chr    Read a character and place it in the location given by the top of the stack
input int    Read a number and place it in the location given by the top of the stack

问题:您将如何重新设计、重写或重命名以前的助记符,原因是什么?

4

3 回答 3

4

我认为我建议的第一个更改是将hold 和 drop 分别更改为 push 和 pop。

然后也许我会将 copy 重命名为 dup (我认为这是面向堆栈的语言中此操作的最常见名称)。

我有点不解,为什么你经常用一个简短的单词解释与助记符不同。例如助记符是保存,解释是存储。助记符是Load,解释是Retrieve。顺便说一句,这两个助记符没有向我充分解释。保存什么在哪里?从哪里加载什么?(编辑问题随后已被编辑以明确这些含义)

感谢您的有趣帖子。

于 2010-05-25T01:10:06.350 回答
3
  • 按 #n,以明确 n 是立即数。
  • 我认为“交换”有时是“exc”或“exch”。
  • “保存”通常是“st”(商店)
  • “负载”通常是“ld”
  • “call”也可以是“jsr”或“bl”。
  • “goto”通常是“jmp”或“bra”
  • "if=0" 通常是 "beq"
  • "if<0" 通常是 "blt"
  • “return”通常是“ret”或“blr”
  • 在 CPU 的上下文中,“exit”通常是“halt”/“hlt”。
  • “print chr”和“print int”可以是“print.c”和“print.i”。有很多方法可以指定指令变体,但通常不在操作数中。

编辑:

如果您不介意使用 CISCy 语法将操作码和寻址模式混为一谈,

  • “推(sp)”而不是“复制”
  • “push N(sp)”而不是“copy N”(模乘以字长)
  • “push *(sp)”而不是“load”(除了它在推送加载的值之前会弹出)
  • “pop *1(sp)”而不是“push”(除了它实际上弹出两次)

另一方面,基于堆栈的代码通常将 push 和 pop 视为隐式。在这种情况下,“imm n”(立即)而不是“push”。那么所有的栈操作都是纯粹的栈操作,很好,也很一致。

我不知道我会怎么写“drop N”——这个描述听起来像是“drop 1”不等同于“drop”,这看起来很奇怪。

于 2010-05-25T03:31:26.980 回答
1

我不确定我是否完全理解你的问题,所以如果我不在基地,请原谅我。

除了您的堆栈之外,我可能会添加一个“状态寄存器”,其中包含由算术运算符设置的各种不同标志(如进位、溢出和零)。

然后我会添加测试这些标志的“if”表格。

我将添加位移和旋转(左右)指令,以及对位进行操作的 AND/OR/XOR/NOT 操作。

您很可能希望进行某种内存访问,除非您希望 I/O 指令将内存视为一个值流,以获得良好的老式图灵机感觉。

于 2010-05-25T03:21:39.613 回答