An important distinction in assembler is the difference between the address of a variable and the value of a variable. The address of a variable is where it is located in memory; the value of a variable is what is stored at that address.
This is the ADDRESS of the variable in memory:
This is the VALUE at that address:
The method used in assembler to get the value at an address is a technique called dereferencing.
! MOV EAX, lpvar ; Copy address into EAX
! MOV EAX, [EAX] ; Dereference it
! MOV nuvar, EAX ; Copy EAX into new variable
Using square brackets around EAX gives access to the information at the address in EAX. This is the case with any 32-bit register. A register enclosed in square brackets is effectively a memory operand. The size of the data accessed at the address is determined by the size of the register used to receive it. In the above example, it would be a 32-bit value since it uses a 32 bit register for the destination operand. Naturally, it can be done with 8 and 16-bit values as well using the correct size register.
Pointers are a useful high-level language abstraction for passing addresses between procedures and performing other types of complex data manipulation.
In assembler, when you use an instruction like:
! LEA EAX, MyVar
…you have put the address of a variable into the EAX register. When you take the next step and put that address into a variable of its own, you will have a POINTER to the address:
! LEA EAX, MyVar
! MOV lpMyVar, EAX
The mechanics of this process are worth understanding as it can generate errors that are hard to track down when the technique is used incorrectly.
You can pass a pointer to another procedure either by its value:
! MOV EAX, lpMyVar ; Copy the value into EAX
! PUSH EAX ; Push it as a parameter
! CALL MyProcedure ; Call the procedure
…or you can pass it by reference:
! LEA EAX, lpMyVar ; Load the address into EAX
! PUSH EAX ; Push it as a parameter
! CALL MyProcedure ; Call the procedure
When you pass an address in this manner, you have added an extra level of indirection so at the procedure end, you have a reference to a reference to an address. To get the address in the procedure, you need to dereference the variable to get back the original address:
! MOV EAX, lpMyVar
! MOV EAX, [EAX]
The original address is now stored in EAX.
See Also