x86 asm: move most data transfer instructions from x86-assembly-cheat

This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-06-21 00:00:01 +00:00
parent fb396be2cd
commit f470d474a6
7 changed files with 287 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#x86-cqto-and-cltq-instructions */
#include <lkmc.h>
LKMC_PROLOGUE
/* CLTQ: top bit is zero: extend with zeroes. */
mov $0x123456787FFFFFFF, %rax
cltq
LKMC_ASSERT_EQ(%rax, $0x000000007FFFFFFF)
/* CLTQ: top bit is one: extend with ones. */
mov $0x1234567880000000, %rax
cltq
LKMC_ASSERT_EQ(%rax, $0xFFFFFFFF80000000)
/* CWTL: zeroes top 32-bits. */
mov $0x123456789ABC8EF0, %rax
cwtl
LKMC_ASSERT_EQ(%rax, $0xFFFF8EF0)
CWTL
/* CBTW. */
mov $0x123456789ABCDE80, %rax
cbtw
LKMC_ASSERT_EQ(%rax, $0x123456789ABCFF80)
CWTL
LKMC_EPILOGUE

View File

@@ -0,0 +1,35 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#x86-cmovcc-instructions */
#include <lkmc.h>
LKMC_PROLOGUE
/* Carry flag clear. */
clc
mov $0, %rax
mov $1, %rbx
/* Don't move: carry flag not set. */
cmovc %rbx, %rax
LKMC_ASSERT_EQ(%rax, $0)
/* Carry flag clear. */
clc
mov $0, %rax
mov $1, %rbx
/* Move because checking NC. */
cmovnc %rbx, %rax
LKMC_ASSERT_EQ(%rax, $1)
/* Carry flag set. */
stc
mov $0, %rax
mov $1, %rbx
/* Move. */
cmovc %rbx, %rax
LKMC_ASSERT_EQ(%rax, $1)
#if 0
/* Immediates not supported:
* Error: operand type mismatch for `cmovc' */
cmovc $1, %rax
#endif
LKMC_EPILOGUE

View File

@@ -0,0 +1,54 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#x86-cqto-and-cltq-instructions */
#include <lkmc.h>
LKMC_PROLOGUE
/* Quad to Octo: top bit is zero: extend with zeroes. */
mov $0x7FFFFFFFFFFFFFFF, %rax
mov $0x123456789ABCDEF0, %rdx
cqto
mov %rax, %r12
mov %rdx, %r13
/* rax is unchanged. */
LKMC_ASSERT_EQ(%r12, $0x7FFFFFFFFFFFFFFF)
/* rdx is filled with zeros. */
LKMC_ASSERT_EQ(%r13, $0)
/* Quad to Octo: top bit is one: extend with ones. */
mov $0x8000000000000000, %rax
mov $0x123456789ABCDEF0, %rdx
cqto
mov %rax, %r12
mov %rdx, %r13
LKMC_ASSERT_EQ(%r12, $0x8000000000000000)
LKMC_ASSERT_EQ(%r13, $0xFFFFFFFFFFFFFFFF)
/* Intel equivalent syntax also accepte by GNU GAS. */
mov $0x7FFFFFFFFFFFFFFF, %rax
mov $0x123456789ABCDEF0, %rdx
cqo
mov %rax, %r12
mov %rdx, %r13
LKMC_ASSERT_EQ(%r12, $0x7FFFFFFFFFFFFFFF)
LKMC_ASSERT_EQ(%r13, $0)
/* Smaller size example: Double to Quad.
* Also zeroes top 32-bits of RDX like many 32 to 64 operaions. */
mov $0xFFFFFFFF7FFFFFFF, %rax
mov $0x123456789ABCDEF0, %rdx
cltd
mov %rax, %r12
mov %rdx, %r13
LKMC_ASSERT_EQ(%r12, $0xFFFFFFFF7FFFFFFF)
LKMC_ASSERT_EQ(%r13, $0)
/* Even smaller size example: Word to Doubleword.
* Unlike the 32-bit one, does not zero out the top 32-bits of RDX. */
mov $0xFFFFFFFFFFFF7FFF, %rax
mov $0x123456789ABCDEF0, %rdx
cwtd
mov %rax, %r12
mov %rdx, %r13
LKMC_ASSERT_EQ(%r12, $0xFFFFFFFFFFFF7FFF)
LKMC_ASSERT_EQ(%r13, $0x123456789ABC0000)
LKMC_EPILOGUE

View File

@@ -0,0 +1,24 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#x86-data-transfer-instructions
*
* Load Effective Address.
*
* Like MOV, but load the address instead of the value.
*
* Useful in particular for RIP relative addressing.
*/
#include <lkmc.h>
LKMC_PROLOGUE
/* RIP relative addressing. */
lea my_label(%rip), %rax
LKMC_ASSERT_EQ(%rax, $my_label)
/* Also supports the usual addressing operations. */
mov $my_label, %rax
mov $2, %rbx
lea 4(%rax,%rbx,2), %rdx
LKMC_ASSERT_EQ(%rdx, $my_label_2)
LKMC_EPILOGUE
my_label: .skip 8
my_label_2:

View File

@@ -0,0 +1,18 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#x86-data-transfer-instructions
*
* LIke MOVZX but sign extend.
*/
#include <lkmc.h>
LKMC_PROLOGUE
/* Top bit is 0, extend with zero. */
mov $0x1234567F, %eax
movsx %al, %ax
LKMC_ASSERT_EQ_32(%eax, $0x1234007F)
/* Top bit is 1: extend with one. */
mov $0x12345680, %eax
movsx %al, %ax
LKMC_ASSERT_EQ_32(%eax, $0x1234FF80)
LKMC_EPILOGUE

View File

@@ -0,0 +1,33 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#x86-data-transfer-instructions
*
* mov and zero extend
*
* unsigned typecast to larger types in 2's complement.
*
* MOV does this automatically from 32 to 64 bits:
* https://stackoverflow.com/questions/11177137/why-do-x86-64-instructions-on-32-bit-registers-zero-the-upper-part-of-the-full-6
*/
#include <lkmc.h>
LKMC_PROLOGUE
/* Top bit is 0, extend with zero. */
mov $0x1234567F, %eax
movzx %al, %ax
LKMC_ASSERT_EQ_32(%eax, $0x1234007F)
/* Top bit is 1: does not matter, stil zero extends. */
mov $0x1234568F, %eax
movzx %al, %ax
LKMC_ASSERT_EQ_32(%eax, $0x1234008F)
#if 0
/* must be a register, otherwise x86 cannot know how to size it:
* Error: unsupported syntax for `movzx' */
movzx $0, %eax
/* Operands have the same size. Fist must be larger.
* Error: unsupported syntax for `movzx' */
movzx %al, %al
#endif
LKMC_EPILOGUE