Aiur

zellux 的博客

gcc 内联汇编中 %c 的用法

这几天看KVM代码的时候看到里面有个内联汇编的语法很陌生(下面的代码截取了部分内联汇编片段): asm ( "mov %c[rax](%3), %%rax \n\t" "mov %c[rbx](%3), %%rbx \n\t" "mov %c[rdx](%3), %%rdx \n\t" "mov %c[rsi](%3), %%rsi \n\t" "mov %c[rdi](%3), %%rdi \n\t" : "=q" (fail) : "r"(vcpu->launched), "d"((unsigned long)HOST_RSP), "c"(vcpu), [rax]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RAX])), [rbx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RBX])), [rcx]"i"(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RCX])) : "cc", "memory" ); stackoverflow上问了下才知道这是gcc的operand substitution语法,%c后面跟上常量名,就能在内联汇编中使用这个常量了。 以这段代码为例,vcpu是struct kvm_vcpu类型,[rax]“i”(offsetof(struct kvm_vcpu, regs[VCPU_REGS_RAX])这句话把vcpu->regs[VCPU_REGS_RAX]相对于vcpu的偏移赋值给了rax这一常量。接下来回到第一行mov %crax, %%eax,%c[rax]等于前面得到的偏移量,加上vcpu并取值后就是vcpu->regs[VCPU_REGS_RAX]中保存的值了,这个指令会把这个值保存在%rax寄存器中,从而完成了vcpu的rax寄存器恢复工作。 阅读全文 →

gcc 中设置特定代码块的优化级别

今天碰到一个gcc优化相关的问题,为了让一个页变成脏页(页表中dirty位被置上),需要执行下面这段代码: uint32_t *page; // ... page[0] = page[0]; 最后一行代码很有可能被gcc优化掉,因为这段代码看起来没有任何实际的作用。那么如何防止gcc对这段代码做优化呢? 设置gcc编译时优化级别为-O0肯定是不合适的,这样对程序性能影响会比较大。stackoverflow上的Dietrich Epp给出了一个强制类型转换的方案: ((unsigned char volatile *)page)[0] = page[0]; 通过volatile关键字禁止gcc的优化,和我之前采用的方法类似。 Plow同学给出了另一个利用gcc 4.4特性的方法: #pragma GCC push_options #pragma GCC optimize ("O0") your code #pragma GCC pop_options 这里用到了gcc 4.4的特性Function Specific Option Pragmas,在特定代码前保存当前的编译选项,然后对特定的代码使用O0优化级别,最后再恢复之前保存的编译选项。 俺觉得这个特性有些场合下挺好用的,在这里分享下,虽然因为编译器版本问题最后我还是用了前面一种方法。 阅读全文 →