手机网站优化指南,wordpress虚拟资源,优秀网页版式设计,免费算命一、实验目标#xff1a;
了解WinMIPS64的基本功能和作用#xff1b;
熟悉MIPS指令、初步建立指令流水执行的感性认识#xff1b;
掌握该工具的基本命令和操作#xff0c;为流水线实验做准备。
二、实验内容
按照下面的实验步骤及说明#xff0c;完成相关操作记录实验…一、实验目标
了解WinMIPS64的基本功能和作用
熟悉MIPS指令、初步建立指令流水执行的感性认识
掌握该工具的基本命令和操作为流水线实验做准备。
二、实验内容
按照下面的实验步骤及说明完成相关操作记录实验过程的截图
1下载WinMIPS64运行样例代码并观察软件各个观察窗口的内容和作用掌握软件的使用方法。
2学会正确使用WinMIPS64的IO方法。
3编写完整的排序程序。
三、实验环境
硬件桌面PC
软件WindowsWinMIPS64仿真器
四、WinMIPS64软件使用
1安装
解压给出的winmips64.zip压缩文件到给定的工作目录中如在我的电脑中的路径是E:\winmips64。
2开始和配置WinMIPS64
双击winmips64.exe文件后打开了WinMIPS64模拟器。
在主窗口中我们可以看见七个子窗口和一条在底部的状态栏。这七个子窗口分别是Pipeline, Code, Data,Registers, Statistics, Cycles和Terminal。这七个窗口的作用如下
Pipeline窗口 展示MIPS64处理器的五级流水线结构及浮点操作单元指示当前指令在不同流水段的状态。Code窗口 显示存储器内容包括地址、机器代码和汇编指令。通过颜色标识指令处于“取指”、“译码”等不同阶段。Cycles窗口 显示流水线的时空图指令执行过程的可视化帮助识别指令间的依赖关系和数据停滞情况。Data窗口 观察内存中的数据包括地址和内容。可通过双击或右键修改整型或浮点型数据。Registers窗口 显示寄存器中的值指示当前写入和前递状态。允许用户交互式修改寄存器值。Statistics窗口 记录模拟周期的统计数据包括指令数、执行周期数、暂停周期数等提供性能分析信息。Terminal窗口 显示运行过程中输出的信息和状态如数据相关的错误提示等帮助用户调试和理解模拟过程。
3装载测试程序
用标准的text编辑器来新建一个名为sum.s的文件这个文件的功能是计算两个整数A、B之和然后将结果传给C。
首先使用asm.exe程序检测一下sum.s是否合法检测方法为用命令行输入asm.exe 目标检测文件.\asm.exe .\sum.s可以发现下图使用asm.exe检测之后没有错误0 errors即sum.s编译非常顺利。
下面我们将sum.s装载到winmips.exe程序中。打开winmips程序之后使用快捷键“ctrl o”打开文件进行装载点击对应的文件即可。将sum.s加载到 winmips64程序中得到初始化页面。
不断地按下F7逐步进行让程序运行得到下图可以发现一些窗口发生了变化。在运行的过程中左上角CyclePipeLine和Code窗口出现了一些彩色标注的方块区域Registers和Data窗口没有发生什么变化statistics窗口有一些行列数据发生了变化。
通过查阅手册和相关资料我们了解到Cycles、Pipeline和Code窗口主要展示程序运行过程中指令的执行过程。这些窗口标识了每条指令所处的阶段包括“取指”、“解码”、“执行”、“访存”和“写回”与课程内容紧密对应。
Registers和Data窗口则提供了程序运行过程中寄存器和内存的数据状态。最后Statistics窗口记录了程序运行过程中的各项统计信息。此外还有一个终端窗口用于与程序进行交互尽管在这个程序中没有使用到。
在对这些窗口有了初步了解后我们可以逐步跟踪程序运行观察不同时间点的状态。计算机能够像流水线一样同时处理多条指令以“取指”、“解码”、“执行”、“访存”和“写回”并行执行从而提高运行效率。下图展示了程序运行结束后的状态。可以看到在某些时刻Cycles窗口中计算机仍在进行取指和解码操作这导致红色方块的执行模块处于空载阶段。从Cycles窗口在程序结束后的状态图中可以发现当ID和IF模块执行完成之后EX模块也开始继续往下执行了。
五、作业一终端IO简单实例
1程序设计
使用winmips64的终端来实现程序的输入输出以”hello world”程序为例。首先需要知道I/O区域的内存映射一个是控制字一个是数据字具体结构如下
控制字CONTROL
地址通常在一个特定的内存地址例如 0x10000。
功能用于指示当前I/O操作的状态或类型。不同的值代表不同的操作比如读取、写入或设置状态。
数据字DATA
地址通常在另一个特定的内存地址例如 0x10008。
功能存储要发送到终端的数据或接收从终端输入的数据。
通过这两个区域程序可以通过设置控制字和相应的数据字实现与终端的交互。具体的映射和使用方式可能因系统和具体实现而有所不同。
程序的运行逻辑如下
1定义数据区只需定义字符串、存储数据和控制变量的地址。
2代码区处理
将字符串地址如0x10008加载到寄存器中。
将字符串内容存储到指定的内存地址。
将变量值4存储到地址0x10000以指示程序打印字符串。
当完成以上这些步骤后程序会将0x10008中的数据打印到终端输出“hello world”。
3代码实现 .data string: .asciiz hello, world! # define string CONTROL: .word32 0x10000 # define control address DATA: .word32 0x10008 # define data address .text main: lwu r30, DATA(r0) # load 0x10008 to r30 daddi r31, r0, string # load string address to r31 sd r31, (r30) # store string address at 0x10008 lwu r30, CONTROL(r0) # load 0x10000 to r30 daddi r31, r0, 4 # load 4 to r31 sd r31, (r30) # store 4 at 0x10000,print string halt # stop program
上面代码主要用了lwudaddisd这三个指令
1lwu从内存中加载一个32位的无符号字word到寄存器中。
用法lwu 寄存器, 偏移(基址寄存器)。如lwu r30, DATA(r0)表示从地址DATA0x10008加载一个无符号字到寄存器r30。
2daddi将一个立即数与指定寄存器中的值相加结果存储在目标寄存器中。这个指令用于处理64位数据。
用法daddi 目标寄存器, 源寄存器, 立即数。如daddi r31, r0, string表示将string的地址加到寄存器r0即0结果存储在r31中。
3sd将一个64位的双字doubleword从寄存器存储到内存的指定地址。
用法sd 源寄存器, (目标地址寄存器)。如sd r31, (r30)表示将寄存器r31中的值存储到寄存器r30所指向的内存地址中。
2检查合法性
用asm.exe检验一下程序的正确性在终端中输入\asm.exe .\helloworld.s得到如下的结果没有错误0 errors即helloworld.s编译非常顺利。
3结果运行
将helloworld.s加载到winmips64中不断地按下F7之后进行单步运行得到下图的结果。得到cycles顺利地进行了流水执行指令没有raw stalls的情况发生然后看终端可以得到打印出了“helloworld”。
六、作业二编写排序算法
1程序设计
实现对一个整数数组的冒泡排序从小到大并在终端中输出排序前后的数组数据。程序逻辑如下
数据区定义定义了输出字符串排序前和排序后、控制地址、数据地址、栈指针、标志变量和待排序的数组。
初始数组数据自定义为9,0,7,2,4,3,1,6,8,5
1主程序
首先加载栈指针SP和控制、数据地址CONTROL和DATA。
打印排序前的数组设置输出格式为字符串加载Before sort字符串并存储地址然后触发打印。设置输出格式为整数循环遍历数组逐个将元素存储到数据地址触发打印。
2冒泡排序调用bubblesort函数对数组进行排序。
bubblesort内部
分配栈空间并保存返回地址和一些寄存器的值。
使用两层循环进行冒泡排序外层循环控制排序的轮数i内层循环控制相邻元素的比较j。在内层循环中比较相邻的元素如果前一个元素大于后一个元素则调用swap函数进行交换。
结束时恢复寄存器和栈指针。
打印排序后的数组同样设置输出格式为字符串加载After sort字符串并存储地址触发打印。设置输出格式为整数循环遍历排序后的数组逐个将元素存储到数据地址触发打印。
结束程序使用halt指令停止程序执行。
需要注意的是
不能将栈指针初始化为0。因为如果将SP设置为0进行SP - 1操作时会指向FFFFFFFF这超出了MIPS模拟器winmips的内存范围可能导致程序崩溃或出现错误。
打印字符串和打印数字时传递给地址0x10000的值不同字符串使用4而数字使用2。这一点需要特别注意以确保程序能正确显示输出。
2代码实现
除了lwudaddisd三条指令还使用如下指令
dsll 将寄存器中的值左移指定的位数结果存入目标寄存器。左移时低位补零适用于乘以2的幂。bne 如果两个寄存器的值不相等则跳转到指定标签。常用于条件判断。jal 跳转到指定标签并保存返回地址到$ra寄存器。常用于调用函数。slt 比较两个寄存器的值如果第一个寄存器小于第二个则将目标寄存器设置为1否则为0。用于条件判断。beq 如果两个寄存器的值相等则跳转到指定标签。与bne相反。j 无条件跳转到指定标签。用于程序流程控制。jr 根据寄存器中的地址进行跳转通常用于返回函数。 具体实现代码如下 .data after: .asciiz After sort the array is:\n # Output after sorting before: .asciiz Before sort the array is:\n # Output before sorting CONTROL: .word 0x10000 # Control address DATA: .word 0x10008 # Data address SP: .word 0x300 # Stack pointer flag: .word 0 # Flag variable array: .word 9,0,7,2,4,3,1,6,8,5 # Array to sort .text main: ld r29, SP(r0) # Load stack pointer ld r16, CONTROL(r0) # Load control address ld r17, DATA(r0) # Load data address # Print before sorting daddi r8, r0, 4 # Set string output format daddi r9, r0, before # Load Before sort string sd r9, (r17) # Store address for printing sd r8, (r16) # Trigger print # Print array before sorting daddi r8, r0, 2 # Set integer output format daddi r2, r0, 10 # Array length daddi r1, r0, 0 # Index i print1: dsll r3, r1, 3 # Calculate array address ld r9, array(r3) # Load array[i] sd r9, (r17) # Store for printing sd r8, (r16) # Trigger print daddi r1, r1, 1 # Increment i (i) bne r2, r1, print1 # Loop if i 10 # Sort the array daddi r4, r0, array # Load array address daddi r5, r0, 10 # Load length jal bubblesort # Call bubble sort # Print after sorting daddi r8, r0, 4 # Set string output format daddi r9, r0, after # Load After sort string sd r9, (r17) # Store address for printing sd r8, (r16) # Trigger print # Print array after sorting daddi r8, r0, 2 # Set integer output format daddi r2, r0, 10 # Array length daddi r1, r0, 0 # Index i print2: dsll r3, r1, 3 # Calculate array address ld r9, array(r3) # Load array[i] sd r9, (r17) # Store for printing sd r8, (r16) # Trigger print daddi r1, r1, 1 # Increment i bne r2, r1, print2 # Loop if i 10 halt # End program bubblesort: daddi r29, r29, -24 # Allocate stack space sd $ra, 16(r29) # Save return address sd r16, 8(r29) # Save r16 sd r17, 0(r29) # Save r17 dadd r22, r4, r0 # Load array address daddi r23, r5, 0 # Load length # Outer loop: for (int i 0; i n; i) and r18, r18, r0 # i 0 loop1: slt r10, r18, r23 # Check i n beq r10, r0, exiti # Exit if i n # Inner loop: for (int j i - 1; j 0; j--) daddi r19, r18, -1 # j i - 1 loop2: slti r10, r19, 0 # Check j 0 bne r10, r0, exitj # Exit if j 0 # Compare and swap dsll r11, r19, 3 # Calculate a[j] dadd r12, r11, r22 # r12 address of a[j] ld r13, 0(r12) # Load a[j] ld r14, 8(r12) # Load a[j 1] slt r10, r14, r13 # Check if a[j 1] a[j] beq r10, r0, exitj # Skip swap if not dadd r4, r0, r12 # Address of a[j] daddi r5, r12, 8 # Address of a[j 1] jal swap # Call swap # Decrement j and repeat inner loop daddi r19, r19, -1 j loop2 exitj: # Increment i and repeat outer loop daddi r18, r18, 1 j loop1 exiti: # Restore stack and return ld r17, 0(r29) # Restore r17 ld r16, 8(r29) # Restore r16 ld $ra, 16(r29) # Restore return address daddi r29, r29, 24 # Restore stack pointer jr $ra # Return to caller swap: # Swap two array elements ld r9, 0(r4) # Load a[i] ld r10, 0(r5) # Load a[j] sd r10, 0(r4) # a[i] a[j] sd r9, 0(r5) # a[j] a[i] jr $ra # Return to caller
3检查合法性
用asm.exe检验一下程序的正确性在终端中输入\asm.exe .\sort.s得到如下的结果没有错误0 errors即sort.s编译非常顺利。
4结果运行
将sort.s加载到winmips64中不断地按下F7之后进行单步运行得到下图的结果。得到cycles顺利地进行了流水执行指令没有raw stalls的情况发生然后看终端可以得到先打印了初始未排序的数组数据9,0,7,2,4,3,1,6,8,5而后打印了排序后的数组数据0,1,2,3,4,5,6,7,8,9。