第一章 汇编语言和汇编指令

article/2025/10/11 22:37:37

【用最少的指令来实现功能】

自用

文章基于《计算机体系结构新讲》(中国地质大学出版社)

 目录

一、汇编指令 

 (1)MIPS汇编指令示例解析

(2)MIPS指令集

二、汇编指令中的操作数

(1)寄存器

(2)立即数

(3)内存

三、MIPS程序控制指令

【if】

【while】

【for】

【switch】 

四、函数调用 

(一)跳转

(二)嵌套

(三)栈

五、逻辑运算


 

一、汇编指令 

什么是汇编语言?

汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。其中,本系列笔记将以MIPS汇编语言为例来进行解析。

 (1)MIPS汇编指令示例解析

a=b+c   //C风格
add a b c  //MIPS汇编
指令代码 操作数1 操作数2 操作数3(MIPS汇编指令格式)

(2)MIPS指令集

521088dd12a24dc9a93ce503a08987cd.jpeg

935aba218b0a45688b01aacd6696febf.jpeg

 

二、汇编指令中的操作数

(1)寄存器

MIPS处理器的汇编语言中,算数运算指令的操作数只能是寄存器。(设计简单)

规定指令由四个部分构成(规则性、统一性)

在MIPS计算机中设计了32个32位的通用寄存器来作为汇编指令的操作数。

寄存器约定

309ba5ed6a994b13a48392f117a41e24.png

 *注:

        $0:恒为常数0。

        $s0~&s7:若使用,必须恢复。

        $sp:若使用,必须恢复。

        $ra:在嵌套调用时,调用函数需将它保存到栈上。

(2)立即数

类似于C语言里面的常数

为何叫立即数?

该数可以在代码中立即获得,不需要先存放到寄存器,等到用的时候再去取。

(3)内存

内存与寄存器的数据交换指令

将内存看作一个一维数组,从而可以使用一个指向内存的指针来简单访问内存从内存中装入(load)数据到寄存器
lw $1 imm($2)s
# $1是用来存储从内存中获取的数据的寄存器
# $2是用来存储访问内存的指针,称为基址
# imm是偏移量(offset),必须是常数(有符号)
# $1=memory[$2 + offest]将寄存器的值存储(store)到内存中
sw $1 imm($2)
# $1是用来保存即将要存入内存的数据的寄存器
# $2是用来存储访问内存的指针,称为基址
# imm是偏移量(offset),必须是常数(有符号)
# memory[$2 + offest]=$1word 字 32位
1 word = 4 Byte = 32 Bit上述memory[i]表示的是内存中的第i个字(word),而基址的单位是字节(Byte),offest的单位也是字节(Byte),但是不管是lw指令还是sw指令,每次但是传递一个字的内容,所以此时就要求基址和offest
的和为4的倍数(实现字对齐)。以上全部是MIPS的字数据传送,下面将介绍MIPS中的字节数据传送:
字节传送指令:lb,sb
形如 lb $1 imm($2) 的指令,是将内存中第(imm+$2)字节的内容传递到$1寄存器中,但是第(imm+$2)字节的内容只有8位,但是寄存器有32位,此时MIPS就会采用符号拓展的方式(lbu指令是采用零拓展的方式)来填充高24位,从而与原有的8位数组成一个32位的数值保存到寄存器中。(sb指令就是将寄存器中一字节的数据传送到内存中)

三、MIPS程序控制指令

条件分支指令:
beq $1 $2 loop  #若$1==$2,则跳转到loop,否则进行下一条指令
ben $1 $2 loop  #若$1!=$2,则跳转到loop,否则进行下一条指令
无条件分支指令:
j loop  #直接跳转到loop(类似与C语言中的goto)

结合条件分支指令实现C语言中if,while,for,switch等等到汇编语言的转换:

【if】

【C语言】
int a;
if(a==0)clause 1;
else if(a<0)clause 2;
elseclause 3;【MIPS汇编】
假设$t0中存放的是abeq $t0 $0 loop1    # $t0==$0 -> jump to loop1slt $t1 $0 $t0      # $0<$t0 -> $t1=1 // $0>$t0 -> $t1=0beq $t1 $0 loop2    # $t1==$0 -> jump to loop2
loop3:clause 3j exit
loop1:clause 1j exit 
loop2:clause 2
exit:

【while】

(1)do...while

【C语言】
do{clause
}while(a>=100)【MIPS汇编】
假设a存放在$t0中 li $t1 100         #int num=100 -> $t1
loop:clauseslt $t2 $t0 $t1    # $t0<$t1 -> $t2=1 // $t0>=$t1 -> $t2=0beq $t2 $0 loop    # $t2==0 -> jump to loop
exit: 

(2)while...

【C语言】
while(a>=100)
{clause;
}【MIPS汇编】
假设a存放在$t0中 li $t1 100         #int num=100 -> $t1slt $t2 $t0 $t1    # $t0<$t1 -> $t2=1 // $t0>=$t1 -> $t2=0li $t3 1           # $t3=1beq $t2 $t3 exit   # $t2==$t3 -> jump to exit
loop:clauseslt $t2 $t0 $t1    # $t0<$t1 -> $t2=1 // $t0>=$t1 -> $t2=0beq $t2 $0 loop    # $t2==0 -> jump to loop
exit:

(3)课内上机do...while实例

题目:将下面C++代码翻译成对应的MIPS汇编语言

void main( )
{
    int i, sum(0);
    cin >> i;
    do  {
        sum = sum + i * 2;
        i++;
    } while ( i<= 5);

    cout << "sum=" << sum << endl;
}

答案:

.data I:.asciiz "please enter the value of I:"result:.asciiz "sum="
.text#print Ili $v0 4la $a0 Isyscall#Enter Ili $v0 5syscall#store the I to $tomove $t0 $v0li $s0 0 #int sub=0li $s1 5Loop: add $t1 $t0 $t0add $s0 $s0 $t1addi $t0 $t0 1slt $t2 $s1 $t0  #if $t0>5 $s1=1; if $t0<=5 $s1=0beq $t2 $0 LoopExit:#print resultli $v0 4la $a0 resultsyscall#print subli $v0 1move $a0 $s0syscall

【for】

【C语言】
for(int i=0;i<100;i++)
{clause;
}【MIPS汇编】    li $t0 100         # $t0=100add $t1 $0 $0      # int i=0 -> $t1
loop:clauseaddi $t1 $t1 1     # i++slt $t2 $t1 $t0    # $t1<$t0 -> $t2=1 // $t1>=$t0 -> $t2=0li $t3 1           # $t3=1beq $t2 $3 loop    # $t2==0 -> jump to loop
exit:

【switch】 

【C语言】
switch(k)
{
case 0:clause 0;break;
case 1:clause 1;break;
case 2:clause 2;break;
case 3:clause 3;break;
default:clause;
}【MIPS汇编】
假设k存放在$t0中bne $t0 $0 loop1    # k!=0 -> jump to loop1
loop0:clause 0j exit
loop1:addi $t1 $t0 -1     # $t1=k-1bne $t1 $0 loop2    # k!=1 -> jump to loop2clause 1j exit
loop2:addi $t1 $t0 -2     # $t1=k-2bne $t1 $0 loop3    # k!=2 -> jump to loop3clause 2j exit
loop3:addi $t1 $t0 -3     # $t1=k-3bne $t1 $0 loop4    # k!=3 -> jump to loop4clause 3j exit
loop4:clause
exit:

四、函数调用 

(一)跳转

课内上机实例

题目 :将下面C++语句翻译成对应的汇编语言

int Test(int a, int b)
{
    int c = 0;
    if (a >= b)  
        c = 4 * a + b;
    else  
        c = 8 * a - b;
    return c;
}

void main() 
{
    int x = 5, y = 6;
    cout << Test(x, y) << endl;
    cout << Test(10, 20) << endl;
}

 答案:

.datafirst:.asciiz"Test(x, y) = "second:.asciiz"\nTest(10, 20) = "
.text
main: li $t1 5   li $t2 6   add $a1 $t1 $0   add $a2 $t2 $0   jal Test   #print first and resultli $v0 4la $a0 first        syscallli $v0 1move $a0 $t0syscallli $t1 10 li $t2 20  add $a1 $t1 $0   add $a2 $t2 $0 jal Test   #print second and resultli $v0 4la $a0 second      syscallli $v0 1move $a0 $t0syscall#finishli $v0 10syscall Test: add $t0 $t0 $0slt $t3 $a2 $a1 beq $t3 $0 else  sll $t0 $t1 2add $t0 $t0 $t2
else:sll $t0 $t1 3sub $t0 $t0 $t2jr $ra 

(二)嵌套

实例

【C语言】
main()
{sumSquare(a,b);
}
int sumSquare(int x,int y)
{return mult(x,x)+y;
}
int mult(int x,int y)
{return x*y;
}【MIPS汇编】
/* a,b : $s0,$s1 */
1000        add $a0 $s0 $0     #x=a
1004        add $a1 $s1 $0     #y=b
1008        addi $ra $0 1016   #$ra=1016
1012        j sumSquare
...                            #主函数
2000   sumSquare:
2004        add $t9 $ra $0     #$t9=1016
2008        addi $ra $0 2024   #$ra=2024
2012        add $t8 $a1 $a0    #$t8=$a1
2016        add $a1 $a0 $0     #$a1=$a0
2020        j mult
2024        add $a1 $t8 $0     #$a1=$t8=y(b)
2028        add $v0 $v0 $a1    #$v0= mult(x,y)+y
2032        add $ra $t9 $0     #$ra=$t9=1016
2036        jr $ra             #jump to 1016
2040    mult:
2044        mul $v0 $a0 $a1    #$v0=x*y
2048        jr $ra             #jump to 2024

(三)栈

对于更多层的嵌套,需要更多的寄存器,所以肯定会出现寄存器不够用的情况,同时在传参数的过程中,只有四个参数寄存器($a0~$a3,详见寄存器约定),也会出现不够用的情况,那么此时就要使用栈(stack)来保存这些数据。

栈是一种先进后出的数据结构,在MIPS汇编语言中需要程序员自己维护栈。(自开自关)

实例:

前面(二)中实例中的sumSquare函数可以结合栈的使用编译成下面的汇编语言
sumSquare:addi $sp $sp -8    #申请栈空间sw $ra 4($sp)      #保存主调函数的返回地址(即上面的1016)[$t9]sw $a1 0($sp)      #保存y[$t8]add $a1 $a0 $0     #mult(x,x)将第二个参数复制成第一个jal mult           #跳转到mult,并且将下一条指令地址保存到$ralw  $a1 0($sp)     #恢复yad $v0 $v0 $a1     #mult()+ylw $ra 4($ap)      #取回主调函数的返回地址addi $sp $sp 8     #恢复栈jr $ra
mult:*注:addi $sp $sp -n 中,n一定是4的倍数,且使用该栈是可以从0用到n-4(间隔为四)。

五、逻辑运算

常见的逻辑运算包括“与”运算和“或”运算,即and和or。

“与“运算(and)逻辑:当且仅当两个输入都为1时,结果才为1;否则为0。

”或“运算(or)逻辑:两个输入中只要有一个为1时,结果即为1;否则为0.

MIPS汇编语言中的三个移位指令:

(1)sll(逻辑左移):左移,空位补0。

(2)srl(逻辑右移):右移,空位补0.

(3)sra(算数右移):右移,空位进行符号拓展。

*注:左移可以用做乘2的幂次,右移可以用作除以2的幂次。

 


http://chatgpt.dhexx.cn/article/GrHTvE7t.shtml

相关文章

pic单片机汇编 c语言,PIC单片机汇编语言指令详解

PIC单片机汇编语言指令详解 pic单片机为最常用单片机之一&#xff0c;许多程序均基于pic单片机进行开发。因此&#xff0c;熟练pic单片机编程尤为重要。为保证大家能准确、熟练掌握pic单片机的使用&#xff0c;本文特带来pic单片机的各种汇编语言指令的讲解。 一、pic的指令系统…

汇编:汇编指令分类

文章目录 一、指令分类二、伪指令1、assume2、segment、ends3、end 三、汇编指令1、退出程序指令2、中断2.1、概念2.2、中断的分类2.3、本质2.4、中断指令 3、call、ret 四、指令处理的数据长度 使用汇编语言编写一个完整的程序&#xff0c;步骤大致如下&#xff1a; 1、编写源…

汇编语言指令及七种寻址方式指令实现

指令讲解 进入debug模式后&#xff1a;&#xff08;进入debug模式之前的讲解 可以参考我的另一篇博文&#xff1a;masm5.0运行 -u::显示机器指令和汇编指令 -d:显示的具体数据 内存单元内容查看 -r:查看寄存器内容 -r&#xff1a;修改寄存器的内容 如修改ax寄存器的值为12…

微机原理之汇编语言指令集

汇编语言指令集 1.1 概述1.1.1 指令集体系结构、机器指令和符号指令1.1.2 符号指令的书写格式 1.2 操作数1.2.1 通用寄存器中的操作数1.2.2 段寄存器和指令指针寄存器1.2.3 标志寄存器 1.3 寻址方式1.3.1 立即寻址1.3.2 寄存器寻址1.3.3存储器操作数寻址1.3.3.1 直接寻址1.3.3.…

MIPS汇编语言指令

MIPS汇编语言指令 寄存器指令集指令格式R型指令I型指令J型指令 寄存器 寄存器在MIPS体系结构中有32个通用寄存器&#xff0c;在汇编程序中可以用编号表示&#xff0c;$0~31 &#xff0c; 也 可 以 用 名 称 表 示 &#xff0c; 如31&#xff0c;也可以用名称表示&#xff0c;如…

汇编常见指令

文章目录 常见的运算类汇编指令add指令sub指令mul乘法指令div除法指令inc&#xff08;自增&#xff09;&#xff08;即C语言&#xff09;dec&#xff08;自减&#xff09;&#xff08;即–&#xff09;push&#xff08;入栈&#xff09;pop&#xff08;出栈&#xff09;and&…

log4j的ConversionPattern

log4j的ConversionPattern参数的意义 http://lizhou.iteye.com/blog/939154 博客分类&#xff1a; java log4j 多线程 Apache Tomcat F# &#xff0d;X: X信息输出时左对齐 %p: 输出日志信息优先级&#xff0c;即DEBUG&#xff0c;INFO&#xff0c;WARN&#xff0c;ERROR&am…

log4j的ConversionPattern参数的意义

1、常用标志&#xff1a; &#xff0d;X: X信息输出时左对齐 %p: 输出日志信息优先级&#xff0c;即DEBUG&#xff0c;INFO&#xff0c;WARN&#xff0c;ERROR&#xff0c;FATAL, %d: 输出日志时间点的日期或时间&#xff0c;默认格式为ISO8601&#xff0c;也可以在其后指定…

conversionpattern(conversionpattern 自定义字段)

请教以下log4j 日志文件不会弄啊。 直接在Myeclipse中编辑properties 文件的时候不能使用中文的。你可以下载个插件&#xff0c;或者干脆在外边编辑~~你用一个类去读&#xff0c;然后在里面用logger去执行&#xff0c;在log4j的配置文件里面针对这个类配置一个把日志写到文件里…

log4j的配置ConversionPattern详细讲解

原文来自https://blog.csdn.net/reserved_person/article/details/52849505感谢大佬 先写下我一直没找到的ConversionPattern里面参数代表的详细含义 参数说明例子%c列出logger名字空间的全称&#xff0c;如果加上{<层数>}表示列出从最内层算起的指定层数的名字空间log…

零阶保持器(ZOH)与一阶低通滤波器频率特性分析

1.零阶保持器&#xff08;ZOH&#xff09;频率特性分析 零阶保持器传递函数&#xff1a; 画 Bode 图进行频率分析&#xff1a; stf(s); T0.0002; %采样周期0.0002s G(1-exp(-T*s))/s; bode(G); 从图中可以看出&#xff1a;随着频率 ω 的的增加&#xff0c;当 ω 在 10000 附…

一阶低通滤波器、功能触发、周期性触发的simulink模型

01--概述 主要简单叙述在基于模型的过程中比较常用的一些算法&#xff0c;一个是一阶低通滤波器&#xff0c;一个是功能触发&#xff0c;另外一个是周期性触发。会简单介绍下这些算法的应用。 02--一阶低通滤波器 其计算公式为&#xff1a;Y(n) A*X(n) (1−A)*Y(n-1) A滤…

一阶低通滤波器的传递函数分析

一、无源一阶低通滤波器分析 由图可以知道&#xff0c;输入信号为Vi,输出函数为Vo&#xff0c; 电阻R的阻抗为R&#xff0c;C电容C阻抗为1/jwC&#xff0c;Vo实际上是Vi在电容C上的分压&#xff0c;则有&#xff1a; 则有&#xff1a; 将jwS变换得到&#xff1a; 再令Vo/Vin 表…

数字 一阶低通滤波器 详细分析 冰三点水

数字 一阶低通滤波器 详细分析 作者&#xff1a;冰三点水 原创内容&#xff0c;转帖请注明出处&#xff1a; http://blog.csdn.net/u013608300/article/details/78814693 微信公众号&#xff1a;工程师看海 事件的起因是下图1&#xff0c;朋友偶然说到一阶低通滤波器&#x…

一阶低通滤波器的数字实现

关于一阶低通滤波器这里就不再赘述了&#xff0c;讲的帖子也挺多&#xff0c;这里记录一下一阶低通滤波器的传递函数与数字实现之间的系数转换。 一阶低通滤波器的传递函数常见为&#xff1a; 其中Tf为RC&#xff0c;并且有&#xff1a; 其中fwres为截止频率。 常用的数字滤波…

了解一阶低通滤波器传递函数

自动控制原理的内容很高深要逐步地学习 一阶RC滤波器的算法实现&#xff08;低通和高通&#xff09; https://blog.csdn.net/qq_27158179/article/details/82661297 了解一阶低通滤波器传递函数 https://blog.csdn.net/qq_27334499/article/details/52186336 最近&#xf…

一阶低通滤波器在stm32中的简单应用

首先来看一个最简单的一阶低通滤波器的电路模型&#xff1a; 不难推出它的传递函数&#xff1a; Tf与滤波器截止频率有关&#xff0c;但是实际程序中会变成一个参数&#xff0c;此时我们可以忽略它。 然而&#xff01;我们的stm32接收到的信号是一串序列&#xff08;离散信号&a…

数字一阶低通滤波器simulink仿真

数字一阶低通滤波器simulink仿真 原理程序所用公式滤波系数计算方法 仿真根据公式搭建使用simulink自带模型 原理 程序所用公式 y(n) q*x(n) (1-q)*y(n-1) 其中&#xff0c;y(n)表示当前的输出&#xff0c;x(n)表示当前的输入&#xff0c;y(n-1)表示上一次的输出&#xff0…

滞后一秒钟的一阶低通滤波器

用于应对输入跳变到5.5V&#xff0c;让电源工作1s钟然后停机。