【计算机本科补全计划】指令:计算机的语言(MIPS) Part3

正文之前

今天学的很尴尬,因为有事情,而且新认识了两个计算机学院的保研大佬,不得不感叹我找的导师之强,第一个去上交的,是被金老师推荐去的,听说是跟了目前亚洲第一人的一个做计算机系统的人,例外一个小大佬居然也是直接跟的金老师。。也就是说我们以后是同门。

前面随便问问计算机学院的情况:

  • 学长:我有个高中同学在金老师手下念博士生,我帮你问问。。。;
  • 学姐:我有个大学同学在金老师实验室读研究生,我给你推荐好友哈。。。;
  • 大佬:金老师是我的助班和学业导师,他人很好的。。。;
  • 小大佬:金老师跟我说还不急着选方向,(PS:“嗯?你也是金老师的研究生呀” ) 嗯,他也是我助班。。。(。。。。)。。。

正文


  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完成 值的交换。

  1. 翻译并且执行程序

参照下面的图片:


链接器的工作分为三个步骤(这个我真不会,后面回头来看吧!):

  • 将代码和数据模块象征性的放入内存
  • 决定数据和指令标签的地址
  • 修补内部和外部引用

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

  • 读取可执行文件头来确定代码段和数据段的大小
  • 为正文和数据创建一个足够大的地址空间
  • 将可执行文件中的指令和数据复制到内存中
  • 把主程序的采纳数复制到栈顶
  • 初始化机器寄存器,将栈顶指针指向的一个空位置
  • 跳转到指令例程,将参数复制到参数寄存器并且调用程序的main函数,当main函数返回时,启动例程通过调用系统exit 终止程序。
  1. 以一个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;
  1. 以一个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<n就把t0置位为1;否则为0 也就是跳出最外层循环。
         beq $t0,$zero,exit1; //t0 等于0 跳转到退出。

综上,我们的第一层循环的总体结构就是:

         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]<v[k] 就可以直接跳转到exit2,否则就执行swap程序

      addi $s1,$s0,-1;
for2tst:slti $t0,$s1,0;
      bne $t0,$zero,exit2;
      sll $t1,$s1,2;
      add $t2,$s2,$t1;
      lw $t3,0($t2);
      lw $t4,4($t2);
      slt $t0,$t4,$t3;
      beq $t0,$zero,exit2;

//执行swap前要先把需要的数据保存到指定的寄存器

      move $a0,$s2;
      move $a1,$s1;
      jal swap;

//j=j-1然后继续进行内层的循环

      addi $s1,$s0,-1;
      j for2tst;

//如果一开始就结束了内层循环,那么就可以 i=i+1 后直接跳转到外层循环,进

exit2:addi $s0,$s0,1;
      j for1tst;

//如果内层循环也已经结束了,那么sort函数也就可以返回数值给他的调用者了。并且,要对调用者的寄存器进行还原,不然会干扰程序的正常运作。

exit1:lw $s0,0($sp);
      lw $s1,4($sp);
      lw $s2,8($sp);
      lw $s3,12($sp);
      lw $ra,16($sp);
      addi $sp,20;

// ra寄存器经过还原后指向调用sort的程序的下一指令,直接返回即可。
      jr $ra;

//swap程序。

swap:
  sll $t1,$a1,2;  
  add $t1,$a0,$t1; 
  lw  $t0,0($t1);  
  lw  $t2,4($t1);  
  sw  $t2,0($t1);
  sw  $t0,4($t1);
  jr $ra;

正文之后

今晚要进行推免的复试报名(其实对于本校的同学貌似就是水一波,但是是必须要走的流程 而且很紧急!)所以现在回到住处,写完文以后就要去找齐所有的证书,幸亏是前阵子统计加分的时候已经整理好了。所以直接拿着用就行了 但是!!为什么缺了一张四级证书!!我还要回去拿!!心疼

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,978评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,954评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,623评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,324评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,390评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,741评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,892评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,655评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,104评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,569评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,254评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,834评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,725评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,950评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,260评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,446评论 2 348

推荐阅读更多精彩内容