GCC内联汇编-什么';s与“挥发性”和“挥发性”的区别;记忆;?

GCC内联汇编-什么';s与“挥发性”和“挥发性”的区别;记忆;?,c,gcc,inline-assembly,C,Gcc,Inline Assembly,在GCC内联汇编中,有两种方法可以防止被优化掉:\uuuu volatile\uuuu关键字和将内存“插入clobber寄存器列表 我的问题是\uuuu volatile\uuuu和“memory”有什么区别-看起来它们是一样的。。。然而,今天我遇到了一个奇怪的情况,这表明他们完全不同!(当我使用“memory”时,我的程序在端口I/O函数中有一个bug,但当我使用\uuuu volatile\uuuu时,它会变好) 区别是什么?我对GCC文档的理解是,\uuuuuu volatile\uuuu

在GCC内联汇编中,有两种方法可以防止被优化掉:
\uuuu volatile\uuuu
关键字和将
内存“
插入clobber寄存器列表

我的问题是
\uuuu volatile\uuuu
“memory”
有什么区别-看起来它们是一样的。。。然而,今天我遇到了一个奇怪的情况,这表明他们完全不同!(当我使用
“memory”
时,我的程序在端口I/O函数中有一个bug,但当我使用
\uuuu volatile\uuuu
时,它会变好)


区别是什么?

我对GCC文档的理解是,
\uuuuuu volatile\uuuu
关键字用于具有副作用的程序集:也就是说,它除了从输出生成输入外,还做其他事情。在您的情况下,我认为“端口I/O功能”会产生副作用

“memory”
clobber仅用于读取/写入除输入/输出操作数以外的内存的程序集。虽然这是一种副作用,但并非所有的副作用都与记忆有关

从:

扩展asm语句的典型用途是操纵输入值以生成输出值。但是,asm语句也可能产生副作用。如果是这样,您可能需要使用volatile限定符来禁用某些优化。 及

“memory”clobber告诉编译器,汇编代码对输入和输出操作数中列出的项目以外的项目执行内存读取或写入(例如,访问输入参数之一指向的内存)。
使用
\uuuuu volatile\uuuuu
可以保证总是通过CPU缓存从RAM Bay中检索该值。正如MichaelRawson在回答中所说,这会产生副作用,但从某种意义上说,通过CPU缓存进行的正常优化是“禁用”的,除此之外什么都没有

在您的情况下,从I/O端口读取的值(存储在变量中)可以比CPU缓存失效更新得更快,因此您可以读取“旧”值。使用
\uuuuu volatile\uuuu
始终读取非缓存的值


您还可以看到:(我不知道您的架构是否是ARM,但te概念是相同的)。

?嗯。。那么,是否有任何情况应该是
\uuuu volatile\uuu
,而
不需要“内存”
?你能告诉我其中一个吗?假设我理解手册,好的,从系统时钟加载时间(显然是
rdtsc
指令)就是其中之一。这有用吗?子集不正确。这意味着volatile也会执行内存重击(它不会)。同样重要的是,“内存”不仅仅意味着你读/写内存。这是指您读取/写入内存“而不是输入和输出操作数中列出的内存”。例如,如果您只是更新输出参数(“+m”),则不需要(一定)内存缓冲。但是,如果您只是将一个空指针传递给asm(例如执行一个memset),那么gcc无法计算您可能会更改多少内存。使用记忆重击器让它假设你改变了一切。谢谢你,迈克尔和大卫!“我似乎明白了,”戴维德沃尔费尔德说,“然而,记忆冲击不是一种副作用吗?”。不。虽然链接的帖子很有用,但内存阻塞器与CPU缓存无关。