News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Question about pointer passing

Started by Kyoy, March 11, 2006, 08:30:47 AM

Previous topic - Next topic

Kyoy

I am confused with an example in hutch's help file.


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 and you have a POINTER to the address.

mov lpMyVar, eax

The mechanics of this process are worth understanding as it can generate errors that are hard to track down. 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


The following points confused me.  I could follow everything but i don't understand the part about calling MyProcedure. Can someone explain what it means and why hutch is doing that? Also, what is the difference between the 2 examples. mov eax, lpMyVar and lea eax, lpMyVar    seem to be the same thing in this case ...

asmfan

mov eax, X  ;copy the value of X to eax. Or eax=X
lea eax, X  ;load effective address of X to eax. Or eax=&X in C.
Russia is a weird place

hutch--

Kyoy,

Its the difference between WHERE a variable is in memory and WHAT is its value. WHERE is the address of the variable is usually a large number depending on what the address is where the VALUE of the variable can be anything within its possible range.

With assembler code you can either pass a direct VALUE or you pass the ADDRESS of that value.

Now what the example does is get an address from a register and stores it in another variable that is called a POINTER because it points at the value in memory. Keep in mind that a register is usually transient where a memory value does not change unless you change it.

Use this idea to follow the example. Get an ADDRESS of something in the EAX register using the LEA instruction, it means LOAD EFFECTIVE ADDRESS. Then copy that address in the register to another variable that we call a pointer.

Once you have the pointer you can then pass the POINTER by value to another procedure or API that requires an ADDRESS by using PUSH and then CALL the procedure.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

donkey

Hi kyoy,

There are two different ways (normally) to store data, Static and Dynamic. Static memory is stored with a fixed address and is usually decalred in your .DATA or .DATA? section in MASM. Dynamic data is stored on the stack and the address is transient depending on the value of the stack pointer (ESP) at the time it is stored. So for Static data the assembler already knows at compile time what the address is going to be and you can use MOV EAX,OFFSET Data because "OFFSET Data" will resolve to an immediate number representing the address of the data. However, it is not possible to know at compile time the value of the stack pointer (ESP), things are being pushed and popped all the time by your program so this is considered a "runtime" address and it has to be calculated at run time. Because of this you cannot use MOV since the assembler cannot calculate the actual address. To make up for this there is the LEA instruction, that even though it means Load Effective Address, it is closer to a math function, it will perform simple arithmetic on the operand you pass it. For example a stack based label like...

LOCAL Data :DWORD

could resolve to Data equ ESP-16, so when the assembler sees the label data it replaces it with ESP-16. If you tried to MOV that label into a register you would end up with MOV EAX,ESP-16 which is an invalid use of that mnemonic so you use LEA...

LEA EAX, Data would resolve to LEA EAX,[ESP-16] and the value 16 would be subtracted from the current value of ESP and moved into the EAX register giving you the "effective address".

Hope this helps.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Kyoy

Thanks i understand the part about the lea and mov. I will still try to avoid using lea (unless i am doing something mathematical like [lea eax,4*eax+eax]) though as i read that its alot slower than mov.

I will still like to understand more clearly what happens at the point when you push eax and call MyProcedure. When the address @ lpMyVar is loaded into eax and pushed onto the stack .... how does that relate to calling another procedure.

Anyway thanks for the help.




   

donkey

The sequence of events for a CALL instruction are fairly straight forward, the program will push parameters onto the stack that will be used by the procedure (or FRAME) as LOCAL parameters. Once all of the parameters are pushed the processor executes a CALL instructions which is in essence a PUSH/JMP that is it pushes the return address onto the stack and then JMPs to the address of the routine. Once the procedure starts it will usually save the value of EBP (Stack base pointer) and set it to the value of ESP (top of stack) and use that to reference the parameters that were pushed prior to the call, for example the last parameter pushed is usually EBP+4 (EBP=Return address) note that these offsets from EBP may vary depending on register preservation etc.. . Once the RET instruction is reached the assemlber will usually restore EBP/ESP to their values on entry and execute a RET which is a POP/JMP/ADD that is it pops the return address off the stack and JMPs to that address and adds the operand to the stack pointer (ESP). The modification of ESP will set the stack pointer to it's value just before the first parameter was pushed, leaving the stack in a balanced state, this is for STDCALL, in C call convention there is no adjustment of ESP, it is up to you (or your assembler) to do that.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable