WinDLX 模拟器实验

简单DLX指令

在这里插入图片描述

5个流水段

1. 取指令周期(IF)

根据PC指示的地址,从内存取指令加载到 IR 寄存器,同时 PC + 4,指向下一条指令的内存地址

IR 用于存储后序时钟周期用到的指令

NPC 用于存储下一个连续的 PC
在这里插入图片描述

2. 指令译码/ 读寄存器周期(ID)

指令译码并访问寄存器堆,读寄存器,将通用寄存器的输出读入临时寄存器(A,B)为随后的周期做准备
在这里插入图片描述
在这里插入图片描述
R型:主要为各种算数/逻辑计算编码
I型:主要用来对各种类型数的存取操作指令编码,即 load,store;为分支指令编码(包括:条件分支、寄存器跳转指令、寄存器跳转链接指令)

3. 执行/有效地址计算周期(EX)

包括:
3.1 存储器访问
​3.2 寄存器-寄存器 ALU操作
​3.3 寄存器-立即数 ALU操作
3.4 分支指令
在这里插入图片描述

4. 内存访问/分支完成周期(MEM)

包括4.1 存储器访问
​ ​ 4.2 分支指令
在这里插入图片描述

5. 写回周期(WB)

​将LMD寄存器 或 ALUOutput寄存器的内容协会寄存器堆
在这里插入图片描述

DLX 寄存器

1. 可见寄存器

  1. R0–R31 (R0值永远是0)
  2. F0–F31(32个32位单精度浮点寄存器)
    或者 F0、F2、··· ··F28、F30(64位双精度浮点寄存器)
  3. FPSR (浮点状态寄存器)
  4. PC (程序计数器)

2. 程序中不可见寄存器

name表述
IMAR指令内存地址寄存器
IR指令寄存器
A,BALU 操作数寄存器
BTA分支目标地址寄存器
ALUALU输出寄存器
DMAR数据内存地址寄存器
SDR存数据寄存器
LDR取数据寄存器

一个完整的例子

我们使用WinDLX 汇编器中的汇编文件fact.s ,这个程序计算数(通过键盘输入)的阶乘。这需要用到文件input.s,它用于接收从键盘输入的数。

1. 开始和配置WinDLX

  1. File / Reset all / 确定
  2. Configuration
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

2. 装载测试程序

  1. File / Load Code or Data

点击 fact.s / select 按钮
点击 input.s / select按钮
点击 load按钮

在这里插入图片描述

3. 模拟

(1) Pipeline 窗口
  • 此图显示DLX处理器的五个流水段和浮点操作 (加 / 减, 乘和除)的单元。
(2) Code 窗口
  • Code 窗口。双击图标,你将看到代表存储器内容的三栏信息,从左到右依次为:
    地址 (符号或数字) / 命令的十六进制机器代码 / 汇编命令
(3) Clock Cycle Diagram 窗口
  • 它显示流水线的时空图。
    在这里插入图片描述
(4) Breakpoint 窗口

在这里插入图片描述

  • 当通过Code 窗口观察代码时,你会看到接下来的几条指令几近一样,它们都是sw-操作:将寄存器中的数写入存储器中。重复按F7 将很枯燥,因此,我们使用断点加快此过程。
(5) Register 窗口

在这里插入图片描述

  • Register 窗口会显示各个寄存器中的内容
(6) Statistics 窗口

在这里插入图片描述

  • Statistics 窗口提供各个方面的信息:模拟中硬件配置情况、暂停及原因、条件分支、 Load/Store指令、浮点指令和traps。窗口中给出事件发生的次数和百分比,如RAW stalls:17(7.91 % of all Cycles)。
    在静态窗口中我们可以比较一下不同配置对模拟的影响。

* 伪指令代码部分

.data标识下面的数据放在数据区中

.data

.asciiz表示在存储区中顺序存放列出的字符串,字符串自动加0结束

Prompt: .asciiz "input An integer which is array’s size value >1 : "

PromptLast: .asciiz “input an integer :”

PrintfFormat: .asciiz "Number : %g "

.align使后面的数据代码按一定规则对齐,表示下一个字开始

.align 2

.word在存储器中顺序存放列出的字

PrintfPar: .word PrintfFormat

.space size在存储器中空出size大小的区域

Printf: .space 8

PrintfValue: .space 1024

.text标识下面的代码存放在代码区中

.text

.global使带有.global的标识可以被全局访问

.global main

指令

  1. 遇到trap指令,DLX 处理器中的流水线将被清空

MISP(DLX)指令集

  1. MIPS CPU的一次操作可加载或存储1到8个字节的数据。由于乘法的结果返回的速度不足以使下一条指令能够自动得到这个结果,乘法结果寄存器是互锁的(interlocked)。在乘法操作完成之前试图读取结果寄存器就是导致CPU停止运行,直到完成。
  2. 和其他一些更简单的RISC体系结构相比,MIPS体系结构的目标之一是:体系结构朝着64位发展,从而使得地址的段式结构变得没有任何必要。(在64位版本的X86核PowerPC中还有这个负担)
  3. 功能分组:
  • 空操作:nop、ssnop(不能和其他指令同时发射,至少需要一个时钟周期)
  • 寄存器间的数据传送指令:move、movf、movt、movn、movz(后四个为条件传递指令)
  • 常数加载指令:dla、la(获取某些标号地址或程序中变量地址的宏指令);dli、li(加载常数立即数指令);lui(加载高位立即数指令)
  • 算术/逻辑操作指令:addu、addiu、daddu,daddiu(加法指令);dsub、sub(会触发溢出陷入的减法操作);dsubu、subu(普通减法指令);abs、dabs(求绝对值操作);dneg、neg、dnegu、negu(一元非操作);and、andi、or、ori、xor、xori、nor、not(按位逻辑指令);drol、dror、rol、ror(循环左移和右移);dsll、dsll32、dsllv(64位左移,低位补零);dsra、dsra32、dsrav(64位算术右移指令);dsrl、dsrl32、dsrlv(64位逻辑右移指令);sll、sllv(32位左移指令);sra、srav(32位算术右移指令);srl、srlv(32位逻辑右移指令);slt、slti、sltiu、sltu(硬件指令,条件满足就写入1,否则写0);seq、sge、sgeu、sgt、sgtu、sle、slue、sne(根据更复杂的条件设置目的寄存器的宏指令)
  • 整数乘法、除法以及求余指令:ddiv、ddivu、div、divu(整数除法的3操作数宏指令分别处理64位或32位有符号或无符号数);divo、divou(明确该指令是带有溢出检查的除法指令);dmul、mul(3操作数64位或32位乘法指令,没有溢出检查);mulo、mulou、dmulo、dumlou(乘法宏指令,如果结果不能存入一个通用寄存器,发生溢出,触发异常);dmult、dmultu、mult、multu(执行有符号/无符号32/64位乘法的机器指令);drem、dremu、rem、remu(求余操作);mfhi、mflo、mthi、mtlo(用于访问整数乘除单元的结果寄存器hi和lo)
  • 存取指令(内存访问指令):lb、lbu(加载一个字节,高位可以补零,或进行符号扩展,以补充整个寄存器的长度);ld(加载一个双字);ldl、ldr、lwl、lwr、sdl、sdr、swl、swr(向左、向右加载、存储一个字、双字);lh、lhu(加载一个半字,高位可以补零,或进行符号扩展,以补充整个寄存器的长度);lw、lwu(加载一个字);pref、prefx(把数据预取到缓冲);sb、sd、sh、sw(存储字节、双字、半字、字);uld、ulh、ulhu、ulw、usd、usw、ush(地址非对齐的数据存取宏指令);l.d、l.s、s.d、s.s(存取双精度和单精度浮点数的指令,地址必须对齐);ldxcl、lwxcl、sdxcl、swxcl(采用基址寄存器+偏移寄存器的寻址方式存取指令);
  • 跳转、分支和子程序调用指令:j(无条件跳转到一个绝对地址,访问256M的代码空间);jal、jalr(直接或间接子程序调用,这种跳转不仅能跳转到指定地址,而且可以顺便把返回地址(当前指令地址+8)放到ra寄存器中);b(基于当前指令地址的无条件相对跳转);bal(基于当前地址的函数调用指令);bc0f、bc0f1、bc0t、bc0t1、bc2f、bc2f1、bc2t、bc2t1(根据协处理器0和2的条件标志进行跳转);bc1f、bc1f1、bc1t、bc1t1(根据浮点条件标志位进行跳转);beq、beq1、beqz、beqz1、bge、bge1、bgeu、bgeu1、bgez、bgez1、bgt、bgt1、bgtu、bgtu1、bgtz、bgtz1、ble、ble1、bleu、bleu1、blez、blez1、blt、blt1、bltu、bltu1、bltz、bltz1、bne、bnel、bnez、bnezl(双操作数和单操作数的比较跳转指令);bgeza1、bgeza11、bltza1、bltza11(如果需要 ,这些指令是用于有条件函数调用的原始机器指令);
  • 断点及陷阱指令:break(产生一个“断点”类型的异常);sdbbp(产生EJTAG异常的断点指令);syscall(产生一个约定用于系统调用的异常类型);teq、teqi、tge、tgei、tgeiu、tgeu、tlt、tlti、tltiu、tltu、tne、tnei(条件异常指令,对一个或两个操作数进行条件测试);
  • 协处理器0的功能:cfc0、ctc0(把数据拷进和拷出协处理器0的控制寄存器);mfc0、mtc0、dmfc0、dmtc0(在通用寄存器和协处理器0寄存器之间交换数据);cfc2、ctc2、dmfc2、dmtc2、mfc2、mtc2(协处理器2的指令);

参考
http://blog.sina.com.cn/s/blog_7f293c900100zdm8.html
在这里插入图片描述

参考:
https://www.cnblogs.com/CoBrAMG/p/9237609.html

汇编资料:
https://www.cnblogs.com/kingwolfofsky/archive/2011/09/02/2163457.html

WINDLX虚拟处理器概述
http://www.docin.com/p-504178555.html

DLX指令系统,命令解释
https://wenku.baidu.com/view/2b886a6db84ae45c3b358ca7.html

实验一 用WinDLX模拟器执行求最大公约数程序gcm.s

1. 原理

相减法(两个数)求最大公约数
1.输入两个正整数a和b;
2.如果a > b,则a = a – b;
3.如果a < b,则 b = b – a;
4.如果a = b,则a(或b)即为两数的最大公约数
5.如果a ≠ b,则重复执行1;
6.输出最大公约数和最小公倍数。

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windlx模拟器中,您可以使用以下步骤实现矩阵相乘: 1. 打开终端并进入要保存代码的目录。 2. 创建名为“matrix_multiplication.c”的新文件。 3. 使用任何文本编辑器打开该文件,并将以下代码复制并粘贴到该文件中: ```c #include <stdio.h> int main() { int m, n, p, q, c, d, k, sum = 0; int first[10][10], second[10][10], multiply[10][10]; printf("Enter the number of rows and columns of first matrix\n"); scanf("%d%d", &m, &n); printf("Enter the elements of first matrix\n"); for (c = 0; c < m; c++) for (d = 0; d < n; d++) scanf("%d", &first[c][d]); printf("Enter the number of rows and columns of second matrix\n"); scanf("%d%d", &p, &q); if (n != p) printf("The matrices can't be multiplied with each other.\n"); else { printf("Enter the elements of second matrix\n"); for (c = 0; c < p; c++) for (d = 0; d < q; d++) scanf("%d", &second[c][d]); for (c = 0; c < m; c++) { for (d = 0; d < q; d++) { for (k = 0; k < p; k++) { sum = sum + first[c][k]*second[k][d]; } multiply[c][d] = sum; sum = 0; } } printf("Product of the matrices:\n"); for (c = 0; c < m; c++) { for (d = 0; d < q; d++) printf("%d\t", multiply[c][d]); printf("\n"); } } return 0; } ``` 4. 保存并关闭该文件。 5. 在终端中,使用以下命令编译该代码: ```bash gcc matrix_multiplication.c -o matrix_multiplication ``` 6. 运行该程序: ```bash ./matrix_multiplication ``` 7. 按照提示输入两个矩阵的维数和元素。程序将输出这两个矩阵的乘积。 请注意,此代码仅限于处理最多10x10大小的矩阵。如果您需要处理更大的矩阵,请相应地修改代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值