X86 assembly language
x86 assembly language is the name for the family of assembly languages which provide some level of backward compatibility with CPUs back to the Intel 8008 microprocessor, which was launched in April 1972. It is used to produce object code for the x86 class of processors. Regarded as a programming language, assembly is "machine-specific" and "low-level". Like all assembly languages, x86 assembly uses mnemonics to represent fundamental CPU instructions, or machine code. Assembly languages are most often used for detailed and time-critical applications such as small real-time embedded systems, operating-system kernels, and  device drivers, but can also be used for other applications, such as the game "Roller Coaster Tycoon", 99% of which was written in x86 assembly. A compiler will sometimes produce assembly code as an intermediate step when translating a high-level program into machine code. Mnemonics and opcodes. Each x86 assembly instruction is represented by a mnemonic which, often combined with one or more operands, translates to one or more bytes called an opcode; the NOP instruction translates to 0x90, for instance and the HLT instruction translates to 0xF4. There are potential opcodes with no documented mnemonic which different processors  may interpret differently, making a program using them behave inconsistently or even generate an exception on some processors. These opcodes often turn up in code writing competitions as a way to make the code smaller, faster, more elegant or just show off the author's prowess. Syntax. x86 assembly language has two main syntax branches: "Intel syntax" and "AT&T syntax". "Intel syntax" is dominant in the DOS and Windows world, and AT&T syntax is dominant in the Unix world, since Unix was created at AT&T Bell Labs. Here is a summary of the main differences between "Intel syntax" and "AT&T  syntax": Many x86 assemblers use "Intel syntax", including NASM, FASM, MASM, TASM, and YASM. GAS, which originally used "AT&T syntax", has supported both syntaxes since version 2.10 via the ".intel_syntax" directive. A quirk in the AT&T syntax for x86 is that x87 operands are reversed, an inherited bug from the original AT&T assembler. The AT&T syntax is nearly universal to all other architectures with the same order; it was originally a syntax for PDP-11 assembly. The Intel syntax is specific to the x86 architecture, and is the one used in the x86 platform's documentation. Registers. x86 processors have a  collection of registers available to be used as stores for binary data. Collectively the data and address registers are called the general registers. Each register has a special purpose in addition to what they can all do: Along with the general registers there are additionally the: The IP register points to the memory offset of the next instruction in the code segment (it points to the first byte of the instruction). The IP register cannot be accessed by the programmer directly. The x86 registers can be used by using the MOV instructions. For example, in Intel syntax: mov ax , 1234h ; copies the value 1234hex (4660d) into register AX mov bx, ax ; copies the value of the AX register into the BX register Segmented addressing. The x86 architecture in real and virtual 8086 mode uses a process known as segmentation to address memory, not the flat memory model used in many other environments. Segmentation involves composing a memory address from two parts, a "segment" and an "offset"; the segment points to the beginning of a 64 KB (64×2) group of addresses and the offset determines how far from this beginning address the desired address is. In segmented addressing, two registers  are required for a complete memory address. One to hold the segment, the other to hold the offset. In order to translate back into a flat address, the segment value is shifted four bits left (equivalent to multiplication by 2 or 16) then added to the offset to form the full address, which allows breaking the 64k barrier through clever choice of addresses, though it makes programming considerably more complex. In real mode/protected only, for example, if DS contains the hexadecimal number 0xDEAD and DX contains the number 0xCAFE they would together point to the memory address 0xDEAD * 0x10  + 0xCAFE = 0xEB5CE. Therefore, the CPU can address up to 1,048,576 bytes (1 MB) in real mode. By combining "segment" and "offset" values we find a 20-bit address. The original IBM PC restricted programs to 640 KB but an expanded memory specification was used to implement a bank switching scheme that fell out of use when later operating systems, such as Windows, used the larger address ranges of newer processors and implemented their own virtual memory schemes. Protected mode, starting with the Intel 80286, was utilized by OS/2. Several shortcomings, such as the inability to access the BIOS  and the inability to switch back to real mode without resetting the processor, prevented widespread usage. The 80286 was also still limited to addressing memory in 16-bit segments, meaning only 2 bytes (64 kilobytes) could be accessed at a time. To access the extended functionality of the 80286, the operating system would set the processor into protected mode, enabling 24-bit addressing and thus 2 bytes of memory (16 megabytes). In protected mode, the segment selector can be broken down into three parts: a 13-bit index, a "Table Indicator" bit that determines whether the entry is in the  GDT or LDT and a 2-bit "Requested Privilege Level"; see x86 memory segmentation. When referring to an address with a segment and an offset the notation of "segment":"offset" is used, so in the above example the "flat address" 0xEB5CE can be written as 0xDEAD:0xCAFE or as a segment and offset register pair; DS:DX. There are some special combinations of segment registers and general registers that point to important addresses: The Intel 80386 featured three operating modes: real mode, protected mode and virtual mode. The protected mode which debuted in the 80286 was extended to allow the 80386 to  address up to 4 GB of memory, the all new virtual 8086 mode ("VM86") made it possible to run one or more real mode programs in a protected environment which largely emulated real mode, though some programs were not compatible (typically as a result of memory addressing tricks or using unspecified op-codes). The 32-bit flat memory model of the 80386's extended protected mode may be the most important feature change for the x86 processor family until AMD released x86-64 in 2003, as it helped drive large scale adoption of Windows 3.1 (which relied on protected mode ) since Windows could now run many applications at once, including DOS applications, by using virtual memory and simple multitasking. Execution modes. The x86 processors support five modes of operation for x86 code, Real Mode, Protected Mode, Long Mode, Virtual 86 Mode, and System Management Mode, in which some instructions are available and others are not. A 16-bit subset of instructions is available on the 16-bit x86 processors, which are the 8086, 8088, 80186, 80188, and 80286. These instructions are available in real mode on all x86 processors, and in 16-bit protected mode (80286 onwards), additional instructions relating  to protected mode are available. On the 80386 and later, 32-bit instructions (including later extensions) are also available in all modes, including real mode; on these CPUs, V86 mode and 32-bit protected mode are added, with additional instructions provided in these modes to manage their features. SMM, with some of its own special instructions, is available on some Intel i386SL, i486 and later CPUs. Finally, in long mode (AMD Opteron onwards), 64-bit instructions, and more registers, are also available. The instruction set is similar in each mode but memory addressing and word size vary, requiring different programming  strategies. The modes in which x86 code can be executed in are: Switching modes. The processor runs in real mode immediately after power on, so an operating system kernel, or other program, must explicitly switch to another mode if it wishes to run in anything but real mode. Switching modes is accomplished by modifying certain bits of the processor's control registers after some preparation, and some additional setup may be required after the switch. Examples. With a computer running legacy BIOS, the BIOS and the boot loader is running in Real mode, then the 64-bit operating system kernel  checks and switches the CPU into Long mode and then starts new kernel-mode threads running 64-bit code. With a computer running UEFI, the UEFI firmware (except CSM and legacy Option ROM), the UEFI boot loader and the UEFI operating system kernel is all running in Long mode. Instruction types. In general, the features of the modern x86 instruction set are: Stack instructions. The x86 architecture has hardware support for an execution stack mechanism. Instructions such as codice_8, codice_9, codice_10 and codice_11 are used with the properly set up stack to pass parameters, to allocate space for local data , and to save and restore call-return points. The codice_11 "size" instruction is very useful for implementing space efficient (and fast) calling conventions where the callee is responsible for reclaiming stack space occupied by parameters. When setting up a stack frame to hold local data of a recursive procedure there are several choices; the high level codice_13 instruction (introduced with the 80186) takes a "procedure-nesting-depth" argument as well as a "local size" argument, and "may" be faster than more explicit manipulation of the registers (such as codice_14 ; codice_15 ; codice_16). Whether it is faster or slower depends on the  particular x86-processor implementation as well as the calling convention used by the compiler, programmer or particular program code; most x86 code is intended to run on x86-processors from several manufacturers and on different technological generations of processors, which implies highly varying microarchitectures and microcode solutions as well as varying gate- and transistor-level design choices. The full range of addressing modes (including "immediate" and "base+offset") even for instructions such as codice_8 and codice_9, makes direct usage of the stack for integer, floating point and address data simple, as well as keeping the ABI specifications and mechanisms relatively simple  compared to some RISC architectures (require more explicit call stack details). Integer ALU instructions. x86 assembly has the standard mathematical operations, codice_19, codice_20, codice_21, with codice_22; the logical operators codice_23, codice_24, codice_25, codice_26; bitshift arithmetic and logical, codice_27/codice_28, codice_29/codice_30; rotate with and without carry, codice_31/codice_32, codice_33/codice_34, a complement of BCD arithmetic instructions, codice_35, codice_36, codice_37 and others. Floating-point instructions. x86 assembly language includes instructions for a stack-based floating-point unit (FPU). The FPU was an optional separate coprocessor for the 8086 through the 80386, it was an on-chip option for the 80486 series , and it is a standard feature in every Intel x86 CPU since the 80486, starting with the Pentium. The FPU instructions include addition, subtraction, negation, multiplication, division, remainder, square roots, integer truncation, fraction truncation, and scale by power of two. The operations also include conversion instructions, which can load or store a value from memory in any of the following formats: binary-coded decimal, 32-bit integer, 64-bit integer, 32-bit floating-point, 64-bit floating-point or 80-bit floating-point (upon loading, the value is converted to the currently used floating-point mode). x86 also includes a  number of transcendental functions, including sine, cosine, tangent, arctangent, exponentiation with the base 2 and logarithms to bases 2, 10, or "e". The stack register to stack register format of the instructions is usually codice_38 or codice_39, where codice_40 is equivalent to codice_41, and codice_42 is one of the 8 stack registers (codice_41, codice_44, ..., codice_45). Like the integers, the first operand is both the first source operand and the destination operand. codice_46 and codice_47 should be singled out as first swapping the source operands before performing the subtraction or division. The addition, subtraction, multiplication, division, store and comparison instructions include  instruction modes that pop the top of the stack after their operation is complete. So, for example, codice_48 performs the calculation codice_49, then removes codice_41 from the top of stack, thus making what was the result in codice_44 the top of the stack in codice_41. SIMD instructions. Modern x86 CPUs contain SIMD instructions, which largely perform the same operation in parallel on many values encoded in a wide SIMD register. Various instruction technologies support different operations on different register sets, but taken as complete whole (from MMX to SSE4.2) they include general computations on integer or floating point arithmetic (addition , subtraction, multiplication, shift, minimization, maximization, comparison, division or square root). So for example, codice_53 performs 4 parallel 16-bit (indicated by the codice_54) integer adds (indicated by the codice_55) of codice_56 values to codice_57 and stores the result in codice_56. Streaming SIMD Extensions or SSE also includes a floating point mode in which only the very first value of the registers is actually modified (expanded in SSE2). Some other unusual instructions have been added including a sum of absolute differences (used for motion estimation in video compression, such as is done in MPEG) and a 16-bit multiply accumulation instruction  (useful for software-based alpha-blending and digital filtering). SSE (since SSE3) and 3DNow! extensions include addition and subtraction instructions for treating paired floating point values like complex numbers. These instruction sets also include numerous fixed sub-word instructions for shuffling, inserting and extracting the values around within the registers. In addition there are instructions for moving data between the integer registers and XMM (used in SSE)/FPU (used in MMX) registers. Memory instructions. The x86 processor also includes complex addressing modes for addressing memory with an immediate offset, a register, a register with an offset, a scaled register with or  without an offset, and a register with an optional offset and another scaled register. So for example, one can encode codice_59 as a single instruction which loads 32 bits of data from the address computed as codice_60 offset from the codice_61 selector, and stores it to the codice_62 register. In general x86 processors can load and use memory matched to the size of any register it is operating on. (The SIMD instructions also include half-load instructions.) Most 2-operand x86 instructions, including integer ALU instructions, use a standard "addressing mode byte" often called the MOD-REG-R/M byte . Many 32-bit x86 instructions also have a SIB addressing mode byte that follows the MOD-REG-R/M byte. In principle, because the instruction opcode is separate from the addressing mode byte, those instructions are orthogonal because any of those opcodes can be mixed-and-matched with any addressing mode. However, the x86 instruction set is generally considered non-orthogonal because many other opcodes have some fixed addressing mode (they have no addressing mode byte), and every register is special. The x86 instruction set includes string load, store, move, scan and compare instructions (codice_63, codice_64, codice_65, codice_66 and codice_67 ) which perform each operation to a specified size (codice_68 for 8-bit byte, codice_54 for 16-bit word, codice_70 for 32-bit double word) then increments/decrements (depending on DF, direction flag) the implicit address register (codice_71 for codice_63, codice_73 for codice_64 and codice_66, and both for codice_65 and codice_67). For the load, store and scan operations, the implicit target/source/comparison register is in the codice_78, codice_79 or codice_62 register (depending on size). The implicit segment registers used are codice_61 for codice_71 and codice_83 for codice_73. The codice_85 or codice_86 register is used as a decrementing counter, and the  operation stops when the counter reaches zero or (for scans and comparisons) when inequality is detected. The stack is implemented with an implicitly decrementing (push) and incrementing (pop) stack pointer. In 16-bit mode, this implicit stack pointer is addressed as SS:[SP], in 32-bit mode it is SS:[ESP], and in 64-bit mode it is [RSP]. The stack pointer actually points to the last value that was stored, under the assumption that its size will match the operating mode of the processor (i.e., 16, 32, or 64 bits) to match the default width of the codice_8/codice_9/codice_10/codice_11  instructions. Also included are the instructions codice_13 and codice_92 which reserve and remove data from the top of the stack while setting up a stack frame pointer in codice_93/codice_1/codice_2. However, direct setting, or addition and subtraction to the codice_96/codice_97/codice_98 register is also supported, so the codice_13/codice_92 instructions are generally unnecessary. This code in the beginning of a function: ...is functionally equivalent to just: Other instructions for manipulating the stack include codice_101/codice_102 for storing and retrieving the (E)FLAGS register. The codice_103/codice_104 instructions will store and retrieve the entire integer register state to and from  the stack. Values for a SIMD load or store are assumed to be packed in adjacent positions for the SIMD register and will align them in sequential little-endian order. Some SSE load and store instructions require 16-byte alignment to function properly. The SIMD instruction sets also include "prefetch" instructions which perform the load but do not target any register, used for cache loading. The SSE instruction sets also include non-temporal store instructions which will perform stores straight to memory without performing a cache allocate if the destination is not already cached (otherwise it will behave like a  regular store.) Most generic integer and floating point (but no SIMD) instructions can use one parameter as a complex address as the second source parameter. Integer instructions can also accept one memory parameter as a destination operand. Program flow. The x86 assembly has an unconditional jump operation, codice_105, which can take an immediate address, a register or an indirect address as a parameter (note that most RISC processors only support a link register or short immediate displacement for jumping). Also supported are several conditional jumps, including codice_106 (jump on zero), codice_107 (jump on non-zero), codice_108 (jump on greater than , signed), codice_109 (jump on less than, signed), codice_110 (jump on above/greater than, unsigned), codice_111 (jump on below/less than, unsigned). These conditional operations are based on the state of specific bits in the (E)FLAGS register. Many arithmetic and logic operations set, clear or complement these flags depending on their result. The comparison codice_112 (compare) and codice_113 instructions set the flags as if they had performed a subtraction or a bitwise AND operation, respectively, without altering the values of the operands. There are also instructions such as codice_114 (clear carry flag) and codice_115 (complement carry flag) which work on the  flags directly. Floating point comparisons are performed via codice_116 or codice_117 instructions which eventually have to be converted to integer flags. Each jump operation has three different forms, depending on the size of the operand. A "short" jump uses an 8-bit signed operand, which is a relative offset from the current instruction. A "near" jump is similar to a short jump but uses a 16-bit signed operand (in real or protected mode) or a 32-bit signed operand (in 32-bit protected mode only). A "far" jump is one that uses the full segment base:offset value as  an absolute address. There are also indirect and indexed forms of each of these. In addition to the simple jump operations, there are the codice_10 (call a subroutine) and codice_11 (return from subroutine) instructions. Before transferring control to the subroutine, codice_10 pushes the segment offset address of the instruction following the codice_10 onto the stack; codice_11 pops this value off the stack, and jumps to it, effectively returning the flow of control to that part of the program. In the case of a codice_123, the segment base is pushed following the offset; codice_124 pops the offset and then the segment  base to return. There are also two similar instructions, codice_125 (interrupt), which saves the current (E)FLAGS register value on the stack, then performs a codice_123, except that instead of an address, it uses an "interrupt vector", an index into a table of interrupt handler addresses. Typically, the interrupt handler saves all other CPU registers it uses, unless they are used to return the result of an operation to the calling program (in software called interrupts). The matching return from interrupt instruction is codice_127, which restores the flags after returning. "Soft Interrupts" of the type described above are used by some  operating systems for system calls, and can also be used in debugging hard interrupt handlers. "Hard interrupts" are triggered by external hardware events, and must preserve all register values as the state of the currently executing program is unknown. In Protected Mode, interrupts may be set up by the OS to trigger a task switch, which will automatically save all registers of the active task. Examples. Section::::"Hello world!" program for DOS in MASM style assembly. Using interrupt 21h for output – other samples use libc's printf to print to stdout. .model small .stack 100h .data msg db 'Hello world!$' .code  start: end start .386 Section::::"Hello world!" program for Windows in MASM style assembly. .model small,c .stack 1000h .data msg db "Hello world!",0 .code includelib libcmt.lib includelib libvcruntime.lib includelib libucrt.lib includelib legacy_stdio_definitions.lib extrn printf:near extrn exit:near public main main proc main endp end %define RVA(x) (x-0x00400000) Section::::"Hello world!" program for Windows in NASM style assembly. section .text push dword hello call dword [printf] push byte +0 call dword [exit] ret section .data hello db "Hello world!" section .idata dd RVA(msvcrt_LookupTable) dd -1 dd 0 dd RVA(msvcrt_string) dd RVA(msvcrt_imports) times 5 dd 0 ; ends the descriptor table msvcrt_string dd  msvcrt.dll, 0 msvcrt_LookupTable: dd RVA(msvcrt_printf) dd RVA(msvcrt_exit) dd 0 msvcrt_imports: printf dd RVA(msvcrt_printf) exit dd RVA(msvcrt_exit) dd 0 msvcrt_printf: dw 1 dw "printf", 0 msvcrt_exit: dw 2 dw "exit", 0 dd 0 section .data ; section for initialized data Section::::"Hello world!" program for Linux in NASM style assembly. str: db 'Hello world!', 0Ah ; message string with new-line char at the end (10 decimal) str_len: equ $ - str ; calcs length of string (bytes) by subtracting the str's start address section .text ; this is the code section global _start ; _start is the entry point and needs global scope to be 'seen ' by the _start: ; definition of _start procedure begins here global main ;main must be defined as it being compiled against the C-Standard Library Section::::"Hello world!" program for Linux in NASM style assembly using the C standard library. extern printf ;declares use of external symbol as printf is declared in a different object-module. segment .data ;section for initialized data segment .text main: Section::::"Hello world!" program for 64-bit mode Linux in NASM style assembly. DEFAULT REL ; use RIP-relative addressing modes by default, so [foo] = [rel foo] SECTION .rodata ; read-only data can go in the .rodata section  on GNU/Linux, like .rdata on Windows Hello: db "Hello world!",10 ; 10 = `\n`. len_Hello: equ $-Hello ; get NASM to calculate the length as an assemble-time constant SECTION .text global _start _start: Running it under strace verifies that no extra system calls are made in the process. The printf version would make many more system calls to initialize libc and do dynamic linking. But this is a static executable because we linked using ld without -pie or any shared libraries; the only instructions that run in user-space are the ones you provide. $ strace ./hello  > /dev/null # without a redirect, your program's stdout is mixed strace's logging on stderr. Which is normally fine execve("./hello", ["./hello"], 0x7ffc8b0b3570 /* 51 vars */) = 0 write(1, "Hello world!\n", 13) = 13 exit(0) = ? + exited with 0 +. Using the flags register. Flags are heavily used for comparisons in the x86 architecture. When a comparison is made between two data, the CPU sets the relevant flag or flags. Following this, conditional jump instructions can be used to check the flags and branch to code that should run, e.g.: do_something: Flags are also used in the x86 architecture  to turn on and off certain features or execution modes. For example, to disable all maskable interrupts, you can use the instruction: The flags register can also be directly accessed. The low 8 bits of the flag register can be loaded into codice_128 using the codice_129 instruction. The entire flags register can also be moved on and off the stack using the instructions codice_101, codice_102, codice_125 (including codice_133) and codice_127. Using the instruction pointer register. The instruction pointer is called codice_135 in 16-bit mode, codice_136 in 32-bit mode, and codice_137 in 64-bit mode. The instruction pointer register  points to the memory address which the processor will next attempt to execute; it cannot be directly accessed in 16-bit or 32-bit mode, but a sequence like the following can be written to put the address of codice_138 into codice_62: next_line: This sequence of instructions generates position-independent code because codice_10 takes an instruction-pointer-relative immediate operand describing the offset in bytes of the target instruction from the next instruction (in this case 0). Writing to the instruction pointer is simple — a codice_105 instruction sets the instruction pointer to the target address, so, for example, a  sequence like the following will put the contents of codice_62 into codice_136: In 64-bit mode, instructions can reference data relative to the instruction pointer, so there is less need to copy the value of the instruction pointer to another register.