First thing you need to know about the processor is that you don't really have a lot to work with - you can't just create your own variables and use them at will. Fortunately, you're given some very fast little variables called registers. Some of them are general-purpose, some are dedicated to performing a specific task. There are six 32-bit registers you can use for almost anything, as well as two more that are dedicated to use on the stack (I'll get to that later):
EAX, EBX, ECX, EDX, ESI, EDI
To retain backwards compatibility with 16-bit predecessors, the above 32-bit registers have the low 16 bits aliased to these registers:
AX, BX, CX, DX, SI, DI
If you were to store 0xCAFEBABE* in EAX, then the value of AX would be 0xBABE. Changing AX to 0xDEAD means that EAX now contains the value 0xCAFEDEAD.
The registers AX, BX, CX, and DX are further subdivided into two registers each. So AX is composed of AH and AL, aliased to the high and low bytes of the word respectively. (E)SI and (E)DI don't do this because they're intended for use as pointer registers, but you can use them for anything, really.
Perhaps an example in C++ would help:
uint32_t eax; //AX points to low word of EAX. Since Intel processors //are little-endian, we don't have to do any pointer //arithmetic. uint16_t& ax = (uint16_t *)&eax; //same for AL uint8_t& al = (uint8_t *)&ax; //AH points to the HIGH byte, so we have to add one //byte to get the proper offset into AX. uint8_t& ah = ((uint8_t *)&ax) + 1;Well, this is all well and good, but how does one do anything to these registers? The most common command is mov. Take a look:
(By the way, a semicolon starts a comment, just like // in C++.)
;eax = 0xCAFEBABE mov eax, 0xCAFEBABE ;ecx = eax mov ecx, eax ;edx = ax ;WRONG - DIFFERENT SIZE mov edx, ax ;al = 0x0BAD ;WRONG - DIFFERENT SIZE mov ax, 0x0BADUnlike higher-level programming languages, you are not allowed to assign a small register to a larger one. The source and destination must be the same size.
There is a trick to getting around this by using the movzx and movsx instructions. movzx clears all the upper bits in the target register, and movsz copies the sign bit over.
unsigned long a; unsigned short b = 5; //[B]movzx a, b[/B] //now a = 5. signed long c; signed short d = -4; // [B]movsx c, d[/B] //now c = -4. //if we were to use movzx then c would equal 65,532 - oops.Right now you can't accomplish much like this, but later on I'll show you how to read and write from RAM, and do some arithmetic.
*The magic number for compiled Java class files.
Next In This Series
Edited by dargueta, 30 November 2010 - 12:18 PM.