assemblyreferencex86masm

Getting the wrong value when I try and pass an argument by refference in MASM ([assembly][x86])


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

Solution

  • 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.

    Program 1

    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
    

    Program 2

    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