作为一个6系的学生,void正在学计算机组成
计组中,需要编写MIPS汇编指令来对自己的CPU进行测试
现在void找到了你,他想请你帮他编写一个程序,模拟mips指令
这些指令的操作对象只包括寄存器
寄存器一共有32个,用$0~$31
表示,也可以称呼$x$号寄存器
其中,零号寄存器有一个特殊的性质,无论对它进行怎样的赋值,它的值都始终为0,不会改变
其余的寄存器均可以自由的赋值
在程序一开始的时候,所有寄存器的值均为0
void想请你实现的MIPS指令集包含8条指令,它们的格式是这样的:
add $1,$2,$3
#井号表示注释,相当于C中的//
#上面这句话的意思是,将2号寄存器和3号寄存器的值相加,存入1号寄存器
sub $1,$2,$3
#将2号寄存器的值减去3号寄存器的值,存入1号寄存器
ori $1,$2,2106
#将2号寄存器的值或上2106,存入1号寄存器
li $1,2106
#将2106加载到1号寄存器,现在$1==2106,也就是0x0000083a
lui $1,2106
#将2106加载到1号寄存器的高16位,低16位赋值为0
#2106的四位十六进制表示为0x083a
#那么用十六进制来表示$1为:0x083a0000
beq $0,$1,3#如果$0和$1相等,则程序从下一条指令开始数三条指令再开始执行
nop
nop
nop
li $1,10#如果$0和$1相等的话,就从这一条开始执行
nop
#本题中的syscall仅仅用于结束程序
#当$2的值为10的时候,执行syscall,这个mips程序就会结束,可以理解为return 0;
#其他情况下均视为不起作用,相当于nop
li $1,20
li $2,10
syscall #程序在这里结束
li $3,5 #这一条不会执行
nop
#这条指令没有任何作用,直接执行下一条就好
输入共$n+1$行
第一行一个整数$n$,表示读入指令的行数
后续$n$行,每行一条指令(注意指令后可能会有注释,但保证每一行必有一条指令, 这与原题不同)
输出有三种情况
program is finished running
,然后每行4个,以空格分割,以十六进制输出32个寄存器的值(使用小写字母,补零至八位)program is finished running(dropped off bottom)
,然后和第一条一样,输出32个寄存器的值program can't be finished
6
li $1,1 # $1 = n
li $2,1 # $2 = m
add $0,$1,$2
add $3,$1,$2
li $2,10
syscall
program is finished running
00000000 00000001 0000000a 00000002
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
给出部分寄存器的值作为参考
$1\le n \le 127$
$1\le strlen(s) \le200$(s为每一行的字符串)
li,lui,ori指令中的数字,$0\le x \le 65535$
beq指令跳转的范围在程序内,无需考虑非法情况
除了beq指令之外不会涉及负数
输入的所有字母均为小写
寄存器编号为$0~$31
不会有多余的空格输入,指令名称之后有一个空格,寄存器和数字均以英文逗号隔开
注:$type[]$ 存储指令操作类型,$RIJ$ 函数取指令操作数。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<ctype.h>
int n, a[35], end_flag = 0, cnt; // end_flag = 1: 程序正常结束
char s[130][205];
int isnegative(int flag, int t) {
if (flag) return -t;
else return t;
}
void RIJ(int i, int *x, int *y, int *z) {
int t, flag;
for (int j = 1; j <= strlen(s[i]); j++) {
if (!isdigit(s[i][j])) {
if (!isdigit(s[i][j-1])) continue;
if (*x == -1) *x = isnegative(flag, t);
else if (*y == -1) *y = isnegative(flag, t);
else *z = isnegative(flag, t);
}
else {
if (!isdigit(s[i][j-1])) {
if (s[i][j-1] == '-') flag = 1;
else flag = 0;
t = s[i][j] - '0';
}
else t = t * 10 + s[i][j] - '0';
}
}
}
int main()
{
scanf("%d ", &n);
for (int i = 0; i < n; i++)
gets(s[i]);
for (int i = 0; i < n; i ++) {
if (s[i][0] == '#') continue;
char type[5];
int x = -1, y = -1, z = -1;
RIJ(i, &x, &y, &z);
strncpy(type, s[i], 3);
if (strcmp(type, "add") == 0) {
if (x) a[x] = a[y] + a[z];
}
else if (strcmp(type, "sub") == 0) {
if (x) a[x] = a[y] - a[z];
}
else if (strcmp(type, "ori") == 0) {
if (x) a[x] = a[y] | z;
}
else if (strcmp(type, "li ") == 0) {
if (x) a[x] = y;
}
else if (strcmp(type, "lui") == 0) {
if (x) a[x] = y << 16;
}
else if (strcmp(type, "beq") == 0) {
if (a[x] == a[y]) i += z;
}
else if (strcmp(type, "sys") == 0) {
if (a[2] == 10) { end_flag = 1; break; }
}
if ((++cnt) > 1e6) {end_flag = -1; break;}
}
if (end_flag == 1) printf("program is finished running\n");
else if (end_flag == 0) printf("program is finished running(dropped off bottom)\n");
else printf("program can't be finished\n");
if (end_flag != -1) {
for (int i = 0; i < 32; i ++) {
printf("%08x ", a[i]);
if ((i + 1) % 4 == 0) printf("\n");
}
}
return 0;
}
$author:$
原题:$\color{gray}{\mathcal{void}}$
改编/Bug代码:$\color{Tan}{\frak{Orange}}$