问题:
#define BUG() \
__asm__ __volatile__( "ud2\n" \
"\t.word %%c0\n" \
"\t.long %%c1\n" \
: : "i" (__LINE__), "i" (__FILE__))
ud2是什么指令?机器码好像是0f 0b ?
BUG()能造成系统停机么?
%%0、%%1是占位符号,那么前面的修饰符'c'是什么含意?(%%c0、%%c1)
除了'c'还有哪些修饰符?在哪里可以查到这些修饰符的信息?
解答:
查了一下手册, UD2是一种让CPU产生invalid opcode exception的软件指令. 内核发现CPU出现这个异常, 会立即停止运行.
'c' 在gcc中, 叫做operand code, c只能用在常量变量(就是constraint是'i')和条件判断指令中. 作用是将这个常量值打印在指令中.
这段代码:
编译后的代码为:
其实除了ud2这条指令, 其他都是assembler directives.
如果没有'c'这个operand code, 产生的指令是:
这段代码对于assembler directives(GAS的输入)来说, 可能是不能正常工作的.
i386的operand code可以在gcc源代码的gcc/config/i386.c中查询到, 我也是很久以前移植过一种CPU ARCH才记得有这么个东西.
L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
C -- print opcode suffix for set/cmov insn.
c -- like C, but print reversed condition
F,f -- likewise, but for floating-point.
O -- if HAVE_AS_IX86_CMOV_SUN_SYNTAX, expand to "w.", "l." or "q.",
otherwise nothing
R -- print the prefix for register names.
z -- print the opcode suffix for the size of the current operand.
* -- print a star (in certain assembler syntax)
A -- print an absolute memory reference.
w -- print the operand as if it's a "word" (HImode) even if it isn't.
s -- print a shift double count, followed by the assemblers argument
delimiter.
b -- print the QImode name of the register for the indicated operand.
%%b0 would print %%al if operands[0] is reg 0.
w -- likewise, print the HImode name of the register.
k -- likewise, print the SImode name of the register.
q -- likewise, print the DImode name of the register.
h -- print the QImode name for a "high" register, either ah, bh, ch or dh.
y -- print "st(0)" instead of "st" as a register.
D -- print condition for SSE cmp instruction.
P -- if PIC, print an @PLT suffix.
X -- don't print any sort of PIC '@' suffix for a symbol.
& -- print some in-use local-dynamic symbol name.
ps. 较新的内核代码都已经将BUG()的实现做了一些修改, 改成了我上面提到的那种, 这可以让出错的指令直接在栈顶, 便于调试.
补充:
https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/Extended-Asm.html
6.43.2.7 x86 Operand Modifiersc Require a constant operand and print the constant expression with no punctuation
void f1()
{
asm("nop");
asm (".word %%0"::"i"(0xff)); => 生成0x00 0x00 => link error: undefined reference to `$255'
asm("nop");
asm (".word %%c0"::"i"(0xff)); => 生成0xff 0x00