assembly

#define assembly: \ I-----------------------------------------------------------------------------------------------------\ I-----------------------------------------------------------------------------------------------------\ I-----------------------------------------------------------------------------------------------------\ I /$$$$$$ /$$ /$$ \ I /$$__ $$ | $$ | $$ \ I | $$ \ $$ /$$$$$$$ /$$$$$$$ /$$$$$$ /$$$$$$/$$$$ | $$$$$$$ | $$ /$$ /$$ \ I | $$$$$$$$ /$$_____//$$_____/ /$$__ $$| $$_ $$_ $$| $$__ $$| $$| $$ | $$ \ I | $$__ $$| $$$$$$| $$$$$$ | $$$$$$$$| $$ \ $$ \ $$| $$ \ $$| $$| $$ | $$ \ I | $$ | $$ \____ $$\____ $$| $$_____/| $$ | $$ | $$| $$ | $$| $$| $$ | $$ \ I | $$ | $$ /$$$$$$$//$$$$$$$/| $$$$$$$| $$ | $$ | $$| $$$$$$$/| $$| $$$$$$$ \ I |__/ |__/|_______/|_______/ \_______/|__/ |__/ |__/|_______/ |__/ \____ $$ \ I /$$ | $$ \ I (((assembly))) | $$$$$$/ \ I \______/ \ I-----------------------------------------------------------------------------------------------------\ I-----------------------------------------------------------------------------------------------------\ I-----------------------------------------------------------------------------------------------------I — it is said that assembly one-to-one corresponds to machine code; it does not; there is a bunch of redundancy: • common operations may have their own instruction codes • instructions may ignore certain bits • prefixes may be senselessly applied to absurdity • different assembly instructions may be implemented as the same machine instruction • assemblers may choose a different, logically equivalent operations if its shorter • assemblers may evaluate what should be illegal machine code at build time, resulting in valid machine code • most of the following are from various Intel sources, so the syntaxes will be Intel assembler specific; syntaxes are discussed in greater detail later on • abstract hardware concepts are also stored in this chapter MEMORY: Measurement: +-----------------+----------+-----------------------------------+ | Name | Equation | In bytes | +-----------------+----------+-----------------------------------+ | bit (b) | N/A | 1/8 | | byte (B) | 8 bits | 1 | | kilobyte (KB) | 1000^1 | 1.000 | | kibibyte (KiB) | 1024^1 | 1.024 | | megabyte (MB) | 1000^2 | 1.000.000 | | mebibyte (MiB) | 1024^2 | 1.048.576 | | gigabyte (GB) | 1000^3 | 1.000.000.000 | | gibibyte (GiB) | 1024^2 | 1.073.741.824 | | terabyte (TB) | 1000^4 | 1.000.000.000.000 | | tebibyte (TiB) | 1024^4 | 1.099.511.627.776 | | petabyte (PB) | 1000^5 | 1.000.000.000.000.000 | | pebibyte (PiB) | 1024^5 | 1.125.899.906.842.624 | | exabyte (EB) | 1000^6 | 1.000.000.000.000.000.000 | | exbibyte (EiB) | 1024^6 | 1.152.921.504.606.846.976 | | zettabyte (ZB) | 1000^7 | 1.000.000.000.000.000.000.000 | | zebibyte (ZiB) | 1024^7 | 1.180.591.620.717.411.303.424 | | yottabyte (YB) | 1000^8 | 1.000.000.000.000.000.000.000.000 | | yobibyte (YiB) | 1024^8 | 1.208.925.819.614.629.174.706.176 | +-----------------+----------+-----------------------------------+ ○ when not specified otherwise the equations are byte based Alignment: • hardware accesses data in blocks; these blocks are sized 2^N bytes and have boundaries between them to access data cross boundaries multiple instructions are necessary, therefor it is faster to access properly aligned data ie data crossing the least amount of boundaries ------------------------------------------------ | Optimal Data Alignments | +-------------+---------------+----------------+ | Data Type | 32-bit CPUs | 64-bit CPUs | | | (in bytes) | (in bytes) | ------------------------------------------------ | char | 1 | 1 | | short | 2 | 2 | | int | 4 | 4 | | long | 8 | 8 | | float | 4 | 4 | | double | 8 | 8 | | long long | 8 | 8 | | long double | 4 | 16 | | Any pointer | 4 | 8 | ------------------------------------------------ • to align every piece of data, compilers self-align, ie. use padding (unused space) between data • padding is not guaranteed to be zeroed • reordering variable declarations can save memory • C structures have as much padding after them that ensures the next variable will be aligned the same as the struct • C++ is C-like, except that classes that look like struct-s may ignore the rule that the address of a struct is the address of its first member! whether they do or not depends on how base classes and virtual member functions are implemented, and also varies by compiler; otherwise everything here observed about C applies Endianness: • named after the trope in "Gulliver's Travels" where the citizens of Liliput start a civil war over which end to start eating a hard boiled eggs from • specifies the order in which bytes are arraged inside a processor word • any ordering works until its consistent • developers prefer big-endian because the memory dumps are more readable • hardware manufacturers prefer little-endian because values can be addressed consistently on narrower schemes ○ the two most common endianesses are • little-endian (more common) • big-endian | 1. | 2. | 4. | 3. | 5. | 6. | 7. | 8. | +----+----+----+----+----+----+----+----+ 0x0000000000000001 -> | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 01 | Big-Endian 0x0000000000000001 -> | 10 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | Little-Endian { // Assume a 16 bit little-endian system char msg[] = "heyo"; // Inspect the memory msg: | 'e' 'h' | 'o' 'y' | } STACK: • LIFO; Last In First Out • stored in the ram in a contiguous block of memory • (in most architectures) implemented growing DOWNWARD in memory (see illustration way BELOW) • when a function is called a stack frame is created ○ stack frame parts: • return value • arguments • return address • saved frame pointer • local variables HEAP: • (in most architectures) implemented growing UPWARD in memory (see illustration way BELOW) • used for storing gigantic data (compared to stack) or when a variable must outlive its scope Of course, if the stack and heap meet, the program will crash. If that occurs, there is no memory available. MEMORY_USAGE: nowadays, on modern kernels its virtualized to the point where each process has its own memory and the heap and the stack cannot touch due to overflowing /-------------------\....High address (0xFFFF) | command line args | |-------------------| | Stack | | | | | V | +-------------------+ | ### unused ### | +-------------------+ | A | | | | | Heap | |-------------------| | .bss | |-------------------| | .data | |-------------------| | .text | \-------------------/....Low address (0x0000) REGISTERS: ---------------------------------------------------------------------------------------------------------- | General Purpose Registers (16) | ---------------------------------------------------------------------------------------------------------- | 64-bit register | Lowest 32-bits | Lowest 16-bits | Higher 8-bits | Lowest 8-bits | Name | ---------------------------------------------------------------------------------------------------------- | rax | eax | ax | ah | al | Accumulator | | rbx | ebx | bx | bh | bl | Base | | rcx | ecx | cx | ch | cl | Counter | | rdx | edx | dx | dh | dl | Data | | rsi | esi | si | N/A | sil | Source index | | rdi | edi | di | N/A | dil | Destination index | | rbp | ebp | bp | N/A | bpl | Base Pointer | | rsp | esp | sp | N/A | spl | Stack Pointer | | r8 | r8d | r8w | N/A | r8b | N/A | | r9 | r9d | r9w | N/A | r9b | N/A | | r10 | r10d | r10w | N/A | r10b | N/A | | r11 | r11d | r11w | N/A | r11b | N/A | | r12 | r12d | r12w | N/A | r12b | N/A | | r13 | r13d | r13w | N/A | r13b | N/A | | r14 | r14d | r14w | N/A | r14b | N/A | | r15 | r15d | r15w | N/A | r15b | N/A | ---------------------------------------------------------------------------------------------------------- ○ naming: e[char]x: • 'e' stands for extended • [char] stands for the register's name, goes alphabetically • 'x' also stands for extended, but for a different extension — Accumulator Register (RAX) • has a special role in some calculations (div, mul...) • has special role in storing strings • stores return values — Counter Register (RCX) — Destination Index Register (RDI) • points to memory where results of sting operations shall be placed — Base Pointer Register (RBP)(/ Frame Pointer (RFP)) • base pointer during function calls • should not be used for data or other uses — Stack Pointer Register (RSP) • points to the current top of the stack • should not be used for data or other uses • on Linux the first 128-bytes after the stack pointer are reserved — Instruction Pointer Register (RIP) • points to the next instruction to be executed • the instruction in RIP has never been executed yet — Flags Register (rFlags || eFlags || Flags) • stores status information about the instruction that was just executed — Flags status bits: --------------------------------------------------------------------- | Name | Symbol | Bit | Use | --------------------------------------------------------------------- | Carry | CF | 0 | Used to indicate if the previous | | | | | operation resulted in a carry. | | Parity | PF | 2 | Used to indicate if the last byte | | | | | has an even number of 1's | | | | | (i.e., even parity). | | Adjust | AF | 4 | Used to support Binary Coded | | | | | Decimal operations. | | Zero | ZF | 6 | Used to indicate if the previous | | | | | operation resulted in a | | | | | zero result. | | Sign | SF | 7 | Used to indicate if the result | | | | | of the previous operation | | | | | resulted in a 1 in the most | | | | | significant bit (indicating | | | | | negative in the context of | | | | | signed data). | | Direction | DF | 10 | Used to specify the direction | | | | | (increment or decrement) | | | | | for some string operations. | | Overflow | OF | 11 | Used to indicate if the previous | | | | | operation resulted in an | | | | | overflow. | --------------------------------------------------------------------- — Debugg registers: • <dr0-dr7> ○ <dr0-3> • contain breakpoint addresses ○ <dr6> • permits the debuger to determine which debug conditions have occurred ○ <dr7> ----------------------------------- | Bit | Description | ----------------------------------- | 0 | Local DR0 Breakpoint | | 1 | Global DR0 Breakpoint | | 2 | Local DR1 Breakpoint | | 3 | Global DR1 Breakpoint | | 4 | Local DR2 Breakpoint | | 5 | Global DR2 Breakpoint | | 6 | Local DR3 Breakpoint | | 7 | Global DR3 Breakpoint | | 16-17 | Conditions for DR0 | | 18-19 | Size of DR0 Breakpoint | | 20-21 | Conditions for DR1 | | 22-23 | Size of DR1 Breakpoint | | 24-25 | Conditions for DR2 | | 26-27 | Size of DR2 Breakpoint | | 28-29 | Conditions for DR3 | | 30-31 | Size of DR3 Breakpoint | ----------------------------------- — Floating point registers: • 128-bit • <xmm0-15> • only used for operations, they cannot access memory • the first eight floating-point arguments are passed in floating-point registers xmm0-xmm7 ------------------- | Float registes: | ------------------- | xmm0 | | xmm1 | | xmm2 | | xmm3 | | xmm4 | | xmm5 | | xmm6 | | xmm7 | | xmm8 | | xmm9 | | xmm10 | | xmm11 | | xmm12 | | xmm13 | | xmm14 | | xmm15 | ------------------- — Floating-point Control and Status Register (MXCSR) ○ status bits: -------------------------------------------- | Name | Symbol | Bit | -------------------------------------------- | Invalid Operation flag | IE | 0 | | Denormal flag | DE | 1 | | Divide-by-Zero flag | ZE | 2 | | Overflow flag | OE | 3 | | Underflow flag | UE | 4 | | Precision Flag | PE | 5 | | Denormals Are Zeros | DAZ | 6 | | Invalid Operation mask | IM | 7 | | Denormal Operation mask | DM | 8 | | Divide-by-Zero mask | ZM | 9 | | Overflow mask | OM | 10 | | Underflow mask | UM | 11 | | Precision mask | PM | 12 | | Rounding Control | RC | 13-14 | | Flush To Zero | FTZ | 15 | | RESERVED | N/A | 16-31 | -------------------------------------------- — Floating-Point Unit (FPU) — Control register ------------------------------------------------ | Name | Symbol | Bit | ------------------------------------------------ | Invalid operation Mask | IM | 0 | | Denormalized operand Mask | DM | 1 | | Zero divide Mask | ZM | 2 | | Overflow Mask | OM | 3 | | Underflow Mask | UM | 4 | | Percision Mask | PM | 5 | | RESERVED | N/A | 6 | | Interupt Enable Mask | IEM | 7 | | Percision Control | PC | 8-9 | | Rounding Control | RC | 10-11 | | Infinity Control | IC | 12 | | RESERVED | N/A | 13-15 | ------------------------------------------------ ○ Interupt Enable Mask: • whether to interupt interupt masks • interupt masks being the first 6 (0-5) bits false : enable masks true : disable masks ○ Percision Control: 00 : 24-bit (REAL4?!) 01 : not used 10 : 53-bit (REAL8?!) 11 : 64-bit (REAL10?!) ○ Rounding Control: 00 : round towards nearest or even if equidistant 01 : round towards -infinity 10 : round towards +infinity 11 : round towards zero ○ Infinity Control: false : do not differentiate between negative and positive infinity, both are treated unsigned true : respect negative and positive infinity — Status register --------------------------------------------------------- | Name | Symbol | Bit | --------------------------------------------------------- | Invalid Operation exception flag | I | 0 | | Denormalized exceptioni flag | D | 1 | | Zero divide exception flag | Z | 2 | | Overflow exception flag | O | 3 | | Underflow exception flag | U | 4 | | Percision exception flag | P | 5 | | Stack Fault exception flag | ST | 6 | | Interrupt Request | IR | 7 | | Condition fields | C[0-3] | 8-10 & 14 | | TOP | TOP | 11-13 | | Busy field | B | 15 | --------------------------------------------------------- ○ exception flags: • whether [exception] exception is raised ○ Interrupt Request: • whether an exception is being handled • never set while using a debugger ○ Condition field: • contain result of some operations {comparisons} ○ TOP: • used for keeping track of whick register is at slot 0 ○ Busy flield: • whether the FPU is executing an exception — Tag register • 8, 2-bit, nameless tag fields • each tag field "little endianly" correspond to a 80-bit register (see BELOW) ○ Correspondance: --------------------------- | Field | Bits | Register | --------------------------- | 0 | 0-1 | 7 | | 1 | 2-3 | 6 | | 2 | 4-5 | 5 | | 3 | 6-7 | 4 | | 4 | 8-9 | 3 | | 5 | 10-11 | 2 | | 6 | 12-13 | 1 | | 7 | 14-15 | 0 | --------------------------- ○ meaning of contents of a tag field: 00 : valid, non-zero value 01 : zero 10 : special value (NAN, infinity or denormal) 11 : empty — Internal flags register • maniged by the FPU • can not be accessed — 8, 80-bit registers • LIFO (Last In First Out) • a limited stack • loading and popping; however registers can be operated on (artimetrics for example) while not at the top • a rolling barrel is a good visualization • on each load the barrel rotates • over writing a register already holding a value will result in a junk value • slots are name as: st(<int>) the word "slot" shall not be mistaken to carry the same meaning as register, as regardless of the rotation of the registers the slot names stay the same; therefor its the programmers responsibility to remember the position of his values ooo OOO OOO ooo oOO --- OOo oOO ; ; OOo oOO --- | 0 | --- OOo oOO ; ; ; ; ; ; OOo oOO | 7 | --- | 1 | OOo oOO ; ; ; ; OOo oOO --- --- OOo oOO --- --- OOo oOO ; ; ; ; OOo oOO | 6 | X | 2 | OOo oOO ; ; ; ; OOo oOO --- --- OOo oOO --- --- OOo oOO ; ; ; ; OOo oOO | 5 | --- | 3 | OOo oOO ; ; ; ; ; ; OOo oO --- | 4 | --- OOo oOO ; ; OOo oOO --- OOo ooo OOO OOO ooo EXTENSIONS: .S : extension to represent hand written assembly files .s : extension used by gcc/g++ for assembly files .asm : windows extension for assembly files COMMENTING: ; [stuff] : single line only # [stuff] || /*[stuff]*/ : behaves as you would expect; GAS specific(!) DATATYPES: /*(0x000000e6)➞*/ res (array) typenames: --------------------------------- --------------------------------- | Declaration | Variable size | | Declaration | Variable size | --------------------------------- --------------------------------- | db | 8-bit | | resb | 8-bit | | dw | 16-bit | | resw | 16-bit | | dd | 32-bit | | resd | 32-bit | | dq | 64-bit | | resq | 64-bit | | ddq | 128-bit integer | | resdq | 128-bit | | dt | 128-bit float | --------------------------------- --------------------------------- SEGMENTATION: • segments are movable relative to each other, ie. their order is irrelevant • can be split in asm • their offset in the binary is stored in a table • their names are encoded literally in the executable — has one or more of the following access rights: • read • write • execute — main conventional segments: • these are often refered to as "sections"; conventionally they are equivalent, however there is a meaningful distinction here to make • these sections are utalized by tools to figure out whats going on — block starting symbol: • ".bss" • used for declaring reserved 0 initialized variables (arrays) • C static vars live here — data: • ".data" • uninitialized if not exists(rdata) • read only • used for const-s else — rdata • ".rdata" • .data, but especially for read only — text: • ".text" • code lives here LABELS: <string>: : creates label named <string> • a label is a location to jump to INTERUPTS:"trap" • hardware supported • crutial to debuggers (breakpoints) — uppon an interupt: 1. execution is suspended 2. state is saved 3. an interupt handler is executed 4. state is restored IDT:"Interupt Description Table" • an array of code addresses to dispatch uppon an interupt or exception • the type of the interupt indexes this table • operating system uses it for system calls RINGS: • hardware support for implementing OS privelage separtion LANGUAGE_STATEMENTS: Notations: [label] : program label [reg] : register operand; The operand must be a register; [src] : source operand; operand value is unchanged after the instruction [im] : immediate value; may be specified in decimal, hex, octal, or binary [mem] : memory location; May be a variable name or an indirect reference [op] : operand, register or memory; [dest] : destination operand; The operand may be a register or memory; the contents will be overwritten with the new result ARC : int, dependent on architecture; (x64 -> 64 || 32, x86 -> 32) //overload with "RX" -> float register //overload with "<int>" -> required size Instructions: • everything BELOW uses the Intel syntax move: mov [dest], [src] : copies [src]'s value to [dest] lea [reg[64]], [mem] : copies [mem]'s value to [reg[64]]; short for "Load Effective Address" movss [dest], [src[32]] : copies [src]'s float value to [dest] movsd [dest], [src[64]] : copies [src]'s double value to [dest] widening: movzx [dest], [src] : copies [src]'s unsigned value to a larger register (16||8 -> 64; 16||8 -> 32; 8 -> 16 (bits)) movsx [dest], [src] : copies [src]'s signed value to a largel register (16||8 -> 64; 16||8 -> 32; 8 -> 16 (bits)) movsxd [dest[64]], [scr[32]] : copies [src]'s signed 32 bit value to a 64 bit register cbw : converts and copies <al>'s signed value to <ax> cwd : converts and extends <ax>'s signed value to <dx:ax> cwde : converts and copies <ax>'s signed value to <eax> cdq : converts and extends <eax>'s signed value to <edx:eax> cdqe : converts and copies <eax>'s signed value to <rax> cqo : converts and extends <rax>'s signed value to <rdx:rax> cvtss2sd [RXdest], [src[32]] : converts [src[32]]'s FLOAT value to FLOAT 64 and copies to [RXdest] shrinking: cvtsd2ss [RXdest], [src[64]] : converts [src[64]]'s FLOAT value to FLOAT 32 and copies to [RXdest] conversion: cvtss2si [reg[32]], [src] : converts [src]'s FLOAT 32 value to INT 32 and copies to [reg[32]] cvtsd2si [reg[32]], [src] : converts [src]'s FLOAT 64 value to INT 32 and copies to [reg[32]] cvtsi2ss [reg[32]], [src] : converts [src]'s INT 32 value to FLOAT 32 and copies to [reg[32]] cvtsi2sd [reg[64]], [src] : converts [src]'s INT 64 value to FLOAT 64 and copies to [reg[64]] arimetric: add [dest], [src] : adds [src] to [dest]'s original value; ([dest] = [dest] + [src]) addss [RXdest], [src] : adds [src]'s FLOAT 32 value to [dest]'s original FLOAT 32 value; ([RXdest] = [RXdest] + [src]) addss [RXdest], [src] : adds [src]'s FLOAT 64 value to [dest]'s original FLOAT 64 value; ([RXdest] = [RXdest] + [src]) inc [dest] : adds one to [dest]'s original value (++[dest]) adc [dest], [src] : adds [src] and <Flags>'s Carry to [dest]'s original value ([dest] = [dest] + [src] + <CF>) sub [dest], [src] : subtracts [src] from [dest]s original value ([dest] = [dest] - [src]) subss [RXdest], [src] : subtracts [src]'s FLOAT 32 value from [dest]s original FLOAT 32 value; ([RXdest] = [RXdest] - [src]) subsd [RXdest], [src] : subtracts [src]'s FLOAT 64 value from [dest]s original FLOAT 64 value; ([RXdest] = [RXdest] - [src]) dec [dest] : subtracts one from [dest]s original value (--[dest]) mul [src] : multiplies [src]' UNSIGNED value with <*a*>'s value and store it in <*a*:*d*>; (<ax:dx> = <ax> * <cx>) mulss [RXdest], [src] : multiplies [src]'s FLOAT 32 value with [RXdest]'s FLAOT 32 value; ([RXdest] = [src] * [RXdest]) mulsd [RXdest], [src] : multiplies [src]'s FLOAT 64 value with [RXdest]'s FLAOT 64 value; ([RXdest] = [src] * [RXdest]) imul [src] : multiplies [src]'s SIGNED value with <*a*>'s value and store it in <*a*:*d*>; (<ax:dx> = <ax> * <cx>) imul [dest], [src] : multiplies [src]'s SIGNED value with [dest]'s value and store it in [dest]:??? imul [dest], [src], [im]: multiplies [src]'s SIGNED value with [im]'s value and store it in [dest]:??? div [src] : divides <*a*> with [src]'s UNSIGNED value; see "Div table" BELOW divss [RXdest], [src] : divides [RXdest]'s FLOAT 32 value with [src]'s FLOAT 32 value and store it in [RXdest]; ([RXdest] = [RXdest] / [src]) divsd [RXdest], [src] : divides [RXdest]'s FLOAT 64 value with [src]'s FLOAT 64 value and store it in [RXdest]; ([RXdest] = [RXdest] / [src]) idiv [src] : divide <*a*> with [src]'s SIGNED value; see "Div table" BELOW sqrtss [RXdest], [src] : takes the square root of [src]'s FLOAT 32 value and store it in [RXdest] sqrtss [RXdest], [src] : takes the square root of [src]'s FLOAT 64 value and store it in [RXdest] string: • operate on contiguous memory stosb : store byte; stores <al>'s value where <rdi> is pointing to and incoments <rdi> by 1 byte stosw : store word; stores <ax>'s value where <rdi> is pointing to and incoments <rdi> by 2 byte stosd : store double-word; stores <eax>'s value where <rdi> is pointing to and incoments <rdi> by 4 byte stosq : store quad-word; stores <rax>'s value where <rdi> is pointing to and incoments <rdi> by 8 byte rep [string operation] : while <rcx> is not 0 perform [string operation] and decrease <rcx> logic: and [src1], [src2] : see logical table BELOW; places result into [src1]; applied bit by bit //tho its pretty logical or [src1], [src2] : see logical table BELOW; places result into [src1]; applied bit by bit xor [src1], [src2] : see logical table BELOW; places result into [src1]; applied bit by bit not [op] : 0->1; 1->0; applied bit by bit shl [op], [src] : shifts [op]'s bits to the LEFT by [src]'s value; will result in [dest]*2^[src]; bits shifted beyond [op] are first shifted into <CF>; the new bits shifted in are all 0s shr [op], [src] : shifts [op]'s bits to the RIGHT by [src]'s value; will result in [dest]/2^[src]; bits shifted beyond [op] are first shifted into <CF>; the new bits shifted in are all 0s sal [op], [src] : artimetric shift left; literally the same as shl sar [op], [src] : artimetric shift right; almost shr BUT the new bits shifted in are all whatever the sign (most significant) bit contained rol [op], [src] : rotate LEFT; (shift left, but the bits pussed out are getting pussed back on the other side) ror [op], [src] : rotate RIGHT; (shift left, but the bits pussed out are getting pussed back on the other side) control: cmp [opt1], [opt2] : compare the [opts]; results are stored in <rFlags> ucomiss [Rxsrc], [src] : compare two FLOAT 32 values; results are stored in <rFlags> ucomisd [Rxsrc], [src] : compare two FLOAT 64 values; results are stored in <rFlags> jmp [label] : execution jumps to [label]; (see ABOVE what a label is) • jmp is not limited by range; the label can be whereever • conditional jumps can only perform "short-jumps" ie, the label must be within -128 or +127 instuctions aways • to solve this, use a conditional jump to jump over a jmp; | Flags and what they are tested for: | je [label] : jumps to [label] if equal; - <ZF> == 1, jne [label] : jumps to [label] if not equal; - <ZF> == 0, SINGED: jg [label] : jumps to [label] if greater; - <ZF> == 0 && <SF> == <OF>, # jge [label] : jumps to [label] if greater or equal; - <SF> == <OF>, # jl [label] : jumps to [label] if less; - <SF> != <OF>, # jle [label] : jumps to [label] if less or equal; - <ZF> == 1 || <SF> != <OF>, UNSIGNED: ja [label] : jumps to [label] if above; - <CF> == 0 && <ZF> == 0, # jae [label] : jumps to [label] if above or equal; - <CF> == 0, # jb [label] : jumps to [label] if below; - <CF> == 1, # jbe [label] : jumps to [label] if below or equal; - <CF> == 1 || <ZF> == 1 ○ naming convention: //THERE ARE WAY MORE j : jump l : less a : above n : not b : below o : overflow c : carry p : parity e : equal s : sign g : greater z : zero stack: push [op] : push [op] to the top of the stack pop [op] : pop the top of the stack into [op] function related: call [function_name] : calls [function_name]; (push <rip> and jump to [function_name]) ret : return; (pop the stack into <rip> effecting in a jump to the line after the call) misc: syscall : calls the system nop : no operation; do nothing (0x90) macros: • macro definitions should be placed in the source file before the data and code sections • it works like C macros functions: //I'm surprised they actually exist at this level • cannot be nested // I'm surprised to learn that they can be in C system calls(/functions): ------------------------ | Register | Usage | ------------------------ | rax | Call code | | rdi | 1st arg | //arguments are not always mandatory (duh) | rsi | 2nd arg | | rdx | 3rd arg | | r10 | 4th arg | | r8 | 5th arg | | r9 | 6th arg | ------------------------ • put the desired information into the right registers and initiate a {syscall} • tho i symbolically use C style function calls below; that's obviously not how you call them... Linux: 0([location], [dest], [size]) : read; reads [size] bytes from [location] into [dest] [locations]: 0 : STDIN [file] : reads [file]; ([file] must be a descriptor of an open file) 1([location], [message], [message.size()]) : write; writes [message] to [location] 1 : STDOUT [file] : writes [file]; ([file] must be a descriptor of an open file) 2(<string>, [access flag]) : open; open <string> file 59(<string>, [argv], [?!]) : execve; run <string> program 60([value]) : exit; exit with [value] 85(<string>, [acces flag]) : creat; creates/overwrites file Div table: -------------------------------------------------- | Divisor Size | Dividend | Quotient | Remainder | -------------------------------------------------- | byte | AX | AL | AH | | word | DX:AX | AX | DX | | doubleword | EDX:EAX | EAX | EDX | | quadword | RDX:RAX | RAX | RDX | -------------------------------------------------- Logical table: ----------------------------------------- |#########| and | or | xor | ----------------------------------------- | [src1] | 0 1 0 1 | 0 1 0 1 | 0 1 0 1 | | [src2] | 0 0 1 1 | 0 0 1 1 | 0 0 1 1 | ----------|---------|---------|---------| | results | 0 0 0 1 | 0 1 1 1 | 0 1 1 0 | ----------|---------|---------|---------| _start: : starts execution Programs: AT&T: • prefix constants with a dollar sign { $0x90 } • prefix registers with a percentage sign { %rax } • source first, destination second in all operations { mov $3, eax } GAS:"Gnu ASsembler" • used internally by gcc/g++ Prefixes: % - register $ - constant Operation suffixes: b - byte (8 bit) s - single (32-bit floating point) w - word (16 bit) l - long (32 bit integer or 64-bit floating point) q - quad (64 bit) t - ten bytes (80-bit floating point) High_level_assembly:"HLA" • rough concept of a language higher than pure assembly, but still basically assembly • modern assemblers are all technically high level assemblers due to their macro systems, but that renders the distinction redundant, so the concept has to shift upwards ○ high level assemblers — Public Domain HLA: https://www.plantation-productions.com/Webster/HighLevelAsm/index.html https://sourceforge.net/p/hlav1/code/HEAD/tree/ • looks fun • million compile errors with modern tools • self-dependency with a binary dll; uncompileable under *nix • the code base is hilariously bad for v1; v3 is implemented in PD HLA... • the solo dev is dead (as of 2024); his memeware may rest in piece with him — IBM HLA: • for z/OS • a bit like as if young Fortran and COBOL had a child by accident, who was retarded, but the family preferred the expression "low level" to describe his difficulties — X#: • C# based; windows oriented • focuses on higher level abstractions