mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
x86 asm: move string instructions from x86-assembly-cheat
This commit is contained in:
131
README.adoc
131
README.adoc
@@ -12311,6 +12311,17 @@ When reading disassembly, many instructions have either a `.n` or `.w` suffix.
|
||||
|
||||
Bibliography: https://stackoverflow.com/questions/27147043/n-suffix-to-branch-instruction
|
||||
|
||||
=== NOP instructions
|
||||
|
||||
* x86: link:userland/arch/x86_64/nop.S[NOP]
|
||||
* ARM: <<arm-nop-instruction>>
|
||||
|
||||
No OPeration.
|
||||
|
||||
Does nothing except take up one processor cycle and occupy some instruction memory.
|
||||
|
||||
Applications: http://stackoverflow.com/questions/234906/whats-the-purpose-of-the-nop-opcode
|
||||
|
||||
== x86 userland assembly
|
||||
|
||||
Arch agnostic infrastructure getting started at: <<userland-assembly>>.
|
||||
@@ -12354,29 +12365,29 @@ Bibliography:
|
||||
|
||||
<<intel-manual-1>> 5.1.2 "Binary Arithmetic Instructions":
|
||||
|
||||
* link:userland/arch/x86_64/add.S[ADD]
|
||||
** link:userland/arch/x86_64/inc.S[INC]
|
||||
** link:userland/arch/x86_64/adc.S[ADC]
|
||||
* link:userland/arch/x86_64/sub.S[SUB]
|
||||
** link:userland/arch/x86_64/dec.S[DEC]
|
||||
** link:userland/arch/x86_64/sbb.S[SBB]
|
||||
* link:userland/arch/x86_64/mul.S[MUL]
|
||||
** link:userland/arch/x86_64/neg.S[NEG]
|
||||
** link:userland/arch/x86_64/imul.S[IMUL]
|
||||
* link:userland/arch/x86_64/div.S[DIV]
|
||||
** link:userland/arch/x86_64/div_overflow.S[DIV overflow]
|
||||
** link:userland/arch/x86_64/div_zero.S[DIV zero]
|
||||
** link:userland/arch/x86_64/idiv.S[IDIV]
|
||||
* link:userland/arch/x86_64/cmp.S[CMP]
|
||||
* link:userland/arch/x86_64/add.S[]: ADD
|
||||
** link:userland/arch/x86_64/inc.S[]: INC
|
||||
** link:userland/arch/x86_64/adc.S[]: ADC
|
||||
* link:userland/arch/x86_64/sub.S[]: SUB
|
||||
** link:userland/arch/x86_64/dec.S[]: DEC
|
||||
** link:userland/arch/x86_64/sbb.S[]: SBB
|
||||
* link:userland/arch/x86_64/mul.S[]: MUL
|
||||
** link:userland/arch/x86_64/neg.S[]: NEG
|
||||
** link:userland/arch/x86_64/imul.S[]: IMUL
|
||||
* link:userland/arch/x86_64/div.S[]: DIV
|
||||
** link:userland/arch/x86_64/div_overflow.S[]: DIV overflow
|
||||
** link:userland/arch/x86_64/div_zero.S[]: DIV zero
|
||||
** link:userland/arch/x86_64/idiv.S[]: IDIV
|
||||
* link:userland/arch/x86_64/cmp.S[]: CMP
|
||||
|
||||
=== x86 logical instructions
|
||||
|
||||
<<intel-manual-1>> 5.1.4 "Logical Instructions"
|
||||
|
||||
* link:userland/arch/x86_64/and.S[AND]
|
||||
* link:userland/arch/x86_64/not.S[NOT]
|
||||
* link:userland/arch/x86_64/or.S[OR]
|
||||
* link:userland/arch/x86_64/xor.S[XOR]
|
||||
* link:userland/arch/x86_64/and.S[]: AND
|
||||
* link:userland/arch/x86_64/not.S[]: NOT
|
||||
* link:userland/arch/x86_64/or.S[]: OR
|
||||
* link:userland/arch/x86_64/xor.S[]: XOR
|
||||
|
||||
=== x86 shift and rotate instructions
|
||||
|
||||
@@ -12400,10 +12411,10 @@ Keeps the same sign on right shift.
|
||||
Not directly exposed in C, for which signed shift is undetermined behavior, but does exist in Java via the `>>>` operator. C compilers can omit it however.
|
||||
+
|
||||
SHL and SAL are exactly the same and have the same encoding: https://stackoverflow.com/questions/8373415/difference-between-shl-and-sal-in-80x86/56621271#56621271
|
||||
* link:userland/arch/x86_64/rol.S[ROL and ROR]
|
||||
* link:userland/arch/x86_64/rol.S[]: ROL and ROR
|
||||
+
|
||||
Rotates the bit that is going out around to the other side.
|
||||
* link:userland/arch/x86_64/rol.S[RCL and RCR]
|
||||
* link:userland/arch/x86_64/rol.S[]: RCL and RCR
|
||||
+
|
||||
Like ROL and ROR, but insert the carry bit instead, which effectively generates a rotation of 8 + 1 bits. TODO application.
|
||||
|
||||
@@ -12411,26 +12422,28 @@ Like ROL and ROR, but insert the carry bit instead, which effectively generates
|
||||
|
||||
<<intel-manual-1>> 5.1.6 "Bit and Byte Instructions"
|
||||
|
||||
* link:userland/arch/x86_64/bt.S[BT]
|
||||
* link:userland/arch/x86_64/bt.S[]: BT
|
||||
+
|
||||
Bit test: test if the Nth bit a bit of a register is set and store the result in the CF FLAG.
|
||||
+
|
||||
....
|
||||
CF = reg[N]
|
||||
....
|
||||
* link:userland/arch/x86_64/btr.S[BTR]
|
||||
* link:userland/arch/x86_64/btr.S[]: BTR
|
||||
+
|
||||
Do a BT and then set the bit to 0.
|
||||
* link:userland/arch/x86_64/btc.S[BTC]
|
||||
* link:userland/arch/x86_64/btc.S[]: BTC
|
||||
+
|
||||
Do a BT and then swap the value of the tested bit.
|
||||
* link:userland/arch/x86_64/setcc.S[SETcc]
|
||||
* link:userland/arch/x86_64/setcc.S[]: SETcc
|
||||
+
|
||||
Set a a byte of a register to 0 or 1 depending on the cc condition.
|
||||
* link:userland/arch/x86_64/popcnt.S[POPCNT]
|
||||
Set a byte of a register to 0 or 1 depending on the cc condition.
|
||||
+
|
||||
Bibliography: https://stackoverflow.com/questions/1406783/how-to-read-and-write-x86-flags-registers-directly/30952577#30952577
|
||||
* link:userland/arch/x86_64/popcnt.S[]: POPCNT
|
||||
+
|
||||
Count the number of 1 bits.
|
||||
* link:userland/arch/x86_64/test.S[TEST]
|
||||
* link:userland/arch/x86_64/test.S[]: TEST
|
||||
+
|
||||
Like <<x86-binary-arithmetic-instructions,CMP>> but does AND instead of SUB:
|
||||
+
|
||||
@@ -12442,12 +12455,12 @@ ZF = (!(X && Y)) ? 1 : 0
|
||||
|
||||
<<intel-manual-1>> 5.1.7 "Control Transfer Instructions"
|
||||
|
||||
* link:userland/arch/x86_64/jmp.S[JMP]
|
||||
** link:userland/arch/x86_64/jmp_indirect.S[JMP indirect]
|
||||
* link:userland/arch/x86_64/jmp.S[]: JMP
|
||||
** link:userland/arch/x86_64/jmp_indirect.S[]: JMP indirect
|
||||
|
||||
==== x86 Jcc instructions
|
||||
|
||||
link:userland/arch/x86_64/jcc.S[Jcc]
|
||||
link:userland/arch/x86_64/jcc.S[]
|
||||
|
||||
Jump if certain conditions of the flags register are met.
|
||||
|
||||
@@ -12472,29 +12485,61 @@ JG vs JA and JL vs JB:
|
||||
|
||||
==== x86 LOOP instruction
|
||||
|
||||
link:userland/arch/x86_64/loop.S[LOOP]
|
||||
link:userland/arch/x86_64/loop.S[]
|
||||
|
||||
Vs <<x86-jcc-instructions,Jcc>>: https://stackoverflow.com/questions/6805692/x86-assembly-programming-loops-with-ecx-and-loop-instruction-versus-jmp-jcond Holy CISC!
|
||||
|
||||
==== x86 string instructions
|
||||
|
||||
<<intel-manual-1>> 5.1.8 "String Instructions"
|
||||
|
||||
These instructions do some operation on an array item, and automatically update the index to the next item:
|
||||
|
||||
* First example explained in more detail
|
||||
** link:userland/arch/x86_64/stos.S[]: STOS: STOre String: store register to memory. STOSD is called STOSL in GNU GAS as usual: https://stackoverflow.com/questions/6211629/gcc-inline-assembly-error-no-such-instruction-stosd
|
||||
* Further examples
|
||||
** link:userland/arch/x86_64/cmps.S[]: CMPS: CoMPare Strings: compare two values in memory with addresses given by RSI and RDI. Could be used to implement `memcmp`. Store the result in JZ as usual.
|
||||
** link:userland/arch/x86_64/lods.S[]: LODS: LOaD String: load from memory to register.
|
||||
** link:userland/arch/x86_64/movs.S[]: MOVS: MOV String: move from one memory to another with addresses given by RSI and RDI. Could be used to implement `memmov`.
|
||||
** link:userland/arch/x86_64/scas.S[]: SCAS: SCan String: compare memory to the value in a register. Could be used to implement `strchr`.
|
||||
|
||||
The RSI and RDI registers are actually named after these intructions! S is the source of string instructions, D is the destination of string instructions.
|
||||
|
||||
The direction of the index increment depends on the direction flag of the FLAGS register: 0 means forward and 1 means backward: https://stackoverflow.com/questions/9636691/what-are-cld-and-std-for-in-x86-assembly-language-what-does-df-do
|
||||
|
||||
These instructions were originally developed to speed up "string" operations such as those present in the `<string.h>` header of the C standard library.
|
||||
|
||||
However, as computer architecture evolved, those instructions might not offer considerable speedups anymore, and modern glibc such as 2.29 just uses <<x86-simd>> operations instead:, see also: https://stackoverflow.com/questions/33480999/how-can-the-rep-stosb-instruction-execute-faster-than-the-equivalent-loop
|
||||
|
||||
===== x86 REP prefix
|
||||
|
||||
Example: link:userland/arch/x86_64/rep.S[]
|
||||
|
||||
Repeat a string instruction RCX times:
|
||||
|
||||
As the repetitions happen:
|
||||
|
||||
* RCX decreases, until it reaches 0
|
||||
* RDI and RSI increase
|
||||
|
||||
The variants: REPZ, REPNZ (alias REPE, REPNE) repeat a given instruction until something happens.
|
||||
|
||||
REP and REPZ also additionally stop if the comparison operation they repeat fails.
|
||||
|
||||
* REP: INS, OUTS, MOVS, LODS, and STOS
|
||||
* REPZ: CMPS and SCAS
|
||||
|
||||
=== x86 miscellaneous instructions
|
||||
|
||||
<<intel-manual-1>> 5.1.13 "Miscellaneous Instructions"
|
||||
|
||||
==== x86 NOP instruction
|
||||
|
||||
link:userland/arch/x86_64/nop.S[NOP]
|
||||
|
||||
No OPeration.
|
||||
|
||||
Does nothing except take up one processor cycle and occupy some instruction memory.
|
||||
|
||||
Applications: http://stackoverflow.com/questions/234906/whats-the-purpose-of-the-nop-opcode
|
||||
NOP: <<nop-instructions>>
|
||||
|
||||
=== x86 random number generator instructions
|
||||
|
||||
<<intel-manual-1>> 5.1.15 Random Number Generator Instructions
|
||||
|
||||
Example: link:userland/arch/x86_64/rdrand.S[RDRAND]
|
||||
Example: link:userland/arch/x86_64/rdrand.S[]: RDRAND
|
||||
|
||||
If you run that executable multiple times, it prints a random number every time to stdout.
|
||||
|
||||
@@ -12508,7 +12553,7 @@ RDRAND sets the carry flag when data is ready so we must loop if the carry flag
|
||||
|
||||
==== x86 CPUID instruction
|
||||
|
||||
Example: link:userland/arch/x86_64/cpuid.S[CPUID]
|
||||
Example: link:userland/arch/x86_64/cpuid.S[]
|
||||
|
||||
Fills EAX, EBX, ECX and EDX with CPU information.
|
||||
|
||||
@@ -13299,6 +13344,8 @@ See: <<arm-adr-instruction>>.
|
||||
|
||||
==== ARM NOP instruction
|
||||
|
||||
Parent section: <<nop-instructions>>
|
||||
|
||||
There are a few different ways to encode NOP, notably MOV a register into itself, and a dedicated miscellaneous instruction.
|
||||
|
||||
Example: link:userland/arch/arm/nop.S[]
|
||||
|
||||
Reference in New Issue
Block a user