Data Control

The mov (move) instruction really should be named the copy instruction. It copies a byte, word, or double word from one location (register or memory) to another.

mov DEST, SRC     ; DEST = SRC

Addressing Modes

In general, DEST can be a register (reg) or memory location (mem).

A memory location can be given by an address or a variable.

In addition, SRC can be an immediate value (imed).

Of course DEST and SRC must have the same size (8, 16, or 32 bits).

Here are the allowable combinations:

mov reg, reg

mov reg, mem

mov mem, reg

mov mem, immed

mov reg, immed

Note that it doesn't make sense for the destination to be an immediate.

Also note that mem to mem moves are not supported:

mov mem, mem   ; ILLEGAL!

Example

The file demo3.c contains several interesting examples. The assembly version is demo3.s.

demo3.c begins with some global variable declarations:

int m1 = 50;
int m2[] = {100, 200, 300};
int* m3 = &m2[0];

Here's a snapshot of memory:

Our first move loads the immediate value -22 into variable m1. The problem is that the assembler doesn't know if -22 is an 8, 16, or 32 bit value. Recall that assemblers don't do type checking, so the assembler doesn't know if m1 is an 8, 16, or 32 bit variable. We need to help out by qualifying the variable using either BYTE PTR, WORD PTR, or DWORD PTR:

asm("mov DWORD PTR _m1, -22");

Our next move loads register eax with variable m3, which contains the address of variable m[0]:

  asm("mov eax, _m3");

We can also specify a memory location using its address:

mov reg, [address]      ; direct mode
mov reg, [reg + offset] ; indirect mode

For example, here's how we can load ebx with the m3[1]:

asm("mov ebx, [eax + 4]");

Finally, we load ebx into m1 since memory to memory moves can't be done in a single instruction:

asm("mov _m1, ebx");

Here's a snapshot of memory when the dust settles:

Push & Pop

push X  ; sub esp, sizeof(X)
        ; mov [esp], X

 

pop X   ; mov X, [esp]
        ; add esp, sizeof(X)