gpt4 book ai didi

assembly - 简单ARM汇编代码分析

转载 作者:行者123 更新时间:2023-12-02 22:10:30 24 4
gpt4 key购买 nike

我开始使用 GNU 工具链学习 ARM 汇编语言,并使用以下代码用 C 创建了一个非常简单的函数示例:

#include <stdint.h>

uint32_t *a;
uint32_t *b;
uint32_t *c;

__attribute__((naked)) void f() {

*a += *c;
*b += *c;
}

在终端中使用此命令查看汇编代码后:

arm-none-eabi-gcc -O1 -S -std=c99 example.c -o -

这就是结果:

    @ Function supports interworking.
@ Naked Function: prologue and epilogue provided by programmer.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
ldr r3, .L2
ldr r2, .L2+4
ldr r3, [r3]
ldr r2, [r2] ; r2 <- &(*c)
ldr ip, [r3]
ldr r0, [r2] ; r0 <- *c
ldr r1, .L2+8
add r0, ip, r0
str r0, [r3]
ldr r3, [r1]
ldr r2, [r2] ; why make the same thing
ldr r1, [r3]
add r2, r1, r2
str r2, [r3]
.L3:
.align 2
.L2:
.word a
.word c
.word b
.size f, .-f
.comm c,4,4
.comm b,4,4
.comm a,4,4

我的问题是为什么编译器加载两倍于指针c的地址,如果我很好理解的话,那就是这一行

ldr  r2, [r2] 

我找不到编译器复制此代码的充分理由。提前致谢。

最佳答案

如果您的指针别名,则需要两次取消引用。考虑一下如果您有 a == c,您的算法会做什么。如果它们不能别名,您需要添加一些 restrict 关键字。下面是一个按照您期望的方式进行优化的示例:

#include <stdint.h>

void f(uint32_t * restrict a, uint32_t * restrict b, uint32_t * restrict c)
{
*a += *c;
*b += *c;
}

和汇编输出(我的评论):

00000000 <f>:
0: e5922000 ldr r2, [r2] // r2 = *c
4: e5903000 ldr r3, [r0] // r3 = *a
8: e0833002 add r3, r3, r2 // r3 = r3 + r2 = *a + *c
c: e5803000 str r3, [r0] // *a = r3 = *a + *c
10: e5910000 ldr r0, [r1] // r0 = *b
14: e0800002 add r0, r0, r2 // r0 = r0 + r2 = *b + *c
18: e5810000 str r0, [r1] // *b = r0 = *b + *c
1c: e12fff1e bx lr

编辑:这里是一个更像您原始示例的示例,第一个没有 restrict 关键字,第二个带有,这次采用 GCC 的输出格式。

示例一(不带 restrict 关键字)代码:

#include <stdint.h>

__attribute__((naked))
void f(uint32_t *a, uint32_t *b, uint32_t *c)
{
*a += *c;
*b += *c;
}

输出:

f:
ldr ip, [r0, #0]
ldr r3, [r2, #0]
add r3, ip, r3
str r3, [r0, #0]
ldr r0, [r1, #0]
ldr r3, [r2, #0]
add r3, r0, r3
str r3, [r1, #0]

示例二(带有restrict关键字)代码:

#include <stdint.h>

__attribute__((naked))
void f(uint32_t * restrict a, uint32_t * restrict b, uint32_t * restrict c)
{
*a += *c;
*b += *c;
}

输出:

f:
ldr r3, [r2, #0]
ldr ip, [r1, #0]
ldr r2, [r0, #0]
add r2, r2, r3
add r3, ip, r3
str r2, [r0, #0]
str r3, [r1, #0]

c 的第二次解引用不在第二个程序中,因此将其缩短了一条指令。

关于assembly - 简单ARM汇编代码分析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27789170/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com