Linux教程

第10部分- Linux ARM汇编 寻址方式

本文主要是介绍第10部分- Linux ARM汇编 寻址方式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

都遵循gas汇编器的语法。

  • 立即寻址指令后面的地址码部分为立即数

            MOV RO, #1234

  • 寄存器寻址中,操作数在寄存器中,指令执行时直接从寄存器中取值进行操作。

      MOV R0, R1

  • 寄存器移位寻址是ARM指令集特有的寻址方式,和寄存器寻址类似,只是操作前需要对寄存器操作数进行移位操作。

LSL:逻辑左移,移位后寄存器空出的低位补0。

LSR:逻辑右移,移位后寄存器空出的高位补0。

ASR:算术右移,移位过程中,符号位保持不变,如果源操作数是正数,则空出的高位补0,否则补1.

ROR:循环右移,移位后移除的低位填入空出的高位。

RRX:带扩展的循环右移,操作数右移一位,移位空出的高位用C标志的值填充。

      MOV R0, R1, LSL #2

R1寄存器左移两位赋值给R0,指令执行后,R0=R1*4。

  • 寄存器间接寻址:地址码给出的寄存器是操作数的地址指针,所需的操作数保存在寄存器指定的存储单元中。

 

LDR R0, [R1]

将R1寄存器的数值作为地址,取出此地址中的值赋给R0寄存器。

  • 基址寻址是将地址码给出的基址寄存器和偏移量相加,形成操作数的有效地址,所需的操作数保存在有效地址所指向的存储单元中。基址寻址多用于查表和数组访问等操作

LDR R0, [R1, #-4]

寄存器R1的数组减去4作为地址,取出此地址中的值赋值给R0。

  • 多寄存器寻址 : 一条指令最多可以完成16个通用寄存器的传送。

LDMIA R0, {R1, R2, R3, R4}

LDM是数据加载指令,指令的后缀IA表示每次执行完加载操作后R0寄存器的值自增1个字。指令执行后,R1=[R0],R2=[R0+#4],R3=[R0+#8],R4=[R0+#12]。

  • 堆栈寻址是ARM处理器特有的一种寻址方式,堆栈寻址使用特定的指令来完成。

LDMFA/STMFA

LDMEA/STMEA

LDMFD/STMFD

LDMED/STMED

STMFD SP1, {R1-R7, LR}

将R1-R7,LR入栈,多用于保存子程序现场。

LDMFD SP1, {R1-R7, LR}

将数据出栈,放入R0-R7,LR寄存器,多用于恢复程序现场。

  • 块拷贝寻址可实现连续地址数据从存储器的某一位置拷贝到另一位置。

LDMIA/STMIA

LDMDA/STMDA

LDMIB/STMIB

LDMDB/STMDB

LDMIA R0!, {R1-R3}

从R0寄存器的存储单元中读取3个字到R1-R3寄存器中。

STMIA R0!, {R1-R3}

存储在R1-R3寄存器的内容到R0指向ed存储单元。

LDMIA/LDMDA中I表示Increasing,D表示decreasing,A表示After,B表示Before。

  • 相对寻址以程序计数器PC的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到的操作数作为有效地址。

BL NEXT

   ...

NEXT:

   ...

BL NEXT是跳到NEXT标号处执行,这里的BL就是采用相对寻址,标号NEXT是偏移量。

Load/store示例

Load示例

定义load.s文件如下:

.data;//数据段

.balign 4  /* 四个字节对齐 */
myvar1: /* 定义变量myvar1 */
    .word 3     /* 值为'3' */
.balign 4 /* 四个字节对齐 */
myvar2: /* 定义变量myvar2 */
    .word 4    /* 值为'4' */
 
.text /* -- 代码段*/
.balign 4 /* 四个字节对齐 */
.global main
main:
    ldr r1, addr_of_myvar1 /* r1 ← &myvar1 */
    ldr r1, [r1]           /* r1 ← *r1 */
    ldr r2, addr_of_myvar2 /* r2 ← &myvar2 */
    ldr r2, [r2]           /* r2 ← *r2 */
    add r0, r1, r2         /* r0 ← r1 + r2 */
    bx lr
 
/* 数据地址 */
addr_of_myvar1 : .word myvar1;//在链接的时候最后确认myvar1的地址
addr_of_myvar2 : .word myvar2;//在链接的时候最后确认myvar2的地址
复制代码

编译:

as -g -o load.o load.s

gcc -o load load.o

 

Store示例

源码如下:

.data;//数据段

.balign 4  /* 四个字节对齐 */
myvar1: /* 定义变量myvar1 */
    .word 0     /* 值为'0' */
.balign 4 /* 四个字节对齐 */
myvar2: /* 定义变量myvar2 */
    .word 0    /* 值为'0' */
 
.text /* -- 代码段*/
.balign 4 /* 四个字节对齐 */
.global main
main:
    
ldr r1, addr_of_myvar1 /* r1 ← &myvar1 */
mov r3,#3
str r3,[r1]//将r3中值保持到[r1],就是myvar1值=3

ldr r2, addr_of_myvar2 /* r2 ← &myvar2 */
mov r3,#4
ldr r3, [r2]           /* r3 ← *r2 */

ldr r1, addr_of_myvar1 /* r1 ← &myvar1 */
ldr r1,[r1];// r1=myvar1值
ldr r2, addr_of_myvar2 /* r2 ← &myvar2 */
ldr r2, [r2]           /* r2 ← *r2 ,就是r2=0*/

add r0, r1, r2         /* r0 ← r1 + r2 ,就是3+0=3*/
bx lr
 
/* 数据地址 */
addr_of_myvar1 : .word myvar1;//在链接的时候最后确认myvar1的地址
addr_of_myvar2 : .word myvar2;//在链接的时候最后确认myvar2的地址
复制代码

as -g -o store.o store.s

gcc -o store store.o

实现了将,

执行验证;

#./store

#echo $?

结果一致。

 

64位Load示例

.arch armv8-a

.data;//数据段

.balign 4  /* 四个字节对齐 */
myvar1: /* 定义变量myvar1 */
    .word 3     /* 值为'3' */
.balign 4 /* 四个字节对齐 */
myvar2: /* 定义变量myvar2 */
    .word 4    /* 值为'4' */
 
.text /* -- 代码段*/
.balign 4 /* 四个字节对齐 */
.global main
main:
    ldr r1, addr_of_myvar1 /* r1 ← &myvar1 */
    ldr r1, [r1]           /* r1 ← *r1 */
    ldr r2, addr_of_myvar2 /* r2 ← &myvar2 */
    ldr r2, [r2]           /* r2 ← *r2 */
    add r0, r1, r2         /* r0 ← r1 + r2 */
    mov x8, 93
	svc 0
 
/* 数据地址 */
addr_of_myvar1 : .word myvar1;//在链接的时候最后确认myvar1的地址
addr_of_myvar2 : .word myvar2;//在链接的时候最后确认myvar2的地址
复制代码

 

编译:

as -g -o load64.o load64.s

gcc -o load64 load64.o

 

64位store示例

.data;//数据段

.balign 4  /* 四个字节对齐 */
myvar1: /* 定义变量myvar1 */
    .word 0     /* 值为'0' */
.balign 4 /* 四个字节对齐 */
myvar2: /* 定义变量myvar2 */
    .word 0    /* 值为'0' */
 
.text /* -- 代码段*/
.balign 4 /* 四个字节对齐 */
.global main
main:
    
ldr x1, addr_of_myvar1 /* r1 ← &myvar1 */
mov x3,#3
str x3,[x1]//将r3中值保持到[r1],就是myvar1值=3

ldr x2, addr_of_myvar2 /* r2 ← &myvar2 */
mov x3,#4
ldr x3, [x2]           /* r3 ← *r2 */

ldr x1, addr_of_myvar1 /* r1 ← &myvar1 */
ldr x1,[x1];// r1=myvar1值
ldr x2, addr_of_myvar2 /* r2 ← &myvar2 */
ldr x2, [x2]           /* r2 ← *r2 ,就是r2=0*/

add x0, x1, x2         /* r0 ← r1 + r2 ,就是3+0=3*/
mov x8, 93
	svc 0 
/* 数据地址 */
addr_of_myvar1 : .dword myvar1;//在链接的时候最后确认myvar1的地址
addr_of_myvar2 : .dword myvar2;//在链接的时候最后确认myvar2的地址
复制代码

as -g -o store64.o store64.s

gcc -o store64 store64.o


这篇关于第10部分- Linux ARM汇编 寻址方式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!