关于MIPS上手应知应会-如何把C语言改写为MIPS!

news2025/9/20 16:01:40

文章目录

  • 寄存器
  • 指令
  • 使用技巧
    • 翻译C/C++
      • if/else语句
      • switch语句
      • for循环
      • while 循环
      • do...while循环
      • 一维数组定义与使用
      • 二维数组定义与使用
      • 例 :哈密顿回路
  • 注意
    • 立即数被符号位扩展
  • 参考链接

寄存器

NameReg. NumUsage
z e r o zero zero0constant value =0(恒为0)
a t at at1reserved for assembler(为汇编程序保留)
v 0 – v 1 v0 – v1 v0–v12 – 3values for results(过程调用返回值)
a 0 – a 3 a0 – a3 a0–a34 – 7Arguments(过程调用参数)
t 0 – t 7 t0 – t7 t0–t78 – 15Temporaries(临时变量)
s 0 – s 7 s0 – s7 s0–s716 – 23Saved(保存)
t 8 – t 9 t8 – t9 t8–t924 – 25more temporaries(其他临时变量)
k 0 – k 1 k0 – k1 k0–k126 – 27reserved for kernel(为OS保留)
g p gp gp28global pointer(全局指针)
s p sp sp29stack pointer (栈指针)
f p fp fp30frame pointer (帧指针)
r a ra ra31return address (过程调用返回地址)

指令

第一页

第二页

使用技巧

翻译C/C++

if/else语句

if(a >= b) //Do something...
else if(a < c+b) //Do something...
else //Do something...
# $s0 = a, $s1 = b, $s2 = c
if_begin:
bgt $s1, $s0, if_else1
	# Do something
if_else1:
add $t0, $s1, $s2
bngt $t0, $s0, if_else2
	# Do something
if_else2:
	# Do something
if_end:

switch语句

switch(a) {
    case 2:
        // Do something
       	break;
    case 4:
        // Do something
        break;
    default:
        // Do something
}
# $s0 = a
switch_begin:
	case_2:
	bne $s0, 2, case_4
    	# Do something
    j switch_end
    
    case_4:
    bne $s0, 4, default
    	# Do something
    j switch_end
    
    default:
    	# Do something
switch_end:

for循环

for(int i = 0; i < n; i++) // Do something
# $s0 = n
li $t0, 0
for_begin:
bne $t0, $s0, end_for 
	# Do something
addi $t0, $t0, 1
j for_begin
end_for:

while 循环

int i = a;
while(i < n) {
    // Do something...
    i++;
}
# $s0 = n, $s1 = a, $t0 = i
move $t0, $s1
while_begin:
bne $t0, $s0, end_while
	# Do something
	addi $t0, $t0, 1
j while_begin
end_while:

do…while循环

do {
    i++;
    //Do something
} while(i < n);
# $t0 = i, $s0 = n
li $t0, 1
dowhile:
	addi $t0, $t0, 1
	# Do something
beq $s0, $t0, end_dowhile
j dowhile
end_dowhile:

一维数组定义与使用

int arr[100];
for(int i = 0; i < 100; i++) arr[i] = i;
.data
	arr: .space 400				#长度100的int型数组,总共使用400字节
.text
	# $t0 = i
	li $t0, 0;
	for_begin:
	beq $t0, 100, end_for
		move $t1, $t0
		sll $t1, $t1, 2			# i*4得到偏移的字节数,MIPS按照字节寻址,地址从x00000000, 0x00000004...以此类推
								# 此外MIPS还是小端地址,如果输入0x12345678,那么0x00000002存的是0x56
		sw $t0, arr($t1)		# 这跟直接访问还挺像的
								# 实际上,arr是指一系列空间的首地址,加上偏移量$t1,得到arr[i]的地址
	addiu $t0, $t0, 1
	j for_begin
	end_for:
	
li $v0, 10						# 类似于C/C++中的return 0
syscall

二维数组定义与使用

#include <iostream>
using namespace std;
int arr[64][64];

int main() {
    int m, n;
    cin >> n >> m;
    for(int i = 0; i < n; i++)
    	for(int j = 0; j < m; j++) cin >> arr[i][j];
    for(int i = n-1; i >= 0; i--)
        for(int j = m-1; j >= 0; j--) cout << i << ' ' << j << ' ' << arr[i][j] << endl; 
    return 0;
}
.data
	arr: .space 16384

# 下面两个宏定义与数组大小密切相关,64*64大小的数组是这么做的
# 我们约定$t7, $t8, $t9只在宏定义中使用
.macro setarr(%d, %i, %j)		# 把arr[i][j]设置为d
	sll $t8, $t8, 6
	add $t9, $t8, %j
	sll $t9, $t9, 2
	sw %d, arr($t9)
.end_macro
.macro getarr(%d, %i, %j)		# 把d赋值为arr[i][j]
	sll $t8, $t8, 6
	add $t9, $t8, %j
	sll $t9, $t9, 2
	lw %d, arr($t9)
.end_macro

.text
	# $s0 = n, $s1 = m
	li $v0, 1
	syscall
	move $s0, $v0
	li $v0, 1
	syscall
	move $s0, $v0
	
	# $t0 = i, $t1 = j
	li $t0, 0
	li $t1, 0
	for_in_i:
	beq $t0, $s0, end_for_in_i
		for_in_j:
		beq $t1, $s1, end_for_in_j
			li $v0, 1
			syscall
			setarr($v0, $t0, $t1)
		addi $t1, $t1, 1
		j for_in_j
		end_for_in_j:
	addi $t0, $t0, 1
	j for_in_i
	end_for_in_i:
	
	# $t0 = i, $t1 = j
	subi $t0, $s0, 1 
	subi $t1, $s1, 1
	for_out_i:
	blt $t0, 0, end_for_out_i
		for_out_j:
		blt $t1, 0, end_for_out_j
			getarr($t3, $t0, $t1)
			# 输出$t0, $t1, $t2这里省略了
		subi $t1, $t1, 1
		j for_out_j
		end_for_out_j:
	subi $t0, $t0, 1
	j for_out_i
	end_for_out_j:
	
li $v0, 10						# 类似于C/C++中的return 0
syscall

例 :哈密顿回路

#include <iostream>
using namespace std;

const int MAXN = 10;

int G[MAXN][MAXN];
bool vis[MAXN];
int n, m;
int ans;

int dfs(int i, int start) {
    bool flag = false;
    vis[i] = true;
    cout << i;
    for(int j = 1; j <= n; j++) if(!vis[j] && G[i][j]) {
        dfs(j, start);
    }
    for(int j = 1; j <= n; j++) if(!vis[j]) {
        flag = true;
        break;
    }
    if(G[i][start] && !flag) ans = 1;
    vis[i] = false;
    return 0;
}

int main() {
    cin >> n >> m;
    for(int i = 0; i < m; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u][v] = G[v][u] = 1;
    }

    for(int i = 1; i <= n; i++) {
        dfs(i, i);
        if(ans == 1) {
            cout << 1 << endl;
            return 0;
        }
    }
    cout << 0 << endl;
    return 0;
}
.data
	graph: .space 1024
	vis: .space 512
	endl: .word '\n'

.macro setGraph(%data, %i, %j)
	sll $t8, %i, 4
	add $t8, $t8, %j
	sll $t8, $t8, 2
	sw %data, graph($t8)
.end_macro
.macro getGraph(%ans, %i, %j)
	sll $t8, %i, 4
	add $t8, $t8, %j
	sll $t8, $t8, 2
	lw %ans, graph($t8)
.end_macro

.text
main:
	# $s0 = n
	li $v0, 5
	syscall
	move $s0, $v0
	# $s1 = m
	li $v0, 5
	syscall
	move $s1, $v0
	
	move $t0, $zero
	for_input:
	# for(i = 0; i != m; i++)
	beq $t0, $s1, end_for_input
		li $v0, 5
		syscall
		move $t1, $v0
		li $v0, 5
		syscall
		move $t2, $v0
		li $t3, 1
		setGraph($t3, $t1, $t2)
		setGraph($t3, $t2, $t1)
	addi $t0, $t0, 1
	j for_input
	end_for_input:
	
	li $t0, 1
	for_iter:
	# for(i = 1; i <= n; i++)
	bgt $t0, $s0, end_for_iter
		move $a0, $t0	# $a0 = p
		move $a1, $t0	# $a1 = start
		jal dfs
		beq $s3, 1, print_ans
	addi $t0, $t0, 1
	j for_iter
	end_for_iter:
	
	print_ans:	
	li $v0, 1
	move $a0, $s3
	syscall
li $v0, 10
syscall

dfs:	# $a0 = p, $a1 = start
addi $sp, $sp, -24
sw $ra, 20($sp)
sw $t0, 16($sp)
sw $t1, 12($sp)
sw $t2, 8($sp)
sw $t3, 4($sp)
sw $t4, 0($sp)
	sll $t0, $a0, 2
	li $t1, 1
	sw $t1, vis($t0)
	li $t0, 1
	for_nextpoint:
	# for(i = 1; i <= n; i++) if(graph[p][i] == 1 && !vis[i])
	bgt $t0, $s0, end_for_nextpoint
		getGraph($t1, $a0, $t0)
		bne $t1, 1, nextpoint_continue
		sll $t2, $t0, 2
		lw $t3, vis($t2)
		bne $t3, $zero, nextpoint_continue
			move $t4, $a0
			move $a0, $t0
			jal dfs
			move $a0, $t4
	nextpoint_continue:
	addi $t0, $t0, 1
	j for_nextpoint
	end_for_nextpoint:

	li $t0, 1	
	for_check:
	bgt $t0, $s0, end_for_check
		sll $t1, $t0, 2
		lw $t2, vis($t1)
		beq $t2, $zero, end_function
	addi $t0, $t0, 1
	j for_check
	end_for_check:

	getGraph($t0, $a0, $a1)
	bne $t0, 1, end_function
	li $s3, 1
	
	end_function:
	sll $t0, $a0, 2
	sw $zero, vis($t0)
lw $ra, 20($sp)
lw $t0, 16($sp)
lw $t1, 12($sp)
lw $t2, 8($sp)
lw $t3, 4($sp)
lw $t4, 0($sp)
addi $sp, $sp, 24
jr $ra

注意

立即数被符号位扩展

  • 算术指令 :add addi sub 总是将立即数做符号位扩展即便指令是无符号的;
    乘 、 除 指令 任何情况下都不进行扩展,总是当成 unsigned
  • 逻辑指令:(andi, ori通常处理无符号数)不对立即 数做符号位扩展
  • load / store指令: 地址计算时总是扩展立即数

参考链接

  1. 谈一谈 MIPS 汇编 Challenge 题:找哈密顿回路:(https://flyinglandlord.github.io/2021/09/30/BUAA-CO-2021/Pre/%E8%B0%88%E4%B8%80%E8%B0%88MIPS%E6%B1%87%E7%BC%96Challenge%E9%A2%98/)

  2. 流水线 MIPS 处理器的设计:https://zobinhuang.github.io/sec_learning/Tech_Computer_Architerture/Architecture_6_MIPS_Pipeline/#1_intro_1

  3. 《初学计算机组成原理之MIPS指令集及汇编》: https://blog.csdn.net/weixin_51599896/article/details/123865620

  4. MIPS指令详解:https://blog.csdn.net/weixin_46308081/article/details/115798605

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1355020.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)

一、图的遍历的定义&#xff1a; 从图的某个顶点出发访问遍图中所有顶点&#xff0c;且每个顶点仅被访问一次。&#xff08;连通图与非连通图&#xff09; 二、深度优先遍历&#xff08;DFS&#xff09;&#xff1b; 1、访问指定的起始顶点&#xff1b; 2、若当前访问的顶点…

SoapUI 怎么下载:实用指南

SoapUI Windows 版本下载 今天带大家过一遍 SoapUI 在 Windows 系统下的安装教程吧&#xff01;各位 开发小伙伴 们可以跟着我一起来~ 下载安装包 下载链接&#xff1a;www.soapui.org/downloads/s… 安装 安装非常简单&#xff0c;只需双击它即可启动&#xff0c;安装程序…

CSS效果(工作中常用)

1、css文字溢出省略号 overflow: hidden; // 溢出隐藏 text-overflow: ellipsis; // 溢出用省略号显示 white-space: nowrap; // 规定段落中的文本不进行换行 overflow: hidden; // 溢出隐藏 text-overflow: ellipsis; // 溢出用省略…

深入了解Python中的进程控制和监控技巧,提高系统稳定性

概要 在计算机系统中&#xff0c;进程管理是一个重要的任务&#xff0c;它涉及创建、启动、监控、终止和管理运行中的进程。Python作为一门强大的编程语言&#xff0c;提供了丰富的库和模块&#xff0c;使得进程管理变得相对容易。本文将介绍如何使用Python来实现系统进程管理…

MQTT基础下载使用

1.下载MQTT(MQTT官网) 下载完后在bin目录下启动cmd 控制台输入emqx start&#xff0c;注意&#xff0c;此时控制台是没有反应的&#xff0c;就回你个D&#xff1a;\EMQX。其实已经打开了。 打开桌面上的MQTTX 并新建连接 这是测试的数据 我订阅了一个test1的订阅 并且我发布…

chrome面向服务的架构SOA

chrome 浏览器面向服务的架构 原来的各种模块会被重构成独立的服务&#xff0c;每个服务都可以独在独立的进程中运行&#xff0c;可以在浏览器的任务管理器中看到各种服务。 "面向服务的架构"&#xff08;Service-Oriented Architecture&#xff0c;SOA&#xff09;…

解决mock单元测试中 无法获取实体类xxx对应的表名

错误描述&#xff1a;在执行单元测试时&#xff0c;执行到new Example时抛出异常&#xff0c;提示无法获取实体类xxx对应的表名 Example example new Example(ServeSubscribeRecord.class);Example.Criteria criteria example.createCriteria();criteria.andEqualTo("se…

一步到位:掌握Python中Lambda表达式的5种实用技巧

一步到位&#xff1a;掌握Python中Lambda表达式的5种实用技巧 引言技巧一&#xff1a;单行函数定义技巧二&#xff1a;与内置函数结合技巧三&#xff1a;在数据结构排序中的应用技巧四&#xff1a;作为回调函数技巧五&#xff1a;与函数式编程结合结语 引言 在Python编程的宇宙…

【unity小技巧】Unity音乐和音效管理器

最终效果 前言 在游戏开发中&#xff0c;音乐和音效的管理是一个重要的环节。好的音乐和合适的音效可以为游戏增添氛围并提升玩家的体验。为了更好地管理音乐和音效&#xff0c;我们可以使用一个专门的音乐和音效管理器。 在本文中&#xff0c;我将向大家介绍如何在Unity中创…

气缸功能块(SMART PLC梯形图代码)

有关气缸功能块的更多介绍,可以参考下面链接文章: https://rxxw-control.blog.csdn.net/article/details/125459568https://rxxw-control.blog.csdn.net/article/details/125459568CODESYS平台双通气缸功能块 https://rxxw-control.blog.csdn.net/article/details/12544822…

听GPT 讲Rust源代码--compiler(6)

File: rust/compiler/rustc_index/src/idx.rs 在Rust的源代码中&#xff0c;idx.rs文件位于rust/compiler/rustc_index/src/目录下&#xff0c;它定义了用于索引访问的Idx trait。以下是该文件的详细介绍&#xff1a; Idx是一个基本的整数索引类型&#xff0c;它用于支持Rust编…

C#/.NET/.NET Core优秀项目和框架2023年12月简报

前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架&#xff08;公众号每周至少推荐两个优秀的项目和框架当然节假日除外&#xff09;&#xff0c;公众号推文有项目和框架的介绍、功能特点以及部分功能截图等&#xff08;打不开或者打开GitHub很慢的同学可以优先…

智能分析网关V4智慧港口码头可视化视频智能监管方案

一、需求背景 近年来&#xff0c;水利港口码头正在进行智能化建设&#xff0c;现场管理已经是重中之重。港口作为货物、集装箱堆放及中转机构&#xff0c;具有昼夜不歇、天气多变、环境恶劣等特性&#xff0c;安全保卫工作显得更加重要。港口码头的巡检现场如何高效、快捷地对…

【MySQL·8.0·源码】MySQL 的查询处理

Query processing MySQL 的 Query 处理可以分为 Parse、Prepare(Resolve/Transform)、Optimize 和 Execute 几个阶段 Parse 词法扫描器将 SQL 语句字符串分解为 tokens&#xff0c;语法分析器将 tokens 组装成语法树的子树结构&#xff0c;并 Reduce 为基本查询结构&#xff0…

Centos 磁盘挂载和磁盘扩容(新加硬盘方式)

步骤总结如下 一、对磁盘进行分区 二、对磁盘进行格式化 三、将磁盘挂载到对应目录 四、做开机自动挂载磁盘 磁盘分区 1.使用命令&#xff1a;fdisk -l 查看磁盘&#xff08;注&#xff1a;正常在Centos7中第一块数据盘标识一般是/dev/sda,第二块数据盘标识一般是/dev/sdb&…

小程序一次性订阅消息(消息通知):java服务端实现

文章目录 引言一、消息订阅1.1 小程序订阅消息功能介绍1.2 消息分类1.2.1 新版一次性订阅消息Beta1.2.2 一次性订阅消息&#xff08;用户通过弹窗订阅&#xff09;1.2.3 长期订阅消息&#xff08;用户通过弹窗订阅&#xff09;1.2.4 设备订阅消息 二、获取模板ID1.登录[微信公众…

10款值得推荐的Blazor UI组件库

前言 经常看到有小伙伴在DotNetGuide技术社区交流群里问有什么好用的Blazor UI组件库推荐的&#xff0c;本文将分享一些开源、实用、美观的Blazor UI组件库&#xff0c;提供给广大C#/.NET开发者们学习和使用&#xff08;注意&#xff1a;排名不分先后&#xff0c;都是十分优秀…

算法与数据结构之数组(Java)

目录 1、数组的定义 2、线性结构与非线性结构 3、数组的表现形式 3.1 一维数组 3.2 多维数组 4、重要特性&#xff1a;随机访问 5、ArrayList和数组 6、堆内存和栈内存 7、数组的增删查改 7.1 插入数据 7.2 删除一个数据 7.3 修改数组 7.4 查找数据 8、总结 什么…

CIFAR图片分类数据集

1. CIFAR介绍 官网链接&#xff1a;CIFAR-10 and CIFAR-100 datasets CIFAR-10是一个更接近普适物体的彩色图像数据集。CIFAR-10 是由Hinton 的学生Alex Krizhevsky 和Ilya Sutskever 整理的一个用于识别普适物体的小型数据集。一共包含10 个类别的RGB 彩色图片&#xff1a;飞机…

机器学习期末复习

机器学习 选择题名词解释&#xff1a;简答题计算题一、线性回归二、决策树三、贝叶斯 选择题 机器学习利用经验 &#xff0c;须对以下&#xff08;&#xff09;进行分析 A 天气 B 数据 C 生活 D 语言 归纳偏好值指机器学习算法在学习的过程中&#xff0c;对以下&#xff08;&a…