|
最近在学linux的内核原理,看linux内核源码时发现好多只折行一次的一个序列语句,linux里都把这段语句包含在一个do {} while(0)的结构中。比如说执行进程切换的switch_to宏,它执行了一段内嵌的汇编代码。源码如下:
#define switch_to(prev,next,last) do { \
asm volatile("pushl %%esi\n\t" \
"pushl %%edi\n\t" \
"pushl %%ebp\n\t" \
"movl %%esp,%0\n\t" /* save ESP */ \
"movl %3,%%esp\n\t" /* restore ESP */ \
"movl $1f,%1\n\t" /* save EIP */ \
"pushl %4\n\t" /* restore EIP */ \
"jmp __switch_to\n" \
"1:\t" \
"popl %%ebp\n\t" \
"popl %%edi\n\t" \
"popl %%esi\n\t" \
:"=m" (prev->tss.esp),"=m" (prev->tss.eip), \
"=b" (last) \
:"m" (next->tss.esp),"m" (next->tss.eip), \
"a" (prev), "d" (next), \
"b" (prev)); \
} while (0)
嵌在asm volatile()中的那段汇编代码只要执行一次,可是为什么又要把它加到do{} while(0)结构里呢?为什么不直接写成以下的形式呢?
#define switch_to(prev,next,last) asm volatile("pushl %%esi\n\t" \
"pushl %%edi\n\t" \
"pushl %%ebp\n\t" \
"movl %%esp,%0\n\t" /* save ESP */ \
"movl %3,%%esp\n\t" /* restore ESP */ \
"movl $1f,%1\n\t" /* save EIP */ \
"pushl %4\n\t" /* restore EIP */ \
"jmp __switch_to\n" \
"1:\t" \
"popl %%ebp\n\t" \
"popl %%edi\n\t" \
"popl %%esi\n\t" \
:"=m" (prev->tss.esp),"=m" (prev->tss.eip), \
"=b" (last) \
:"m" (next->tss.esp),"m" (next->tss.eip), \
"a" (prev), "d" (next), \
"b" (prev));
linux源代码中有很多类似的写法,请教高人原因。 |
|