News:

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

Main Menu

OPTION STACKBASE fails in x86

Started by aw27, March 20, 2017, 06:15:33 PM

Previous topic - Next topic

aw27

Hello developers,

This one does not work.

.686

    .MODEL FLAT, C
    option casemap:none
    OPTION STACKBASE:ESP
   
.code
   
sub2 proc private dest, src
   mov ecx, src
   mov edx, dest
   mov eax, dword ptr [ecx]
   mov dword ptr [edx], eax
   
   ret
sub2 endp

proc1 proc public dest : ptr, src : ptr
   invoke sub2, dest, src
   ret
proc1 endp

end

habran

Try to initialise source and destinu and see if it works.
Cod-Father

aw27

That's what I did, I am calling proc1  from high level language.
It works like a charm if I do not use the  OPTION STACKBASE:ESP  :(

habran

JWasm 2.12 produces exactly the same code. We can investigate, provide the proper source code please.
Cod-Father

aw27


I know JWasm produces the same error, it is a common bug.
Follows attachment.

habran

As I said before, you don't initialise parameters and it can be anything there.
Here is an example with initialised src and dest which works as expected:

.686
.MODEL FLAT, C
option casemap:none
OPTION STACKBASE:ESP

.data
src dd "ABCD"
dest dd 0


.code
   
sub2 proc private dest3, src3
   mov ecx, src3
   mov edx, dest3
   mov eax, dword ptr [ecx]
   mov dword ptr [edx], eax
   
   ret
sub2 endp

proc1 proc public dest1 : ptr, src1 : ptr
local bob:DWORD
local dob:DWORD
   lea eax,bob
   mov dob,eax
   invoke sub2, ADDR dest, ADDR src
   ret
proc1 endp

end


it produces:

--- AW32.asm -------------------------------------------------------------------
    14:    mov ecx, src3
01331010 8B 4C 24 08          mov         ecx,dword ptr [src3] 
    15:    mov edx, dest3
01331014 8B 54 24 04          mov         edx,dword ptr [dest3] 
    16:    mov eax, dword ptr [ecx]
01331018 8B 01                mov         eax,dword ptr [ecx] 
    17:    mov dword ptr [edx], eax
0133101A 89 02                mov         dword ptr [edx],eax 
    18:   
    19:    ret
0133101C C3                   ret 
    20: sub2 endp
    21:
    22: proc1 proc public dest1 : ptr, src1 : ptr
0133101D 83 EC 08             sub         esp,8 
    23: local bob:DWORD
    24: local dob:DWORD
    25:    lea eax,bob
01331020 8D 44 24 04          lea         eax,[bob] 
    26:    mov dob,eax
01331024 89 04 24             mov         dword ptr [esp],eax 
    27:    invoke sub2, ADDR dest, ADDR src
01331027 68 00 40 33 01       push        1334000h 
0133102C 68 04 40 33 01       push        1334004h 
01331031 E8 DA FF FF FF       call        sub2 (01331010h) 
01331036 83 C4 08             add         esp,8 
    28:    ret
01331039 83 C4 08             add         esp,8 
0133103C C3                   ret 
--- No source file -------------------------------------------------------------
Cod-Father

johnsa

I'm not 100% convinced yet on this, the parameters (if initalized in hll) should be fine, the asm code if being used as a library shouldn't need the params initialised, the generated code should be the same either way..

johnsa



; Disassembly of file: test86.obj
; Mon Mar 20 23:28:15 2017
; Mode: 32 bits
; Syntax: MASM/ML
; Instruction set: 80386

.386
.model flat

public _proc1


_text   SEGMENT PARA PUBLIC 'CODE'                      ; section number 1

_sub2   LABEL NEAR
        mov     ecx, dword ptr [esp+8H]                 ; 0000 _ 8B. 4C 24, 08
        mov     edx, dword ptr [esp+4H]                 ; 0004 _ 8B. 54 24, 04
        mov     eax, dword ptr [ecx]                    ; 0008 _ 8B. 01
        mov     dword ptr [edx], eax                    ; 000A _ 89. 02
        ret                                             ; 000C _ C3

_proc1  PROC NEAR
        push    dword ptr [esp+8H]                      ; 000D _ FF. 74 24, 08
        push    dword ptr [esp+4H]                      ; 0011 _ FF. 74 24, 04
        call    _sub2                                   ; 0015 _ E8, FFFFFFE6
        add     esp, 8                                  ; 001A _ 83. C4, 08
        ret                                             ; 001D _ C3
_proc1  ENDP

_text   ENDS

_data   SEGMENT PARA PUBLIC 'DATA'                      ; section number 2

_data   ENDS

END



I'm not sure why there is an add esp,8 at all in proc1... i guess the problem might be:

  push    dword ptr [esp+8H]                      ; 000D _ FF. 74 24, 08
  push    dword ptr [esp+4H]                      ; 0011 _ FF. 74 24, 04

push is going to move the stack pointer each time.. so the original arguments if they're at esp+8 and esp+4 would mean it should be:

  push    dword ptr [esp+8H]                      ; 000D _ FF. 74 24, 08
  push    dword ptr [esp+8H]                      ; 0011 _ FF. 74 24, 04

.. just thinking out aloud :)

aw27

#8
Quote from: habran on March 21, 2017, 08:21:32 AM
As I said before, you don't initialise parameters and it can be anything there.
Here is an example with initialised src and dest which works as expected:

The sad reality is that it is initialized, values are set before call (no need to be) and crashes.  :(
Your example manipulates the reality, were the references carried over from sub2 to another sub it would crash as well.  ::)

johnsa

I can confirm the issue is the pushes

it's using esp to lookup the current parameters on the stack, but then esp is being modified with each push (this moving the position of the arguments on the stack relative to the esp register).

aw27

Quote from: johnsa on March 21, 2017, 08:39:24 PM
I can confirm the issue is the pushes

it's using esp to lookup the current parameters on the stack, but then esp is being modified with each push (this moving the position of the arguments on the stack relative to the esp register).

True :t

jj2007

Quote from: johnsa on March 21, 2017, 08:39:24 PMit's using esp to lookup the current parameters on the stack, but then esp is being modified with each push (this moving the position of the arguments on the stack relative to the esp register).

It's a bit tricky but I use it occasionally:

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
StreamOut proc cookie, pBuffer, NumBytes, pBytesWritten
      invoke RtlMoveMemory, [esp+12], [esp+12], [esp+12]      ; dest, source, count
      mov eax, [esp+12]
      ret 4*4
StreamOut endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef


What I don't see yet is why this is a problem in the x64 world ::)

johnsa

If you're referring to the other thread about the same stackbase:rsp issue ?

My suggestion temporary there is just use:

option frame:auto
option win64:11
option stackbase:rsp

then that code should be 100% (for now), that said there is no reason for the bug to be there so we will fix it. :)

this particular case here is just a plain old bug and we're fixing it now.

johnsa

Hi,

OPTION STACKBASE:ESP has been removed.

There are many issues with it, it clearly wasn't a well thought-out addition.

1) No other assembler supports it.. hence we'd be producing non portable 32bit code
2) It totally violates the standard ABI..
3) The side-effects of how it works used in conjunction with the ABI using PUSH is just bad ..
4) There could be side-effects related to it's use in win32 (x86) with SEH and VEH that I've not yet fully been able to dig through.

If anyone has any other thoughts on this, please share! :)

On that note, the test-piece as mentioned works perfectly without it.
STACKBASE:ESP will throw an assemble-time error now.

aw27

Quote from: johnsa on March 24, 2017, 01:11:31 AM
Hi,
OPTION STACKBASE:ESP has been removed.

I will be good with that but someone with a Godfather's Marlon Brando face wrote once:
"Unless you know exactly what are you doing, I would suggest you to use:
.....
option STACKBASE:RSP   ; use rsp as a stack base instead of rbp"