Summary of Intel 80x86 instructions

Prepared by Lin Jensen , Bishop's University , for CSc 116 Assembly Language class, April 2002

This summary lists only the most useful general-purpose instructions. Where there are differences between treating signed v. unsigned numbers, I have only included the forms for signed numbers (this applies to mutiplication, division, and jumps for less or greater.) There are a great many "complex" instructions that are not actually needed (e.g. loope, rep movsb), and many varient forms. Most instructions can operate on 8- 16- or 32-bit quantities, so long as all operands are the same size.

Registers

There are 4 general purpose registers, named EAX, EBX, ECX, EDX.

Each of these registers is 32 bits. The lower 16 bits  and lowest 8 bits of EAX can be refered to using the names AX and AL respectively, and similarly for the others.

There are also 2 "index" registers, named ESI and EDI. In fact, all registers can be used for indirect addressing.

Two "saved" registers are associated with the stack . They must be preserved across function calls:


Instructions, grouped by function

Move

Data movement instructions do NOT affect the status flags. Thus merely moving a value into a register does not enable one to branch depending on its value, an arithmetic (or logic) instruction has to be used for the test.

mov   dest, src         ; move src to dest, one (but not both) may be in memory
; src may be immediate (constant)
xchg  op1, op2          ; exchange 2 operands, at least one must be a register
lea   reg, memory_reference  ; "load effective address" calculates the address 
; of the memory reference, and stores it in the reg.

Arithmetic

All arithmetic instructions set status flags according to their results, these can be used by following jump instructions to decide whether to branch or not. The most important are Carry, Zero, Sign, and Overflow.

add   dest, src         ; dest := dest + src, same limitations as mov
sub   dest, src         ; dest := dest - src
cmp   dest, src         ; same as sub except result NOT stored. Sets status flags only
imul  dest, src         ; just one variant. Only the Overflow flag has meaning (too large)
cdq                     ;   preceeds idiv to sign-extend eax (into edx) to a 64-bit number 
idiv src ; eax := [edx:eax]/src, edx := remainder. The dividend is 64 bits.
inc   op                ; increment (add 1 to) operand, sets OSZ (not C)
dec op ; decrement (subtract 1 from) operand, sets OSZ (not C)
neg   op                ; negate operand (2's complement)

Jump and branch instructions

jmp   label             ; unconditional jump to label:

Conditional jumps (known to us as branch instructions) test the status flags as necessary to decide whether to jump or not. Thus they usually follow a CMP instruction, less frequently another arithmetic or logic instruction. The machine language instruction stores an 8-bit displacement relative to the current instruction, this imposes a severe limit on how far one can branch. Sometimes inserting one additional instruction will cause a "jump out of range" error, which you must work around using the opposite branch and a JMP. There are some "aliases." JE and JZ are the same instruction , as are JL and JNGE.

je   label    ; jump if equal (or zero), tests the Z-flag
jne  label    ; jump if not equal
jl   label    ; jump if less (signed)   tests S- and O-flags
jg   label    ; jump if greater         tests SZO flags
jle  label    ; jump if less than or equal   opposite of jg
jge  label    ; jump if greater than or equal 

Function call and return

The CALL  instruction pushes the return address on the stack and then jumps to the procedure (function).
RET pops the return address off the stack (into the IP) thus returning control to the instruction following the call. Naturally this depends upon proper use of the stack and stack pointer (ESP). There is no need to save the return address when a function calls another function.

By convention, function results are returned in EAX. ESP and EBP must be preserved by functions, there are no fixed conventions regarding arguments. High level languages, and the Windows operating system, pass arguments on the stack.

Stack operations

PUSH pushes its operand on the stack

POP pops a value off the stack into its operand. In both cases the stack pointer (ESP) is modified accordingly. You must bear in mind that CALL and RET also do a push and pop respectively. (Bytes cannot be pushed or popped.)

Logic and shifting

AND, OR, NOT, XOR, all set the S and Z flags. Operands just like ADD.

A common trick for clearing a register, and also setting S=0 and Z=1, is

      xor eax,eax       ;set eax = 0
sal   op, cnt       ; shift arithmetic left the op, by cnt bits. Last bit out goes in Carry
sar op, cnt ; shift arithmetic right (sign-extended, leftmost bit is replicated)
shl op, cnt ; shift left
shr op, cnt ; shift right (0-s enter from left)
;  cnt can be 1, an 8-bit immediate, or register CL
; op can be register or memory
The last bit shifted out is always stored in the Carry flag.

There are also rotate instructions, ROL and ROR. Each bit shifted out is brought in at the other end. Again, the last bit rotated is also copied to the Carry flag.

Addressing modes

Source data can be immediate, examples:
257    ; decimal number
'A' ; ascii character ( same as 65 or 41h)
0DFh ; hexadecimal number: note leading numeric digit ( 0 here) and trailing H
offset mynum; the address of mynum in the data segment
both soruce and destination  can be register, direct memory addressing, or various forms of indirect memory addressing. However, in general, it is not possible for both destination and source to refer to memory. examples:
	add munum, 47	; direct memory reference, mynum := mynum + 47
sub eax, [ebx] ; the number in memory pointed to by ebx is subtracted from the
; contents of register eax (which changes as a result
mov bl, [ebx+edi+1] ; memory address is the sum of 2 registers and a constant,
; one byte is loaded

That just about covers the essential instructions, except for the floating coprocessor instructions , of course.

Note to outsiders:

This summary was prepared  for an introductory class , which was taught using MIPS assembly language. Therefore, it deliberately ignores the complications and limitations of the old 16-bit architecture, in favor of programming in the "flat" memory model, ignoring segment registers.

Last updated 1 April 2003. Back to Lab 12