News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

confusion about function calls in GoAsm

Started by garyhess, November 10, 2012, 04:47:58 AM

Previous topic - Next topic

garyhess

I'm trying to build a function but I'm getting an unexpected result. Here's the data definition and function call:


.Data
bigNum1 DD 100H Dup 0
numDoubleWords DD 2

.Code
Invoke getSumBigNumDigits, Addr bigNum1, Addr numDoubleWords


The function looks like this:


getSumBigNumDigits Frame bigNum1, numDoubleWords

Mov Eax, [numDoubleWords]

.DEBUGGING_BREAK_1

Ret
EndF


I'm looking at this in the debugger. I would expect that Eax = 2 at .DEBUGGING_BREAK_1. However, Eax = 4B7962, which is the ADDRESS of numDoubleWords (instead of the value).

Can anyone help with an explanation of how this works? How can I get "Mov Eax, [numDoubleWords]" to work in the normal way?

Thanks!
Gary

MichaelW

The problem is not in your MOV EAX statement, it's in your invoke statement where you're passing the address of numDoubleWords instead of the value of numDoubleWords.
Well Microsoft, here's another nice mess you've gotten us into.

garyhess

I'm passing the address, but I want to use the address to access the variable's value like this:

Mov Eax, [numDoubleWords]

Is there a way to do that inside the function? I found a work-around in another function I built, but I want to do it more cleanly here.

(The same code works correctly OUTSIDE of the function, but the behavior changes INSIDE the function.)

dedndave

try this...
        mov     edx,[numDoubleWords]       ;EDX = address pointed to by numDoubleWords
        mov     eax,[edx]                  ;EAX = value at that address


it's faster if you can stick some unrelated instruction(s) in between
as the MOV EAX,[EDX] is dependant on the MOV EDX,address being completed

one advantage is - if you can retain the address, you can use it again later in the routine   :P

Yuri

Quote from: garyhess on November 10, 2012, 04:47:58 AM
Can anyone help with an explanation of how this works? How can I get "Mov Eax, [numDoubleWords]" to work in the normal way?
It does work the normal way. You pass a pointer and you get a pointer. Then you use it to read the actual value, just as dedndave suggested.
The global variable numDoubleWords and the function parameter numDoubleWords are two different entities. The first contains 2 and the second its address. Inside the function, this name refers to the parameter, not the global variable.

MichaelW

Quote from: garyhess on November 10, 2012, 06:38:19 AM
(The same code works correctly OUTSIDE of the function, but the behavior changes INSIDE the function.)

As Yuri pointed out, inside the function [numDoubleWords] specifies the function parameter and outside the function it specifies the global variable. So even though the source statements are the same they access two different memory operands: the address that Invoke stored on the stack inside the function, and the contents of the global outside the function.

.Data
    bigNum1 DD 100H Dup 0
    numDoubleWords DD 2
.Code

getSumBigNumDigits Frame bigNum1, numDoubleWords

    Nop
    Nop
    Nop

    Mov Eax, [numDoubleWords]
    Push eax
    Invoke printf, "EAX inside function  : %Xh%c", eax, 10
    Add esp, 12
    Pop eax
    Invoke printf, "[EAX] inside function: %Xh%c", [eax], 10
    Add esp, 12

    Ret
EndF

START:

    Invoke printf, "Address of global    : %Xh%c", ADDR numDoubleWords, 10
    Add esp, 12

    Mov Eax, [numDoubleWords]
    Invoke printf, "EAX outside function : %Xh%c", eax, 10
    Add esp, 12

    Nop
    Nop
    Nop

    Invoke getSumBigNumDigits, Addr bigNum1, Addr numDoubleWords
    Call _getch

Ret


00401000                    fn_00401000:
00401000 55                     push    ebp
00401001 89E5                   mov     ebp,esp
00401003 90                     nop
00401004 90                     nop
00401005 90                     nop
00401006 8B450C                 mov     eax,[ebp+0Ch]
00401009 50                     push    eax
0040100A 6A0A                   push    0Ah
0040100C 50                     push    eax
0040100D 6804244000             push    402404h
00401012 E8E91F0000             call    fn_00403000
00401017 83C40C                 add     esp,0Ch
0040101A 58                     pop     eax
0040101B 6A0A                   push    0Ah
0040101D FF30                   push    dword ptr [eax]
0040101F 6821244000             push    402421h
00401024 E8D71F0000             call    fn_00403000
00401029 83C40C                 add     esp,0Ch
0040102C 5D                     pop     ebp
0040102D C20800                 ret     8
00401030                    start:
00401030 6A0A                   push    0Ah
00401032 6800244000             push    402400h
00401037 683E244000             push    40243Eh
0040103C E8BF1F0000             call    fn_00403000
00401041 83C40C                 add     esp,0Ch
00401044 A100244000             mov     eax,[402400h]
00401049 6A0A                   push    0Ah
0040104B 50                     push    eax
0040104C 685B244000             push    40245Bh
00401051 E8AA1F0000             call    fn_00403000
00401056 83C40C                 add     esp,0Ch
00401059 90                     nop
0040105A 90                     nop
0040105B 90                     nop
0040105C 6800244000             push    402400h
00401061 6800204000             push    402000h
00401066 E895FFFFFF             call    fn_00401000
0040106B E8961F0000             call    fn_00403006
00401070 C3                     ret


Address of global    : 402400h
EAX outside function : 2h
EAX inside function  : 402400h
[EAX] inside function: 2h


For information on memory operands see chapter 3 of the MASM Programmer's Guide, available as a CHM here.

BTW, the printf and _getch calls require that you link with msvcrt.dll (assuming that it is not included automatically).
Well Microsoft, here's another nice mess you've gotten us into.

garyhess

Thanks again. I downloaded the MASM Programmer's Guide and there's a lot of useful info there.

I thought there might be some way to make the variable names work the same inside and outside the function, but now I understand why that's not possible. I renamed them as follows to make it clear they are pointers (after studying Donkey's string library):

getSumBigNumDigits Frame pBigNum1, pNumDoubleWords

Then I created a local version of the DD variable and also loaded the array pointer (pBigNum1) into a register.


Local numDoubleWords

Mov Edx, [pNumDoubleWords]        ; Edx = address pointed to by pNumDoubleWords
Mov Eax, [Edx]                  ; Eax = value at that address
Mov [numDoubleWords], Eax
Mov Esi, [pBigNum1] ; Esi = pointer to big number



That worked OK, I just had to rewrite the code a bit.

I had created another function a few weeks ago that was recursive and found this nomenclature to be disturbing since the original call and the recursive call looked a lot different (despite doing the same thing).

dedndave

masm and goasm use different syntax
not sure the masm users manual is going to be all that helpful
or - maybe you are posting in the wrong subforum   :P

MichaelW

Quote from: dedndave on November 11, 2012, 11:42:28 AM
masm and goasm use different syntax
not sure the masm users manual is going to be all that helpful

The syntax is somewhat different, but the instructions, addressing modes, etc are the same.

Well Microsoft, here's another nice mess you've gotten us into.