跟着void学计组

时间限制: 1000 ms 内存限制: 65536 kb
总通过人数: 0 总提交人数: 3
Special Judge

题目背景

作为一个6系的学生,void正在学计算机组成

计组中,需要编写MIPS汇编指令来对自己的CPU进行测试

现在void找到了你,他想请你帮他编写一个程序,模拟mips指令

补充知识

这些指令的操作对象只包括寄存器

寄存器一共有32个,用$0~$31表示,也可以称呼$x$号寄存器

其中,零号寄存器有一个特殊的性质,无论对它进行怎样的赋值,它的值都始终为0,不会改变

其余的寄存器均可以自由的赋值

在程序一开始的时候,所有寄存器的值均为0


void想请你实现的MIPS指令集包含8条指令,它们的格式是这样的:

add指令

add $1,$2,$3
#井号表示注释,相当于C中的//
#上面这句话的意思是,将2号寄存器和3号寄存器的值相加,存入1号寄存器

sub指令

sub $1,$2,$3
#将2号寄存器的值减去3号寄存器的值,存入1号寄存器

ori指令

ori $1,$2,2106
#将2号寄存器的值或上2106,存入1号寄存器

li指令

li $1,2106
#将2106加载到1号寄存器,现在$1==2106,也就是0x0000083a

lui指令

lui $1,2106
#将2106加载到1号寄存器的高16位,低16位赋值为0
#2106的四位十六进制表示为0x083a
#那么用十六进制来表示$1为:0x083a0000

beq指令(与mips稍有区别,不使用label)

beq $0,$1,3#如果$0和$1相等,则程序从下一条指令开始数三条指令再开始执行
nop
nop
nop
li $1,10#如果$0和$1相等的话,就从这一条开始执行
nop

syscall指令

#本题中的syscall仅仅用于结束程序
#当$2的值为10的时候,执行syscall,这个mips程序就会结束,可以理解为return 0;
#其他情况下均视为不起作用,相当于nop
li $1,20
li $2,10
syscall #程序在这里结束
li $3,5 #这一条不会执行

nop指令

nop
#这条指令没有任何作用,直接执行下一条就好

输入格式

输入共$n+1$行

第一行一个整数$n$,表示读入指令的行数

后续$n$行,每行一条指令(注意指令后可能会有注释,但保证每一行必有一条指令, 这与原题不同

输出格式

输出有三种情况

  1. 程序能正常结束(使用syscall),则输出一行program is finished running,然后每行4个,以空格分割,以十六进制输出32个寄存器的值(使用小写字母,补零至八位)
  2. 程序运行到最后一条指令,如果没有正常使用syscall结束,则输出一行program is finished running(dropped off bottom),然后和第一条一样,输出32个寄存器的值
  3. 程序无法结束,一直在运行,执行的指令条数超过了 $1e5$ 条,则输出一行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

不会有多余的空格输入,指令名称之后有一个空格,寄存器和数字均以英文逗号隔开

Bug 代码

注:$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}}$

相关推荐