ARM 汇编数组
ARM Assembly Arrays
我试图弄清楚数组在 ARM 汇编中的工作原理,但我不知所措。我想将大小为 20 的数组初始化为 0、1、2 等等。
A[0] = 0
A[1] = 1
我什至不知道如何打印我必须查看的内容是否正确。这是我目前所拥有的:
.data
.balign 4 @ Memory location divisible by 4
string: .asciz "a[%d] = %d\n"
a: .skip 80 @ allocates 20
.text
.global main
.extern printf
main:
push {ip, lr} @ return address + dummy register
ldr r1, =a @ set r1 to index point of array
mov r2, #0 @ index r2 = 0
loop:
cmp r2, #20 @ 20 elements?
beq end @ Leave loop if 20 elements
add r3, r1, r2, LSL #2 @ r3 = r1 + (r2*4)
str r2, [r3] @ r3 = r2
add r2, r2, #1 @ r2 = r2 + 1
b loop @ branch to next loop iteration
print:
push {lr} @ store return address
ldr r0, =string @ format
bl printf @ c printf
pop {pc} @ return address
ARM 本身就让我很困惑,我不知道我做错了什么。如果有人能帮助我更好地理解这是如何工作的,我将不胜感激。
如前所述,您的 printf 有问题,您可以使用工具链本身查看调用约定,然后遵守该约定。
#include <stdio.h>
unsigned int a,b;
void notmain ( void )
{
printf("a[%d] = %d\n",a,b);
}
给予
00001008 <notmain>:
1008: e59f2010 ldr r2, [pc, #16] ; 1020 <notmain+0x18>
100c: e59f3010 ldr r3, [pc, #16] ; 1024 <notmain+0x1c>
1010: e5921000 ldr r1, [r2]
1014: e59f000c ldr r0, [pc, #12] ; 1028 <notmain+0x20>
1018: e5932000 ldr r2, [r3]
101c: eafffff8 b 1004 <printf>
1020: 0000903c andeq r9, r0, ip, lsr r0
1024: 00009038 andeq r9, r0, r8, lsr r0
1028: 0000102c andeq r1, r0, ip, lsr #32
Disassembly of section .rodata:
0000102c <.rodata>:
102c: 64255b61 strtvs r5, [r5], #-2913 ; 0xb61
1030: 203d205d eorscs r2, sp, sp, asr r0
1034: 000a6425 andeq r6, sl, r5, lsr #8
Disassembly of section .bss:
00009038 <b>:
9038: 00000000 andeq r0, r0, r0
0000903c <a>:
903c:
调用约定一般是第一个参数在r0,第二个在r1,第三个在r2,直到r3,然后使用堆栈。这有很多例外,但我们可以在这里看到,通常可以正常使用 printf 调用的编译器需要 r0 中格式字符串的地址。 a 的值然后分别在 r1 和 r2 中的 b 的值。
您的 printf 具有 r0 中的字符串,但使用该格式字符串的 printf 调用需要三个参数。
上面的代码使用了尾部优化和分支到 printf 而不是调用它并从中返回。这些天的 arm 约定更喜欢堆栈在 64 位边界上对齐,因此您可以放置一些寄存器,您不必关心保留在 push/pop 上以保持对齐
push {r3,lr}
...
pop {r3,pc}
这样做肯定不会对您造成伤害,不这样做可能会或可能不会造成伤害,具体取决于下游的假设。
假设 r1(标签 a)是字对齐地址,您的设置和循环应该可以正常运行。如果你弄乱了你的字符串,它可能会或可能不会,应该首先放置字符串,或者在 a 之前放置另一个对齐语句,以确保数组对齐。有一些指令集功能可以简化代码,但它看起来功能正常。
这可能对其他想了解如何使用 arm assembly 语言为数组分配内存的人有所帮助
这里有一个简单的例子,添加对应的数组元素并存储在第三个数组中。
.global _start
_start:
MOV R0, #5
LDR R1,=first_array @ loading the address of first_array[0]
LDR R2,=second_array @ loading the address of second_array[0]
LDR R7,=final_array @ loading the address of final_array[0]
MOV R3,#5 @ len of array
MOV R4,#0 @ to store sum
check:
cmp R3,#1 @ like condition in for loop for i>1
BNE loop @ if R3 is not equal to 1 jump to the loop label
B _exit @ else exit
loop:
LDR R5,[R1],#4 @ loading the values and storing in registers and base register gets updated automatically R1 = R1 + 4
LDR R6,[R2],#4 @ similarly
add R4,R5,R6
STR R4,[R7],#4 @ storing the values back to the final array
SUB R3,R3,#1 @ decrment value just like i-- in for loop
B check
_exit:
LDR R7,=final_array @ before exiting checking the values stored
LDR R1, [R7] @ R1 = 60
LDR R2, [R7,#4] @ R2 = 80
LDR R3, [R7,#8] @ R3 = 100
LDR R4, [R7,#12] @ R4 = 120
MOV R7, #1 @ terminate syscall, 1
SWI 0 @ execute syscall
.data
first_array: .word 10,20,30,40
second_array: .word 50,60,70,80
final_array: .word 0,0,0,0,0
我试图弄清楚数组在 ARM 汇编中的工作原理,但我不知所措。我想将大小为 20 的数组初始化为 0、1、2 等等。
A[0] = 0
A[1] = 1
我什至不知道如何打印我必须查看的内容是否正确。这是我目前所拥有的:
.data
.balign 4 @ Memory location divisible by 4
string: .asciz "a[%d] = %d\n"
a: .skip 80 @ allocates 20
.text
.global main
.extern printf
main:
push {ip, lr} @ return address + dummy register
ldr r1, =a @ set r1 to index point of array
mov r2, #0 @ index r2 = 0
loop:
cmp r2, #20 @ 20 elements?
beq end @ Leave loop if 20 elements
add r3, r1, r2, LSL #2 @ r3 = r1 + (r2*4)
str r2, [r3] @ r3 = r2
add r2, r2, #1 @ r2 = r2 + 1
b loop @ branch to next loop iteration
print:
push {lr} @ store return address
ldr r0, =string @ format
bl printf @ c printf
pop {pc} @ return address
ARM 本身就让我很困惑,我不知道我做错了什么。如果有人能帮助我更好地理解这是如何工作的,我将不胜感激。
如前所述,您的 printf 有问题,您可以使用工具链本身查看调用约定,然后遵守该约定。
#include <stdio.h>
unsigned int a,b;
void notmain ( void )
{
printf("a[%d] = %d\n",a,b);
}
给予
00001008 <notmain>:
1008: e59f2010 ldr r2, [pc, #16] ; 1020 <notmain+0x18>
100c: e59f3010 ldr r3, [pc, #16] ; 1024 <notmain+0x1c>
1010: e5921000 ldr r1, [r2]
1014: e59f000c ldr r0, [pc, #12] ; 1028 <notmain+0x20>
1018: e5932000 ldr r2, [r3]
101c: eafffff8 b 1004 <printf>
1020: 0000903c andeq r9, r0, ip, lsr r0
1024: 00009038 andeq r9, r0, r8, lsr r0
1028: 0000102c andeq r1, r0, ip, lsr #32
Disassembly of section .rodata:
0000102c <.rodata>:
102c: 64255b61 strtvs r5, [r5], #-2913 ; 0xb61
1030: 203d205d eorscs r2, sp, sp, asr r0
1034: 000a6425 andeq r6, sl, r5, lsr #8
Disassembly of section .bss:
00009038 <b>:
9038: 00000000 andeq r0, r0, r0
0000903c <a>:
903c:
调用约定一般是第一个参数在r0,第二个在r1,第三个在r2,直到r3,然后使用堆栈。这有很多例外,但我们可以在这里看到,通常可以正常使用 printf 调用的编译器需要 r0 中格式字符串的地址。 a 的值然后分别在 r1 和 r2 中的 b 的值。
您的 printf 具有 r0 中的字符串,但使用该格式字符串的 printf 调用需要三个参数。
上面的代码使用了尾部优化和分支到 printf 而不是调用它并从中返回。这些天的 arm 约定更喜欢堆栈在 64 位边界上对齐,因此您可以放置一些寄存器,您不必关心保留在 push/pop 上以保持对齐
push {r3,lr}
...
pop {r3,pc}
这样做肯定不会对您造成伤害,不这样做可能会或可能不会造成伤害,具体取决于下游的假设。
假设 r1(标签 a)是字对齐地址,您的设置和循环应该可以正常运行。如果你弄乱了你的字符串,它可能会或可能不会,应该首先放置字符串,或者在 a 之前放置另一个对齐语句,以确保数组对齐。有一些指令集功能可以简化代码,但它看起来功能正常。
这可能对其他想了解如何使用 arm assembly 语言为数组分配内存的人有所帮助 这里有一个简单的例子,添加对应的数组元素并存储在第三个数组中。
.global _start
_start:
MOV R0, #5
LDR R1,=first_array @ loading the address of first_array[0]
LDR R2,=second_array @ loading the address of second_array[0]
LDR R7,=final_array @ loading the address of final_array[0]
MOV R3,#5 @ len of array
MOV R4,#0 @ to store sum
check:
cmp R3,#1 @ like condition in for loop for i>1
BNE loop @ if R3 is not equal to 1 jump to the loop label
B _exit @ else exit
loop:
LDR R5,[R1],#4 @ loading the values and storing in registers and base register gets updated automatically R1 = R1 + 4
LDR R6,[R2],#4 @ similarly
add R4,R5,R6
STR R4,[R7],#4 @ storing the values back to the final array
SUB R3,R3,#1 @ decrment value just like i-- in for loop
B check
_exit:
LDR R7,=final_array @ before exiting checking the values stored
LDR R1, [R7] @ R1 = 60
LDR R2, [R7,#4] @ R2 = 80
LDR R3, [R7,#8] @ R3 = 100
LDR R4, [R7,#12] @ R4 = 120
MOV R7, #1 @ terminate syscall, 1
SWI 0 @ execute syscall
.data
first_array: .word 10,20,30,40
second_array: .word 50,60,70,80
final_array: .word 0,0,0,0,0