汇编指令入门

目录

1.寻址模式

2.条件跳转

3.中断

4.递归函数的底层逻辑

5.汇编语言实现6的阶乘递归函数


计算机通过指令指挥计算机工作。

CPU被时钟驱动,不断读取PC指针指向的指令,并移动PC指针,从内存中读取指令并执行(周而复始)。不同的CPU架构使用不同指令,目前比较广泛的是RISC(精简指令集)

1.寻址模式

寻址模式是指令集的一部分,决定地址如何计算以及指令有几个操作符。(指令集不同,寻址模式也不同)

寄存器寻址:

操作数在CPU内部的寄存器中,指令指定寄存器号。对于16位操作数,寄存器可以是:$s1、$s2等,这种寻址方式由于操作数就在寄存器中,不需要访问存储器来取得操作数,因而可以取得较高的运算速度。

立即寻址:

MIPS中,该寻址方式是直接在指令中给出操作数。在这种寻址方式中,操作数作为立即数直接编码在指令中。这意味着操作数的值是预先给定的,并且可以直接从指令本身获取而不需要从其他寄存器或内存中读取。例如,汇编语言中的:

addi $s1, $s2, 10

表示将立即数10与寄存器s2的内容相加,结果存储在寄存器s1中。

立即数寻址的优点包括执行速度快和操作简单,因为所需的操作数已经包含在指令中,无需额外的内存访问周期。(这种寻址方式中,如32位的操作数的大小有限制:-2^{15}1  ~  2^{15}

偏移量寻址:

基地址寄存器 + 立即数偏移量。这意味着无论是从内存加载数据还是将数据存储到内存,都需要指定一个基址寄存器和一个立即数作为偏移量,因为它是 16 位的,所以这个立即数必须在 -32768 到 32767 之间,

例如,汇编语言的伪代码:

lw $t1, 4($sp)

表示将地址为$sp加上立即数偏移量4的内存内容加载到寄存器t1中,$sp是堆栈寄存器4就是所说的立即数偏移量。

lw指令用于从内存中加载数据到寄存器,不能直接从寄存器读值

PC相对寻址:

PC相对寻址在MIPS架构中主要用于实现跳转指令,例如分支和函数调用。在这种寻址方式下,下一个PC指针的位置依赖于当前位置到Lable的距离(当前代码行和Label所在的代码行之间的相对差),将更新后的PC值(通常是PC+4,因为在取得指令后PC会自动增加)与相对差相加,得到最终的目标地址。

2.条件跳转

相对寻址:j LABEL

寄存器间接寻址:jr $a0

jal LABEL——将当前PC+4(即当前代码的下一行位置)存入$ra寄存器然后再跳转到LABEL。

将if-else翻译成汇编:

# java代码   
int i = 0;
int j = 1;
int f = 0;
if (i == j) {
   f = i + j;
} else {
   f = i - j;
}
#汇编代码
addiu $s1, $0, 0
addiu $s2, $0, 0
bne $s1, $s2, ELSE
add $s3, $s1, $s2
nop
j EXIT
ELSE:
sub $s3, $s1, $s2
EXIT:

 将循环翻译成汇编:

#java代码
int sum = 0;
for (int i = 0; i < 100; i++) {
     sum += i;
}
#汇编代码
addi $s1, $0, 0 #sum=0
addi $s2, $0, 0 #i=0
addi $s3, $0, 100 #100
LOOP:
beq $s2, $s3, EXIT
add $s1, $s2, $s1
add $s2, $s2, 1
j LOOP
nop
EXIT:

 汇编实现函数

将函数调用传参理解成调用前压栈,调用后出栈的程序。

#java代码
public class demo {
    public static void main(String[] agrs) {
        func(3);
    }

    public static int func(int n) {
        return n + 2;
    }
}
#对应的汇编
addiu $s1, $0, 3 # n=3
sw $s1, 0($sp)
addiu $sp, $sp, -4
jal FUNC
nop
j EXIT
nop
FUNC:
sw $ra, 0($sp)
addiu $sp, $sp, -4
lw $t1, 4($sp)
lw $s2, 8($sp)
addu $s3, $s2, 2
jr $t1   #跳回到函数调用处
nop
EXIT:

sp是堆栈指针(StackPointer)的常见表示方式,它指示的是当前栈顶的位置。在具体的实现上,sp通常是作为一个专门的寄存器存在于处理器中,以便快速地访问和管理栈空间。以下是$sp的一些作用:

  • 存储管理:$sp用于管理栈空间,包括在函数调用时保存局部变量、返回地址和其他临时数据。
  • 上下文切换:当发生函数调用或中断时,$sp帮助保存当前执行上下文到栈中,并在函数返回或中断处理完成后恢复上下文。
  • 运算限制对于RISC处理器而言,堆栈中的数据不能直接用于CPU运算,必须先加载到寄存器中才能进行处理(通过lw指令)
  • 指针功能:在某些架构中,如ARM处理器,通常会有一个固定的寄存器作为堆栈指针,例如R13寄存器被用作$sp

3.中断

  1.  OS加载时,写入中断向量表
  2. 产生中断请求时,发送给CPU
  3. 查询中断向量表,确定中断向量
  4. 根据中断向量定位中断响应程序
  5. OS接管中断

中断请求包括:硬件设备发送给主板的、硬件中断(CPU异常、除以0、时钟信号)、软件中断(异常、切换到内核态等)

中断向量表:一般存在于内存中的一块区域,存储了中断类型和中断响应程序的对应关系,每一行叫做一个中断向量。中断向量表如下:

中断类型

ISR地址

描述

00

0x0000

除以0

01

0x0004

单步

09

0x0024

键盘

18

0x0048

打印机

异步IO底层就是通过中断实现的

 中断的意义:提高工作效率、故障恢复(异常处理、紧急事件)、简化编程模型(try/catch,计时器)

4.递归函数的底层逻辑

依次将每一层的函数包括(传参、调用位置、返回值)压入栈中,开始向下层递归的时候,每一层的返回值都默认赋值为0(因为没到最底层,不知道每层的返回值该是多少),然后达到递归终止条件时,从最底层往上返回时,再给每一层的返回值赋值。

递归函数涉及到栈操作,在向最底层递归时,各个数据压入栈,当到了最底层,触及到了递归终止条件时,开始进行出栈操作,通过下图能看到压栈的方向,第一层执行的函数被压到了栈底,最底层的函数位于栈顶。

 

5.汇编语言实现6的阶乘递归函数

这里面使用到了立即寻址、寄存器寻址、PC相对寻址和偏移量寻址的知识,也使用到了条件跳转。

#递归函数
addiu $sp, $0, 0x10010080
#设置参数
addiu $s0, $0, 6 #n
#压栈操作,指针下移4位
sw $s0, 0($sp)
addiu $sp, $sp, -4

jal FACT
nop #在mips指令集中有预执行的概念,所以跳转指令后都要跟一个nop
j END #函数结束
nop

FACT:
#压栈返回地址
sw $ra, 0($sp) #调用jal之后,会把“跳转地址+4”存入ra寄存器
addiu $sp, $sp, -4

#读取参数,上面进行了两次压栈,所以应该加8
lw $s0, 8($sp)

#压栈返回值,目前还不知道返回值,所以先占位
sw $0, 0($sp)
addiu $sp, $sp, -4

#终止递归 if(n==1){ return 1 }
addiu $s3, $0, 1
bne $s0, $s3, RECU
nop
#读取返回地址
lw $t1, 8($sp)
#出栈:返回值和返回地址
addiu $sp, $sp, 8
#压栈返回值
addiu $s0, $zero, 1 #return 1
sw $s0, 0($sp)
addiu $sp, $sp, -4

jr $t1
nop

RECU:#递归函数体
#return fact(n-1)*n
#压栈参数
addiu $s1, $s0, -1
sw $s1, 0($sp)
addiu $sp, $sp, -4

jal FACT
nop

#现在的栈。 参数 | 返回地址 | 返回值 | 子函数的参数 | 子函数的返回值 | 当前sp
#取当前参数
lw $s0, 20($sp)
#子函数返回值
lw $s1, 4($sp)
#返回地址
lw $t1, 16($sp)

mult $s1, $s0
mflo $s2

#出栈
addiu $sp, $sp, 16
#返回值压栈
sw $s2, 0($sp)
addiu $sp, $sp, -4

jr $t1
nop
END:

  • 48
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值