- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
__asm__ __volatile__ ()
的基本作用是什么?对于 ARM 架构,“内存”
的意义是什么?
最佳答案
asm volatile("" ::: "memory");
创建一个编译器级别的内存屏障,强制优化器不对跨越屏障的内存访问进行重新排序。
例如,如果您需要以特定顺序访问某个地址(可能是因为该内存区域实际上由不同的设备而不是内存支持),您需要能够将此告诉编译器,否则它可能只会优化您的步骤是为了提高效率。
假设在这种情况下,您必须递增地址中的一个值,读取一些内容并递增相邻地址中的另一个值。
int c(int *d, int *e) {
int r;
d[0] += 1;
r = e[0];
d[1] += 1;
return r;
}
问题是编译器(gcc
在这种情况下)可以重新安排您的内存访问以获得更好的性能,如果您要求它(-O
)。可能导致如下指令序列:
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
同时加载 d[0]
和 d[1]
的上述值。假设这是您想避免的事情,那么您需要告诉编译器不要重新排序内存访问,那就是使用 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;
}
所以你会得到你想要的指令序列:
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
应该注意的是,这只是编译时内存屏障,以避免编译器重新排序内存访问,因为它没有放置额外的硬件级指令来刷新内存或等待加载或存储完成。如果 CPU 具有架构能力并且内存地址是正常
类型而不是强排序
或设备
(ref ).
关于c - __asm__ __volatile__ 的工作 ("": : : "memory"),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14950614/
我想把C的outb函数移植到D上。 static __inline void outb (unsigned char value, unsigned short int port) { __a
我有一个分配内存的代码,将一些缓冲区复制到分配的内存,然后跳转到该内存地址。 问题是我无法跳转到内存地址。我正在使用 gcc 和 __asm__ 但我无法调用该内存地址。 我想做这样的事情: addr
我在预处理的 C 代码中看到了以下代码。 asm 在函数声明后做什么? extern int scanf (const char *__restrict __format, ...) __asm__
在尝试编译我的项目时,它使用了一些第三方头文件,使用 mingw 4.4,我遇到了以下错误: Assembler messages: Error: junk at end of line, first
几天以来我一直在尝试编写一个非常简单的内联汇编代码,但没有任何效果。我有 NetBeans 作为 IDE 和 MinGW 作为编译器。我最新的代码是: uint16 readle_uint16(con
我想在 c 中使用 char 变量并将其添加到汇编代码中。 char c = 'X'; __asm__ __volatile__("movb '"c"', %ah\n"); 但是当我使用它时,它说需要
我的项目使用C++,包含一个c头文件ira.h如下: #ifdef __cplusplus extern "C" { #endif extern inline void disable_ir
这个问题在这里已经有了答案: CPUID implementations in C++ (3 个答案) 关闭去年。 我正在尝试使用以下 cod 读取 cpuid 信息,但它不起作用。我正在使用 Vi
__asm__ __volatile__ () 的基本作用是什么?对于 ARM 架构,“内存” 的意义是什么? 最佳答案 asm volatile("" ::: "memory"); 创建一个编译器级
我有一段代码调用了 BIOS 文本输出函数,INT 0x10, AH=0x13: static void __stdcall print_raw(uint8_t row, uint8_t col, u
这是一本旧书上的一个小函数: unsigned long f() { __asm__("movl %eax,%esp"); } 函数解释为获取堆栈点,但似乎不是。它实际上获取了一个比我的帧地址低
这个问题在这里已经有了答案: Calling printf in extended inline ASM (1 个回答) 关闭 3 年前。 我正在尝试使用 c __asm__ 打印 AAAA,如下所
我使用的是 VS2012 C++ Windows 7,我需要获取有关 CPU 多线程的信息以计算可用逻辑处理器的数量。 我正在使用此代码(来自 This SO Post) typedef __int3
据我所知,__asm { ... }; 之间的唯一区别和 __asm__("...");是第一次使用mov eax, var第二个使用 movl %0, %%eax与 :"=r" (var)在末尾。还
我研究了一些来自 的C代码 http://www.mcs.anl.gov/~kazutomo/rdtsc.html 他们使用诸如 __inline__、__asm__ 等东西,如下所示: 代码1: s
我试图理解这段代码中发生了什么,特别是在 __asm__ 中。我如何单步执行汇编代码,以便打印每个变量以及不打印什么? 具体来说,我试图逐步解决这个问题,以弄清楚 8() 是什么意思,并了解它如何知道
我在 Linux 环境中处理 Nasm 和 GNU C 内联 asm 有一段时间了,这个功能工作得很好......但现在我正在切换到 Windows 环境,我想使用 Masm(与 VS2008)我不能
这段代码我是在x86_64上写的,编译运行良好, __asm__("nop" : "=eax"(foo) : //"eax"(foo),"ebx
这个问题已经有答案了: What does double underscore ( __const) mean in C? (4 个回答) 已关闭 7 年前。 在c中使用(__)“双下划线”的含义是什
一个代码库有一个 COMPILER_BARRIER宏定义为 __asm__ volatile("" ::: "memory") .宏的目的是防止编译器跨屏障重新排序读写。请注意,这显然是编译器屏障,不
我是一名优秀的程序员,十分优秀!