News:

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

Some oddities with a struct and a local var

Started by cobold, March 20, 2010, 08:17:20 PM

Previous topic - Next topic

cobold

Hello to everyone,

a simple program gives me some trouble. Usually I try to find out what's wrong by myself, but I'm stuck for some hours so please could someone have a look at this and help me?

Probem 1
I'm passing the value of GetTickCount and the address of a structure (UPTIME) to a PROC.

  • inside the PROC the values that I move to the structure are correct, outside the PROC they are all ZERO
  • after the call, the variable 'ms" has a changed value, and I'm asking myself why this happens, because it is a LOCAL var in main

Problem 2
mov LZ[0], days up to LZ[8], minutes  - everything works fine, BUT
for some reason
mov LZ[12], seconds - causes an exception and the funny thing is that
mov LZ[16], millis - works.

For gods sake! What am I doing wrong? What an idiot I am.


INCLUDE \masm32\include\masm32rt.inc

RunTime PROTO :DWORD, :DWORD    ;1st parameter VALUE milliseconds
                                ;2nd parameter ADDRESS of UPTIME struc
; -------------------------------------------------------------------------
    UPTIME STRUCT     ; SIZE = 5 dwords = 20 bytes
        ttt DWORD ?     ; stLZ[0]
        hhh DWORD ?     ; stLZ[4]
        mmm DWORD ?     ; stLZ[8]
        sss DWORD ?     ; stLZ[12]
        mss DWORD ?     ; stLZ[16]
    UPTIME ENDS
; -------------------------------------------------------------------------
.DATA?
    stLZ    UPTIME <?,?,?,?,?>    ; would <?> be acceptable?
; -------------------------------------------------------------------------
.CODE
start:
    call main
    inkey
    invoke ExitProcess,0

main PROC
    LOCAL ms    :DWORD

    call GetTickCount
    mov ms,eax

    print chr$(13,10)
    print "ms BEFORE call: "        ; BEFORE the call ms has correct value
    print str$(ms),13,10,13,10
   
    invoke RunTime,ms,OFFSET stLZ   ; or ADDR, does not matter, always fails
   
    print "ms AFTER  call: "        ; AFTER the call ms has changed
    print str$(ms),13,10            ; WHY, it's local to main and the proc
                                    ; only receives the value of ms
                                   
; AFTER the call all values are zero
; but in the proc the values are correct
    print str$(stLZ.ttt), " days "
    print str$(stLZ.hhh), " hours "
    print str$(stLZ.mmm), " minutes "
    print str$(stLZ.sss), ","
    print str$(stLZ.mss), " seconds.",13,10

    ret
main ENDP
; -------------------------------------------------------------------------
RunTime proc ms:DWORD, LZ:DWORD

    xor edx,edx
    mov eax,ms
    mov ebx,86400000        ; Tage = ms\86400000
    div ebx
    mov LZ[0],eax      ; ttt
    pushad
    print chr$(9)
    print " in proc days: "
    print str$(LZ[0]),32
    popad

    mov eax,edx
    xor edx,edx
    mov ebx,3600000
    div ebx
    mov LZ[4],eax      ; hhh
    pushad
    print " hrs: "
    print str$(LZ[4]),32
    popad

    mov eax,edx
    xor edx,edx
    mov ebx,60000
    div ebx
    mov LZ[8],eax      ; mmm
    pushad
    print " min: "
    print str$(LZ[8]),32
    popad

    mov eax,edx
    xor edx,edx
    mov ebx,1000
    div ebx
    ;mov LZ[12],eax     ; !!!! fails, why !!!
    mov LZ[16],edx      ; does not fail, why can I refer to LZ[16] the 5th DWORD
                        ; and NOT to LZ[12] the 4th DWORD, the seconds ?
    pushad
    print " sec.msec "
    print str$(LZ[16]),13,10
    popad
       
    ret
RunTime endp
end start


Output
C:\Asm>uptime

ms BEFORE call: 7522656

         in proc days: 0  hrs: 2  min: 5  sec.msec 656
ms AFTER  call: 2
0 days 0 hours 0 minutes 0,0 seconds.
Press any key to continue ...


Thanks a lot for ANY help.

rgds

qWord

hi,
look at this:
RunTime proc uses esi ebx ms:DWORD, pLZ: ptr UPTIME
    mov esi,pLZ
    assume esi:ptr UPTIME
   
    xor edx,edx
    mov eax,ms
    mov ebx,86400000        ; Tage = ms\86400000
    div ebx
    mov [esi].ttt,eax       ; ttt
...
RunTime endp
FPU in a trice: SmplMath
It's that simple!

MichaelW

cobold,

To access a structure through an address, the address must be in a register and the register used as part of an indirect memory operand.  This uses a different syntax that qWord's example, but the end result should be the same:

INCLUDE \masm32\include\masm32rt.inc

RunTime PROTO :DWORD, :DWORD    ;1st parameter VALUE milliseconds
                                ;2nd parameter ADDRESS of UPTIME struc
; -------------------------------------------------------------------------
    UPTIME STRUCT     ; SIZE = 5 dwords = 20 bytes
        ttt DWORD ?     ; stLZ[0]
        hhh DWORD ?     ; stLZ[4]
        mmm DWORD ?     ; stLZ[8]
        sss DWORD ?     ; stLZ[12]
        mss DWORD ?     ; stLZ[16]
    UPTIME ENDS
; -------------------------------------------------------------------------
.DATA?
    stLZ    UPTIME <?,?,?,?,?>    ; would <?> be acceptable?
; -------------------------------------------------------------------------
.CODE
start:
    call main
    inkey
    invoke ExitProcess,0

main PROC
    LOCAL ms    :DWORD

    call GetTickCount
    mov ms,eax

    print chr$(13,10)
    print "ms BEFORE call: "        ; BEFORE the call ms has correct value
    print str$(ms),13,10,13,10

    invoke RunTime,ms,OFFSET stLZ   ; or ADDR, does not matter, always fails

    print "ms AFTER  call: "        ; AFTER the call ms has changed
    print str$(ms),13,10            ; WHY, it's local to main and the proc
                                    ; only receives the value of ms

; AFTER the call all values are zero
; but in the proc the values are correct
    print str$(stLZ.ttt), " days "
    print str$(stLZ.hhh), " hours "
    print str$(stLZ.mmm), " minutes "
    print str$(stLZ.sss), ","
    print str$(stLZ.mss), " seconds.",13,10

    ret
main ENDP
; -------------------------------------------------------------------------
RunTime proc uses ebx esi ms:DWORD, LZ:DWORD

    MOV ESI, LZ

    xor edx,edx
    mov eax,ms
    mov ebx,86400000        ; Tage = ms\86400000
    div ebx

    ;mov LZ[0],eax      ; ttt
    MOV [ESI].UPTIME.ttt, EAX

    pushad
    ;print chr$(9)
    print " in proc days: "

    ;print str$(LZ[0]),32
    print str$([ESI].UPTIME.ttt),32

    popad

    mov eax,edx
    xor edx,edx
    mov ebx,3600000
    div ebx

    ;mov LZ[4],eax      ; hhh
    MOV [ESI].UPTIME.hhh, EAX

    pushad
    print " hrs: "

    ;print str$(LZ[4]),32
    print str$([ESI].UPTIME.hhh),32

    popad

    mov eax,edx
    xor edx,edx
    mov ebx,60000
    div ebx

    ;mov LZ[8],eax      ; mmm
    MOV [ESI].UPTIME.mmm, EAX

    pushad
    print " min: "

    ;print str$(LZ[8]),32
    print str$([ESI].UPTIME.mmm),32

    popad

    mov eax,edx
    xor edx,edx
    mov ebx,1000
    div ebx
    ;mov LZ[12],eax     ; !!!! fails, why !!!
    ;mov LZ[16],edx      ; does not fail, why can I refer to LZ[16] the 5th DWORD
                        ; and NOT to LZ[12] the 4th DWORD, the seconds ?
    MOV [ESI].UPTIME.mss, EAX

    pushad
    print " sec.msec "

    ;print str$(LZ[16]),13,10
    print str$([ESI].UPTIME.mss),32

    popad

    ret
RunTime endp
end start


Also, if you use the other syntax, you need to remove the assume when you have finished using it:

assume esi:NOTHING
eschew obfuscation

jj2007

Alternatively, you can pass the structure itself instead of a pointer to it. However, it will be local... good for reading but useless for writing ;-)
INCLUDE \masm32\include\masm32rt.inc

; -------------------------------------------------------------------------
    UPTIME STRUCT     ; SIZE = 5 dwords = 20 bytes
        ttt DWORD ?     ; stLZ[0]
        hhh DWORD ?     ; stLZ[4]
        mmm DWORD ?     ; stLZ[8]
        sss DWORD ?     ; stLZ[12]
        mss DWORD ?     ; stLZ[16]
    UPTIME ENDS

RunTime PROTO :DWORD, :UPTIME ;1st parameter VALUE milliseconds
                                ;2nd parameter UPTIME struc itself, NOT the address

; -------------------------------------------------------------------------
.DATA?
    stLZ    UPTIME <?,?,?,?,?>    ; would <?> be acceptable?
; -------------------------------------------------------------------------
.CODE
start:
    call main
    inkey
    invoke ExitProcess,0

main PROC
    LOCAL ms    :DWORD

    call GetTickCount
    mov ms,eax

    print chr$(13,10)
    print "ms BEFORE call: "        ; BEFORE the call ms has correct value
    print str$(ms),13,10,13,10
   
    invoke RunTime,ms,stLZ   ; or ADDR, does not matter, always fails
   
    print "ms AFTER  call: "        ; AFTER the call ms has changed
    print str$(ms),13,10            ; WHY, it's local to main and the proc
                                    ; only receives the value of ms
                                   
; AFTER the call all values are zero
; but in the proc the values are correct
    print str$(stLZ.ttt), " days "
    print str$(stLZ.hhh), " hours "
    print str$(stLZ.mmm), " minutes "
    print str$(stLZ.sss), ","
    print str$(stLZ.mss), " seconds.",13,10

    ret
main ENDP
; -------------------------------------------------------------------------
RunTime proc ms:DWORD, LZ:UPTIME

    xor edx,edx
    mov eax,ms
    mov ebx,86400000        ; Tage = ms\86400000
    div ebx
    mov LZ.ttt,eax      ; ttt
    pushad
    print chr$(9)
    print " in proc days: "
    print str$(LZ.ttt),32
    popad

    mov eax,edx
    xor edx,edx
    mov ebx,3600000
    div ebx
    mov LZ.hhh,eax      ; hhh
    pushad
    print " hrs: "
    print str$(LZ.hhh),32
    popad

    mov eax,edx
    xor edx,edx
    mov ebx,60000
    div ebx
    mov LZ.mmm,eax      ; mmm
    pushad
    print " min: "
    print str$(LZ.mmm),32
    popad

    mov eax,edx
    xor edx,edx
    mov ebx,1000
    div ebx
    ;mov LZ[12],eax     ; !!!! fails, why !!!
    mov LZ.sss,edx      ; does not fail, why can I refer to LZ[16] the 5th DWORD
                        ; and NOT to LZ[12] the 4th DWORD, the seconds ?
    pushad
    print " sec.msec "
    print str$(LZ.sss),13,10
    popad
       
    ret
RunTime endp
end start

cobold

Hello,

first of all, a big thank you for everyone who helped me (qWord, MichaelW and jj2007)!
The program is working now but let me resume to see if I have understood everything:

- if I want to pass a structure to a PROC, I have three possibilites:


  • 1. pass the address of the structure (by reference), address must be in a register
    1.a. qWord:
    assume esi:PTR myStruct
    mov [esi].x, eax
    assume esi:nothing


  • 1.b. MichealW:
    mov [esi], ADDR myStruct
    mov [esi].myStruct.x, eax


  • 2. jj2007: pass the structure itself (by value), address must be in a register
    - parameter is myStruct itself
    mov myStruct.x, eax
    - changes are LOCAL to PROC

brgds

cobold

jj2007

Quote from: cobold on March 21, 2010, 10:29:32 AM
  • 2. jj2007: pass the structure itself (by value), address must be in a register
    - parameter is myStruct itself
    mov myStruct.x, eax
    - changes are LOCAL to PROC

The add doesn't have to be in a register. Note that my option is possible but not very efficient, as many paras have to be pushed on the stack.



BogdanOntanu

Quote from: cobold on March 21, 2010, 10:29:32 AM
Hello,

first of all, a big thank you for everyone who helped me (qWord, MichaelW and jj2007)!
The program is working now but let me resume to see if I have understood everything:

- if I want to pass a structure to a PROC, I have three possibilites:


  • 1. pass the address of the structure (by reference), address must be in a register
    1.a. qWord:
    assume esi:PTR myStruct
    mov [esi].x, eax
    assume esi:nothing


  • 1.b. MichealW:
    mov [esi], ADDR myStruct
    mov [esi].myStruct.x, eax


  • 2. jj2007: pass the structure itself (by value), address must be in a register
    - parameter is myStruct itself
    mov myStruct.x, eax
    - changes are LOCAL to PROC

brgds

Well, by your own explanations I think that you are still not fully understanding the problem at hand.

What you need to understand is the essential conceptual difference in between variables and pointers to variables. And you also need to understand the differentce in between global variables and PROC local variables.

BTW. Those are not "oddities" they are basic concepts of ASM and programming in general.

Hints:
1) You say that you have tried ADDR variable and OFFSET and none worked. This is a huge conceptual error.

OFFSET is calculated at compile time and the resulted address is thus fixed for the whole execution time of the application ... while ADDR should refer to the local addrees of a variable in a PROC and it might or might not change at each and every execution of your application.

Hence if you bluntly try to use OFFSET and ADDR "just to see if it works" then it means that you do not have a grasp of what local and global variables are and when and where they are created and how sholuld one use and refer to them.

2) You say that "address should be in resgister" in you own understanding explanations. This is a "rule of thumb" taht is true and kind of practical but too short and concise for somebody that expalins or really understands well what a pointer is.

Pointers are always and by definition hold in a register when dereferenced on x86 architecture. You do need something to point to a variable or a memory location... hence what could "that" be? what else but a register?

For a human that understands this "rule of thumb" that states that a pointer "should be in a register" is obviouse and kind of implicit. There is no other conceptual possible way. Hence I think that you did not understood this either :D

And in order to show that you did NOT understand this I quote again your explanation for jj2007's method of access:
Quote

  • 2. jj2007: pass the structure itself (by value), address must be in a register
    - parameter is myStruct itself
    mov myStruct.x, eax
    - changes are LOCAL to PROC

Exactly NOT true. Here in this case when you MUST NOT have the address in a register. In consequence you did not understood it.

Then the rule of thumb: "changes are LOCAL to PROC"... Well well. This is true for ALL cases when you send values and not pointers.

Then from MichaelW:
Quote
1.b. MichealW:
mov [esi], ADDR myStruct

Exactly NOT true. In fact Michael wrote : "MOV ESI,LZ" ... this is a huge diference.

The best way to say thank you to somebody that tries help you is is to make the effort to understand what they say... not to say or write "thank you".


Let us see it logically:
==================

a) you take the contents of a variable or a structure member (let's say "var_a" located at 0x40_2000h containing the DWORD value 3) and then you transmit this value (aka the number 3) as a parameter to a PROC (this argument is sent as a value on the stack for the STDCALL calling convention)

b) inside the PROC you change this argument's value from 3 to 7. Le's say that this argument is placed on stack at address 0x12_000h. This address is variable and changes with each and every call to your PROC and hence you have no way of knowing it at compile time.

It is now obviouse that all you have changed is the argument that you have placed on the stack for the sole use of the PROC. You have changed the value at 0x12_0000h from 3 to 7... BUT the value at 0x40_2000h is STILL 3 and untouched. In fact the PROC was not informed where in memory is "var_a" located, it was only informed about the content of "var_a"

Obviousely the original contents of the variable located at address 0x40_1000 are unreachable and untouchable since your PROC has no ideea of where the contents placed into it's argument came from... From the point of wiev of the PROC "3" coud have been a simple number and not a variable at all.

Now, WHAT IF you want to directly access variable "var_a" from inside the PROC and have it sent as an argument?.

In this case,  instead of sending the value "3" as an argument on stack at address 0x12_0000h ... you will send the value 0x40_2000h at the same address 0x12_0000h. Do yous ee the difference?  The argument does not contain the value of the variable but the address of the variable.

In order to obtain the value 0x40_2000h you could use the OFFSET operator here because "var_a " is defined into ".data" or ".data?" and it is known at compile time.

Now if you write "7" to the location to the argument you only overwrite what is at 0x12_0000h with "7"; ie you will only destroy the value/number 0x40_2000h stored on stack but you will not touch the original variable loacted at 0x40_2000h. 

OR is you read directly from your argument you will obtain "0x40_2000h" but not the contents of "3".

It is now clear that you need to get the value of the pointer from there into a register. Let say into ESI by doing "MOV ESI, my_pointer_argument".

Now if ESI contains 0x40_2000 you can read and change the value "3" directly: MOV [esi],7 to write or MOV eax,[esi] to read into EAX.

Both will access the original variable at 0x40_2000h. It is said the ESI points to "var_a" because it does contain the addres of that variable and not the contents. And when you access [ESI] you acceess "the memory location that is pointed by ESI" and not the ESI register itself.

Those are "The BASICS" and must be very clearely understood. Everything else is very simple.

For example in your case:
==================
The very same thing would  happen if you nest 2 Procedures like in your example when PROC Main will CALL PROC RUnTime.

Because variable "ms" is local to PROC MAIN you can NOT use the OFFSET operator on it. This address will only be known at RUN-TIME. Hence you MUST use ADDR.

And if you want the contents of a variable to be changed by a lower or deeper level PROC then you must send this argumnent as a pointer to that variable and not as the contents/value of that variable.

There are many variations to this layout and you will never understand them corectly by using a set of "rules of thumb". You must understand the basic concepts of  pointers and local variables and apply them to your specific case .... and then you do not need "the rules" anymore.

When you still need the rules then it means that you have not yet fully understood.



As a side note: ADDR gets translate into a "LEA target,ms" by MASM  ie. into a calculation at run time and inside INVOKE you can get burned if you use EAX as one of the INVOKE arguments ... because an ADDR variable will generate a LEA EAX,variable and PUSH EAX and this changes your EAX silently.



Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

cobold

Hello Bogdan,

I know very well that you are an expert and I am not. I really appreciate your answer. Not only because you took yourself the time to write it, but because you explain things very detailed.

Anyway, you seem to underestimate my skills, f.ex. when you

QuoteAnd in order to show that you did NOT understand this I quote again your explanation for jj2007's method of access:
Quote

    * 2. jj2007: pass the structure itself (by value), address must be in a register
      - parameter is myStruct itself
      mov myStruct.x, eax
      - changes are LOCAL to PROC


Exactly NOT true. Here in this case when you MUST NOT have the address in a register. In consequence you did not understood it.

I agree with you , I copied and pasted this from point 1 (address must be in register) and forgot to delete it. Well, you cannot know this, and as a consequence you think that I am an idiot that does not understand basic concepts. You did not insult, BUT your choice of words is relatively harsh.

Please let me say thank you for your answer, even if you say
QuoteThe best way to say thank you to somebody that tries help you is is to make the effort to understand what they say... not to say or write "thank you".

To make this clear: I really appreciate your posts, your explanations and your proficiency. BUT let ME decide when I say "thank you" or not. You can think of my skills whatever you want, and of course you are free to post your opinion.
On the other hand - what you say is right, BUT your words suggest that I "DO NOT make the effort" to understand. Can you read my mind? Do you know whether I make an effort to understand or not? Obviously you think so. As I said, you must be a mindreader.

Also please excuse my choice of words, because:
QuoteBTW. Those are not "oddities" they are basic concepts of ASM and programming in general.

how can I dare to call something I don't fully understand an "oddity", when in fact I'm a stupid jerk that doesn't even know basic concepts.

You are absolutely right, Bogdan. I should have written
"jerk who doesn't understand basic concepts needs help, but don't expect me to say "thank you" because that's superfluous"

For sure, I'm an inferior programmer, but at least I have some manners.

best regards

the cobold

cobold

Mr. God, dear Bogdan,

I'm an austrian, and my english is far from being perfect.
But now let me show you, Mr. PERFECT BOGDAN, your mistakes in the english language:

QuoteWhat you need to understand is the essential conceptual difference in between variables and pointers to variables. And you also need to understand the differentce in between global variables and PROC local variables.

What I need to understand is the essential difference between variables and pointers... and NOT "in betweeen" as you wrote.
But I can help you:
You either know the difference between a or b OR
a is "between" a or b
The best way to thank me is not writing "thank you", but try to understand what is wrong in YOUR sentence!
Because it tells me that you "don't have FULLY understood the english grammar"

QuotePointers are always and by definition hold in a register
.. HELD in a register.. the passive form, if you are willing to understand but this tells me:
QuoteWell, by your own explanations I think that you are still not fully understanding the problem at hand.


Well, to tell you something funny: Let the native speakers in this forum correct us. The problem at hand is that we are all going to die - BOGDAN - sooner or later; and I don't give a damn, whether it's sooner or later!

I'm sick and I have to die, but you don't have to tell me what's "logical" or true or not!!

I'm sorry, but if you want to humble me --> as long as I can speak --> object it


may yr life b longer!


the cobold



hutch--

Come on guys, you have to watch us native English speakers, we butcher the language in ways you would not approve of. Still, a detailed answer is more use to you than a simple generalised one but always allow that there can be collective and minor language and cultural differences filtered back and forth through English where the best we native English speakers can do is see the variations on the way past.

Now look at it on the bright side, if you had to filter communications through the dialect of English that we speak here in OZ there really would be a mismatch of intent in both directions.  :bg
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

BogdanOntanu

#10
Quote from: cobold on March 22, 2010, 03:55:45 AM
Mr. God, dear Bogdan,

I'm an austrian, and my english is far from being perfect.
But now let me show you, Mr. PERFECT BOGDAN, your mistakes in the english language:
...

Cobold, Please excuse for my grammar and orthographic mistakes in my posts. I do assure you that I do know how to write correctly in English but when I was writting that post I was in a hurry. Mea culpa.

For this mistake I ask forgiveness and I really hope that you have been able to understand the concepts and the overall message despite my grammar and orthography mistakes.

Please note that I fluently speak English, French, German, Italian and Spanish and because I know so many languages lately I am less carefully when I write then when I speak. It is true that when I started learning foregin languages I used to pay more attention to grammar. I will try to improve in the future.

Quote
I'm sorry, but if you want to humble me --> as long as I can speak --> object it

It was not my intention to "humble you". Please excuse if my English mistakes make it look that way.

My intention was only to point out some conceptual mistakes and obvious missunderstandings in your statements.

When I speak "relatively harsh" it does not mean that I consider myself superior to you. Instead I am simply honest and offering suggestions.  I do consider that honesty and attempting to help by clearly speaking my mind is more usefull than being extra polite.

It is my personal style of teaching. Please excuse if it got you offendend, it was not my intention.

Also please note that I have never said or written the bad words that you say about yourself. They are only in your mind. Such words or thoughts about you have never been in my mind.

Quote
I'm sick and I have to die, but you don't have to tell me what's "logical" or true or not!!

I am sorry to hear that. Apparently we all have to die sooner or later. But as long as we are talking ASM  in here then I guess that we can put our personal medical issues aside and concentrate on the technical ASM issues that we can eventually solve, teach or improve here...
Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro

japheth

Quote from: BogdanOntanu on March 21, 2010, 03:15:35 PM
As a side note: ADDR gets translate into a "LEA target,ms" by MASM  ie. into a calculation at run time and inside INVOKE you can get burned if you use EAX as one of the INVOKE arguments ... because an ADDR variable will generate a LEA EAX,variable and PUSH EAX and this changes your EAX silently.

Usually not silently - a warning is displayed: "register value overwritten by INVOKE"

So it's only a problem if the callee expects EAX to contain a parameter value - which is rather unusual.

jj2007

Quote from: japheth on March 22, 2010, 02:26:59 PM

Usually not silently - a warning is displayed: "register value overwritten by INVOKE"


Actually, both Masm and JWasm throw an error, not a warning.

include \masm32\include\masm32rt.inc

.data
AppName db "Masm32 is great!", 0

.code

start:
call MyTest
exit

MyTest proc
LOCAL locbuf[260]:BYTE
  mov eax, offset AppName
  invoke lstrcpy, addr locbuf, eax ; OK, lea eax, locbuf comes after push eax
  MsgBox 0, addr locbuf, "Test", MB_OK
  mov eax, offset AppName
  invoke lstrcpy, eax, addr locbuf ; error A2133:register value overwritten by INVOKE
  ret
MyTest endp

end start

cobold

Bogdan,

QuoteCobold, Please excuse for my grammar and orthographic mistakes in my posts. I do assure you that I do know how to write correctly in English but when I was writting that post I was in a hurry. Mea culpa.
I'm sorry that I have critized your grammar, because it has nothing to do with my original question. I just felt "insulted" somehow, so I wrote that.

QuoteInstead I am simply honest and offering suggestions.  I do consider that honesty and attempting to help by clearly speaking my mind is more usefull than being extra polite.
Ironically, I prefer that too. Thanks for your post and let's forget this issue!

BogdanOntanu

Quote from: japheth on March 22, 2010, 02:26:59 PM
...
Usually not silently - a warning is displayed: "register value overwritten by INVOKE"

So it's only a problem if the callee expects EAX to contain a parameter value - which is rather unusual.


Yes Japeth, you are correct. My mistake. I think I might be wrongly remembering this kind of ADRR/INVOKE problem from an earlyer version of MASM or maybe from TASM.

Anyway I do hope that it is good to know that in the context of an INVOKE the "ADDR argument" kind of statement is translated into a "LEA EAX,argument" and "PUSH EAX"  sequence.
Ambition is a lame excuse for the ones not brave enough to be lazy.
http://www.oby.ro