flat assembler
Message board for the users of flat assembler.
 Home   FAQ   Search   Register 
 Profile   Log in to check your private messages   Log in 
flat assembler > Windows > Question about locals (stack variables)

Author
Thread Post new topic Reply to topic
StakFallT



Joined: 19 Jan 2006
Posts: 48
Question about locals (stack variables)
Is it possible to pass a local variable (variable taking up space on the stack) to another procedure? Obviously, when moving to another procedure causes a new stack frame to be created and the esp/ebp registers no longer will match what they were before. However, let's say I had:


Code:

proc some_procedure_A SomeParameter:DWORDSomeOtherParameter:DWORD
locals
     Str_Escapeddd 0
endl




and I want to pass Str_Escaped to a string that actually generated an escaped string. Obviously the variable being on the stack is not going to have a heap address, and the complexities of the stack frames being different once control-flow is passed to another function , would it be possible to take the absolute address of the variable sitting on the stack and pass that to another function?

Right now I have something along the lines of:

Code:

proc some_procedure_A UnEsc_String:DWORDSomeOtherParameter:DWORD
locals
     Str_Escapeddd 0
endl


     ...


     push edx
     xor edxedx

     lea edx, [Str_Escaped]

         push EscapeCharacter
         push edx
         push UnEsc_String
     call Escape_String 




I'd like to have the Escape_String procedure operate on the stack location that Str_Escaped (now stored in edx) is sitting at. However, it doesn't seem to work correctly. It's not failing, but it's value is never changed. It's changed in the "current" stack frame of the new procedure, but not of the calling procedure. I could always set eax to the value and return that and then set it in the calling procedure, but I'd like the procedure to be able to operate on a passed in local if possible.

Is this not working (or maybe not possible) because the address is based on a "relative" position and upon entering another procedure the relative position is no longer correct? Thanks!

-- StakFallT
Post 19 Nov 2017, 19:03
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 894
You can certainly take the address of a local variable; after all, [esp+X] resolves to an absolute address, so when you use it in lea, you get an "absolute" address, even though 'X' is relative to esp. This is very common actually, but only if the called function is down the stack chain.

Note that you can't use that address to a function "above" yours (i.e. your function returns to it) because then the address points below 'esp' which is considered invalid and can be trashed by any other calls etc.

The stack is not super special. It's just a memory region, like the heap, and esp is just a normal pointer to it. It has a few "special" quirks (mostly due to the OS, not the processor) but you don't need to worry about that right now (it's low level stuff with exceptions).

Everytime you call or push something on the stack, the pointer gets decremented. Any address above the pointer is valid to pass around other functions, so as long as esp is below your "address" that you pass to another function, it's perfectly fine and common.

I don't know why it's not working, but your code looks valid to me, I suspect Escape_String is wrong itself. Did you take the value from the stack and then dereference it? Showing Escape_String will solve the problem.


BTW the xor edx, edx is redundant Wink
Post 19 Nov 2017, 20:38
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15312
Location: Bigweld Industries
Str_Escaped is only four bytes in length, three bytes for characters and one byte for the terminating zero. Are you sure it isn't a pointer to a string? If it is then you push the value of the pointer, not the address of the pointer.

Code:
;...
         push EscapeCharacter
         push dword[Str_Escaped;<--- push the value?
         push UnEsc_Strin
;...

BTW: If you remove the colon then you can remove the size override.

Code:
     Str_Escaped dd 0 ;no colon
;...
         push [Str_Escaped;no "dword" override needed
;...

Post 20 Nov 2017, 00:10
View user's profile Send private message Visit poster's website Reply with quote
StakFallT



Joined: 19 Jan 2006
Posts: 48
@Furs ok I think I got it working. It seems I had to lea the variable to a register and pass that, and then inside the procedure I had to lea the parameter again (for when I pass it to my memory allocation procedure). It's kinda screwy but I think it makes sense now. I needed the first lea for the stack address (didn't want to use hardset/static relative-addresses) but then when they gets passed to another procedure, that value gets put into a "temporary" that is... on the stack. thus, I then had to lea that parameter since being in the new procedure is another stack frame all of its own (which I know... it just didn't dawn on me). Either way, I'm going to have to abandon using the local variables though I think (or at least accessing them directly) because it seems when I come back from that second routine, esp's address goes higher pushing the modified parameter quite a bit lower since that second procedure does a bunch of other stuff as well. I could allocate something on the heap and pass that around, I could use globals, etc. There's some options but I think I'm definitely going to have to think this through. Thanks!



@revolution since my original post, I have modified the code. It now looks like

locals
Str_Escaped rd 4
endl

You did say something rather interesting... I thought addresses even as values are still stored as 4 bytes, because the registers are 4 hexadecimal values (on 32-bits) and memory addresses are natively DWORDs (on 32-bits)? I'm pretty sure I've seen addresses butted right up next to each other with no null-terminator in between. Is that incorrect? Should there still be null-terminators. I feel like, obviously, strings needs null-terminators, but memory addresses it's assumed to be 4-bytes, though I guess depending on how they're being read (is a variable already set to its value and you're passing that around vs. actual string parsing of that memory address) it could matter.
Post 20 Nov 2017, 02:25
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15312
Location: Bigweld Industries
If you are storing string data at the address Str_Escaped then it might be more prudent to define it as byte data

Code:
Str_Escaped rb 16 ;16 bytes of data

When you use "rd 4" you still reserve 16 bytes (4 dwords) but the label is tagged as dword data. This "works" if you only ever use LEA to get the address but it makes the code harder to understand.

For 32-bit code addresses are indeed 4 bytes, you don't need any terminator bytes between them. But don't confuse the address with the value at the address. You can use a 32-bit register to point to the address of a single byte

Code:
var db 0x12
mov esi,var ;<--- esi is a 32-bit address pointer to the single byte 0x12
mov al,[esi;<--- al now has the value 0x12

Post 20 Nov 2017, 02:36
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >

Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001-2005 phpBB Group.

Main index   Download   Documentation   Examples   Message board
Copyright © 2004-2016, Tomasz Grysztar.