天天看点

【西电微电子计算机组成原理】lc-3 上机题:机器码求和并输出十六进制

问题一:12个整数求和的实现:

要求:将寄存器累加值送到控制台进行显示,显示方式采用16进制即可,并给出显示截图;

题目来自康老师文件,以及作业要求是机器码,汇编码的是下一次上机

实现求和

提示:这里描述项目中遇到的问题:

这个是题目给的代码,,

0011 000000000000 ; Start at x3000
1110 001011111111 ; R1 x3100 (PC+0xFF)
0101 011011100000 ; R3 0
0101 010010100000 ; R2 0
0001 010010101100 ; R2 12
0000 010000000101 ;若 Z, 转到 x300A (PC+5)
0110 100001000000 ; 将下个数字加载到 R4
0001 011011000100 ;加到 R3= R3+R4
0001 001001100001 ; R1累加 (指针)
0001 010010111111 ; R2减一 (计数器)
0000 111111111010 ;转到 x3004 (PC-6)
           
如果不需要输出直接到这里就行

实现十六进制输出

求和:

0011 000000000000 ; Start at x3000
1110 001011111111 ; R1 x3100 (PC+0xFF)
0101 011 011 1 00000 ; R3 0
0101 010 010 1 00000 ; R2 0
0101 000 000 1 00000 ; R0 0
0001 010010101100 ; R2 12
0000 010 000000110 ;若 Z, 转到(PC+6)
0110 100 001 000000 ; 将下个数字加载到 R4
0001 011 011 000100 ;加到 R3= R3+R4
0101 000 000 1 00000 ; R0 0
0001 001 001 100001 ; R1累加 (指针)
0001 010 010 111111 ; R2减一 (计数器)
0000 111 111111001 ;转到(PC-7)
0001 000 011 000000;将r3给到r0 因为输出指令trap x21是输出r0的,得把结果给到r0;
;转十六进制地址
0000 111 001000001 ;3050,at300d pc+1000001 这里改改,十六进制文件执行地址在x3050,这里直接跳转过去。
           

十六进制:

大概就是减去16,然后取余数,进位的再同理取余;以及加个判断是否为0的条件会简化运行

0011 000001010000 ; Start at x3050
;initialize
0101 001 001 1 00000 ;r1 0 (十位
0101 010 010 1 00000 ;r2 0 (百位
0101 011 011 1 00000 ;r3 0 (千位
0101 100 100 1 00000 ;r4 0 (个位
0101 101 101 1 00000 ;r5 0
0101 110 110 1 00000 ; R6 0 (判断用
0101 111 111 1 00000 ; R7 0
;first 
0001 000 000 1 00000 ; R0 r0   [001
;0000 010 000001111;if z ,turn to next pc+15
0000 100 000000011;若n,转(pc+3
0001 000 000 1 10000;r0=r0-16
0001 001 001 1 00001;r1++
0000 111 111111011;turn to pc-5
0001 000 000 1 01111;r0=r0+16 [001
0001 000 000 1 00001;
0001 001 001 111111;r1=r1-1
;digit or alphabet 就是字母A(10)的ascii和数字的是不一样的嘛,判断一下转去加上数字得到对应ascii就能输出
;0001 110 000 1 00000 ;r6 r0
0001 110 000 1 10111 ;r6=r6-9
0000 100 000000101;if n,r0+48 turn to pc+5;if pz,r0+55
0001 000 000 1 01111;r0+55 这里当时上机还不会别的代码,直接+15+15+15+10来实现的;之后的也是笨方法,如果会asm来写就简单很多
0001 000 000 1 01111
0001 000 000 1 01111
0001 000 000 1 01010
0000 111 000000100;turn to pc+3
0001 000 000 1 01111;r0+48
0001 000 000 1 01111
0001 000 000 1 01111
0001 000 000 1 00011
0001 100 000 1 00000 ;r4 r0 store 各位
;接下来的也是差不多,复制粘贴改改寄存器的代号就行
;second
0001 001 001 1 00000 ; R1 r1   [001
0000 010 000001110;if z ,turn to next 
0000 100 000000011;若n,转(pc+3
0001 001 001 1 10000;r1=r1-16
0001 010 010 1 00001;r2++
0000 111 111111010;turn to pc-6
0001 001 001 1 01111;r1=r1+16 [001
0001 001 001 1 00001;
0001 010 010 1 11111;r2=r2-1
;digit or alphabet
0001 110 001 1 10111 ;r6=r1-9
0000 100 000000101;if n,r1+48 turn to pc+5
0001 001 001 1 01111;r0+55
0001 001 001 1 01111
0001 001 001 1 01111
0001 001 001 1 01010
0000 111 000000100;turn to pc+3
0001 001 001 1 01111;r1+48
0001 001 001 1 01111
0001 001 001 1 01111
0001 001 001 1 00011
;下面的代码注释就乱了别看注释
;third
0001 010 010 1 00000 ; r2   [001
0000 010 000001110;if z ,turn to next 
0000 100 000000011;若n,转(pc+3
0001 010 010 1 10000;
0001 011 011 1 00001;
0000 111 111111010;turn to pc-6
0001 010 010 1 01111;r1=r1+16 [001
0001 010 010 1 00001;
0001 011 011 1 11111;r2=r2-1
;digit or alphabet
0001 110 010 1 10111 ;r6=r1-9
0000 100 000000101;if n,r1+48 turn to pc+5
0001 010 010 1 01111;r0+55
0001 010 010 1 01111
0001 010 010 1 01111
0001 010 010 1 01010
0000 111 000000100;turn to pc+3
0001 010 010 1 01111;r1+48
0001 010 010 1 01111
0001 010 010 1 01111
0001 010 010 1 00011
;这里改个跳转加的偏移码,因为它没有进位了
;forth
0001 011 011 1 00000 ; r3  [001
0000 010 000001100;if z ,turn to next 
0000 100 000000010;若n,转(pc+2
0001 011 011 1 10000;r1=r1-16
0000 111 111111011;turn to pc-5
0001 011 011 1 01111;r1=r1+16 [001
0001 011 011 1 00001;
;0001 010 010 1 11111;r2=r2-1
;digit or alphabet
0001 110 011 1 10111 ;r6=r1-9
0000 100 000000101;if n,r1+48 turn to pc+5
0001 011 011 1 01111;r0+55
0001 011 011 1 01111
0001 011 011 1 01111
0001 011 011 1 01010
0000 111 000000100;turn to pc+3
0001 011 011 1 01111;r1+48
0001 011 011 1 01111
0001 011 011 1 01111
0001 011 011 1 00011

;output分别从高位到低位输出
0001 000 011 1 00000 
1111 0000 001 00001;output r0
0001 000 010 1 00000 
1111 0000 001 00001;output r0
0001 000 001 1 00000 
1111 0000 001 00001;output r0
0001 000 100 1 00000 
1111 0000 001 00001;output r0

1111 0000 00100101;halt
           

然后注意nzp判断是基于上一个寄存器存入的内容就行了。

以及自己写的文件可以自己加上后缀这样编辑器就可以直接打开了,就不用每次都复制粘贴;比如你写的二进制就加.bin;十六进制加.hex;汇编写的加.asm。

这里附上测试数据:

3100 ;start at x3100
0001
0002
0003
0004
0005
0006
0007
0008
0009
000a
000b
000c`
           

问题三:5.5例子:字符数统计

课本也有,就是黑黄皮那本,计算机系统概论;主要还是要求的十六进制输出,所以之前写的就一劳永逸,跳到十六进制文件地址输出就行。

0011 000000000000   ;start at 3000
0101 010 010 100000 ;初始化
0010 011 000010000  ;x3012的内容地址导入r3
1111 0000 00100011  ;input
0110 001 011000000  ;r1=r3
0001 100 001 111100 ;eot?就是判断结束符0004
0000 010 000001000  ;if z,output
1001 001 001 111111 ;-r1
0001 001 001 100001 ;r1+1
0001 001 001 000000 ;r1=r1+r0
0000 101 000000001  ;ifnp,pc+1
0001 010 010 100001 ;r2++
0001 011 011 100001 ;r3++
0110 001 011 000000 ;r1=r3
0000 111 111110110  ;pc-10
0010 000 000000100  ;
0001 000 000 000010 ;r0=r0+r2
0000 111 000111111;转16进制(上边提到了)入口3050 x3010 pc+11 1111 
1111 0000 00100101  ;halt在这加断点单步看
0011 000100000000;3100,at x3012
           

测试数据:

3100;start
;都是大写字母,与小写区分(但题目没说是否区分大小写
0041;A
0042;B
0043;
0044;
0045;
0041;
0041;
0043;
0047;
0004;eot
           

好的到这就结束了,啥啥指令跳转的绕晕了小破站有个视频讲的挺好的。

继续阅读