int tmul_bug(long x, long y, long *dest) { long result = 0; *dest = x*y; asm("setae %al"); return result; } int tmul_ok(long x, long y, long *dest) { int result = 0; *dest = x*y; asm("setae %%bl # Set low-order byte\n\t" "movzbl %%bl, %[val] # Zero extend to be res" : [val] "=r" (result) /* Output */ : /* No inputs */ : "%bl" /* Overwrites */ ); return result; } int tmul_ok2(long x, long y, long *dest) { unsigned char result = 0; *dest = x*y; asm("setae %[b] # Set result" : [b] "=r" (result) /* Output */ ); return (int)result; } int umult_ok(unsigned long x, unsigned long y, unsigned long *dest) { /* * GCC's asm choose the register to store asm operands * according to the type/size of the variable */ unsigned char result; asm("movq %[x],%%rax #Get x\n\t" "mulq %[y] # Unsigned long mult x*y\n\t" "movq %%rax,%[p] #Store low-order 8bytes at dest\n\t" "setae %[b] #Set result" : [p] "=m" (*dest), [b] "=r" (result) /* Outputs */ : [x] "r" (x), [y] "r" (y) /* Inputs */ : "%rax", "%rdx" /* Overwrites */ ); return (int) result; }