自己动手写CPU - 6

自己动手写CPU_qq85058522的博客-CSDN博客

CPU不加功能了,但汇编器可以有。

下面写一个把汇编(助记符)翻译成机器码的小工具。Python熟些,就用它了。很简单,就是字符串替换。直接上代码。

import sys

if len(sys.argv) != 2:
    print("usage: python assembler xxx.asm")
    exit(0)
code_path = sys.argv[1]
print('processing %s' % code_path)

op_dict={'ldr':0,'mov':0,'add':1,'sub':2,'and':3,'or':4,'cmp':5,'beq':6,'bne':7}
for i,line in enumerate(open(code_path).readlines()):
    try:
        line = line.split('//')[0]
        line = line.replace('bne', "bne r7 ")
        line = line.replace('beq', "beq r7 ")
        (op,in1,in2) = line.lower().replace(',',' ').split()
        # print(op,in1,in2)

        bin_op = op_dict[op]
        bin_in1 = int(in1[1:])
        bin_in2 = int(in2[1:])
        if '#' in in2: bin_in2 += 0x0800   #1<<11: [11]表示立即数

        code = (bin_op<<12) + (bin_in1<<8) + (bin_in2)
        print("%d: op = 'h%04x" % (i,code))

    except:
        print("@@@line %d: error(s) occured."%i)

从命令行运行时传入xxx.asm即可,否则会报错,提示usage: python assembler xxx.asm。

主要代码就下面这10行:

        line = line.split('//')[0]
        line = line.replace('bne', "bne r7 ")
        line = line.replace('beq', "beq r7 ")
        (op,in1,in2) = line.lower().replace(',',' ').split()

这4行对指令做预处理,去掉注释并按空格逗号分隔成3段。这里bne/beq只有两段,稍做转换,这样所有指令可以对齐,方便使用相同的规则来处理。

        bin_op = op_dict[op]
        bin_in1 = int(in1[1:])
        bin_in2 = int(in2[1:])
        if '#' in in2: bin_in2 += 0x0800   #1<<11: [11]表示立即数

这4行是指令转码。按op分段解码,转换成二进制码。

        code = (bin_op<<12) + (bin_in1<<8) + (bin_in2)
        print("%d: op = 'h%04x" % (i,code))

这2行是将3个分段的二进制加起来,形成一条机器码。这里打印出来,然后复制到FPGA环境,就可以编译下载并运行新程序了。

把一节的程序拿过来试试:

ldr r0,#0
ldr r1,#1
add r0,r1
add r1,#1
cmp r1,#11
bne #2
mov r7,r7   //while(1);

输出

processing r:/code.asm
0: op = 'h0800
1: op = 'h0901
2: op = 'h1001
3: op = 'h1901
4: op = 'h590b
5: op = 'h7f02
6: op = 'h0707

可以用了。

你可能感兴趣的:(自己动手写CPU,fpga开发)