计算机组成原理move,指令:计算机的语言(MIPS) --计算机组成原理(3)

722e9e2f61b7564390341cdc3b271376.png

1.并行与指令:同步。

当不同的任务之间需要访问问一个位置的数据的时候,就会出现数据竞争的风险,这个时候急需要同步来处理,负责就会引起程序运行错误的结果。同步运行需要依赖于硬件提供的同步指令,可以由用户调用。主要是加锁和解锁的同步操作。要实现操作的原子性(不可被分割打断),需要由硬件对两个同时执行的交换操作(一种同步机制,通过交换原语实现)进行排序,一种可行的办法是:指令对,链接取数和条件存数。 关键就在于临时寄存器的特性!!这一点我也是写笔记才明白的!!!

again: addi $t0,$zero,1;

ll $t1,0($s1);

sc $t0,0($s1);

beq $t0,$zero,again;

add $s4,$zero,$t1

其中ll 和 sc 分别对应着链接取数和条件存数 这两个指令,$s1 中存放着我们的锁单元,对应着我们一种资源,当 $t1 从锁单元中取出来值,如果有任何处理器插入改变了锁单元的值,指令都会将 $t0 变为 0(诸位莫忘了 $t0 是一个临时存储器,如果发生了别的处理器的操作,临时寄存器会被瞬间归零),那么这段指令就会重新执行。直到完全完成原子交换,$s1 所指向的锁单元中的值与 $s4 完成 值的交换。

2.翻译并且执行程序

参照下面的图片:e3eb96624bd1dbe8c9f156c17fc76989.png

链接器的工作分为三个步骤:

• 将代码和数据模块象征性的放入内存

• 决定数据和指令标签的地址

• 修补内部和外部引用

加载器在UNIX系统中执行的工作步骤:

• 读取可执行文件头来确定代码段和数据段的大小

• 为正文和数据创建一个足够大的地址空间

• 将可执行文件中的指令和数据复制到内存中

• 把主程序的采纳数复制到栈顶

• 初始化机器寄存器,将栈顶指针指向的一个空位置

• 跳转到指令例程,将参数复制到参数寄存器并且调用程序的main函数,当main函数返回时,启动例程通过调用系统

• exit 终止程序。

3.以一个C交换程序作为例子

//C语言版本:

void swap(int v[],int k)

{

int temp;

temp = v[k];

v[k] = v[k+1];

v[k+1] = temp;

}

下面我们用以下常见的步骤将其手动翻译为汇编程序:

// 用$a0 $a1 来存储v的基址和k的值。 因为swap是叶过程(不会产生调用的过程),所以为temp分配唯一的临时寄存器$t0;

swap:

sll $t1,$a1,2; // 因为我们用字来存储数据,所以地址距离应该是4倍,所以要左移两位 ,等同与*4;

add $t1,$a0,$t1; // 把v[k]的位置传入进来 到$t0

lw $t0,0($t1); // 读取v[k]的值;

lw $t2,4($t1); // 读取v[k+1]的值;因为地址固定相差四位,所直接读取4($t1)即可

//交换两个值 用sw

sw $t2,0($t1);

sw $t0,4($t1);

//因为是叶过程,所以会被调用,就需要一个跳转调用者的返回指令

jr $ra;

4.以一个C排序程序(用冒泡法)作为例子

//C语言版本:

void sort(int v[],int n)

{

int i,j;

for(i=0;i < n;i+=1)

{

for(j=i-1;j > =0 && v[j]>v[j+1];j -= 1)

{

swap(v,j);

}

}

}

下面我们用以下常见的步骤将其手动翻译为汇编程序:

为sort 的两个参数分配寄存器为:$a0和$a1 为变量i,j 分配 $s0,$s1;首先,最外层的循环,初始化:

move $s0,$zero; // 其实这个是伪指令,是一种方便操作的方式,真实的代码应该是 add $s0,$zero,$zero;

然后在for中还有一个 i++的功能需要实现,那就是在末尾加上一个:

addi $s0,$s0,1;

然后第二个判断条件需要放在每一次循环的开头,如果i>=n 就会退出,否则就继续执行下去 采用小于则置位以及等于就跳转的命令,

for1tst: slt $t0,$s0,$a1; //如果i综上,我们的第一层循环的总体结构就是:

move $s0,$zero;

for1tst: slt $t0,$s0,$a1;

beq $t0,$zero,exit1;

~~~~~~~body~~~~~~~~

addi $s0,$s0,1;

j for1tst;

exit1:

然后是第二层循环,类似的,先给定初始条件,然后准备好结束条件,同时对于swap要重新给定寄存器,或者是在进入swap之前把原来的被占用的寄存器的内容放到另外的寄存器,然后结束swap的时候在逆向的返回原来的值;

综合程序如下:(for中的对a0 a1 的引用换成了 s2(v的基址) s3(n) 方便读写)

//定义整个函数的基调:首先腾出四个地方来存放数据,当前这些寄存器可能内部有sort的调用者的数据,所以为了避免丢失,要把当前寄存器的值保存到堆栈中

sort:addi $sp,$sp,-20;

sw $ra,16($sp); //此处是将调用sort的调用者的位置保存到堆栈中;

sw $s3,12($sp);

sw $s2,8($sp);

sw $s1,4($sp);

sw $s0,0($sp);

// 在swap中要用到a0 a1 两个寄存器,所以先把其中的值保存起来比较好。

move $s2,$a0;

move $s3,$a1;

//对最外层for循环进行初始化,s0表示i值,s3表示n,t0 则是判定条件所需要的临时寄存器;

move $s0,$zero;

for1tst: slt $t0,$s0,$s3;

beq $t0,$zero,exit1;

//内部循环的内容,初始化s1表示j=i-1; 内层for循环,分别有两个判定条件判断是否进行内层循环,否则调到exit2 结束内层循环,满足条件就进入循环体,取出数值,然后t1表示v[k]的k,t2表示v[k]的位置,取出来v[k]和v[k+1],然后进行比较,如果v[k+1]

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值