News:

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

Nested procedures: are they actually supported or not?

Started by MazeGen, January 09, 2005, 08:45:45 PM

Previous topic - Next topic

Ratch

rea,

     Yes, you could update a stack compensation variable for every PUSH/POP or other stack modification you do.  And one can easily write a MACRO to do it.  No doubt MASM does that for their PROC-ENDP scheme.  But why bother.  It's so easy to count forward and backward for numbers less than 10.  And because I never encountered accumulated PUSHes/POPs greater than ten, I never had to take off my shoes.  I just don't see what keeping a variable does for you except make extra work.  Perhaps an example will enlighten me.  Ratch
     

Randall Hyde

Quote from: Ratch on January 20, 2005, 04:43:36 PM
MazeGen,
QuoteSimilar. Any time you add or remove some of these substitutive sequencies, you have to rewrite the structure.That is a big limitation of your method

     Some might consider it a bother, but it is not a limitation.  You only have to edit the pertinent parts of the structure.  Not a big deal as far as I can see.  Likewise if you choose to compensate references to the stack directly after pushing and popping.   It just doesn't seem very onerous to me.  Not if one is always cognizant of what s/he and the stack are doing, which is what a programmer should be aware of anyway.
Unless, of course, two paths in the code merge at some point and the ESP value is different along both paths.
Doesn't happen very often, but it *does* happen. In such cases, indexing off ESP cannot reference local variables in the common code sequence because ESP's value isn't always the same.

Quote
QuoteI wonder how do you handle extensive procedures - it has to be very complicated

     Not at all. It is very methodical.  Perhaps I don't understand what you mean by extensive. 

     My method is quite flexible.  For instance, I can SUB ESP,4*DWORD within Sub1 just before calling Sub2.  Sub2 can then fill in those 4 items of data according to its STRUC map and return to Sub1.  So then Sub1 has 4 items of data/params ready to go.  Can PROC-ENDP do that easily?  I don't know.  Ratch


Sure proc/endp can do that. Another thing to consider is this -- if you call several routines that use the C calling convention (specifically, the caller is responsible for popping the parameters), it is possible to leave parameters on the stack across several calls and clean them up only upon exiting the procedure making the calls. This saves one instruction per call. Not a lot, but it is a common optimization compilers make and one that assembly programmers should be aware of. While you can adjust your ESP offset values based on what you leave on the stack, this scheme quickly leads to the problem I mention above.

Using ESP as a base pointer register *can* be done in some special cases. But in general, it's very difficult (arguable impossible) to do all indexing off ESP.

Another issue alluded to in this thread: accessing local variables in a (statically nested) caller's activation record. The examples I've seen presented in this thread fall completely apart when you have recursion. People need to keep in mind the difference between static nesting and lexical nesting. Unless you have static links or a display, it's very difficult to access objects that are not local to the currently running procedure, but are local to other procedures (that have directly or indirectly called the current procedure).
Cheers,
Randy Hyde

Ratch

Randall Hyde,
     Very interesting points you make.  I think I can come up with some solutions.  Rather than try to hypothesize on how I will solve those problems, I will just say that I will TRY to overcome them when they occur for me.  If someone can post a small example that demonstrates the problem, I will be more than happy to take a crack at solving it.  Ratch

rea

mmm, yes, I was refering to some like C can do, also I where thinking that "I can " call fastLocals the ones that you do for preserve a register, they are still local to the proc, but in some way there are not a part of the proc, but a part of preserve the value... anyway.


For example:

x:
sub esp, 24

; some names for locals where defined like x esp+8, v1 esp,... by the way
%define x esp+8
; from this part I can access locals and arguments
add dword[x], 5
push eax
push ebx
invoke calculationT ; it destroy those registers
add [x], eax ; *
invoke calculationZ, dword[x]
·
·
·
pop ebx
pop eax
·
·
·


*this isnt right, even that calculationT dosent have C calling convention, I will not pop the values for access my local ;), altought I can do some like add [x+8], eax and instead of do that, is pheraphs more easy take a extra variable that handle that in the fly, also it need modificate push and pop for provide a little more control....



QuoteUnless, of course, two paths in the code merge at some point and the ESP value is different along both paths.
Doesn't happen very often, but it *does* happen.

You are refering for example to blocks?, I think it will more easy, with the same technique.... but I dont know if what Im thinking is the same that you have in mind...... Im a little aware that sometimes a local is not necesary for a function only if certain path is followed, I dont know if when this path is reached that the space for the nested locals is reached or is only a "semantic" behaviour, for example:

(it is a raw example, in fact isnt implementing nothing, but show the point :))

xthing:
sub esp, 12
sub [esp], eax
jnz .end
add [esp+4], ecx ; **
sub [esp+8], ecx ; also **
; make more operatios with this ones
mov ecx, [esp+4]
add [esp], ecx
.end:
·
·
·

** are say local variables they will be necesary in remote case that such path can be reached....

But supose that this function is recursive and that you have a buffer (only used when the stop condition is reached), then you will allocate for each call supose 512 bytes, then if in some case that your functions being called 10 times you will have allocated in the stack 5120 bytes, and the thing is that the buffer is only used one time.... :).


QuoteIn such cases, indexing off ESP cannot reference local variables in the common code sequence because ESP's value isn't always the same.

You are refering some thing like the above, but in the case that is more than one path and diferents paths make a substraction of the esp for his own locals????? for example, one path substract 12, other 20, 36, 48, then if you dosent aling before get out of this path, sure it will be very dificult to know what is the align or extra compensation for this "fastlocals"....

It is not posible to calculate in the paths that is posible and balance in the cases that is not automaticaly posible???

For example is easy when you have paths that are consecutive.... a=12, b= 20, c= 36, d= 48, you only add them...
but the dificult is when you have more than one path to follow: b follow a, there is a choice for path a or c, and d is after any of them. ( (a+b) Xor (c) ) => d, after the execution how many are (before execute the path d)??? 32 or 36? :), the only way that I see for solve this is realign the stack again for have at the end a zero path :) and in that way will not matter if the first or the second path (some one will like to say me how many impact is there for align the stack in those cases)....


I think I have in mind some things (is the only solution that I have in mind from some time a go ...), but best is to know if you have a example to take over ;) or otehr solution ;) (if I have understood correctly or the anterior is uncorrect?), in my case I have only finded other problem and is: when you allocate space for locals and use the locals in that way and then you align esp!!!, in fact you are not sure where the return address is and keep the track of where the ret address is important in that case I supose you are forced also to use ebp, but that will be more a fault of the programmer (I gues?)


The majority of the index I think can be done with esp, you only need to take care more of what is happening :D, because esp is the one changing (and should be taked in count when is changed), not like ebp (this one is really more easy) ;).