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
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.
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.)
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
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.
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 (http://www.masmforum.com/board/index.php?topic=5433.msg40530#msg40530).
BTW, the printf and _getch calls require that you link with msvcrt.dll (assuming that it is not included automatically).
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).
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
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.