• ARM 汇编寻址方式


    ARM支持9种寻址方式:立即数寻址,寄存器寻址,寄存器偏移寻址,寄存器间接寻址,基址变址寻址,多寄存器寻址,相对寻址,堆栈寻址,块拷贝寻址。

    立即数寻址

    将数据直接存放的指令中发给CPU,首先由于ARM的一条指令占了32bit,而操作码本身也要占据一些位,所以留给立即数的位数肯定不到32bit,其次并不是满足指定位数的数字都是立即数,ARM中的立即数必须可以通过某个8bit的数据经过循环右移得到

    MOV R0,#255     ;R0 <- #255,#0~#255都是立即数
    ADD R0, R0, #1  ;R0 <- (R0+#1)
    

    寄存器直接寻址

    将寄存器中的数据用作操作数

    MOV R0, R1          ;R0 <- R1
    ADD R0,R1, R2     ;R0 <- (R1 + R2)
    

    寄存器间接寻址

    将寄存器中的数据作为主存中操作数的地址,去到相应的主存地址取得操作数,用[R0]表示将R0中的数据当作操作数的地址...,[R0]!表示将R0中的数据当作操作数的地址并将操作后的结果地址给R0

    LDR R0,[R1]        ;将R1指向的数据加载到R0中 
    STR R0, [R1]!        ;将R0存储的数据加载到R1指向的主存地址中,加载完毕R1中为操作后的地址
    ADD R0,R1,[R2]
    

    寄存器偏移寻址

    现将寄存器的值进行移位,再将移位后的数据当作操作数

    MOV R0,R2,LSL  #1   ;R2的值左移1位,结果赋给R0。
    MOV R0,R2,LSL  R1 ;R2的值左移R1位,结果放入R0。
    

    有6种移位操作:

    LSL:逻辑左移(Logical Shift Left),寄存器中字的低端空出的位补0。
    LSR:逻辑右移(Logical Shift Right),寄存器中字的高端空出的位补0。
    ASL:算术左移(Arithmetic Shift Left),和逻辑左移LSL相同。
    ASR:算术右移(Arithmetic Shift Right),移位过程中符号位不变,即如果源操作数是正数,则字的高端空出的位补0,否则补1。
    ROR:循环右移(Rotate Right),由字的低端移出的位填入字的高端空出的位。
    RRX:带扩展的循环右移(Rotate Right eXtended),操作数右移一位,高端空出的位用进位标志C的值来填充,低端移出的位填入进位标志位。
    

    寄存器基址变址寻址

    可以看作寄存器间接寻址的增强版,不再直接从寄存器指向的地址中取操作数,而是从寄存器指向的地址再偏移一个量之后再取操作数

    LDR R0,[R1,#4]    ;取R1的内容当作主存的地址,在此基础上+4byte,从该地址处取操作数。
    LDR R0,[R1,#4]!  ;同上,操作完毕后,!表示指令执行完毕把最后的数据地址写到R1,即R1原来的地址+4
    LDR R0,[R1,R2]    ;将寄存器R1的内容加上寄存器R2的内容形成操作数的地址,取得的操作数存入寄存器R0中。
    STR R0, [R1,#-4];将R1中的数值减4作为地址,把R0中的数据存放到这个地址中。
    LDR R0,[R1],#4   ;把R1指向的数据放到R0中,操作完成后[R1]自增4byte
    

    批量寄存器寻址

    LDMIA  R0,{R1,R2,R3,R4}     ;将R1,R2,R3,R4中的数据依次放入R0指向的内存地址,R0+4指向的内存地址...
    LDMIA  R0,{R1-R4}  ;同上。
    

    相对寻址

    通过使用语句的中的标号进行寻址,通常配合跳转指令使用

        BL   FCN  ;相对寻址,跳转到NEXT处执行。
        ...
    FCN:
        ...
    

    堆栈寻址

    堆栈即Stack,因为CPU的寄存器总是及其有限的,很多时候我们不得不使用内存来存储数据,比如进行多级跳转的时候,这时候堆栈就是一个很好的工具,每次跳转就将当前函数的返回地址存储到内存,最底层被调用的子函数会最先返回,就先将压入栈的现场返回,以此类推...,ARM使用SP(R13)作为栈指针,ARM设计的内存栈模型有2×2=4种
    按照栈在内存增长的方向分为递增栈递减栈
    递增(Increase)堆栈:向堆栈写入数据时,堆栈由低地址向高地址生长。
    递减(Descend)堆栈:向堆栈写入数据时,堆栈由高地址向低地址生长。

    根据堆栈指针SP指向的位置,又可以把堆栈分为满堆栈空堆栈两种。
    满堆栈(Full Stack):SP始终指向栈顶元素,压栈的时候先移动SP,再将数据放入SP指向的地址。
    空堆栈(Empty Stack):SP始终指向下一个将要放入元素的位置,压栈时先将数据放入SP指向的地址,再移动SP
    最后,可以得到4种基本的堆栈类型:

    满增栈(FA):堆栈指针指向最后压入的数据,且由低地址向高地址生长。
    满减栈(FD):堆栈指针指向最后压入的数据,且由高地址向低地址生长。常用这种
    空增栈(EA):堆栈指针指向下一个将要压入数据的地址,且由低地址向高地址生长。
    空减栈(ED):堆栈指针指向下一个将要压入数据的地址,且由高地址向低地址生长。

    STMFD  SP!,{R1-R7, LR} ;将R1-R7和LR的数据按照压入FD栈
    LDMFD  SP!,{R1-R7, PC} ;从FD栈中取得数据依次放入R1-R7,PC
    

    块拷贝寻址

    块拷贝寻址提供了一块内存和一组寄存器之间的拷贝,按照内存使用方式的不同,可以分为2×2=4种。地址增方向/地址减方向×先偏移/后偏移。堆栈寻址就可以看作是块拷贝寻址的的一个实例。
    即:
    IB:Increment Before Operating
    IA:Increment After Operating
    DB:Decrement Before Operating
    DA:Decrement After Operating

    STMIA  R0!,{R1—R7}  ;将R1-R7的寄存器中的值放入R0指向的地址,R0自动更新,指向操作后的地址
    
  • 相关阅读:
    Android驱动开发
    LCD控制器时序参数的确定(基于TFT LCD: KD50G9-40NM-A3)
    Delphi IDHTTP用法详解
    Delphi开发Android的几个注意
    Delphi 调试连接 任意Android手机/平板/盒子
    Delphi XE10在 Android下调用静态库a文件
    Delphi的FIFO实现
    Delphi获取Android下GPS的NMEA 0183数据
    【CJOJ1603】【洛谷1220】关路灯
    【洛谷2986】【USACO10MAR】伟大的奶牛聚集
  • 原文地址:https://www.cnblogs.com/xiaojiang1025/p/5951461.html
Copyright © 2020-2023  润新知