NO

Author Topic: Mysterious Bloating of Stack Frame  (Read 2223 times)

PabloMack

  • Guest
Mysterious Bloating of Stack Frame
« on: March 28, 2020, 11:02:41 PM »
I have written a function in assembler and it crashes the program. Here is the call to the function from C:

//Write VER.Nxt
er ver_NxtW(VER *VRec,uo Src)
 {
  //Convert from uo
▶return up_uo((up *)&VRec->Vix[VER_Ofs_Nxt],&Src);
 }

uo is just "unsigned long long" and up is a 40-bit number
composed a struct with a "long" and a "char".

When in the debugger at the point of '▶', the value
of Src should only be 16 bytes beyond the RSP. However,
looking at the registers and memory, it is 56 bytes from
the RSP. Apparently the C Compiler is pushing a bunch
of stuff on the stack that is not contributing to either
function. Is there a document I can read that describes
POCC's policies for building and tearing down a function
call stack frame. I am not finding it in the help. It need
it for the purposes of writing assembly language
functions.

I have attached a picture of Registers and Memory beginning
with where the RSP points to. up_uo is the name of
the assembly function that is being called. What it tries
to do is to load the two addresses relative to the RSP
but they are pretty far from where I expect them to be.
I have also attached a copy of the assembler file so you
can see what it is trying to do.

Thanks.
« Last Edit: March 28, 2020, 11:08:00 PM by PabloMack »

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2266
    • http://www.smorgasbordet.com
Re: Mysterious Bloating of Stack Frame
« Reply #1 on: March 29, 2020, 06:12:05 PM »
Microsoft is responsible for the calling conventions used on Windows, so they better explain it.
Maybe this, or the surrounding pages, will help:
https://docs.microsoft.com/en-us/cpp/build/stack-usage?view=vs-2019
/Pelle

PabloMack

  • Guest
Re: Mysterious Bloating of Stack Frame
« Reply #2 on: March 30, 2020, 01:45:40 PM »
Okay. I'll study this. But I think there is something that you don't understand.

THESE ARE NOT WINDOWS OPERATING SYSTEM CALLING CONVENTIONS.
What Microsoft explains in the document is their compiler's calling conventions.
The only conventions for the Windows Operating System is for when you make
calls to the operating system and if you plan to link to Microsoft libraries. The OS
doesn't care how you make internal calls to your own code.

The Watcom compiler offers you no less that EIGHT calling conventions
that you can choose from and they are ALL windows compatible calling conventions.
Even though these run in the 32-bit environment, you could implement all of these in
the 64-bit environment. See attached picture of calling convention selection panel.

After reading it, all I can say is "What a freeking mess!" I suppose that all this
inefficient junk was put in there for the stack unwinding stuff that C++/C# has for
the try/throw/catch stuff that I never use and C doesn't need. It sure does bloat
the stack just like I indicated in the thread's title. The compiler that I plan to
implement won't have all this stuff in it. It is no wonder that the embedded
world doesn't like C++/C# because it runs so slowly and because it requires so
much more memory. The only thing good you get out of it is that throws
can walk the chain and figure out where you are in the stack. But at such a
high cost. They really don't accomplish much because they are just
controlled crash landings when the software fails. They are ways for the
software to give the last cry for help before they die.

Thanks for the info!

« Last Edit: March 30, 2020, 02:20:06 PM by PabloMack »

PabloMack

  • Guest
Re: Mysterious Bloating of Stack Frame
« Reply #3 on: March 30, 2020, 04:43:42 PM »
Okay. I have it working. Having RCX,RDX,R08,R09 saved on the stack
by caller makes it easier to use passed arguments but it causes
wasteful stack usage when those arguments don't exist. I always
used stack-only argument passing in the past because the stack
space is allocated and deallocated by the function that actually
uses the space and only when needed. This makes for smaller code
in the long run and faster execution. Also, if a function is called
many times, the waste is multiplied by the number of calls when
using the MS convention. When letting the called function do
the allocation as needed, the register saving is done in only
one place so it is much more efficient in the long run. But we have
grown used to a lot of waste in the Windows environment. That
makes it a good candidate for replacement IMHO.
« Last Edit: March 30, 2020, 04:52:23 PM by PabloMack »