News:

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

creating pad macro

Started by Emil_halim, November 15, 2010, 08:06:14 PM

Previous topic - Next topic

Emil_halim

hi all

i want to make a macro to automatically align a record with 64 bytes length , if the record length less than 64 it will add the rest size
to be equal and aligned with 64. in the same size i want to access to it's fields as normal.

here is my trying , but it did not compiled , any help please?

#macro pad64(struc):size;
       ?size : byte := 0; 
       #while(@size(struc)>size)
              ?size := size + 64;
       #endwhile       
       @text(@string:struc + "; " + "@nostorage;");
       @text("byte["+@string:size + "]");
#endmacro


Sevag.K

you don't need a macro, hla can do it for you.


program tt;

#include("stdlib.hhf")

type
myrec:
record
f0:dword;
f1:dword;
align( 64 );
endrecord;

static

align(4);
r0 :myrec;
r1 :dword;

begin tt;

mov( &r1, eax );
sub( &r0, eax );
stdout.put( (type uns32 eax ), nl );

end tt;


Emil_halim

this is great when you create a new record by yourself.

but if you already have a record and want to padding it with 64 bytes length without having to recreate it,
in this case it is the time to create a macro for adapting the size of our record.

Sevag.K

i'm not sure i know what you mean, but you can also use align almost anywhere.



static
r0 :someRecord;
align(64);
r1 :someRecord;
align(64);


another option, you can make a new record and inherit the original one and place your alignment in there


type
rec0 :record
var0 :dword;
endrecord;

rec1 :record inherits( rec0 );
align(64);
endrecord;

static

r0 :rec1;
r1 :rec1;


if you're dead set on making your own pad64 macro, this will work:


#macro pad64( _rec_ ):_lbl_;

_rec_;
#if( @size(_rec_) MOD 64 > 0 )
_lbl_:byte[ 64 - (@size(_rec_) MOD 64) ]
:= [ ( 64 - (@size(_rec_) MOD 64) ) dup [#0] ]
#endif

#endmacro


you only need the last line if you want to initialize the padded bytes with zero.

here is an example of all 3 methods in use


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

type
rec0 :record
var0 :byte[31];
endrecord;

rec1 :record inherits( rec0 );
align(64);
endrecord;

#macro pad64( _rec_ ):_lbl_;

_rec_;
#if( @size(_rec_) MOD 64 > 0 )
_lbl_:byte[ 64 - (@size(_rec_) MOD 64) ]
:= [ ( 64 - (@size(_rec_) MOD 64) ) dup [#0] ]
#endif

#endmacro

static
r0 :rec0;
align(64);
r1 :rec0;
align(64);
r2 :rec1;
r3 :rec1;
r4 :pad64( rec0 );
r5 :pad64( rec0 );


begin tt;

mov( &r1, eax );
sub( &r0, eax );
stdout.put((type uns32 eax ), nl);

mov( &r3, eax );
sub( &r2, eax );
stdout.put((type uns32 eax ), nl);

mov( &r5, eax );
sub( &r4, eax );
stdout.put((type uns32 eax), nl);


end tt;


if none of these are what you are talking about, i'll need a better description of what you want.

Emil_halim

you have got my words correctly , nice explanation.

the first choice gives align value must be 16 or less when compiled with Fasm
and gives invalid combination with segment alignment : 64.

any way , i will choose the macro one but still have a problem.

i want to access to the members of record when padding it , i.e if only i declare it with byte i
can not access to it's members.

i think adding @noStorage statement will solve the problem.

for example

if i have the next record , and want to access u member

rec0 :record
var0 :byte[31];
i : int32;
u : uns64;
c : char;
endrecord;

r4 :pad64( rec0 );

i.e.

mov(r4.u , eax);


gives memory operand must by a byte,word or dword.

hope you get my point now.


Edited

another thing i found

when choose menu make->source HLABE it gave the folowing

    r4__hla_1886 :byte[44];
    _075d__lbl____hla_1887:Byte; @nostorage;
    :Byte[20] := 20 dup [0];


so you got r4__hla_1886 & _075d__lbl____hla_1887 variables!!!!!!!!!!!

instead you have to got only one variable , 2 varaibles west the memory as you know.


Emil_halim

this is what i done until now , works ok.

#macro pad64( _rec_ ):theVar,pad,sz;
?sz : byte := 64 - (@size(_rec_) MOD 64) ; 
forward( theVar );
        theVar : _rec_ ;
        pad : byte[@text(@string:sz)];
#endmacro


any suggestion are welcome.

Sevag.K

Quote from: Emil_halim on November 16, 2010, 10:54:03 AM
you have got my words correctly , nice explanation.

the first choice gives align value must be 16 or less when compiled with Fasm
and gives invalid combination with segment alignment : 64.

could be a bug or limitation with fasm.

Quote
any way , i will choose the macro one but still have a problem.

i want to access to the members of record when padding it , i.e if only i declare it with byte i
can not access to it's members.

i think adding @noStorage statement will solve the problem.

for example

if i have the next record , and want to access u member

rec0 :record
var0 :byte[31];
i : int32;
u : uns64;
c : char;
endrecord;

r4 :pad64( rec0 );

i.e.

mov(r4.u , eax);


gives memory operand must by a byte,word or dword.

hope you get my point now.

you can't put a 64 bit value into a 32 bit register.  you have to type cast it.

ie:

mov( (type dword r4.u[0]), eax );  // move the L.O. dword of r4.u into eax



Quote
Edited

another thing i found

when choose menu make->source HLABE it gave the folowing

    r4__hla_1886 :byte[44];
    _075d__lbl____hla_1887:Byte; @nostorage;
    :Byte[20] := 20 dup [0];


so you got r4__hla_1886 & _075d__lbl____hla_1887 variables!!!!!!!!!!!

instead you have to got only one variable , 2 varaibles west the memory as you know.



yes, if you want to pad it without using align, the quick way is to define two addresses.  by the way, your own macro does this too.

if you don't want the addresses, you can insert the bytes without an address, using the following syntax:

byte 0, 0, 0, ... 0;

so you'll have to adjust your macro to write in the correct number of zeros and commas.

here is an adjusted macro that does just that, using only the record label.


#macro pad64b( _rec_ ):_size_;

_rec_;
?_size_ := 64-(@size(_rec_) MOD 64 );

#if( _size_ > 0 )

byte
?_size_ := _size_ -1;

#while( _size_ > 0 )

?_size_ := _size_ - 1;
0,

#endwhile
0

#endif

#endmacro


Emil_halim

ok this is perfect.

here is the final test

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

type
rec0 :record
var0 :byte[31];
i : int32;
u : uns64;
c : char;
endrecord;

rec1 :record inherits( rec0 );
align(64);
endrecord;

#macro pad64b( _rec_ ):_size_;

_rec_;
?_size_ := 64-(@size(_rec_) MOD 64 );

#if( _size_ > 0 )

byte
?_size_ := _size_ -1;

#while( _size_ > 0 )

?_size_ := _size_ - 1;
0,

#endwhile
0

#endif

#endmacro
#macro pad64( _rec_ ):pad,sz;
    ?sz : byte := 64 - (@size(_rec_) MOD 64) ; 
    _rec_ ;
        #if((@size(_rec_) MOD 64) >0);
         pad:byte[@text(@string:sz)];
        #endif
    #endmacro

static
r0 :rec0;
align(64);
r1 :rec0;
align(64);
r2 :rec1;
r3 :rec1;
r4 :pad64( rec0 );
r5 :pad64b( rec0 );


begin tt;

mov( &r1, eax );
sub( &r0, eax );
stdout.put((type uns32 eax ), nl);

mov( &r3, eax );
sub( &r2, eax );
stdout.put((type uns32 eax ), nl);

mov( &r5, eax );
sub( &r4, eax );
stdout.put((type uns32 eax), nl);

mov( 10, r4.i);
mov( r4.i , eax);
stdout.put((type uns32 eax), nl);

mov( 20, r5.i);
mov( r5.i , eax);
stdout.put((type uns32 eax), nl);

end tt;


the last thing that want to be commented, align a size bigger than 16 bytes gives error with Fasm & masm ??????????

Sevag.K


i don't know why it does this.  you should ask randall on the aoaprogramming list.  it could be a bug with hla or there may be a good reason why this is done.

Emil_halim


i will. thanks for your help.