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寄存器恢复工作。 阅读全文 →

汇编文件中导出函数符号

Linux 2.4.18的linux/linkage.h文件定义了若干相关的宏 #define SYMBOL_NAME(X) X #ifdef __STDC__ #define SYMBOL_NAME_LABEL(X) X##: #else #define SYMBOL_NAME_LABEL(X) X/**/: #endif #define __ALIGN .align 16,0x90 #define __ALIGN_STR ".align 16,0x90" #define ALIGN __ALIGN #define ALIGN_STR __ALIGN_STR #define ENTRY(name) .globl SYMBOL_NAME(name); ALIGN; SYMBOL_NAME_LABEL(name) 用ENTRY(name)就能定义函数了。后来发现Flux OSKit中本来就提供了类似功能的宏,定义在inc/asm.h中。 使用的时候需要再写一个c语言的wrapper function(至少2.4.18里面是这么做的) asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); 阅读全文 →