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

第10部分- Linux ARM汇编 寻址方式都遵循gas汇编器的语法。寄存器寻址中,操作数在寄存器中,指令执行时直接从寄存器中取值进行操作。寄存器移位寻址是ARM指令集特有的寻址方式,和寄存器寻址类似,只是操作前需要对寄存器操作数进行移位操作。LSL:逻辑左移,移位后寄存器空出的低位补0。LSR:逻辑右移,移位后寄存器空出…

第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汇编 寻址方式分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/17122.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注