The Intel 80x86 Processor
The Intel Family:
model
reg bus mem
8088 16
8 1Mb
8086 16
16 1Mb
80286 16
16 16Mb
80386 32
32 4GB
80486 32
32 4GB
P5 32
64 4GB
Starting with the 80286, Intel processors offer two modes of operation:
real mode: one program at a
time
protected mode: multi tasking
enabled
Later models also offer advanced architectural features that greatly increase
speed.
Viewing the Machine
Run a program under the VC++ debugger (press the F5 key). Close all
of the windows, then from [View]/[Debug Windows] menu select [Memory],
[Registers], and [Disassembly]. Arrange the windows in your main window
as shown below:

The [Disassembly] window shows the assembly language translation of
our program. The [Memory] window shows the entire contents of memory. The
[Registers] window shows the values of all registers.
Memory Model
The [Memory] window shows the contents of all 2^32 bytes of memory.
Of course most of these bytes ate 00. By resizing the window we can control
the word size being displayed. The right column interprets the bytes as
characters:

Intel processors are little endian machines that require words to be
aligned.
All addresses are assumed to be offsets from the beginning of a segment:
ADDRESS = SEGMENT * 16 + OFFSET
Register Set
The I8x86 processors have four general purpose 32-bit registers:
eax, ebx, ecx, edx
In addition, there are two 32-bit index registers, which can be used for
copying strings:
esi = source index
edi = destination index
There are four control registers:
eip = instruction pointer
esp = stack pointer
ebp = base pointer
efl = flags register
There are six 16-bit segment registers:
cs = code segment
ds = data segment
ss = stack segment
es = extra segment
fs, gs = extra segments
Flags
OF = V (overflow flag)
CF = C (carry flag)
ZF = Z (zero flag)
SF = N (sign flag)
Instruction Set
Move
mov ARG1, ARG2 /* ARG1 = ARG2
*/
Arithmetic
add ARG1, ARG2 /* ARG1 += ARG2
*/
sub ARG1, ARG2 /* ARG1 -= ARG2
*/
neg ARG1 /* ARG1 = -ARG1 */
cmp ARG1, ARG2 /* alu = ARG1
- ARG2 */
Bitwise Operations
and ARG1, ARG2 /* ARG1 &=
ARG2 */
or ARG1, ARG2 /* ARG1 |= ARG2
*/
xor ARG1, ARG2 /* ARG1 ^= ARG2
*/
not ARG1 /* ARG1 = ~ARG1 */
Shifts
shr ARG1, ARG2 /* ARG1 = ARG1
>> ARG2 */
sal ARG1, ARG2 /* ARG1 = ARG1
<< ARG2 */
shl ARG1, ARG2 /* ARG1 = ARG1
<<< ARG2 */
ror ARG1, ARG2 /* ARG1 >>>>
ARG2 */
rol ARG1, ARG2 /* ARG1 <<<<
ARG2 */
Jumps
Unconditional
jmp LABEL /* goto LABEL */
call PROC /* PROC() */
ret /* return */
Conditional
jXX LABEL /* if (XX) goto LABEL
*/
Where XX =
1. unsigned: a, ae, b, be,
c, nc
2. signed: g, ge, l, le, o,
no
3. flags: e, ne, s, ns, cxz,
p, np
For example:
cmp eax, ebx /* alu = eax -
abx */
jl LABEL /* if (SF != OF &&
ZF = 0) goto LABEL */
In other words:
if (eax < ebx) goto LABEL
Arguments
mov eax, 42 /* eax = 42 */
mov eax, x /* eax = x */
mov ebx, OFFSET x /* eax = &x
*/
mov eax, [ebx] /* eax = *ebx
*/
mov eax, x[42] /* eax = x[42]
*/
Tuning a Program
We can insert a block of assembly code into a VC program using an _asm
block:
void main()
{
TOP:
PROMPT("Enter a
number: ");
GETWORD(mem[0]);
_asm
{
mov eax, mem[0] ; load
add eax, eax ; add eax to itself
mov reg0, eax ; store
}
PROMPT("double
your number = ");
PUTWORD(reg0);
NEWLINE();
goto TOP;
return;
}
The practice of inserting assembly
code into a high-level program is called tuning.
Often code that is frequently
executed will be written in assembly. Be careful, this means your program
can't be ported to a different platform.
Here's a program that computes
the number of bricks to build a staircase of
height n (i.e., the nth triangle
number). It does so by simply summing all
of the non-negative integers
below n:
void main()
{
TOP:
PROMPT("Enter height of
staircase: ");
GETWORD(mem[0]);
_asm
{
mov eax, mem[0]
mov ebx, 0
AGAIN:
cmp eax, 0
; alu = eax - 0
jbe DONE
; if (eax <= 0) goto DONE
add ebx, eax
sub eax, 1
jmp AGAIN
DONE:
mov reg0, ebx
}
PROMPT("# steps required
= ");
PUTWORD(reg0);
NEWLINE();
goto TOP;
return;
}