我开始使用GNU工具链研究ARM汇编语言,并使用以下代码在C中创建一个非常简单的函数示例:
#include <stdint.h>
uint32_t *a;
uint32_t *b;
uint32_t *c;
__attribute__((naked)) void f() {
*a += *c;
*b += *c;
}
Run Code Online (Sandbox Code Playgroud)
在终端中使用此命令后查看汇编代码:
arm-none-eabi-gcc -O1 -S -std=c99 example.c -o -
Run Code Online (Sandbox Code Playgroud)
这就是结果:
@ 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
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么编译器加载指针c的地址的两倍,如果我很清楚,那就是行
ldr r2, [r2]
Run Code Online (Sandbox Code Playgroud)
我找不到编译器复制此代码的充分理由.提前致谢.
如果您的指针别名,则需要两个解引用.想一想你的算法做了什么a == c
.如果他们不能使用别名,则需要添加一些restrict
关键字.这是一个优化您期望的方式的示例:
#include <stdint.h>
void f(uint32_t * restrict a, uint32_t * restrict b, uint32_t * restrict c)
{
*a += *c;
*b += *c;
}
Run Code Online (Sandbox Code Playgroud)
和汇编输出(评论我的):
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
Run Code Online (Sandbox Code Playgroud)
编辑:这是一个更像原始示例的示例,第一个没有restrict
关键字,第二个是GCC的输出格式.
示例一(没有restrict
关键字)代码:
#include <stdint.h>
__attribute__((naked))
void f(uint32_t *a, uint32_t *b, uint32_t *c)
{
*a += *c;
*b += *c;
}
Run Code Online (Sandbox Code Playgroud)
输出:
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]
Run Code Online (Sandbox Code Playgroud)
示例二(带restrict
关键字)代码:
#include <stdint.h>
__attribute__((naked))
void f(uint32_t * restrict a, uint32_t * restrict b, uint32_t * restrict c)
{
*a += *c;
*b += *c;
}
Run Code Online (Sandbox Code Playgroud)
输出:
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]
Run Code Online (Sandbox Code Playgroud)
第二个解除引用c
不在第二个程序中,用一条指令缩短它.
归档时间: |
|
查看次数: |
1678 次 |
最近记录: |