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
SETRECORDSIZEMACRO MACRO
SETRECORDSIZEMACRO 1000 works for me.
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
: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
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
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(?)
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
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 ;-)
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:
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 ?
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!!>)
: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 . . .
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"
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 . . .
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).
Quote from: RuiLoureiro on Today at 02:50:18 AM
i don't get the echo ... why ?
Because the ECHO directives are placed inside the conditional block
"IF srs_val NE LenOfRecords".
. Yes it is and
I DON'T KNOW WHY !
. This is your first version that i saved
in my file LkdList10.mac.
. My version was done from this version
by copy/paste/modify.
I don't know why %echo is BEFORE ENDIF.
After working correctly i never watched
where was the ENDIF.
. But it is true that i forgot that detail.
Copy/paste problems ? maybe.
Thanks
Quote
SETRECORDSIZE1 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 ;; ???
$RECORDSIZE = srs_log2p1
$RECORDSIZE4 = LenOfRecords / 4
ENDM
I did use the ECHO directive only for debugging purpose, to give a direct feed back what the macro does ... I thought this was clear.
Just remove them in the final version.
Quote from: RuiLoureiro on Today at 02:50:18 AM
It 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".
-----------------------------------------------
I think you are taking my words in a wrong way.
What i said means this:
MACROx MACRO thisX
...
;; the bad idea
;;-------------
thisX = 12345 ;; redefine thisX
;; because we may give it
;; with «MACROx thisX»
...
ENDM
Well, when i write elsewhere
MACROx 15 ;; replace thisX by 15
i get:
;MACROx MACRO thisX
...
;;-------------
;; the bad idea
;;-------------
15 = 12345 ;; redefine thisX
...
;ENDM
it seems to be clear.
In any way, thanks for your lesson. :t
Quote from: qWord on June 06, 2014, 04:53:49 AM
I did use the ECHO directive only for debugging purpose, to give a direct feed back what the macro does ... I thought this was clear.
Just remove them in the final version.
No it is helpful qWord.
If we define the NODE structure with a length of 200
bytes and we do COMPUTERECORDSIZE 60
we have problems unless we use
COMPUTERECORDSIZE sizeof NODE.
Download the next version 10 of LinkedList
that i will post and you can see all this work.
To be simple, i never used: %
/TEXTEQU/CATSTR/INSTR/SUBSTR or EXITM.
I need to try to use it. But one day
Thank you so much, qWord :t
Hi
How do i convert MACRONAME to a string to be printed ?
Thanks :t
TESTTHISMACRO MACRO MACRONAME, $start, $end
LOCAL labelAA
;;
;; I want to print the string "MACRONAME"
;; HERE
;;
;; when i call
;;
;; TESTTHISMACRO thismacro, 1, 100
;;
;; i want to print the string: "thismacro",0
...
ENDM
Quote from: RuiLoureiro on July 29, 2014, 08:43:58 PM
Hi
How do i convert MACRONAME to a string to be printed ?
Thanks :t
TESTTHISMACRO MACRO MACRONAME, $start, $end
LOCAL labelAA, $tmpstr$, labelBB
;;
;; I want to print the string "MACRONAME"
;; HERE
;;
;; when i call
;;
;; TESTTHISMACRO thismacro, 1, 100
;;
;; i want to print the string: "thismacro",0
...
ENDM
SOLUTION I $tmpstr$ CATSTR <chr$(">, <
MACRONAME>, <",13,10)>
print $tmpstr$
SOLUTION II $tmpstr$ CATSTR <
">, <
MACRONAME>
, <">
.data
labelBB db $tmpstr$, 0
.code
print addr labelBB,13,10Is there another way ?
include \masm32\include\masm32rt.inc
TESTTHISMACRO MACRO MACRONAME, $start, $end
print "This is &MACRONAME with &$start and &$end", 13, 10
ENDM
.code
start: TESTTHISMACRO TheName, TheStart, TheEnd
exit
end start
Output: This is TheName with TheStart and TheEnd
Hi Jochen,
is far better :t
Thanks