// do stuff with the input Foo structure and write the result to the
// output Bar structure.
static inline void MemFrob(const struct Foo* input, struct Bar* output) {
register const Foo* r0 asm("r0") = input;
register Bar* r1 asm("r1") = output;
__asm__ __volatile__(
"svc #0x0f0000 \n\t"
: "+r" (r0), "+r" (r1)
:
: "r2", "r3", "cc", "memory"
);
}
对于这种特定的情况,目标平台是一个ARM7系统,代码正在用GCC5.3.0进行编译。正在执行的系统调用具有与C函数调用相同的调用约定。经过一些尝试和错误,我得到了上面的“工作”,但我还不相信它是正确的,并且会一直工作,服从于优化编译器的奇思妙想。
我希望能够删除“内存”clobber,并确切地告诉GCC哪些内存将被修改,但是GCC扩展的Asm文档讨论了如何为特定寄存器赋值,然后是内存约束,但如果它们可以合并,则不讨论。到目前为止,从上面的示例中删除“memory”clobber可能会导致GCC在继续的代码中不使用输出。
我还希望能够在不使用输出的情况下删除volatile。但是到目前为止,从上面的示例中删除volatile会导致GCC根本不发出程序集。
长话短说:这就是“m”
约束的用途。通常,如果您正在使用volatile
或__volatel__
,并使用asm
,这是因为您的代码中存在错误。编译器的主要工作之一是流分析,所以只要你给它足够的信息来做正确的流分析,一切都会正常工作。
这里有一个固定版本:
void MemFrob(const struct Foo* input, struct Bar* output) {
register const Foo* r0 asm("r0") = input;
register Bar* r1 asm("r1") = output;
__asm__ (
"svc #0x0f0000"
: "=m"(*r1) // writes data to *output (but does not read)
: "m"(*r0), // reads data in *input
"l"(r0), "l"(r1) // This is necessary to ensure correct register
: "r2", "r3", "cc"
);
}
您可以在https://gcc.godbolt.org/(推荐-o2
编译器选项)上测试它。输出如下:
svc #0x0f0000
bx lr
我对下面的代码段有一个问题。结果可能有一个结果[0,1,0](这是用JCStress执行的测试)。那么这是怎么发生的呢?我认为数据写入(data=1)应该在Actor2(guard2=1)中写入到guard2之前执行。我说得对吗?我问,因为很多时候我读到挥发物周围的说明没有重新排序。此外,根据这一点:http://tutorials.jenkov.com/java-concurrency/vola
这里是一个虚拟的*z++=*x++**y++指令。请注意,x、y和z指针寄存器必须指定为输入/输出,因为asm会修改它们。 在第一个示例中,在输入操作数中列出和有什么意义?同一份文件指出: 特别是,如果不将输入操作数指定为输出操作数,就无法指定输入操作数被修改。
有没有人要对我说或评论? 跟随生成的程序集 多亏了弄臣的解决之道:
我试图通过Composer在客户端的Magento 2上安装一个扩展,但我遇到了旧的PHP内存溢出错误。 我的客户端由Bluehost托管,不幸的是,这意味着我不能直接进入并更改php.ini中的内存限制,因为它是只读的,而且它们的cPanel MultiHP ini编辑器不会影响SSH。我的客户机已经与Bluehost联系过,他们被告知Bluehost不允许更改SSH内存限制,但是,我的客户机最
换句话说,你是可以平等地将它们视为存储空间,还是应该坚持将它们用于特定目的?
a)为什么除了“00”之外还有其他输出? b)如何修改代码以便始终打印“00”。 对于a)我的回答是:在没有任何volatile/同步构造的情况下,编译器可以重新排序一些指令。特别是“this.initialint=val;”和“this.flag=true;”可以切换,这样就可以发生这种情况:线程都启动了,t1充电在前面。给定重新排序的指令,它首先设置flag=true。在它到达“this.in