News:

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

INVOKE and ADDR directives

Started by guro, April 06, 2011, 11:14:46 AM

Previous topic - Next topic

guro

So: is it possible not to use the ADDR directive explicitly in MASM but use the other mechanism (manually) that donkey proposed with EBP register?
Is it possible to select the register that INVOKE will use in case of an ADDR var argument to resolve its address?

donkey

No, you cannot select a register, EAX is always used. In MASM it is far too much work for the advantage gained to use the PUSH EBP method instead of the standard INVOKE implementation. The example just demonstrated a "better" way of getting the offset of a local variable, however using it would make your code unreadable and difficult to debug, it is meant to be implemented at the compiler level. It was mainly in response to Redskull's comment (shamelessly taken out of context):

Quoteand you must manually use the LEA instruction to calculate it
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jj2007

Quote from: donkey on April 06, 2011, 02:21:07 PM
So a more transparent way is to use the following:

; First DWORD local
push ebp
add DWORD PTR [esp],-4
call function


Feasible but one byte longer, Edgar. And adding/subtracting to a memory location is slow.
As long as it throws that overwrite error, I can live with trashing eax.

clive

The other thing to remember with the standard ABI is that EAX can be destroyed by the called subroutine and is assumed to contain the return value afterwards. Using it as a scratch register should not be an issue.

If you want better (finer/explicit) register level management, you have to do it manually, which is what we all did before INVOKE existed.
It could be a random act of randomness. Those happen a lot as well.

donkey

Quote from: jj2007 on April 06, 2011, 03:58:03 PM
Feasible but one byte longer, Edgar. And adding/subtracting to a memory location is slow.
As long as it throws that overwrite error, I can live with trashing eax.

Its pretty much up to the individual, I don't agree with trashing registers for no good reason and extra overhead of a single byte still falls within a cache line so there is no second fetch.

Jochen you must be joking, any extra execution time is a non-issue, if you're worried about an extra cycle or two of execution time the function should have been in-lined and not a separate procedure which adds quite a bit of overhead.

Quote from: clive on April 06, 2011, 04:08:44 PM
The other thing to remember with the standard ABI is that EAX can be destroyed by the called subroutine and is assumed to contain the return value afterwards. Using it as a scratch register should not be an issue.

If you want better (finer/explicit) register level management, you have to do it manually, which is what we all did before INVOKE existed.

I have said that this was meant for compiler level implementation and was just to point out another way aside from LEA.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

jj2007

Quote from: donkey on April 06, 2011, 04:14:39 PM
Jochen you must be joking, any extra execution time is a non-issue, if you're worried about an extra cycle or two...
I have said that this was meant for compiler level implementation and was just to point out another way aside from LEA.

It is one extra cycle (I timed it :bg) and one extra byte, for no compelling reason except if you need eax as input to the subroutine.
By the way, for a long time we haven't had a proper war on register destruction and the like. Ready to go?

:wink  :thumbu

donkey

Quote from: jj2007 on April 06, 2011, 07:15:22 PM
By the way, for a long time we haven't had a proper war on register destruction and the like. Ready to go?

:wink  :thumbu

If you look through that thread I didn't get involved then and am not likely to get involved now. But it would be a boring war.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

MichaelW

Quote from: donkey on April 06, 2011, 02:40:46 PM
Offset gives a segment relative offset, it has nothing to do with the start address of the executable. In the FLAT programming model it is the offset from 0.

Offset returns the value of the location counter for the segment. By default the location counter is set to 0 at the start of the segment, but within limits you can use the ORG directive to change it, at the start of the segment or elsewhere in the segment.
eschew obfuscation

donkey

Quote from: MichaelW on April 06, 2011, 09:10:13 PM
Quote from: donkey on April 06, 2011, 02:40:46 PM
Offset gives a segment relative offset, it has nothing to do with the start address of the executable. In the FLAT programming model it is the offset from 0.

Offset returns the value of the location counter for the segment. By default the location counter is set to 0 at the start of the segment, but within limits you can use the ORG directive to change it, at the start of the segment or elsewhere in the segment.



Well, there are any number of hacks you can do but most don't
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

hutch--

Lets not confuse things here, an executable file is loaded by the OS at 400000h (its hInstance) while a DLL also loaded into the running process has its load address (DLL hInstance) relocated by the OS loader unless its set to load at a specific address. The important factor here is that in a protected mode operating system each application is loaded into its own memory space with each running application (and DLLs) using the same range of addressing. (A hInstance returned by GetModuleHandle()) is the same 400000h as the next running application's hInstance. The difference is the OS provides the memory space for each application with the same addressing range.

Now you can use the terminology of calling section addresses RVAs but in terms of a running application (including its DLLs [ not system DLLs] ) you have an instant GP fault by addressing below 400000h so in application terms the load address is the effective reference for an OFFSET within the applications addressable space.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

donkey

Quote from: hutch-- on April 07, 2011, 02:23:48 AM
Now you can use the terminology of calling section addresses RVAs but in terms of a running application (including its DLLs [ not system DLLs] ) you have an instant GP fault by addressing below 400000h so in application terms the load address is the effective reference for an OFFSET within the applications addressable space.

No it isn't, the value in the segment register is the reference for OFFSET, the load address is nothing more than the load address and has nothing at all to do with the OFFSET operator. You might as well say that short jumps, which are relative to EIP are referenced from the load address under that logic.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

hutch--

You are confusing absolute addressing that does not exist in ring3 user mode with addressing relative to the provided memory space from the operating system. Your only reference to segment registers under FLAT memory model is they are set to the same value.

With MASM the operator OFFSET is specifically a "distance" from a reference point, not an absolute address, you truly would have enjoyed the bad old days with Win3.? where you did not have hardware provided protected mode and had to rely on everyone else not making a mess of memory allocation. You are also confusing the current location in CODE with an ADDRESS that is an OFFSET, EIP is dynamic, OFFSET is STATIC and they refer to different targets.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

donkey

Hi Hutch,

No, I'm not confusing anything, but any way you need to envision it so it works for you is fine by me.

Here's a good doc from Intel that describes the FLAT model, it might help to explain it to you

http://www.intel.com/design/intarch/papers/esc_ia_p.htm
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

hutch--

I confess I never had a problem with PECOFF.DOC from Microsoft or the original definition of FLAT memory model in MASM 6.1. Ain't like anything has changed in the base concept since then.

RE the notion of OFFSET used in MASM and where it is referenced from,


Virtual Address (VA)
Same as RVA (see above), except that the base address of the image file is not subtracted. The address is called a "Virtual Address" because Windows NT creates a distinct virtual address space for each process, independent of physical memory. For almost all purposes, a virtual address should be considered just an address. A virtual address is not as predictable as an RVA, because the loader might not load the image at its preferred location.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

donkey

 ::)

I give up. I'm out of this thread, its taken a turn that puts it beyond the limits of sanity.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable