For folks that are not familiar with the Intel notation for complex addressing mode, it can look a bit daunting but in fact it is technically simple with only a limited number of variables that effect how it works. This small example shows the basics of complex addressing mode in what I hope is a simple enough to make sense way.
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
FUNCTION PBmain as LONG
#IF 0 ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
there are 4 variable components of Intel addressing notation
------------------------------------------------------------
1. The BASE address
(This is usually a register but can be a displacement)
2. the INDEX
(an array index that is normally ADDED to the base address)
3. the index MULTIPLIER with the range 1 2 4 8
(matches array elements of the same byte size)
4. the DISPLACEMENT in bytes
(added or subtracted from the total address of any of the above if used)
-------------------------------------------------------------------------
Each of these capacities match an instruction built into the processor
that is called an OPCODE. Assembler coding is normally written in what
are called MNEMONICS as this simplifies the vast range of processor opcodes
and makes the code much easier to read and write.
When you try to write something that does not work, its not a syntax error,
it is the case where there is no OPCODE to match what you are trying to do.
The ASSEMBLER will normally detect these problems if there is no valid OPCODE
to match what is written.
EXAMPLES
mov eax, pByteData ; load the ADDRESS of BYTE data into EAX
mov ecx, [eax] ; copy the base address in EAX ([eax]) into the ECX register
mov ecx, 2 ; use ECX as an INDEX
mov edx, lpData ; load the data address into EDX
mov eax, [edx+ecx] ; ADD the INDEX in ECX to the BASE ADDRESS in EDX & copy to EAX
mov ecx, 4 ; use ECX as the INDEX
mov edx, pArray ; load the ADDRESS of a DWORD sized array
mov eax, [edx+ecx*4] ; mul the index by 4 and add it to EDX then copy result to EAX
mov ecx, 4 ; use ECX as the INDEX
mov edx, pArray ; load the ADDRESS of a DWORD sized array
mov eax, [edx+ecx*4-16] ; change the ADDRESS with a displacement (in bytes).
If the array is 16 bit (WORD sized) use a multiplier of 2
If the array is 64 bit (QUAD sized) use a multiplier of 8
#ENDIF ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
#REGISTER NONE
LOCAL aptr as DWORD ' the ARRAY POINTER
LOCAL vshow as DWORD ' variable for DISPLAY
dim arr(8) as DWORD
arr(0) = 0
arr(1) = 1
arr(2) = 2
arr(3) = 3
arr(4) = 4
arr(5) = 5
arr(6) = 6
arr(7) = 7
arr(8) = 8
aptr = VarPtr(arr(0)) ' get the ADDRESS of the first array member
! mov eax, aptr ; load it into a register
! mov eax, [eax] ; get its content by dereferencing it
! mov vshow, eax ; store the result in a variable
msgbox format$(vshow) ' display the result
! mov eax, aptr ; load it into a register
! mov ecx, 3 ; use ECX as an array index
! mov eax, [eax+ecx*4] ; change the address by changing the INDEX
! mov vshow, eax ; store the result in a variable
msgbox format$(vshow) ' display the result
! mov eax, aptr ; load it into a register
! mov ecx, 6 ; use ECX as an array index
! mov eax, [eax+24] ; change the address by changing the DISPLACEMENT (add 24 bytes)
! mov vshow, eax ; store the result in a variable
msgbox format$(vshow) ' display the result
! mov eax, aptr ; load it into a register
! mov ecx, 3 ; use ECX as an array index
! mov eax, [eax+ecx*4-4] ; change the address by changing the INDEX and DISPLACEMENT
! mov vshow, eax ; store the result in a variable
msgbox format$(vshow) ' display the result
erase arr()
End FUNCTION
' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤