第14部分- Linux ARM汇编数组/结构体/索引

第14部分- Linux ARM汇编数组/结构体/索引

 

我们先来看下,如果在C代码中两个定义如下,一个数组和一个结构体。

int a[100];

struct my_struct

{

  char f0;

  int f1;

} b;

 

在32位ARM汇编中的定义如下:

.data
.balign 4
a: .skip 400
.balign 4
b: .skip 8

结构体my_struct实际是5个字节,但是这里定义了8个自己,因为是4字节对齐的,多出的3个自己就是Padding,填充用。

      我们看个完整的例子。

示例填充数组

ARM32为例。

.data
 
.balign 4
a: .skip 400
.balign 4
b: .skip 8
.text
 
.global main
main:
    ldr r1, addr_of_a       /* r1 ← &a */
    mov r2, #0              /* r2 ← 0 */
loop:
    cmp r2, #100            /* 检查索引是否达到100了*/
    beq end                 /* 到达100则结束*/
    add r3, r1, r2, LSL #2  /* r3 ← r1 + (r2*4) ,获取数组中各项地址*/
    str r2, [r3]            /* *r3 ← r2 ,将索引复制给数组各项*/
    add r2, r2, #1          /* r2 ← r2 + 1 ,索引自加1*/
    b loop                  /* 循环开始处*/
end:
    bx lr
addr_of_a: .word a

as -g -o array.o array.s

gcc -o array array.o

上面这段代码完成了如下C代码片段:

for (i = 0; i < 100; i++)

  a[i] = i;

 

索引模式

上面的模式操作有些过时。

在获取数组地址的时候可以使用ARM提供的索引方法。

[Rsource1, +#immediate]或者
[Rsource1, -#immediate]

寄存器方法:

[Rsource1, +Rsource2] 或者
[Rsource1, -Rsource2]

综合的方法:

[Rsource1, +Rsource2, shift_operation #immediate]或者
[Rsource1, -Rsource2, shift_operation #immediate]

str r2, [r1, #+12]  /* *(r1 + 12) ← r2 */

执行前后r1是没有变化的。

更新索引

以上这些的话不会自动更新索引,因为是要循环100次的,每次操作完需要更新索引。

[Rsource1], #+immediate 或者
[Rsource1], #-immediate

循环片段可以改成如下:

loop:
    cmp r2, #100            /*检查索引是否达到100了*/
beq end                 /*到达100则结束
str r2, [r1], #4        /* *r1 ← r2 then r1 ← r1 + 4 */
    add r2, r2, #1          /* r2 ← r2 + 1 ,自加*/
    b loop                  /* Go to the beginning of the loop */
end:

[Rsource1], +Rsource2或者
[Rsource1], -Rsource2

再或者

[Rsource1], +Rsource2, shift_operation #immediate 或
[Rsource1], -Rsource2, shift_operation #immediate

这些操作是执行后再跟新索引的。

前更新索引

我们看下执行前跟新索引的操作。命令如下,区别是加了一个!号。

[Rsource1, #+immediate]!或
[Rsource1, #-immediate]!

代码小片段如下:

ldr r2, [r1, #+12]!  /* r1 ← r1 + 12 then r2 ← *r1 */
add r2, r2, r2       /* r2 ← r2 + r2 */
str r2, [r1]         /* *r1 ← r2 */

此外还有:

[Rsource1, +Rsource2]! 或
[Rsource1, +Rsource2]!

或者
[Rsource1, +Rsource2, shift_operation #immediate]!或
[Rsource1, -Rsource2, shift_operation #immediate]!

几个命令的差异卡看上去比较小,主要是注意感叹号和中括号。

使用如上这些可以轻松获取的结构体中的某个变量便宜。

例如C语法中的:

b.f1 = b.f1 + 7;

其中b是结构体如下:

struct my_struct

{

  char f0;

  int f1;

} b;

可以通过如下代码片段实现,r1是结构体的基地址:

ldr r2, [r1, #+4]!  /* r1 ← r1 + 4 then r2 ← *r1 ,跳过f0变量*/
add r2, r2, #7     /* r2 ← r2 + 7 */
str r2, [r1]       /* *r1 ← r2 */

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
结构体数组是一种数据结构,它是由多个相同类型的结构体元素组成的数组。每个结构体元素可以包含多个不同类型的成员变量,这些成员变量可以用来表示一个实体的多个属性。 结构体指针是指向结构体的指针变量。通过结构体指针,可以方便地对结构体进行操作和访问。可以使用指针来访问结构体的成员变量,也可以通过指针修改结构体的值。 例如,下面是一个示例代码,展示了如何定义和使用结构体数组结构体指针: ```c #include <stdio.h> // 定义一个结构体 struct Person { char name[20]; int age; }; int main() { // 定义一个结构体数组 struct Person people[3]; // 初始化结构体数组 strcpy(people[0].name, "Alice"); people[0].age = 20; strcpy(people[1].name, "Bob"); people[1].age = 25; strcpy(people[2].name, "Charlie"); people[2].age = 30; // 遍历结构体数组并打印每个人的信息 for (int i = 0; i < 3; i++) { printf("Person %d: Name = %s, Age = %d\n", i+1, people[i].name, people[i].age); } // 定义一个结构体指针 struct Person *personPtr; // 将结构体数组的地址赋给结构体指针 personPtr = people; // 通过结构体指针访问和修改结构体的值 printf("First person's name: %s\n", personPtr->name); printf("First person's age: %d\n", personPtr->age); // 修改结构体的值 strcpy(personPtr->name, "David"); personPtr->age = 35; // 通过结构体数组访问修改后的值 printf("First person's name after modification: %s\n", people[0].name); printf("First person's age after modification: %d\n", people[0].age); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值