I’m trying to do some Code Optimization to Eliminate Branches, the original c code is
if( a < b )
k = (k<<1) + 1;
else
k = (k<<1)
I intend to replace it with assembly code like below
mov a, %rax
mov b, %rbx
mov k, %rcx
xor %rdx %rdx
shl 1, %rcx
cmp %rax, %rax
setb %rdx
add %rdx,%rcx
mov %rcx, k
so I write c inline assembly code like blow,
#define next(a, b, k)\
__asm__("shl $0x1, %0; \
xor %%rbx, %%rbx; \
cmp %1, %2; \
setb %%rbx; \
addl %%rbx,%0;":"+c"(k) :"g"(a),"g"(b))
when I compile the code below i got error:
operand type mismatch for `add'
operand type mismatch for `setb'
How can I fix it?
Here are the mistakes in your code:
setb %blworks whilesetb %rbxdoesn’t.T = (A < B)should translate tocmp B,A; setb Tin AT&T x86 assembler syntax. You had the two operands to CMP in the wrong order. Remember that CMP works like SUB.Once you realize the first two error messages are produced by the assembler, it follows that the trick to debugging them is to look at the assembler code generated by gcc. Try
gcc $CFLAGS -S t.cand compare the problematic lines int.swith an x86 opcode reference. Focus on the allowed operand codes for each instruction and you’ll quickly see the problems.In the fixed source code posted below, I assume your operands are unsigned since you’re using SETB instead of SETL. I switched from using RBX to RCX to hold the temporary value because RCX is a call clobbered register in the ABI and used the
"=&c"constraint to mark it as an earlyclobber operand since RCX is cleared before the inputsaandbare read:main() translates to:
You can see the result of
next()being moved into RSI before eachprintf()call.