Risc-V学习日记07

Risc-V学习日记07
Day15
//发现作业涉及的知识是下一个视频里的md
exercise_5_1
    b3 05 95 00
        00 95 05 b3(小端序)
            计算器(程序员):9505b3
                00       95       05       b3
                00000000-10010101-00000101-10110011
                    查看OP:
                        [b3]1-01100-11
                    为ADD  0000000 rs2 rs1 000 rd 0110011
                        0000000|0-1001|0101-0|000|0101-1|01100|11
                        funct7:0000000
                        funct3:000
                        rs2:01001
                            9
                        rs1:01010
                            10
                        rd:01011
                            11
                    ADD x11,x10,x9

ADDI(ADD Immediate)
    语法
        ADDI RD, RS1, IMM
    例子
        addi x5, x6, 1 
            x5 = x6 + 1
    编码格式:
        I-type
    RV32I Base Instruction Set:
        imm[11:0] rs1 000 rd 0010011
        opcode (7): 0010011(OP-IMM)
    立即数可以表达的数值范围:    
        由于imm[11:0]只占12bit表达范围有限
            由于会被"符号扩展"为一个32位的数
                #[-2^11 ,+2^11),即[-2048, 2047)
        要赋值一个大数 (32 位) 怎么办
            先引入一个新的命令先设置高20位,存放在rs1
                构造高20位命令
                    LUI再加上剩余12位
                然后复用现有的ADDI命令补上剩余的低12位即可   
        例子
            利用 LUI + ADDI 来为寄存器加载一个大数
                0x12345678
                    lui x1,0x12345   #x1=0x12345000
                    addi x1,x1,0x678 #x1=0x12345678
                *** 0x12345FFF
                    ***错误方法
                        lui x1, 0x12345 # x1 = 0x12345000
                        addi x1, x1, "0xFFF" # x1 = 0x12345FFF
                        ***"0xFFF"为一个负数得不出应有的结果
                    解决方法:
                        解决方法一(太过复杂):
                            借一位:lui x1, 0x12346 # x1 = 0x12346000
                            addi x1, x1, -1 # x1 = 0x12345FFF
                            此时答案才为正确
                        解决方法二(正解):
                            伪指令:
                                LI:
                                    语法
                                        LI RD, IMM
                                    例子
                                        li x5, 0x12345678 
                                            x5 = 0x12345678
                                LI (Load Immediate)是一个伪指令(pseudoinstruction)
                                汇编器会根据 IMM 的实际情况自动生成正确的真实指令(instruction)    
    SUBI
        并没有提供SUBI指令,可以用+(-1)实现[RS1=-1]

LUI (Load Upper Immediate)
    语法
        LUI RD, IMM
    例子
        lui x5, 0x12345
            x5 = 0x12345 << 12
                左移12位,右边空出12位填0
                    相当于12345-0000-0000-0000-0000    
    编码格式:
        U-type
    RV32I Base Instruction Set:
        imm[31:12] rd 0110111
        opcode (7):0110111
    作用:
        LUI 指令会构造一个 32 bits 的立即数
            这个立即数的高 20 位对应指令中的 imm[31:12]
            低 12 位清零
                这个立即数作为结果存放在 RD 中    

基于算术运算指令实现的其他伪指令
    NEG 
        语法:
            NEG RD, RS  
        等价指令:
            SUB RD, x0, RS
            x0写不了只能读出0
                x0-RS=RD
                    RD=0-RS
        指令描述:
            对 RS 中的值取反并将结果存放在RD 中
        例子:
            neg x5, x6
    MV
        语法
            MV RD, RS  
        等价指令
            ADDI RD, RS, 0
            RD=RS1+0
        指令描述
            将 RS 中的值拷贝到 RD 中
        例子
            mv x5, x6
    NOP 
        语法
            NOP     
        等价指令    
            ADDI x0, x0, 0 
            x0=x0+0
        指令描述    
            什么也不做
        例子    
            nop
exercise_asm/code/li
    伪指令LI:
        作用:
            ***替代lui实现复杂的赋值操作
        语法
            LI RD, IMM
        例子
            li x5, 0x12345678 
                x5 = 0x12345678
            LI (Load Immediate)是一个伪指令(pseudoinstruction)
            汇编器会根据 IMM 的实际情况自动生成正确的真实指令(instruction)
        {
                .text			# Define beginning of text section
                .global	_start		# Define entry _start

            _start:
                # imm is in the range of [-2,048, +2,047]
                li x5, 0x80

                addi x5, x0, 0x80

                # imm is NOT in the range of [-2,048, +2,047]
                # and the most-significant-bit of "lower-12" is 0
                li x6, 0x12345001

                lui x6, 0x12345
                addi x6, x6, 0x001

                # imm is NOT in the range of [-2,048, +2,047]
                # and the most-significant-bit of "lower-12" is 1
                li x7, 0x12345FFF	

                lui x7, 0x12346
                addi x7, x7, -1

            stop:
                j stop			# Infinite loop to stop execution

                .end			# End of file
        }

AUIPC    
    语法
        AUIPC RD, IMM
    例子
        auipc x5, 0x12345 
            x5 = 0x12345 << 12 + PC
            左移十二位和PC相加
                相对值变化了相对于PC[若是LUI则是相对于0]
                效果:
                    表达范围更宽了
            对比:
                AUIPC:
                    将 20 位立即数(imm)左移 12 位,得到一个 32 位的数(offset),低 12 位补零: 
                        offset = imm << 12
                    将当前 PC 的值与 offset 相加,得到目标地址: 
                        Target_address = PC_current + offset
                    由于 offset 是一个 32 位的数,因此 AUIPC 可以覆盖的地址范围是 
                        PC_current 所在的整个 32 位地址空间
                            换句话说,AUIPC 可以表示目标地址相对于当前 PC 的任意偏移量,从而拥有更广泛的表达范围。
                LUI(Load Upper Immediate)指令
                    只是将一个 20 位的立即数加载到目标寄存器的高位
                    低位补零。这意味着 LUI 只能表示一个 20 位的常数,且低 12 位始终为零
                    它不能像 AUIPC 一样根据当前 PC 动态地计算目标地址。
    编码格式:
        U-type
    RV32I Base Instruction Set:
        imm[31:12] rd 0010111
        opcode (7):0010111
    作用:
        和 LUI 指令类似,AUIPC 指令也会构造一个 32bits 的立即数
        这个立即数的高 20 位对应指令中的 imm,低 12 位清零
            ***但和 LUI 不同的是,AUIPC 会先将这个立即数和 PC 值相加
            将相加后的结果存放在 RD 中
    由来:
        LI构造出来的地址是一个绝对值
        例子:
            动态库(Dynamic Link Library,简称为DLL)
                解释:
                    是一种计算机程序库(或称为共享库)
                    它包含了一系列可被多个程序共享和重用的代码、数据和资源。
                    与静态库(Static Library)不同,动态库在程序运行时动态加载到内存,并且可以在不同的程序间共享,从而节省系统资源和内存空间。
                动态链接:
                    解释:
                        在编译时,程序并不将动态库的代码和数据嵌入到可执行文件中,而是在程序运行时动态加载。
                        这意味着多个程序可以共享同一个动态库,从而减少了重复的内存占用。
                    示例:
                        假设数学函数库的大小为100KB,"Program A"和"Program B"的大小分别为200KB和300KB
                        地址:
                            编译动态库: 首先,我们将"MathLibrary.dll"编译为一个动态库,其中包含一些数学函数的实现,例如"add"函数和"subtract"函数。
                            编译程序: 接下来,我们编译"Program",它调用了"MathLibrary.dll"中的数学函数。
                            加载过程: 当我们运行"Program"时,操作系统的动态链接器将加载"MathLibrary.dll"到进程的地址空间中。此时,会发生以下变化:
                                a. 加载地址: 动态链接器决定将"MathLibrary.dll"加载到进程的某个空闲地址空间中。这个加载地址通常是在运行时[动态分配]的,因此每次加载的位置可能不同。
                                b. 重定位:在"MathLibrary.dll"被加载到进程的地址空间后,动态链接器需要处理库内部的重定位问题。这是因为在编译时,"MathLibrary.dll"的代码和数据是按照编译时的加载地址进行的,
                                          但在运行时,它被加载到了不同的地址空间。[因此,动态链接器会根据实际加载地址,对库内的地址引用进行重定位,使得代码和数据正确地映射到新的地址]。
                            符号解析: 一旦重定位完成,"Program"中的函数调用将会被解析为正确的地址,以便正确地调用"MathLibrary.dll"中的数学函数
                        优点节省空间:
                            静态链接:
                                1.静态链接时,每个程序都会包含数学函数库的副本,因此它们在运行时不会共享代码。
                                2.当我们编译"Program A"和"Program B"时,编译器将数学函数库的代码嵌入到这两个程序的可执行文件中
                                3.总共占用了100KB + 200KB + 300KB = 600KB
                            动态链接:
                                1.动态链接时,我们将数学函数库单独编译成一个动态库文件
                                2.当编译"Program A"时,它只包含调用数学函数库的函数名称和引用,而不会包含实际的数学函数库代码
                                3."Program A"在运行时,操作系统的动态链接器会加载MathLibrary.dll,并将其中的代码和数据加载到内存中
                                4.当编译"Program B"时,它也只包含数学函数库的引用,而不会包含实际的数学函数库代码
                                5."Program B"在运行时,同样的动态链接器会检测到MathLibrary.dll已经加载过了,所以不会重新加载,而是直接共享已加载的代码和数据
                                6.总共只占用了100KB + 200KB + 100KB = 400KB

LA (Load Address)LA是一个伪指令(pseudo-instruction)
    语法
        LA RD, LABEL
    例子
        la x5, foo
    作用:
        常用于加载一个函数或者变量的地址
    解释:
        具体编程时给出需要加载的 label,
        编译器会根据实际情况利用 auipc 和其他指令自动生成正确的指令序列
    代码:
        {
            	.text			# Define beginning of text section
                .global	_start		# Define entry _start

            _start:
                la x5, _start		# x5 = _start,
                                    #x5是最终目标赋值寄存器,_start[label理解为地址]{自动分配}
                                    #效果:将地址_start赋值给x5
                jr x5
                                    #跳转到x5,由于此时x5的地址为_start,重新执行_start,_start会一直循环执行
            stop:
                j stop			# Infinite loop to stop execution

            exit:

                .end			# End of file
        }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值