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

文章目录

  • 寄存器
  • 指令
  • 使用技巧
    • 翻译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.mfbz.cn/a/290653.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TypeScript Array(数组)

目录 1、数组初始化 2、Array 对象 3、数组迭代 4、数组在函数中的使用 4.1、作为参数传递给函数 4.2、作为函数的返回值 5、数组方法 数组对象是使用单独的变量名来存储一系列的值。数组非常常用。假如你有一组数据&#xff08;例如&#xff1a;网站名字&#xff09;…

Java中的IO与NIO篇----第三篇

系列文章目录 文章目录 系列文章目录前言一、信号驱动 IO 模型二、异步 IO 模型三、JAVA NIO四、NIO 的缓冲区前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一、…

P1423 小玉在游泳python

s float(input()) sum 0 step 0 meter 2.0 while sum < s:sum metermeter 0.98 * meterstep 1 print(step)

三、C语言中的分支与循环—switch语句(4)分支结构 完

本章分支结构的学习内容如下&#xff1a; 三、C语言中的分支与循环—if语句 (1) 三、C语言中的分支与循环—关系操作符 (2) 三、C语言中的分支与循环—条件操作符 与逻辑操作符(3) 三、C语言中的分支与循环—switch语句&#xff08;4&#xff09;分支结构 完 本章循环结构的…

linux创建pyspark虚拟环境

一、创建虚拟环境 conda create -n test python3.6.6 二、注意添加镜像 vi /root/.condarc channels:- http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/- http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/- http://mirrors.ustc.edu.cn/anaconda/pkgs/ma…

jmeter使用心得(一)

jmeter作为接口测试的常用工具之一&#xff0c;在我们的测试中经常会用到&#xff0c;往期的文章中&#xff0c;我们也分享过jmeter的各种功能和用法&#xff0c;基本覆盖了方方面面&#xff0c;可以满足各种接口测试的需求。但实际测试中我们也会发现&#xff0c;jmeter这么强…

测试管理-缺陷管理工具安装

前言&#xff1a; 项目生命周期里面&#xff0c;开发软件后&#xff0c;需要进行正规的测试&#xff0c;测试除了需要编写测试用例和写测试总结外&#xff0c;还需要进行bug的闭环控制&#xff0c;方便追踪。之前用过惠普的QC系统&#xff0c;这个是收费的&#xff0c;专业做缺…

【网络】网络层IP地址和IP数据报的格式

&#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&am…

图像分割 分水岭法 watershed

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 本文的C#版本请访问&#xff1a;图像分割 分水岭法 watershed&#xff08;C#&#xff09;-CSDN博客 Watershed算法是一种图像处理算…

区域HIS系统源码,二级医院、专科医院his系统源码,经扩展后能够应用于医联体/医共体

二级医院、专科医院his系统源码&#xff0c;java语言开发 基于云计算技术的B/S架构的HIS系统&#xff0c;为医疗机构提供标准化的、信息化的、可共享的医疗信息管理系统&#xff0c;实现医患事务管理和临床诊疗管理等标准医疗管理信息系统的功能。 系统利用云计算平台的技术优…

宏集PC Runtime软件助推食品行业生产线数字化革新

一、前言 近年来&#xff0c;中国食品行业发展迅速且灵活多变&#xff0c;在当前经济下行的情形下&#xff0c;食品行业正面临着日益激烈的竞争&#xff0c;导致企业利润下降。 为了保持企业市场竞争力&#xff0c;国内某top10食品企业采用宏集SCADA解决方案—PC Runtime软件…

【linux】日志管理和分析

一、概述 在Linux系统的管理和运维中&#xff0c;日志文件起到至关重要的作用。它们记录了系统运行过程中的各种事件&#xff0c;包括系统故障、性能数据和安全事件。 二、 日志的作用和分类 日志的作用 日志文件记载了系统的生命线&#xff0c;利用它们可以&#xff1a; 1…

Linux操作系统基础(08):Linux的用户权限

1. 用户权限是什么 在Linux中&#xff0c;用户权限是指用户对文件、目录或者系统资源的访问权限&#xff0c;用户权限决定了用户可以执行哪些操作&#xff0c;比如读取、写入、执行等等&#xff0c;用户权限与文件权限紧密不可分。 用户权限可以分为三种&#xff1a; 读取权限…

青蛙目标检测数据集VOC格式600张

青蛙&#xff0c;一种两栖动物&#xff0c;以其独特的形态和习性&#xff0c;成为了大自然中的一道亮丽风景。 青蛙的外观非常特别&#xff0c;绿色的皮肤上布满了大小不一的斑点&#xff0c;既有助于它们在草丛中隐身&#xff0c;又能够有效地迷惑天敌。头部扁平&#xff0c;…

珠海盈致浅析MES生产管理系统的优点

MES系统是用于管理和控制制造过程的信息化系统.它具有许多优点&#xff1a; 1. 生产过程可视化:MES系统提供实时的生产过程监控和数据收集,使管理人员能够清晰地了解生产线上的各个环节,包括设备状态、生产进度、质量指标等.这使得管理人员能够作出准确的决策并快速响应变化. 2…

实现文本 内容展开 / 收起

<template><el-table :data"tableData" style"width: 100%" height"250"><el-table-columnfixedprop"date"label"日期"width"150"></el-table-column><el-table-columnprop"name…

聚丙烯腈,到预测期结束时将达到36亿美元的市场规模

聚丙烯腈 (PAN) 是一种合成聚合物&#xff0c;广泛用于各种应用&#xff0c;包括纺织品、碳纤维生产和水处理。近年来&#xff0c;受航空航天、汽车和建筑行业对碳纤维增强复合材料需求不断增长的推动&#xff0c;全球 PAN 市场稳步增长。 全球 PAN 市场预计从 2020 年到 2025 …

HttpClient库与代理IP在爬虫程序中的应用

目录 前言 一、HttpClient库的基本使用方法 二、代理IP的使用方法 三、代理IP池的使用方法 四、总结 前言 在编写爬虫程序时&#xff0c;我们经常会使用HttpClient库来发送HTTP请求&#xff0c;获取网页内容。然而&#xff0c;有些网站可能会对频繁的请求进行限制&#x…

CMake入门教程【核心篇】包含目录(include_directories)

&#x1f608;「CSDN主页」&#xff1a;传送门 &#x1f608;「Bilibil首页」&#xff1a;传送门 &#x1f608;「本专栏容」&#xff1a;CMake入门教程 &#x1f608;「动动你的小手」&#xff1a;点赞&#x1f44d;收藏⭐️评论&#x1f4dd; 文章目录 1. 基本用法2. 添加单个…

【SpringBoot开发】之商城项目案例(订单及订单项生成)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringBoot开发之商城项目系列》。&#x1f3af…
最新文章