__asm​​__ __volatile__工作(QUOT;":::"内存") [英] Working of __asm__ __volatile__ ("" : : : "memory")

查看:337
本文介绍了__asm​​__ __volatile__工作(QUOT;":::"内存")的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么基本上 __ asm__ __volatile__()做的,什么是对ARM架构的记忆的意义?


解决方案

  ASM挥发性(:::内存);

创建一个编译器级别的内存屏障强制优化器不会重新排序内存访问跨越障碍。

例如,如果您需要在一个特定的顺序(可能是因为内存区域实际上是由不同的设备,而不是内存支持)访问某些地址,你需要能够告诉这个编译器,否则它可能只是优化您步骤的效率着想。

在这种情况下

假设你必须在地址递增的值,读出的东西,并在相邻的地址递增的另一个值。

  INT C(INT * D,INT * E){
        INT R;
        D [0] + = 1;
        R = E [0];
        D [1] + = 1;
        返回ř;
}

问题是编译器( GCC 在这种情况下)可以重新安排你的内存访问,如果你问它( -O )。可能导致的指令像下面的顺序:

  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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆