News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

issues with dereferencing iteration of array of long elements in a loop

Started by cyrus, January 14, 2024, 12:20:40 PM

Previous topic - Next topic

cyrus

Quote from: jj2007 on January 16, 2024, 11:33:22 PM
Quote from: cyrus on January 16, 2024, 02:32:30 PMI even modified it again to use R12 instead of RBX just in case I use RBX somewhere else. Although no functions ever use it, it is still a volatile register

1. The phrase could refer to rbx or r12, it's ambiguous
2. Both are non-volatile registers


Thanks. I guess thats why RBX did work but out of habit, I was used to just sticking to R12-15 but good to know.

I do need to read more into the ABI but I do a lot of other things as well, not just programming in asm

cyrus

Ok I just wanted to say thank you sinsi for opening my eyes about the stack alignment. That plagued me. I had a program where I had call printf just to get it to work (or any function). But after analyzing it all the way through, I realized my stack was indeed unaligned.

My other program I was about to post up but didn't need to because so far it looks to be working pretty solid, was one that calls GetTcpTable which, requires 2 calls to be made. One must initialize
SizePointer by making 2 calls to GetTcpTable. First being [in], second call, [out] receiving the actual size. This is because the tcp table is dynamic depending on what's in it at the current time of calling the function and retreiving the data. The data goes into a struct of type
PMIB_TCPTABLE. The size from
SizePointer is what is used to allocate size for this struct. I did that on the stack using that size. The issue was that the size always varied. And I needed to either subtract stack space or push bytes on the stack. This time I did subtract the size on the stack. But here is the kicker. That may not be stack-aligned. So what was my trick? I took the whole size, divided it by 16 using 'div ebx' so ensure that I would have enough room. I noticed most calls for my particular tcp table ranged from about 512 to 772 or so bytes. Each call varied depending on when Microsoft decides to connect to some rogue server whenever it wants  :smiley:

After division, I checked if there was a remainder. If there was, I added 1 to the quotient, not the total size. The quotient + 1 x 16 again would give me a grand total that is stack-aligned. I subtract this from the stack to give me the struct I needed. Then I just added that size back and resumed to 'begin'. I tested this by calling printf between so that I know whats' going on. It ends up in an infinite loop which is the intended goal here,

https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-gettcptable

cyrus

Quote from: sinsi on January 15, 2024, 02:11:06 PM
Quote from: NoCforMe on January 15, 2024, 01:33:04 PMAbout your question about using a static buffer (one declared in your .data section) instead of one allocated on the stack: pretty much 6 of one, half a dozen of the other. Not more or less efficient either way. It's true that you can initialize the static buffer when you declare it. But again, if you're using it multiple times with your Enum function, there's no need to "clear" it each time anyhow. A static buffer will take up space in your program; however, you can minimize the space it occupies in the .exe file by declaring it in your .data? section (uninitialized data), but then you can't initialize it in the declaration; you'll have to use code to initialize it if you need to do that.
Just to add to that, if your procedure is recursive, or gets called by multiple threads, you have to use the stack, otherwise each running procedure will clobber the other's buffer (since it is the same buffer).

This is why I love using the stack, just to be sure that data is always new.

NoCforMe, yea for this particular one, or any other one where that buffer gets filled from a call to a function such as GetModuleBaseName, I don't need a new buffer. In fact, for that program, I just declared 256 bytes in the .data section, then just 'lea r8, buf' (which is the 3rd argument to that function)

sinsi

If you need to allocate a variable-sized buffer, the best way (for me) is
 - allocate the amount of memory with HeapAlloc (or whatever you use)
 - store that address somewhere (non-volatile register or locally on the stack)
 - do what you need to do to fill the buffer
From here, you could
 - process the buffer
 - HeapFree
or just return the address to the caller in RAX and let them process and free the buffer

Tá fuinneoga a haon déag níos fearr :biggrin:

cyrus

Quote from: sinsi on January 17, 2024, 11:02:30 AMIf you need to allocate a variable-sized buffer, the best way (for me) is
 - allocate the amount of memory with HeapAlloc (or whatever you use)
 - store that address somewhere (non-volatile register or locally on the stack)
 - do what you need to do to fill the buffer
From here, you could
 - process the buffer
 - HeapFree
or just return the address to the caller in RAX and let them process and free the buffer



Yes I totally forgot about that. If the buffer I need is larger than 8192, I usually end up calling malloc or HeapAlloc/HeapFree as well but sometimes I forget the simplest things. This relieves headaches of dealing with the stack but I'm glad I went through this in case I don't want to allocate memory from the heap and need to use the stack for simplicity.

TimoVJL

Windows PAGESIZE is 4096, so good to remember that with stack if use it without probing.
May the source be with you