分类: LINUX
2010-09-22 00:34:53
|
1 static inline int swap_int(int *a, int b) { 2 asm volatile ("xchg %0, %1" : "+r" (b) , "+m" (*a)); 3 return b; 4 }
int
. This code works perfectly fine on both architectures, provided that you're using a compiler that understands the asm
statement, such as gcc. Later, this similar piece of code appears:1 static inline int swap_char(char *a, char b) { 2 asm volatile ("xchg %0, %1" : "+r" (b) , "+m" (*a)); 3 return b; 4 }
Error: bad register name `%dil'
b
argument, the constraint r
is used, indicating that the value should be stored in any
general-purpose register. In the first example, this is just fine. All
of them will do for 32-bit operations. The second example, on closer
examination, actually requires a register whose lower byte is
accessible. On x86, there are only four general-purpose registers where
this is true: EAX, EBX, ECX and EDX. On x86_64, this is also true for
the ESI and EDI registers that are also treated as general-purpose
registers on x86.%edi
register, which satisfies the r
constraint. Later, the xchg
instruction is interpreted as referring to two byte-sized values due to the size of the arguments *a
and b
. Thus, the compiler translates the instruction to its 8-bit form and replaces the register placeholder %0
with the 8-bit form of the %edi
register, which is %dil
. During assembly, this fails because %dil
doesn't actually exist on x86.%dil
, it should warn about the real problem. q
constraint instead of r
.