News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Debugging: how to recognise a no stack frame proc

Started by jj2007, March 04, 2020, 11:29:21 PM

Previous topic - Next topic

JK

Hi jj2007,


if i get this right, you want an automated test, if the stack is balanced, when you leave any kind of procedure. What about doing it the other way round ?

Save ESP before the procedure call (invoke ...) and test it afterwards. You could wrap invoke with a macro and add the test code inside this macro. The more, the procedure name is already there as a parameter - so it´s easy to output a meaningful debug message, and it´s easy to adapt existing code, just replace "invoke" with your new macro .

jj2007

Quote from: JK on March 11, 2020, 04:48:09 AMSave ESP before the procedure call (invoke ...) and test it afterwards. You could wrap invoke with a macro

Hi JK,

Your idea is good but there are three problems:

1. many people do not invoke but push parameters manually (even I do that often)
2. when invoking procs that have a stack frame, your macro will not see the problem because esp is ok
3. when invoking procs that do have a stack frame, your macro will not be able to print the message because the return will be to no man's land.

daydreamer

there is alternative to pushs/pops to save/restore general purpose registers,bigger opcodes(3bytes) to save/restore in SIMD registers,but doesnt mess up stack
there is fastcall convention as alternative to use stack together with invoke if its your own made PROC's
you use registers instead of stack for data
windows api call you need to stick to invoke/stack
if you only call the PROC from one place in the code,a MACRO version of that proc,would get rid of possibility of ret to "nomansland",but if you want to use it several times,its no good to use it 5 times,because that will insert it inline resulting in 5 times bigger code than one PROC
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

jj2007

Great ideas, daydreamer. Post some examples, please. Code :cool:

hutch--

If its a test of the stack balance, that is in fact easy, allocate a variable then move ESP into it BEFORE you call the proc then display the variable in either a MessageBox or at the console.. After the proc has returned compare the two results, if they are the same, the stack is balanced, if not you have something to fix.

jj2007

Quote from: hutch-- on March 11, 2020, 10:50:56 PM
If its a test of the stack balance, that is in fact easy, allocate a variable then move ESP into it BEFORE you call the proc then display the variable in either a MessageBox or at the console.. After the proc has returned compare the two results, if they are the same, the stack is balanced, if not you have something to fix.

Apart from being a clumsy way to do that check: Most of the time the stack will be balanced even if you have a bug. The miraculous leave instruction balances the stack for you, and leaves subtle little problems such as esi edi ebx out of tune. Often there is no immediate crash, but it may bite you later. Thanks to @MbRet, I've identified three little problems in my editor - and it looked stable before, I work with it every day.

hutch--

This is what I don't understand what you are trying to do. At the minimum a proc with no stack frame has a start address and at one or more locations, it is exited by a RET. I still don't know if this is with a disassembly, parsed source code or assembled code. If you do the normal STDCALL preservation of registers, the stack increments by the size of the PUSH mnemonic up to the number of preserved registers.

I still don't know what you are trying to achieve.

daydreamer

Quote from: jj2007 on March 11, 2020, 10:15:23 PM
Great ideas, daydreamer. Post some examples, please. Code :cool:
inspired by windows message proc handler switch,using readable constants instead of numbers
so far,same problem with unbalanced stack so I solved with commented out so I use eax instead(fastcall)
maincompos proc ; vers:DWORD
mov vers2,eax

lea ebx,cbuffer
mov eax,0
mov ecx,0
@@L1:
        mov [ebx+ecx*4],eax
     
     inc ecx
     cmp ecx,1000000
     jne @@L1
;mov ebx,esi
switch vers2 ;check if mul,SSE2,SSE,fpu,AVX version

case ordinary
    jmp @@v1
case sse2
    ;jmp SSE2vers
case sse
    ssem
case fpu
    ;jmp fpuvers
case avx
    jmp avxvers
endsw



gonna test conditional assembly on PROC's not needed when using MACRO version
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

hutch--


jj2007

Quote from: hutch-- on March 12, 2020, 02:56:48 AM
I think he wanted code that actually worked.

Correct :tongue:

Quote from: hutch-- on March 12, 2020, 12:35:41 AMAt the minimum a proc with no stack frame has a start address and at one or more locations, it is exited by a RET. I still don't know if this is with a disassembly, parsed source code or assembled code.

It won't work with frameless procs, sorry. There is no way to do certain calculations:

My editor has about 200 procs, counted as "endp", full word search. About 130 have now instead of
ret
xxx endp

@MbRet
xxx endp

It's a simple Find & Replace action. What @MbRet does is:
- go back to the start of the proc
- check if there is a stack frame
- count the number of LOCALs allocated over the stack
- go back to the RET position
- count the number of POPs (mostly pop ebx, edi, esi from xxx proc uses esi edi ebx)
- calculated the expected esp
- shout foul if it doesn't coincide with the factual esp
- correct the stack if necessary, so that the uses work correctly
- do a quick check if the return address is in the .code section of your program
- print a line to the screen if it isn't (the program will crash but after that line)
- last but not least: insert a ret

In the testing phase, the program runs a tiny bit slower because of all those checks, and it adds some bloat. Once @MbRet stops printing error messages, you simply switch it off, and then all it does is insert the ret.

I have discovered three errors so far in the 200 procs and 20k lines of code. That is not much, but it was three bugs too many :cool:

P.S.: No MasmBasic needed :mrgreen:
P.P.S: Inspired by this thread, I've implemented a new function: find push or pop :cool:

daydreamer

my point was to use registers instead of stack similar to 64bit mode does,Hutch probably has better example of 64bit using 4 general purpose registers and XMM0-XMM3 for floats
this thread inspired me to test conditional assembly together with MACRO version of PROC's
but I cant get it to work properly,when I want it to assemble
using one MACRO instead of PROC+
YESPROC=1 ;if assemble proc's or not
IFDEF (YESPROC)
...code
ENDIF
all unused PROC in .inc file is not assembled and results in more than -1k smaller exe
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

jj2007

Zip it and post it, daydreamer. We are curious to see code - complete code.

hutch--

magnus,

In win32 you can do a simulated version of FASTCALL but you only have 3 registers you can use, EAX ECX & EDX. As win32 does not normally use the 3 available registers and only works with stack memory with STDCALL, you can use the 3 registers and put any others on the stack with the normal PUSH notation. Whether you will see any difference is another matter but it can be done.

daydreamer

Hutch,from Intel optimize manual,its alternative save/restore registers to SIMD registers and dont messup stack,but it takes opcode takes 3bytes instead of 1byte for push/pop
maybe good outside innerloop,but when unrolling inside innerloop maybe too many 3byte MOVD makes it too big to fit into cacheline
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

jj2007

You attached code, daydreamer :thumbsup:

Can you explain where exactly you are testing your ideas?