首页 > 其他分享 >计组学习05——Introduction to Assembly Language

计组学习05——Introduction to Assembly Language

时间:2022-12-17 20:11:06浏览次数:68  
标签:Assembly 计组 Language s3 s2 s1 s0 指令 寄存器

感觉可算到了真正计组重要的部分(毕竟我是因为挖操作系统的时候感觉计组知识严重不足来补的计组。
为了看清楚问题和ppt,倍速减慢截取字幕消失的那几帧....
然后还有一些解释看不懂跟不上,去上网搜索
还遇到了看不懂的单词,有些我也不知道官方翻译是什么,这就是没有基础就学习国外教程的痛苦...
应该是阳了,这几天学习效率也不算高,从下一阶段准备开始加速学习了...现在的效率距离目标还是很远的...

计组学习 —— Introduction to Assembly Language

从高级程序语言(比如C),到汇编语言程序(比如RISC-V),我们逐渐深入计算机的硬件。

在这门课里,我终于知道了为什么

硬件与变量

与高级程序语言不同,汇编语言往往没有变量这个概念,而是使用寄存器来存储值

关于寄存器:

  • 寄存器就是小块的固定大小的内存。32位或者64位
  • 可以被读写
  • 数量有限制,32位的机器只有32给普通寄存器
  • 非常快

如果使用的变量多于32个怎么办?

  • 把使用最频繁的放入寄存器中,之后把剩下的放到内存里,这个方法也叫溢出到内存(spilling to memory)

为什么不把所有的变量都放到内存呢?

  • smaller is faster:寄存器比内存快了100-500倍
  • 内存分级:
    • 寄存器:32个*32位 = 128字节
    • RAM: 4-32GB
    • SSD:100-1000GB

寄存器的分类:

  • 我们使用x0-x31来为32个寄存器命名

  • 同时,寄存器由于功能不同,所以也有自己的名字

    • s开头的寄存器,表示他是一个安全(safe)寄存器
    • t开头的寄存器,一般用于储存临时变量(tmp)
  • s0-s1 对应 x8-x9

  • s2-s11对应x18-x27

  • t0-t2 对应 x5-x7

  • t3-t6 对应x28-x31

零寄存器

什么是程序中最重要的数字?

  • 没错,答案就是零寄存器
  • x0表示零寄存器,它的值永远是0,来表示一些错误或者别的,永远不可能被改变!!!

相关寄存器

寄存器 ABI名 用途 Saver
x0 zero 读取时永远为0,写入起不到任何效果 -
x1 ra 存储函数返回的地址(return address) Caller
x2 sp 存放栈指针(stack pointer) Callee
x3 gp 全局指针 global pointer -
x4 tp 线程指针 thread point -
x5-x7 t0-t2 临时 (temporaries) 寄存器,Callee 可能会使用这些寄存器,所以 Callee 不保证这些寄存器中的值在函数调用过程中保持不变,这意味着对于 Caller 来说,如果需要的话,Caller 需要自己在调用 Callee 之前保存临时寄存器中的值。 Caller
x28-x31 t3-t6 临时寄存器,同上 Caller
x8-x9 s0/fp - s1 保存 (saved) 寄存器,Callee 需要保证这些寄存器的值在函数返回后仍然维持函数调用之前的原值,所以一旦 Callee 在自己的函数中会用到这些寄存器则需要在栈中备份并在退出函数时进行恢复。 Callee
x18-x27 s2-s11 保存寄存器,同上 Callee
x10-x11 a0-a1 参数 (argument) 寄存器,用于在函数调用过程中保存第一个和第二个参数,以及在函数返回时传递返回值。 Caller
x12-x17 a2-a7 参数 (argument) 寄存器,如果函数调用时需要传递更多的参数,则可以用这些寄存器,但注意用于传递参数的寄存器最多只有 8 个 (a0 ~ a7) ,如果还有更多的参数则要利用栈。 Caller

Caller :调用者,Callee : 被调用函数【这里可以视为在 Caller (函数)中调用 Callee (函数)】
Caller 维护的寄存器,在运行被调函数前不会被保存,函数返回时这些寄存器可能会被改变,所以在调用前由 Caller 保存维护。
Callee 维护的寄存器,在运行被调函数前会被保存,函数返回后这些寄存器与运行被调函数前相同。

原文链接:https://blog.csdn.net/m0_52132972/article/details/126574474

汇编指令

基本命令格式:

op dst, src1, src2

  • op即为操作名
  • dst为结果储存的寄存器
  • src1为操作的第一个寄存器
  • src2为操作的第二个寄存器

基础算数指令

  • 整数加法

    add s1, s2, s3

  • 整数减法

    sub s1, s2, s3

  • 假设abcde分别对应s0-s5,那么 a=(b+c)-(d+e):

    add t1, s3, s4

    add t2, s1, s2

    sub s0, t2, t1

Immediates

命令格式:

opi dst, src, imm

  • 在操作后面加一个i,会把第二个source替换为一个常数,叫做immediate
  • immediate最大可以到12位
  • immediate可以认识符号

那么问题来了: 假设a为s0,b为s1 , a=(5+b)-3

addi t1, s1, 5

addi s0, t1, -3

为什么第二句话不写成 subi s0 t1 3呢?

  • 因为当我们能用一个命令执行的时候,就不要浪费另一条指令的空间,
  • 减少使用的指令的种类和数量,可以降低风险

Data Transfer数据传输指令

数据之间的运输是指寄存器和内存之间的运输

命令格式:

memop reg, off(bAddr)

  • memop 对于内存的操作名
  • reg 资源最终要储存的寄存器
  • bAddr 指向内存的指针寄存器
  • off 为地址的偏移量
  • 我们最终要到达的地址为: bAddr+off

Load Word(lw)指令:

  • 从内存中的bAddr+off获取数据放入到reg中

Store Word(sw)指令:

  • 从内存中获取数据储存到reg中

假设我们有一个int类型数组array[],储存到s3中,有一个int类型的数字b储存在s2中,实现: array[10]=array[3]+b:

lw t0,12(s3) # t0=array[3]

add t0,s2,t0 # t0=array[3]+b

sw t0,40(s3) # array[10]=array[3]+b

注意到!我们的off在计算时,需要程序员去考虑元素的大小!在这道题中,假设操作系统的int是4字节的,因为我们默认是按字节寻址的,所以也需要手动把单位都转化为字节

Load Byte(lb),Store Byte(sb)指令:

  • 在sb操作中,最高的24位将被忽略
  • 在lb操作中,最高的24位将通过符号拓展的方式填充

看实例~,假设 s0 = 0x00000180

lb s1,1(s0) # s1=0x00000001 ,因为偏移量为1位,所以我们获取到0x01(00000001)这8位,前面的24位都被符号位填充为0

lb s2,0(s0) # s2=0xFFFFFF80 ,0x80(10000000),所以前面24位全被1填满,十六进制下全是FF

sb s2,2(s0) # *(s0)=0x00800180,我在s0中偏移两位的储存我在s2中加载的值,因为只取s2最低的8位,所以只有80,之后把这个80写入到s0对应的位置

**Load Half(lh),Store Half(sh) **

无需多言,就是把 lb和sb的命令,从忽略24位/填充24位,变成了忽略16位/填充16位

Unsigned Instruction

在上述操作中,我们如果在lh/lb后面加一个u,变成lhu/lbu,就多加了一个意思,把无符号的东西加载到其中。

如果仔细思考,可以发现没有sbu或者shu同样没有lwu,因为这些指令实际上是没有意义的

lbu或者lhu,拓展的是最高有效位的符号!

流程控制

Branch If Equal(beq)

beq reg1,reg2,label

  • 如果reg1寄存器里的值等于reg2寄存器里的值,跳转执行label
  • 否则进行下一条指令

Branch If Not Equal(bne)

显然,两个寄存器不等于的话直接跳转label

Jump(j)

j label

无条件跳转到label

Branch Less Than(blt)

blt reg1,reg2,label

  • 如果reg1<reg2 那么跳转到label

Branch Greater Than or Equal(bge)

bge reg1,reg2,label

  • 如果reg1≥reg2,跳转到label

可以思考发现,没有必要小于等于,因为只需要交换两个分支顺序就可以变成大于等于了,为了精简指令,所以没有判断小于等于

关于流程控制的解释

其实流程控制的本质是控制pc指针,因为一条条指令的本质也是数据,pc指针指向的就是当前执行的指令,而流程控制改变了pc的值,所以我们可以控制语句的执行顺序。

同时我们要控制PC是一个偶数,因为每一条指令都是偶数字节,从0开始,加上或者减去偶数,它永远都是偶数

转换指令

  • 众所周知,左移一位比乘2快得多,我们在汇编层面也要支持移位操作,才能最大化速度。
  • 但是右移不一定与除法相同

在移位时,可以保留值

Instruction Name RISCV
Shift Left Logical 逻辑左移 sll s1,s2,s3
Shift Left Logical Imm 逻辑左移数字 slli s1,s2,imm
Shift Right Logical 逻辑右移 srl s1,s2,s3
Shift Right Logical Imm逻辑右移数字 srli s1,s2,imm
Shift Right Arithmetic算数右移 sra s1,s21s3
Shift Right Arithmetic Imm算数右移数字 srai s1,s2,imm
  • 只会检测变量的最低五位,这意味着:

    • 读取s3这样的数字时,只有最低5位有效
    • 使用Immediate时,数值之应该是0-31
  • 逻辑位移,会用0填充高位

  • 算数位移,会进行符号拓展

其他拓展

Multiplication(mul and mulh)

mul dst, src1, src2

mulh dst, src1, src2

  • src1*src2的结果:更低的32位在mul里,更高的32位在mulh里

Division(div)

div dst, src1, src2

rem dst, src1, src2

  • src1/src2 的结果商在div里,余数在rem里

Bitwise Instructions位运算

Instruction C RISCV
And a = b & c and s1,s2,s3
And Immediate a = b & 0x1 andi s1,s2,0x1
Or a = b | c or s1,s2,s3
Or Immediate a = b | 0x5 ori s1,s2,0x5
Exclusive Or a = b ^ c xor s1,s2,s3
Exclusive Or Immediate a = b ^ 0xF xori s1,s2,0xF

Compare Instructions比较指令

  • Set Less Than(slt)

    slt dst, reg1, reg2

    如果reg1<reg2,dst为true,否则为false

  • Set Less Than Imm (slti)

    slt dst, reg1, imm

可以使用比较指令写出另一种流程控制语句


最后附上参考并总结的博客~

(21条消息) RISC-V 常用汇编指令_程序DNA的博客-CSDN博客_riscv汇编指令

标签:Assembly,计组,Language,s3,s2,s1,s0,指令,寄存器
From: https://www.cnblogs.com/ZzTzZ/p/16989463.html

相关文章

  • 计组学习04——Floating Points
    计组学习——FloatingPoint浮点数的表示0bxx.xxxx\(2^1\2^0\.2^{-1}\2^{-2}\2^{-3}\2^{-4}\)这是6位数字分别的含义可以很容易发现,浮点数的精度是一个很大......
  • Minimizing Go WebAssembly Binary Size
    MinimizingGoWebAssemblyBinarySizehttps://dev.bitolog.com/minimizing-go-webassembly-binary-size/ PostedonOctober9,2020byOmriCohenEstimatedrea......
  • 计组学习02——C and Pointers
    计组学习——CandPointers由于已经比较熟悉C了,上课时跳过了许多已经熟知的部分,只记录自己不太熟的地方。UnionsinC定义和struct基本一样unionfoo{inti......
  • Adding Macro Scripting language support to existing ATL/WTL Application
    AddingMacroScriptinglanguagesupporttoexistingATL/WTLApplication  DownloadATLScriptHostDemoProject-83KbScreenShotsTheATLScriptHosta......
  • 计组学习01——Number Rep
    计组学习——NumberRepresentationNumberRepresentation数字的表示方式有符号数的表示原码,把第一位数字表示为符号位,​ 如果000表示0,001表示为1,101表示-1,这样就会......
  • [assembly: AssemblyVersion("1.0.1.*")] 指定版本字符串不符合所需格式 - major[.min
    [assembly:AssemblyVersion("1.0.1.*")]指定版本字符串不符合所需格式-major[.minor[.build[.revision]]]...报如下错误,解决方法:打开项目文件,修改 打开项目文件......
  • 版本号自动生成,获得Assembly版本号
    usingSystem.Reflection;获得AssemblyInfo.cs中指定的版本号Assemblya=Assembly.GetAssembly(typeof(Try));AssemblyNamename=a.GetName();Console.WriteLine(name......
  • 关于 ABAP 开发对象的原始语言版本(Original Language)
    当创建新的存储库对象时,例如ABAP词典中的程序、类或数据库表,必须指定其原始语言。ABAP开发框架隐式将当前登录语言设置为其原始语言。作为开发项目中开发对象的一部分......
  • 关于 ABAP 开发对象的原始语言版本(Original Language)
    当创建新的存储库对象时,例如ABAP词典中的程序、类或数据库表,必须指定其原始语言。ABAP开发框架隐式将当前登录语言设置为其原始语言。作为开发项目中开发对象的一部分创......
  • 计组Review1
    1GB的内存,它是以字节编址的,假设内存地址为32位,128KB的高速缓存。现在有一个数据位于0x123456(字节编址),会映射到那些不同情形的内存单元上,还有TAG和总缓存大小。1.直接映......