summaryrefslogtreecommitdiff
path: root/CSAPP/tmul_asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'CSAPP/tmul_asm.c')
-rw-r--r--CSAPP/tmul_asm.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/CSAPP/tmul_asm.c b/CSAPP/tmul_asm.c
new file mode 100644
index 0000000..e496618
--- /dev/null
+++ b/CSAPP/tmul_asm.c
@@ -0,0 +1,51 @@
+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;
+}