__asm__ __volatile__工作(QUOT;":::"内存") [英] Working of __asm__ __volatile__ ("" : : : "memory")
问题描述
什么基本上 __ asm__ __volatile__()
做的,什么是对ARM架构的记忆
的意义?
ASM挥发性(:::内存);
创建一个编译器级别的内存屏障强制优化器不会重新排序内存访问跨越障碍。
例如,如果您需要在一个特定的顺序(可能是因为内存区域实际上是由不同的设备,而不是内存支持)访问某些地址,你需要能够告诉这个编译器,否则它可能只是优化您步骤的效率着想。
在这种情况下假设你必须在地址递增的值,读出的东西,并在相邻的地址递增的另一个值。
INT C(INT * D,INT * E){
INT R;
D [0] + = 1;
R = E [0];
D [1] + = 1;
返回ř;
}
问题是编译器( GCC
在这种情况下)可以重新安排你的内存访问,如果你问它( -O 获得更好的性能code>)。可能导致的指令像下面的顺序:
00000000 c为C计算值:
0:4603 MOV R3,R0
2:C805 LDMIA R0,{R0,R2}
4:3001增加了R0,#1
6:3201 R2补充说,#1
8:6018 STR R0,[R3,#0]
答:6808 LDR R0,[R1,#0]
C:605A STR R2,[R 3,#4]
E:4770 BX LR
以上为值D [0]
和 D [1]
在同一时间加载。让我们假设这是你想避免,那么你需要告诉编译器不要重新排序内存访问的东西,那就是使用 ASM挥发性(:::内存)
INT C(INT * D,INT * E){
INT R;
D [0] + = 1;
R = E [0];
ASM挥发性(:::内存);
D [1] + = 1;
返回ř;
}
所以你希望它是你会得到你的指令序列:
00000000 c为C计算值:
0:6802 LDR R2,[R0,#0]
2:4603 MOV R3,R0
4:3201增加了R 2,#1
6:6002 STR R2,[R0,#0]
8:6808 LDR R0,[R1,#0]
答:685A LDR R2,[R 3,#4]
C:3201 R2补充说,#1
E:605A STR R2,[R 3,#4]
10:4770 BX LR
12:bf00 NOP
应当指出,这只是编译时间存储器屏障,以避免编译器重新排列存储器访问,因为它使任何额外的硬件级指令刷新存储器或等待负荷或商店完成。处理器仍然能够记录存储器访问,如果他们有建筑能力和内存地址在正常
类型,而不是坚决责令
或设备
(<一个href=\"http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0211k/Babcddgd.html\">ref).
What basically __asm__ __volatile__ ()
does and what is significance of "memory"
for ARM architecture?
asm volatile("" ::: "memory");
creates a compiler level memory barrier forcing optimizer to not re-order memory accesses across the barrier.
For example, if you need to access some address in a specific order (probably because that memory area is actually backed by a different device rather than a memory) you need to be able tell this to the compiler otherwise it may just optimize your steps for the sake of efficiency.
Assume in this scenario you must increment a value in address, read something and increment another value in an adjacent address.
int c(int *d, int *e) {
int r;
d[0] += 1;
r = e[0];
d[1] += 1;
return r;
}
Problem is compiler (gcc
in this case) can rearrange your memory access to get better performance if you ask for it (-O
). Probably leading to a sequence of instructions like below:
00000000 <c>:
0: 4603 mov r3, r0
2: c805 ldmia r0, {r0, r2}
4: 3001 adds r0, #1
6: 3201 adds r2, #1
8: 6018 str r0, [r3, #0]
a: 6808 ldr r0, [r1, #0]
c: 605a str r2, [r3, #4]
e: 4770 bx lr
Above values for d[0]
and d[1]
are loaded at the same time. Lets assume this is something you want to avoid then you need to tell compiler not to reorder memory accesses and that is to use asm volatile("" ::: "memory")
.
int c(int *d, int *e) {
int r;
d[0] += 1;
r = e[0];
asm volatile("" ::: "memory");
d[1] += 1;
return r;
}
So you'll get your instruction sequence as you want it to be:
00000000 <c>:
0: 6802 ldr r2, [r0, #0]
2: 4603 mov r3, r0
4: 3201 adds r2, #1
6: 6002 str r2, [r0, #0]
8: 6808 ldr r0, [r1, #0]
a: 685a ldr r2, [r3, #4]
c: 3201 adds r2, #1
e: 605a str r2, [r3, #4]
10: 4770 bx lr
12: bf00 nop
It should be noted that this is only compile time memory barrier to avoid compiler to reorder memory accesses, as it puts no extra hardware level instructions to flush memories or wait for load or stores to be completed. CPUs can still reorder memory accesses if they have the architectural capabilities and memory addresses are on normal
type instead of strongly ordered
or device
(ref).
这篇关于__asm__ __volatile__工作(QUOT;&QUOT;:::&QUOT;内存&QUOT;)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!