I'm trying to learn how to pass and access values by reference in MASM.
I wrote a simple program that will display val1
and val2
using the Irvine.inc library.
INCLUDE Irvine32.inc
.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCall: DWORD
.data ;date values
array DWORD 100, 100, 200
val1 DWORD 50
val2 DWORD 6000
charVal BYTE 'x', 0
.code ;Code
main PROC
mov eax, val1 ;this is a test to see if it works properly.
call WriteDec ;writes eax in Decimal form to the console
push OFFSET val1 ;push two values by reference onto the stack
push OFFSET val2
call PrintNum
INVOKE ExitProcess, 0
main ENDP
PrintNum PROC
push ebp ;save ebp so we can go back to the program
mov ebp, esp ;esp should point to the top of the stack
pushad ;why do we need to do this?
mov eax, 0 ;zero out eax because I though that might be the problem
mov eax, [ebp+12] ;this should move what is in the value of ebp+12 into eax (val1)
call WriteDec ;this writes what is in eax to the console
mov eax, [ebp+8] ;this should move what is in the value of ebp+8 into eax (val2)
call WriteDec ;this writes what is in eax to the console
pop ebp ;get back to correct ebp section of the code
popad ;needed to do this because pushad from before
ret
PrintNum ENDP
End main
The program isn't writing out the value in the address. What am I doing wrong?
After taking into account what @Jester said. My code works with the added mov eax, [eax]
.
I have now tried to do it again in a different test program and it works without mov eax, [eax]
. What is the difference here?
.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCall: DWORD
.data ;date values
val1 DWORD 200
val2 DWORD 100
.code ;Code
main PROC
push val1 ;needed to add the offset not the value
push val2 ;needed to add the offset not the value
call PrintVars
INVOKE ExitProcess, 0
main ENDP
PrintVars PROC
push ebp
mov ebp, esp
mov eax, [ebp+12] ;mov address of val1 into eax
;mov eax, [eax] ;use address to get actual value
call WriteDec ;write the dec to the console
call Crlf ;carage return
mov eax, [ebp+8] ;mov address of val2 into eax
;mov eax, [eax] ;deference address to actual value
call WriteDec ;write the dec to console
call Crlf ;carage return
pop ebp
ret
PrintVars ENDP
End main
Because you are using MASM, an instruction like push OFFSET val1
pushes the address of the label val1, and an instruction like push val1
pushes the value that is stored at the address val1.
In NASM, an instruction like push val1
would push the address of the label val1, and an instruction like push dword [val1]
would push the value that is stored at the address val1.
In the first program, where you pushed the address of the label, your PrintNum proc will have to dereference since you want the value that is stored at the address so you can print it.
push OFFSET val1 ; Push two values by reference onto the stack
push OFFSET val2
call PrintNum
...
PrintNum PROC
mov eax, [esp+8] ; OFFSET val1
mov eax, [eax] ; Get value stored at val1
call WriteDec
mov eax, [esp+4] ; OFFSET val2
mov eax, [eax] ; Get value stored at val2
call WriteDec
ret
In the second program, where you pushed the value that is stored at the address of the label, your PrintVars proc no longer needs to dereference as you already have the value itself.
push val1 ; Push two values by value onto the stack
push val2
call PrintVars
...
PrintVars PROC
mov eax, [esp+8] ; Value stored at val1
call WriteDec
mov eax, [esp+4] ; Value stored at val2
call WriteDec
ret