News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

result error

Started by Emil_halim, November 12, 2010, 07:33:53 PM

Previous topic - Next topic

Emil_halim

hi all.

the next code should print that 'i = 100' but it print strange value of i variable, any help?


program ClassTest;
#include( "stdlib.hhf" )

type
    demoClass:
        class
       
            var
                i:int32;
                               
            procedure create;       
           
            procedure  geti;           
            procedure  seti( i:int32 );
                       
        endclass;     
       
static
    vmt( demoClass );
   
procedure demoClass.create; @nodisplay; @noframe;
begin create;
    if( esi = NULL ) then 
        push( eax );
        mem.alloc( @size( demoClass ));
        mov( eax, esi );
        pop( eax );
    endif;
    mov( &demoClass._VMT_, this._pVMT_ );
    mov( 0, this.i );
    ret();
end create;

procedure  demoClass.geti; @nodisplay; @noframe;
begin geti;
    mov( this.i, eax );
    ret(); 
end geti;

procedure  demoClass.seti( i:int32 ); @nodisplay; @noframe;
begin seti;
    push( eax );
    mov( i, eax );
    mov( eax, this.i );
    pop( eax );   
    ret(_parms_);
end seti;

var
   tmp : int32;
   cls : demoClass;

begin ClassTest;

   cls.create();   
   
   cls.seti(100);
   cls.geti();
   mov(eax,tmp);
   stdout.put( "i = " , tmp , nl);

end ClassTest;



Sevag.K

you're using @nodisplay; @noframe options.

you have to build the stack frame yourself if you use these options and you have parameters.


procedure  demoClass.seti( i:int32 ); @nodisplay; @noframe;
begin seti;
    // setup frame
    push( ebp );
    mov( esp, ebp );
   
   
    push( eax );
    mov( i, eax );
    mov( eax, this.i );
    pop( eax );
   
    // restore stack and return
    mov( ebp, esp );
    pop( ebp );   
    ret(_parms_);
end seti;


if you have vars, you'll need to add a sub( _vars_, esp ); right after mov( esp, ebp );
also, if you have vars and they are not dword aligned, you'll have to manually align the stack as well.

Emil_halim

ok , got it.

thanks for your help.

edited

here is the procedure without stack frame

procedure  demoClass.seti( i:int32 ); @nodisplay; @noframe;
begin seti;   
    push( eax );
    //mov( i, eax );
    mov( [esp+8] , eax ); // i in the stack
    mov( eax, this.i );
    pop( eax );     
    ret(_parms_);
end seti;


so is there a way to let hla use esp instead of ebp when  emit a parameter of procedure and found  @noframe ? 

Sevag.K

no, and there is no way to automatically predict the esp offset locations of parameters at any given point in the procedure.

i wouldn't recommend that you get in the habit of using esp as a base pointer.  esp constantly changes as you push and pop values on the stack and if you use esp as a base pointer, you'll have to recalculate parameter offsets.


dedndave

#4
if you make a PROC that looks like this...
SomeProc PROC uses ebx esi edi Parm1:DWORD,Parm2:DWORD

        LOCAL   Var1:DWORD
        LOCAL   Var2:DWORD

        mov     eax,Parm1
        mov     ebx,Parm2
        mov     ecx,Var1
        mov     edx,Var2

        ret

SomeProc ENDP

the actual code that the assembler generates looks something like this
SomeProc:
        push    ebx
        push    esi
        push    edi
        push    ebp
        mov     ebp,esp
        sub     esp,8             ;make room for 2 local dwords

        mov     eax,[ebp+20]      ;Parm1
        mov     ebx,[ebp+24]      ;Parm2
        mov     ecx,[ebp-4]       ;Var1
        mov     edx,[ebp-8]       ;Var2

        pop     ebp               ;usually, LEAVE is used to MOV ESP,EBP and POP EBP
        pop     edi
        pop     esi
        pop     ebx
        ret     8                 ;return and remove 2 dword parms from stack

notice that the stack address in EBP won't change, regardless of what is PUSH'ed or POP'ed
while the stack address in ESP continually changes as items are PUSH'ed or POP'ed

Emil_halim

Sevag.K & dedndave

yes i agree with you , in general cases using ebp is the wright choice as an offset to our parametres
but in my case , there is no local variables so that using esp to pick up our parameter is not problem
espcially you are know what you are going to do.
beside using stack frame in my case has no meaning because there is no local variables.

Sevag.K


it's not just the local variables.  anything you push on the stack will change the offset.  for example, in your source, comment out the push/pop eax instructions and try to compile and run it again.  you will find that your [esp+8] is no longer valid, your parameter is now at [esp+4].

if you want to forgo the frame building step, you'll have to access your parameters the hard way :)



dedndave

i am not sure which assembler you use   :P
i generally prefer to handle the stack frame myself, rather than let the assembler do it for me
but, that is because i am old, and was used to masm before they had such conveniences - lol
for masm, you may use an OPTION directive to disable PROC prologues and epilogues

to illustrate what Sevag is telling you, the following code loads the different parms into registers
notice how the stack offset must be calculated differently each time something is PUSH'ed (or POP'ed)
in this case, the offset is the same to access 3 different parms   :P
        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

vBase   PROC    dwValue:DWORD,lpBuffer:DWORD,dwBase:DWORD

        push    esi
        mov     edx,[esp+16]  ;dwBase
        push    edi
        mov     esi,[esp+16]  ;lpBuffer
        push    ebx
        push    eax,[esp+16]  ;dwValue
        push    ebp

;some code here

        pop     ebp
        pop     ebx
        pop     edi
        pop     esi
        ret     12            ;return and discard 3 dword parms

vBase   ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

Emil_halim

Sevag.K:

one of the major reason to switch from c++ to hla asm is the speed of asm code. so you have the full
control in your hand when program in asm. when hla emit a stack frame for a procedure that has no
local variables , it west the speed.

every push proccesse can be calculated before we pick up the parameters , so there is no problem.
just i want hla when see @noframe after a procedure don't automatically use the ebp to locate the parameters.

dedndave:

i am using hla assembler, yes i know what sevage was talking about.

any way thanks for both of you.

Sevag.K


i know what you're saying.  you're asking if you can have low level control using the high level functionality of hla.  the answer is no.  if you want low level control, you have to do it the hard way :)

the hard way requires either manually calculating offsets based on the base register of your choice, or writing elaborate and complicated macros to do this for you.

another way is to use val expansions.  it doesn't have to be val, you can also use const here.  a good advice is to name your constants with the offset in the name.


val
p4 :text :=[esp+4];
p8 :text :=[esp+8];
p12 :text :=[esp+12];
p16 :text :=[esp+16];
//...

...

mov( p8, eax );
mov( eax, this.i );

...




Emil_halim


ok , nice solution , i will use it.