Figure 1   Common Intel x86 Registers

EAX Multipurpose. Return values from a function are usually stored in EAX. Low 16 bits are referenced as AX. AX can be further subdivided into AL (the low 8 bits), and AH (the upper 8 bits of AX).
EBX Multipurpose. Low 16 bits are referenced as BX. BX can be further subdivided into BL (the low 8 bits), and BH (the upper 8 bits of BX).
ECX Multipurpose. Often used as a counter, for example, to hold the number of loop iterations that should be performed. Low 16 bits are referenced as CX. CX can be further subdivided into CL (the low 8 bits), and CH (the upper 8 bits of CX).
EDX Multipurpose. Low 16 bits are referenced as DX. DX can be further subdivided into DL (the low 8 bits), and DH (the upper 8 bits of DX).
ESI Multipurpose. In certain operations that move or compare memory, ESI contains the source address. Low 16 bits are referenced as SI.
EDI Multipurpose. In certain operations that move or compare memory, EDI contains the destination address. Low 16 bits are referenced as DI.
ESP Stack pointer. Implicitly changed by PUSH, POP, CALL, and RET instructions.
EBP Base pointer. Usually points to the current stack frame for a procedure. Procedure parameters are usually at positive offsets from EBP (for example, EBP+8). Local variables are usually at negative offsets (for example, EBP-16). Sometimes, optimizing compilers won't use a stack frame, and use EBP as a multipurpose register.
EFLAGS Rarely directly referenced. Instead, instructions implicitly set or clear bitfields within the EFLAGS register to represent a certain state. For example, when the result of a mathe Matical operation is zero, the Zero flag is toggled on in the EFLAGS register. The conditional jump instructions make use of the EFLAGS register.
FS 16-bit. Under Win32, the FS register points to a data structure with information pertaining to the current thread. FS is a segment register (segment registers are beyond the scope of this discussion). Intel CPUs have six segment registers, but the Operating system sets the M up and maintains the M. Win32 compilers only need to explicitly refer to the FS segment register, which is used for things like structured exception handling and thread local storage.


Figure 2   InstructionDemo.CPP


 //==========================================
 // Matt Pietrek
 // Microsoft Systems Journal, February 1998
 // Program: InstructionDemo.CPP
 // FILE: InstructionDemo.CPP
 //==========================================
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <stdlib.h>
 #include <stdio.h>
 
 // Force the Se functions inline (/O2 would normally do this
 #pragma intrinsic( memset, strlen, strcmp )
 
 __declspec(thread) int tlsVariable = 0; // Make a thread local variable
 
 int g_myGlobalVariable;                 // Make a global variable
 
 void MySubProcedure( void );
 
 int main( int argc, char *argv[] )
 {
     char szBuffer[128];
     char *pszString = "Hello";
     unsigned long   localUnsignedLong = 2;
     unsigned char   localUnsignedChar = 2;
     long            localSignedLong = 2;
     char            localSignedChar = 2;
     int             i;
 
     g_myGlobalVariable = 0x12345678;        // Assignment to global
             
     localSignedLong = localSignedChar;      // signed type promotion
 
     // Conditional execution    
     if ( localUnsignedLong == 2 )
         localSignedLong = 1;
     else
         localSignedLong = 2;    
 
     // Using TEST
     if ( localUnsignedLong & 0x00040008 )
         i = 3;
 
     // AND'ing off bitfields
     localUnsignedLong &= 0x01020304;
 
     // OR'ing on bitfields  
     localSignedLong |= 0x05060708;
 
     // LOOP code    
     for ( i = 0; i < 4; i++ )
         localUnsignedLong += i;
 
     // Procedure invocation
     printf( "%u %u %08X %s", localUnsignedLong, argc, &argc, szBuffer );
 
     // Using STOSD / STOSB  
     memset( szBuffer, 0, sizeof(szBuffer) );
 
     // Using SCASB
     i = strlen( szBuffer );
 
     MySubProcedure( );
         
     return 0;
 }
 
 void MySubProcedure( void )
 {
     tlsVariable = 2;
     
     // Use of try/except code
     __try
     {
         g_myGlobalVariable = 2;
     }
     __except( EXCEPTION_EXECUTE_HANDLER )
     {
         g_myGlobalVariable = 4; 
     }
 }

Figure 3   InstructionDemo Mixed Source and Assembly


int main( int argc, char *argv[] )
{
401000:    PUSH       EBP
401001:    MOV        EBP,ESP
401003:    SUB        ESP,00000098
401009:    PUSH       EDI
    char *pszString = "Hello";
40100A:    MOV        DWORD PTR [EBP-0000008C],00406030

    unsigned long     localUnsignedLong = 2;
401014:    MOV        DWORD PTR [EBP-00000088],00000002

    unsigned char     localUnsignedChar = 2;
40101E:    MOV        BYTE PTR [EBP-00000094],02

    long              localSignedLong = 2;
401025:    MOV         DWORD PTR [EBP-00000084],00000002

    char              localSignedChar = 2;
40102F:    MOV        BYTE PTR [EBP-00000098],02

    g_myGlobalVariable = 0x12345678;        // Assignment to global
401036:    MOV        DWORD PTR [004088E8],12345678

    localSignedLong = localSignedChar;      // signed type promotion
401040:    MOVSX      EAX,BYTE PTR [EBP-00000098]
401047:    MOV        DWORD PTR [EBP-00000084],EAX

    // Conditional execution    
    if ( localUnsignedLong == 2 )
40104D:    CMP        DWORD PTR [EBP-00000088],02
401054:    JNE        00401062

        localSignedLong = 1;
401056:    MOV        DWORD PTR [EBP-00000084],00000001
    else
401060:    JMP        0040106C

        localSignedLong = 2;    
401062:    MOV        DWORD PTR [EBP-00000084],00000002

    // Using TEST
    if ( localUnsignedLong & 0x00040008 )
40106C:    MOV        ECX,DWORD PTR [EBP-00000088]
401072:    AND        ECX,00040008
401078:    TEST       ECX,ECX
40107A:    JE         00401086

        i = 3;
40107C:    MOV        DWORD PTR [EBP-00000090],00000003

    // AND'ing off bitfields
    localUnsignedLong &= 0x01020304;
401086:    MOV        EDX,DWORD PTR [EBP-00000088]
40108C:    AND        EDX,01020304
401092:    MOV        DWORD PTR [EBP-00000088],EDX

    // OR'ing on bitfields    
    localSignedLong |= 0x05060708;
401098:    MOV        EAX,DWORD PTR [EBP-00000084]
40109E:    OR         EAX,05060708
4010A3:    MOV        DWORD PTR [EBP-00000084],EAX

    // LOOP code    
    for ( i = 0; i < 4; i++ )
4010A9:    MOV        DWORD PTR [EBP-00000090],00000000
4010B3:    JMP        004010C4

4010B5:    MOV        ECX,DWORD PTR [EBP-00000090]
4010BB:    ADD        ECX,01
4010BE:    MOV        DWORD PTR [EBP-00000090],ECX
4010C4:    CMP        DWORD PTR [EBP-00000090],04
4010CB:    JNL        004010E1

        localUnsignedLong += i;
4010CD:    MOV        EDX,DWORD PTR [EBP-00000088]
4010D3:    ADD        EDX,DWORD PTR [EBP-00000090]
4010D9:    MOV        DWORD PTR [EBP-00000088],EDX
4010DF:    JMP        004010B5

    // Procedure invocation
    printf( "%u %u %08X %s", localUnsignedLong, argc, &argc, szBuffer );
4010E1:    LEA        EAX,[EBP-80]
4010E4:    PUSH       EAX
4010E5:    LEA        ECX,[EBP+08]
4010E8:    PUSH       ECX
4010E9:    MOV        EDX,DWORD PTR [EBP+08]
4010EC:    PUSH       EDX
4010ED:    MOV        EAX,DWORD PTR [EBP-00000088]
4010F3:    PUSH       EAX
4010F4:    PUSH       00406038
4010F9:    CALL       004011C0
4010FE:    ADD        ESP,14

    // Using STOSD / STOSB    
    memset( szBuffer, 0, sizeof(szBuffer) );
401101:    MOV        ECX,00000020
401106:    XOR        EAX,EAX
401108:    LEA        EDI,[EBP-80]
40110B:    REP        STOSD

    // Using SCASB
    i = strlen( szBuffer );
40110D:    LEA        EDI,[EBP-80]
401110:    OR         ECX,FF
401113:    XOR        EAX,EAX
401115:    REPNE      SCASB
401117:    NOT        ECX
401119:    ADD        ECX,FF
40111C:    MOV        DWORD PTR [EBP-00000090],ECX

    MySubProcedure( );
401122:    CALL       0040112E

    return 0;
401127:    XOR        EAX,EAX

}
401129:    POP        EDI
40112A:    MOV        ESP,EBP
40112C:    POP        EBP
40112D:    RET

void MySubProcedure( void )
{
40112E:    PUSH       EBP
40112F:    MOV        EBP,ESP
401131:    PUSH       FF
401133:    PUSH       00405058
401138:    PUSH       004012F8
40113D:    MOV        EAX,FS:[00000000]
401143:    PUSH       EAX
401144:    MOV        DWORD PTR FS:[00000000],ESP
40114B:    SUB        ESP,08
40114E:    PUSH       EBX
40114F:    PUSH       ESI
401150:    PUSH       EDI
401151:    MOV        DWORD PTR [EBP-18],ESP

    tlsVariable = 2;
401154:    MOV        EAX,[004088EC]
401159:    MOV        ECX,DWORD PTR FS:[0000002C]
401160:    MOV        EDX,DWORD PTR [ECX+EAX*4]
401163:    MOV        DWORD PTR [EDX+00000004],00000002

    __try
    {
40116D:    MOV        DWORD PTR [EBP-04],00000000

        g_myGlobalVariable = 2;
401174:    MOV        DWORD PTR [004088E8],00000002
40117E:    MOV        DWORD PTR [EBP-04],FFFFFFFF
401185:    JMP        004011A1

    __except( EXCEPTION_EXECUTE_HANDLER )
401187:    MOV        EAX,00000001
40118C:    RET

40118D:    MOV        ESP,DWORD PTR [EBP-18]

        g_myGlobalVariable = 4;    
401190:    MOV        DWORD PTR [004088E8],00000004

    }
40119A:    MOV        DWORD PTR [EBP-04],FFFFFFFF

}
4011A1:    MOV        ECX,DWORD PTR [EBP-10]
4011A4:    MOV        DWORD PTR FS:[00000000],ECX
4011AB:    POP        EDI
4011AC:    POP        ESI
4011AD:    POP        EBX
4011AE:    MOV        ESP,EBP
4011B0:    POP        EBP
4011B1:    RET