News:

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

Main Menu

A problem with a macro

Started by RuiLoureiro, June 05, 2014, 04:39:07 AM

Previous topic - Next topic

RuiLoureiro


Hi all,
        In the folowing macro if we do
   
            SETRECORDSIZEMACRO  1000
       
        it doesn´t assemble. We wait and nothing!

        Is there a best way to implement it ?
        Thanks


SETRECORDSIZEMACRO  MACRO   kInt

                    IF  kInt LE $RECORDSIZE_256

                        IF  kInt EQ $RECORDSIZE_32

                            LenOfRecords equ $RECORDSIZE_32
                            $RECORDSIZE  equ $SHLRECORDSIZE_32

                        ELSEIF  kInt EQ $RECORDSIZE_64

                                LenOfRecords equ $RECORDSIZE_64
                                $RECORDSIZE  equ $SHLRECORDSIZE_64
                               
                        ELSEIF  kInt EQ $RECORDSIZE_128

                                LenOfRecords equ $RECORDSIZE_128
                                $RECORDSIZE equ $SHLRECORDSIZE_128
                        ELSE                                   
                                LenOfRecords equ $RECORDSIZE_256
                                $RECORDSIZE  equ $SHLRECORDSIZE_256
                        ENDIF
                    ;---------------------------------------------------
                    ELSEIF  kInt EQ $RECORDSIZE_512

                            LenOfRecords equ $RECORDSIZE_512
                            $RECORDSIZE  equ $SHLRECORDSIZE_512

                    ELSEIF  kInt EQ $RECORDSIZE_1024

                            LenOfRecords equ $RECORDSIZE_1024
                            $RECORDSIZE  equ $SHLRECORDSIZE_1024

                    ELSEIF  kInt EQ $RECORDSIZE_2048

                            LenOfRecords equ $RECORDSIZE_2048
                            $RECORDSIZE  equ $SHLRECORDSIZE_2048

                    ELSE                               
                            LenOfRecords equ $RECORDSIZE_4096
                            $RECORDSIZE  equ $SHLRECORDSIZE_4096
                    ENDIF
                   
                    $RECORDSIZE4    = $RECORDSIZE / 4                   
ENDM


jj2007

SETRECORDSIZEMACRO  MACRO

SETRECORDSIZEMACRO 1000 works for me.

qWord

I guess that kInt should be round up to the next higher power of two. e.g.:
SETRECORDSIZE MACRO   kInt
IF kInt LE 0
.err <what ever>
EXITM
ENDIF

srs_val = kInt
.radix 2
srs_txt TEXTEQU %srs_val
.radix 10
srs_log2p1 SIZESTR srs_txt
srs_pow2 = 1 SHL (srs_log2p1-1)
IF srs_val NE srs_pow2
IF srs_pow2 EQ 80000000h
.err <value to large>
ENDIF
srs_pow2 = srs_pow2 * 2
ENDIF

%echo _kInt=kInt --> @CatStr(%srs_pow2)
;LenOfRecords = srs_pow2 ???
ENDM
MREAL macros - when you need floating point arithmetic while assembling!

RuiLoureiro

 :greensml:
Jochen,
        The name is a name and
        i called «SETRECORDSIZEMACRO».
        Why not? Where is a different rule ?
        Thank you Jochen !  :t

qWord,
«I guess that kInt should be round up to the next higher power of two»
Yes, of course, you know!

        I tried to undestand what you did
        and i am close.
        Ok, LenOfRecords is srs_pow2. But
        i need the exponent also to
        the variable $RECORDSIZE.
        If kInt = 512 = 2^9 we must get
        $RECORDSIZE = 9.
        Could you do it ?
        Thank you qWord !  :t

qWord

Quote from: RuiLoureiro on June 05, 2014, 06:46:02 AMI tried to undestand what you did
        and i am close.
        Ok, LenOfRecords is srs_pow2. But
        i need the exponent also to
        the variable $RECORDSIZE.
        If kInt = 512 = 2^9 we must get
        $RECORDSIZE = 9.
        Could you do it ?
The trick is to convert the integer value to a string literal in base 2. The size of that string can be used to get the binary logarithm (more detailed: string size = Floor(log2(x))+1).
Thus the binary exponent is: srs_log2p1-1
MREAL macros - when you need floating point arithmetic while assembling!

RuiLoureiro

Ok, i will try it tomorrow
Thanks :t
Meanwhile i tried with 4000
and i got the same problem.
It has nothing to do with that macro.
The problem seems to be here:

MemForRecords       equ AllocRecords * LenOfRecords
                ;»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
                ; The memory structure for linked list,
                ; must be defined in .DATA in this way:
                ;»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»

                dq NumOfLkdFields dup(0)
                ;
                dd 0                  ; 44 for pNewRecordLIST   => for current record pointer               
                dd 0                  ; 40 for NewallocLIST     => current alloc
                dd 0                  ; 36 for FindFlagLIST     => find flag
                dd 1                  ; 32 for IDXallocLIST     => alloc first record
                ;
                dd offset _FrmRecord  ; 28 for pFrmRecordLIST   => for record format
                dd 0                  ; 24 for SizeStringLIST   => any string length                 
                dd 0                  ; 20 for NumRecordsLIST   => number of records in the list
                dd NumOfFields        ; 16 for NumFieldsLIST    => number of fields
                dd LenOfRecords       ; 12 for SizeRecordLIST   => size of each record
                dd AllocRecords       ;  8 for TotRecordsLIST   => number of allocated records
                dd 0                  ;  4 for pMemallocLIST    => memory pointer
;_LkdDataABase   db MemForRecords dup(?)

qWord

sorry, forgot the case when the pwr2 is doubled  :redface:
should be something like:
SETRECORDSIZE MACRO   kInt
IF kInt LE 0
.err <what ever>
EXITM
ENDIF

srs_val = kInt
.radix 2
srs_txt TEXTEQU %srs_val
.radix 10
srs_log2p1 SIZESTR srs_txt
srs_pow2 = 1 SHL (srs_log2p1-1)
IF srs_val NE srs_pow2
IF srs_pow2 EQ 80000000h
.err <value to large>
ENDIF
srs_pow2 = srs_pow2 * 2
srs_log2p1  = srs_log2p1  + 1 ;; update log2
ENDIF
$RECORDSIZE = srs_log2p1 - 1
LenOfRecords = srs_pow2
ENDM
MREAL macros - when you need floating point arithmetic while assembling!

jj2007

Quote from: RuiLoureiro on June 05, 2014, 06:46:02 AM
:greensml:
Jochen,
        The name is a name and
        i called «SETRECORDSIZEMACRO».
        Why not? Where is a different rule ?

Rui,
There is no such rule, but when you wrote "it doesn't assemble", I thought it might have been one "MACRO" too much ;-)

RuiLoureiro

Quote
Rui,
There is no such rule, but when you wrote "it doesn't assemble", I thought it might have been one "MACRO" too much ;-)
Jochen,
             i understood exactly what you say here. I was kidding with you !  :biggrin:

RuiLoureiro

qWord,
        First of all, thank you so much !  :t
        Now, some questions. The first is this:

        When i do: 
                            SETRECORDSIZE  -200
        i get:

Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

Assembling: ...\LinkedList12\LkdList10.asm
...\LinkedList12\LkdList10.prj(103) : error A2045: missing angle bracket or brace in literal
SETRECORDSIZE(3): Macro Called From
...\LinkedList12\LkdList10.prj(103): Include File
_
Assembly Error
       
        It seems to mean that we dont need to do
       
            IF kInt LE 0
            .err <what ever>
            ENDIF       

        But, meanwhile, you are a gentle man !       
        replace it by this:
Quote
   IF kInt LE 0
             .err <Hey, bear! it cannot be a negative number!>
   ENDIF       
What do you say about this ?

qWord

The exclamation mark has a special meaning in angle brackets: the character flowing the "!" is treaded as literal in any case.  Because of that, the closing  ">" is recognized as part of the string and MASM complains about the missing bracket.
.err @CatStr(<Hey, bear!! it cannot be a negative number!!>)
MREAL macros - when you need floating point arithmetic while assembling!

RuiLoureiro

 :biggrin:
Hi qWord,
            It works very well.  ;)
            Thank you so much.  :t

%%%%%%%%%%%%%%%%%%%%%%%%
i am learning something about MACROS with you
%%%%%%%%%%%%%%%%%%%%%%%%

    note: i followed your explanation.
   
    I took your macro and i did this

        COMPUTERECORDSIZE kInt


COMPUTERECORDSIZE   MACRO   kInt

                  IF kInt LE 0
                        .err <Hey, bear, it cannot be a negative number>
            EXITM
                    ELSE
                   
                        ;; iInt = kInt
                        ;; IF iInt LE 16
                                               
                        IF kInt LE 16

                            ;;------------------------------------------------
                            ;;set it to 32 because the structure needs 8 bytes
                            ;;  so the length for anything is only 8 bytes
                            ;;          if we choose kInt=1 to 16
                            ;;------------------------------------------------

                            ;;iInt = 32

                            kInt = 32                           

                        ENDIF                   
              ENDIF

                    ;;------------------------------------------
                    ;; convert kInt into a decimal value srs_val
                    ;;------------------------------------------
              srs_val = kInt                      ;; value of kInt
              ;; srs_val = iInt                      ;; value of kInt

                    ;;------------------------------------------
                    ;; Take Base 2 and convert the value srs_val
                    ;;         to a text "string" srs_txt
                    ;;------------------------------------------
              .radix 2
        srs_txt TEXTEQU %srs_val            ;; string of binary digits

                    ;;------------------------------------------
                    ;; Take Base 10 and get the size of srs_txt.
                    ;; The most significant bit is at position
                    ;;        size of srs_txt - 1     
                    ;;------------------------------------------
              .radix 10

               sizebinarytext SIZESTR srs_txt      ;; size of it = number of binary digits

                    ;;------------------------------------------
                    ;; $RECORDSIZE is the exponent of power 2^x
                    ;;    To multiply by LenOfRecords we do
                    ;;           SHL  by $RECORDSIZE
                    ;;------------------------------------------
                    $RECORDSIZE   = sizebinarytext - 1   ;; exponent of 2^
                    LenOfRecords = 1 SHL $RECORDSIZE     ;; length of each record

              IF srs_val NE LenOfRecords

          IF LenOfRecords EQ 80000000h
       .err <value to large>
          ENDIF

                      ;;-----------------------------------------
                      ;;       set the next LenOfRecords
                      ;;-----------------------------------------
       LenOfRecords = LenOfRecords * 2
                      $RECORDSIZE  = $RECORDSIZE + 1

                      ;;------------------------------------------------
                      ;; $RECORDSIZE  is used to get each record pointer
                      ;; LenOfRecords is used to alloc memory for
                      ;;               the database
                      ;;------------------------------------------------
                %echo LenOfRecords=kInt --> @CatStr(%LenOfRecords)
                %echo $RECORDSIZE =kInt --> @CatStr(%$RECORDSIZE)

              ENDIF
ENDM
       

Quote
Example of what we are doing above

---------------------------------
For numbers from 32 to 63
        '0' is any x
---------------------------------

                       5  4  3  2  1  0    <- position
;-----------------------------------------------                                       
32   = 2^5  =    1  0  0  0  0  0B   => size =6   =>  size-1 = 5
                     ----------------------
                     ----------------------
                                            1    -> if we shift left this "1" by 5
                        1  0  0  0  0  0    <- we get this, which is =32 !

log2(2^5)= 5 = size-1

+++++++++++++++++++++++++++++
           now i have this problem
+++++++++++++++++++++++++++++

When i use iInt 
       and
           COMPUTERECORDSIZE 15

     i dont get the echo:
     
        LenOfRecords=15 --> 16
        $RECORDSIZE =15 --> 4

    Why ?
------------------------------------------------------
When i use kInt 
       and
           COMPUTERECORDSIZE 15           <---- is in .prj(98)
       i get this:
Quote
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

Assembling: ...\LinkedList12\LkdList10.asm
...\LinkedList12\LkdList10.prj(98) : error A2008: syntax error : integer
COMPUTERECORDSIZE(18): Macro Called From
...\LinkedList12\LkdList10.prj(98): Include File
LenOfRecords=15 --> 16
$RECORDSIZE =15 --> 4
_
Assembly Error
Prima qualquer tecla para continuar . . .


qWord

The macro parameters are not variables, they are placeholders for text replacement. Before "executing" the macro, MASM does search for the parameter IDs in the macro body and replace all occurrences with the corresponding text from the macro call. Thus "kInt = 32" becomes "15 = 32" after text replacement (for COMPUTERECORDSIZE 15). To solve the problem, just move the equate initialization (srs_val = kInt) at top of the macro and overwrite it if needed. Also remarks that there are ELSEIF-clauses, which makes live easier: "ELSEIF kInt LE 16"


MREAL macros - when you need floating point arithmetic while assembling!

RuiLoureiro

Quote
The macro parameters are not variables,
they are placeholders for text replacement.
Before "executing" the macro, MASM does search for the parameter IDs in the macro
body and replace all occurrences with the corresponding text from the macro call.

Thus the "kInt = 32" becomes "15 = 32" after text replacement.

It seems to mean this (more or less) by other words :
-Redefinitions of input parameters
are not allowed because...

Now, using your hint, just as you said:

       and
             COMPUTERECORDSIZE 15

        i don't get the echo:
     
             LenOfRecords=15 --> 16
             $RECORDSIZE =15 --> 4

        The question is: why ?
        I know that Len...=32 and $REC...=5

COMPUTERECORDSIZE   MACRO   kInt
                    ;;------------------------------------------
                    ;; convert kInt into a decimal value srs_val
                    ;;------------------------------------------
              srs_val = kInt                      ;; value of kInt

                  IF kInt LE 0
                        .err <Hey, bear, it cannot be a negative number>
            EXITM

                    ELSEIF kInt LE 16
                        ;;---------------                       
                        ;; set it to 32
                        ;;---------------
                        srs_val = 32                           
              ENDIF

                    ;;------------------------------------------
                    ;; Take Base 2 and convert the value srs_val
                    ;;         to a text "string" srs_txt
                    ;;------------------------------------------
              .radix 2
        srs_txt TEXTEQU %srs_val            ;; string of binary digits

                    ;;------------------------------------------
                    ;; Take Base 10 and get the size of srs_txt
                    ;; the most significant bit is at position
                    ;;        size of srs_txt - 1     
                    ;;------------------------------------------
              .radix 10

               sizebinarytext SIZESTR srs_txt      ;; size of it = number of binary digits

                    ;;------------------------------------------
                    ;; $RECORDSIZE is the exponent of power 2^x
                    ;;    To multiply by LenOfRecords we do
                    ;;           SHL  by $RECORDSIZE
                    ;;------------------------------------------
                    $RECORDSIZE   = sizebinarytext - 1   ;; exponent of 2^
                    LenOfRecords = 1 SHL $RECORDSIZE     ;; length of each record

              IF srs_val NE LenOfRecords

          IF LenOfRecords EQ 80000000h
       .err <value to large>
          ENDIF

                      ;;-----------------------------------------
                      ;;       set the next LenOfRecords
                      ;;-----------------------------------------
          LenOfRecords = LenOfRecords * 2
                      $RECORDSIZE  = $RECORDSIZE + 1

                      ;;------------------------------------------------
                      ;; $RECORDSIZE  is used to get each record pointer
                      ;; LenOfRecords is used to alloc memory for
                      ;;               the database
                      ;;------------------------------------------------
                %echo LenOfRecords=kInt --> @CatStr(%LenOfRecords)
                %echo $RECORDSIZE =kInt --> @CatStr(%$RECORDSIZE)

              ENDIF
ENDM

         
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997.  All rights reserved.

Assembling: ...\LinkedList12\LkdList10.asm
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

O volume na unidade C não tem nome
O número de série do volume é ...

Directório de ...\LinkedList12

05-06-2014  11:26           100.768 LkdList10.asm
04-06-2014  17:07            37.330 LkdList10.cnv
04-06-2014  17:07            14.190 LkdList10.dat
05-06-2014  10:32            23.828 LkdList10.deb
04-06-2014  17:07             2.451 LkdList10.equ
05-06-2014  17:40            52.224 LkdList10.exe
04-06-2014  17:07            19.191 LkdList10.frm
04-06-2014  17:08             7.038 LkdList10.glb
04-06-2014  18:14           250.339 LkdList10.inc
05-06-2014  17:40            45.327 LkdList10.mac
05-06-2014  17:40           107.761 LkdList10.obj
05-06-2014  16:30             8.225 LkdList10.prj
04-06-2014  17:09             3.784 LkdList10.pro
04-06-2014  17:50            16.115 LkdList10.txt
              14 ficheiro(s)          688.571 bytes
               0 Dir(s)        44.560.060.416 bytes livres
Prima qualquer tecla para continuar . . .

qWord

Quote from: RuiLoureiro on June 06, 2014, 02:50:18 AMIt seems to mean this (more or less) by other words :
-Redefinitions of input parameters
are not allowed because...
It is no redefinition - the identifier "kInt" is replaced by "15" when you call "COMPUTERECORDSIZE 15". Macro parameters are always treaded as strings/text - in your case the string is a numeric literal "15". In contrast to that, equates assigned with = are internally represented as binary values. The conversion from numeric literals (=strings) to equates is implicit done when using the "=" operator. However, converting equates to numeric literals (=string/text) requires the expansion operator "%".
For example:
foo = 123456 ; assign value
COMPUTERECORDSIZE %foo

Due to the expansion operator, the equate "foo" is converted to the string "123456", which is then used for text replacement in the macro body.[1]
For
COMPUTERECORDSIZE foo
the string "foo" is used for replacement in the macro body. This, for example, means the that "kInt = 32" becomes "foo = 32", which is valid. It is not wise to design macros in this way, because it requires that the corresponding macro parameter are equates.
Just as side note, remarks that macro parameters are trimmed (unless using angle brackets).

Quote from: RuiLoureiro on June 06, 2014, 02:50:18 AMi don't get the echo ...  why ?
Because the ECHO directives are placed inside the conditional block "IF srs_val NE LenOfRecords".

[1]The expansion operator does assume singed integer values. However, when using % with TEXTEQU/CATSTR/INSTR/SUBSTR or EXITM, the values are treaded as unsigned integers. For example "xyz TEXTEQU %(-1)" does assign the string "4294967295" to the text macro xyz (the expression "(-1)" does produce a temporary equate, btw).
MREAL macros - when you need floating point arithmetic while assembling!