flat assembler
Message board for the users of flat assembler.

Index > Main > proc macro bug

Author
Thread Post new topic Reply to topic
AsmER



Joined: 25 Mar 2006
Posts: 64
Location: England
AsmER 28 Oct 2006, 15:22
I was trying to seach if somebody has reported it before, but I haven't find anything like that so there is what I've found:

The proc macro doesn't calculate properly how many bytes should be released from the stack. i.e:
Code:
...
push    [VW]
push    [vd]
push    [vd]
push    [vd]
call    TESTP
...
proc    TESTP, p1:DWORD, p2:DWORD, p3:DWORD, p4:DWORD
        local l1:DWORD
        local l2:DWORD
        ret ;this macro produces 'retn 0x10'
endp
...
VW      dd      0xbbbbbbbb
vd      dd      0xaaaaaaaa
...
    

works fine, but the code bellow doesn't:
Code:
...
push    word [VW]
push    [VD]
push    [VD]
push    word [VD]
call    TESTP
...
proc    TESTP, p1:WORD, p2:DWORD, p3:DWORD, p4:WORD
        local l1:DWORD
        local l2:DWORD
        ret ; this one produce 'retn 0x10' as well.
endp
...
VW      dd      0xFFFFFFFF
VD      dd      0xEEEEEEEE
...
    


After the call to TESTP procedure 'ret' releases 16 (0x10) bytes from the stack (like p1 and p4 would be DWORD values). It does even if there are no local variables [they are there because, my proc was using them when after 4hours of debugging I found out that there is a problem with the stack].
My fasm version is 1.67.13 (Oct 26, 2006).

_________________
;\\ http://theasmer.spaces.live.com \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Post 28 Oct 2006, 15:22
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 28 Oct 2006, 15:40
With proc32 the parameters on stack are always aligned up to occupy the multiply of 32 bits. If you define parameter of type BYTE, you still have to use the full 32-bit area for it, in order to keep the stack aligned properly. For this reason "invoke" and "stdcall" macros use "pushd" to store all the parameters.
However if you call the procedures without using a macros, you have to remember about the proper stack layout.

If you look at other languages aswell, you'll notice that this is usual in the Win32 world, fasm's macros only adopted the existing standards.

PS. The same applies to Win64 world, however there each parameter occupies 8 bytes - always. Even if it just a byte, the whole 64-bit area has to be reserved (though it doesn't have to be zero-filled).
Post 28 Oct 2006, 15:40
View user's profile Send private message Visit poster's website Reply with quote
AsmER



Joined: 25 Mar 2006
Posts: 64
Location: England
AsmER 28 Oct 2006, 15:49
So if I want to pass some WORD value to my proc using the stack, then I will need to play with [EBP+XX] like a long time before. I didn't learn fasm macros syntax jet, but will it be possible to create a macro which would calculate it in the way I want?
Post 28 Oct 2006, 15:49
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 28 Oct 2006, 16:33
Perhaps the most straightforward way is to not use macros at all (if you want to utilize the true power of assembly, no macros! Wink). Try this:
Code:
        push    word [VW]
        push    [VD]
        push    [VD]
        push    word [VD]
        call    TESTP
; ...

TESTP:

  virtual at ebp+8
    .p1 dw ?
    .p2 dd ?
    .p3 dd ?
    .p4 dw ?
    .params_length = $ - (ebp+8)
  end virtual

        push    ebp
        mov     ebp,esp

        mov     ax,[.p1]

        leave
        ret     .params_length


VW      dd      0xFFFFFFFF
VD      dd      0xEEEEEEEE    
Post 28 Oct 2006, 16:33
View user's profile Send private message Visit poster's website Reply with quote
Goplat



Joined: 15 Sep 2006
Posts: 181
Goplat 28 Oct 2006, 17:09
You're not supposed to push WORDs on the stack in 32 bit mode, since that misaligns your stack pointer, and according to official Intel docs that has performance implications.

If you push them in pairs it should be OK. Would something like this work?
Code:
...
push    [VD]
push    [VD]
push    word [VW]
push    word [VD]
call    TESTP
...
proc    TESTP, p1:WORD, p3:DWORD, p4:DWORD
        label p2 WORD at p1+2
        ...
endp
    
Post 28 Oct 2006, 17:09
View user's profile Send private message Reply with quote
AsmER



Joined: 25 Mar 2006
Posts: 64
Location: England
AsmER 30 Oct 2006, 14:01
Thanks Goplat, it would work, but since I just wanted to save few bytes on the user's computer, I think I will change the structure of my program, so all variables will be 32bit, and I wont have any problems anymore Smile

_________________
;\\ http://theasmer.spaces.live.com \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Post 30 Oct 2006, 14:01
View user's profile Send private message 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


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.