/* https://cirosantilli.com/linux-kernel-module-cheat#x86-binary-arithmetic-instructions * * Unsigned multiply. * * The result is spread across edx:eax. */ #include LKMC_PROLOGUE /* 64-bit hello world: * * rdx : rax = rax * rbx * 0x0 : 4 = 2 * 2 */ mov $2, %rax mov $2, %rbx mul %rbx /* Move to callee saved registers to persist after our asserts. */ mov %rax, %r12 mov %rdx, %r13 mov %rbx, %r14 LKMC_ASSERT_EQ(%r12, $4) LKMC_ASSERT_EQ(%r13, $0) /* rbx is untouched. */ LKMC_ASSERT_EQ(%r14, $2) /* 64-bit with a carry: * * rdx : rax = rax * rbx * 0x1 : 0x0000000000000002 = 0x8000000000000001 * 2 */ mov $0x8000000000000001, %rax mov $2, %rbx mul %rbx mov %rax, %r12 mov %rdx, %r13 LKMC_ASSERT_EQ(%r12, $2) LKMC_ASSERT_EQ(%r13, $1) /* 8-bit is special: does not use dx for output: * * ah : al = al * bl * 0x10 : 0 = 2 * 0x80 */ mov $0, %eax mov $2, %al mov $0x80, %bl mov $0, %dl mul %bl LKMC_ASSERT_EQ_32(%eax, $0x100) /* 16-bit * * dx : ax = ax * bx * 0x1 : 0x0000 = 2 * 0x8000 */ mov $0, %eax mov $0, %edx mov $2, %ax mov $0x8000, %bx mov $0, %dx mul %bx mov %eax, %r12d mov %edx, %r13d LKMC_ASSERT_EQ_32(%r12d, $0) LKMC_ASSERT_EQ_32(%r13d, $1) /* 32-bit */ mov $2, %eax mov $0x80000000, %ebx mov $0, %edx mul %ebx mov %eax, %r12d mov %edx, %r13d LKMC_ASSERT_EQ_32(%r12d, $0) LKMC_ASSERT_EQ_32(%r13d, $1) #if 0 /* No immediate form, although imul has one: * http://stackoverflow.com/questions/20499141/is-it-possible-to-multiply-by-and-immediate-with-mul-in-x86-assembly/33202309#33202309 * * Error: operand type mismatch for `mul' */ mul $2 #endif /* Memory version */ .data mylong: .long 0x11111111 .text movl $2, %eax mull mylong LKMC_ASSERT_EQ_32(%eax, $0x22222222) LKMC_EPILOGUE