Page 1 of 1

Repeat / Duplicate for DataSection

Posted: Thu Feb 23, 2012 4:18 pm
by wilbert
As far as I know, when you want 80 times a quad value of 100 inside the data section, you have to specify it 80 times at the moment.
I would appreciate some sort of duplicate or repeat option so you can say you want a value n times repeated.

Re: Repeat / Duplicate for DataSection

Posted: Thu Feb 23, 2012 4:27 pm
by Shield
Try this as a workaround (god I love that word...)

I'm not sure if the generated code is correct (don't have the time to check), so be careful.
It doesn't work with PB's Data instruction.

Code: Select all

For i = ?start To ?stop - 1 Step SizeOf(Quad)
	Debug PeekQ(i)	
Next

DataSection
	start:
	!repeat 80
	!dq 100
	!end repeat
	stop:
EndDataSection

Re: Repeat / Duplicate for DataSection

Posted: Thu Feb 23, 2012 4:39 pm
by wilbert
I don't know about Windows and Linux but on OS X it doesn't work. :(
I prefer something cross platform but when it comes to data handling, FASM and NASM don't use the same syntax :?

A compiler directive like ...
CompilerIf #PB_Assembler = #PB_Assembler_FASM
CompilerIf #PB_Assembler = #PB_Assembler_NASM

might also do.

Re: Repeat / Duplicate for DataSection

Posted: Thu Feb 23, 2012 5:49 pm
by Danilo
Good request.

What about extending the request for a 'Times' keyword for use in Macros, too?
Could be useful in Macros to repeat something n times.
wilbert wrote:I don't know about Windows and Linux but on OS X it doesn't work. :(
I prefer something cross platform but when it comes to data handling, FASM and NASM don't use the same syntax :?
'times' is NASM syntax and works also with FASM. Does the following work on OS X?

1st try:

Code: Select all

Macro ASMRepeat
    !times
EndMacro

Macro Times(_times_,_value_,_type_) ; type: b, w, d, q, t
    _value_
    CompilerIf _times_ <> 1
    ASMRepeat _times_ - 1   d#_type_ _value_
    CompilerEndIf
EndMacro

i=1
Restore start
Repeat
    Read.q q.q
    Debug RSet(Str(i),3,"0") + ": " + Hex(q)
    i+1
Until q=0


DataSection
   start:
   Data.q Times(16,      $100, q)
   Data.b Times( 8,       $AB, b)
   Data.w Times( 4,     $1234, w)
   Data.l Times( 2, $AABBCCDD, d)
   Data.q 0
EndDataSection
2nd try:

Code: Select all

Macro ASMRepeat
    !times
EndMacro

Macro Times(_type_,_times_) ; type: b, w, d, q, t
    ASMRepeat _times_ d#_type_
EndMacro

i=1
Restore start
Repeat
    Read.q q.q
    Debug RSet(Str(i),3,"0") + ": " + Hex(q)
    i+1
Until q=0


DataSection
   start:
   Data.q -1
   Times(q,2) $01,$02,$03
   Times(q,4) $100
   Times(b,8) $AB
   Times(w,4) $1234
   Times(d,2) $AABBCCDD
   Data.q 0
EndDataSection

Re: Repeat / Duplicate for DataSection

Posted: Thu Feb 23, 2012 10:07 pm
by wilbert
It seems to repeat something but it also results in a number of errors like

- integer supplied to a DQ instruction
- symbol 'AB' undefined
- symbol 'AABBCCDD' undefined
- phase error detected at the end of assembly.

Re: Repeat / Duplicate for DataSection

Posted: Mon Feb 27, 2012 12:33 pm
by wilbert
It turns out dq only works with double precision numbers and not with a quad integer for nasm.
Hex values need to be encoded with 0x instead of $.
Besides that the code seems to work. This works on OS X

Code: Select all

Macro ASMRepeat
    !times
EndMacro

Macro Times(_type_,_times_) ; type: b, w, d, q, t
    ASMRepeat _times_ d#_type_
EndMacro

i=1
Restore start
Repeat
    Read.q q.q
    Debug RSet(Str(i),3,"0") + ": " + Hex(q)
    i+1
Until q=0


DataSection
   start:
   Data.q -1
   Times(b,4) 0x01, 0x02
   Times(b,8) 0xAB
   Times(w,4) 0x1234
   Times(d,2) 0xAABBCCDD
   Data.q 0
EndDataSection

Re: Repeat / Duplicate for DataSection

Posted: Wed Jan 02, 2013 4:41 pm
by Tenaja
I'd like to +1 this feature request; it would be nice to have this a native implementation.
I found this thread by searching for how to generating repeating data. ("+Duplicate +Data" found the thread.)

In the meantime, I have added a cleaner way to repeat Strings. I also renamed the Macro... I would rather do Rep than do Time. :)

This shows the two methods of producing repeating strings (original vs new), and the full code with demo code below it:

Code: Select all

	Rep(b,4) "Hi", 0 		; Duplicates a STRING--This WORKS; produces: times 4 db "Hi", 0
	RepString("Yo",4)		; Duplicates a STRING-- Also WORKS:			 times 4 db "Yo", 0

Code: Select all

Macro ASMRepeat
	!times
EndMacro

Macro DQ
	"
EndMacro

Macro Rep(_type_,_times_) ; type: b, w, d, q, t
	ASMRepeat _times_ d#_type_
EndMacro

Macro RepString(s, _times_) ; String type only
	ASMRepeat _times_ db s, 0
EndMacro

i=1
Restore start
Repeat
	Read.q q.q
	Debug RSet(Str(i),3,"0") + ": " + Hex(q)
	i+1
Until q=0

; ------------------------------------
; Print the Hi's:
	Read.s s.s
Debug s
	Read.s s.s
Debug s
	Read.s s.s
Debug s
	Read.s s.s
Debug s
; Print the Yo's:
	Read.s s.s
Debug s
	Read.s s.s
Debug s
	Read.s s.s
Debug s
	Read.s s.s
	Debug s
	
	
; ------------------------------------

DataSection
	start:
	Data.q -1
	Rep(b,4) 0x01, 0x02
	Rep(b,8) 0xAB
	Rep(w,4) 0x1234
	Rep(d,2) 0xAABBCCDD
	Data.q 0
	
	Rep(b,4) "Hi", 0 		; Duplicates a STRING--This WORKS; produces: times 4 db "Hi", 0
	RepString("Yo",4)		; Duplicates a STRING-- Also WORKS:			 times 4 db "Yo", 0
	
EndDataSection
Replicating data

Re: Repeat / Duplicate for DataSection

Posted: Wed Jan 02, 2013 6:17 pm
by freak
The following code is crossplatform (no asm needed) and works for all types. It can repeat 0-999 times. The macro can be extended easily to support more, but I don't see the sense in repeating the same value in a datasection more than 1000 times :)

Code: Select all

; repeat once
Macro _R1(_type_, _val_)
  Data._type_ _val_
EndMacro

; repeat 10 times
Macro _R10(_type_, _val_)
  _R1(_type_, _val_): _R1(_type_, _val_): _R1(_type_, _val_): _R1(_type_, _val_): _R1(_type_, _val_)
  _R1(_type_, _val_): _R1(_type_, _val_): _R1(_type_, _val_): _R1(_type_, _val_): _R1(_type_, _val_)
EndMacro

; repeat 100 times
Macro _R100(_type_, _val_)
  _R10(_type_, _val_): _R10(_type_, _val_): _R10(_type_, _val_): _R10(_type_, _val_): _R10(_type_, _val_)
  _R10(_type_, _val_): _R10(_type_, _val_): _R10(_type_, _val_): _R10(_type_, _val_): _R10(_type_, _val_)
EndMacro

; repeat _count_ times (0-999)
Macro Times(_type_, _val_, _count_)
  CompilerIf (_count_) > 999
    CompilerError "Repeat count cannot be more than 999"
  CompilerEndIf
  
  CompilerIf (_count_) >= 900: _R100(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) >= 800: _R100(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) >= 700: _R100(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) >= 600: _R100(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) >= 500: _R100(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) >= 400: _R100(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) >= 300: _R100(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) >= 200: _R100(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) >= 100: _R100(_type_, _val_): CompilerEndIf  
  
  CompilerIf (_count_) % 100 >= 90: _R10(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 100 >= 80: _R10(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 100 >= 70: _R10(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 100 >= 60: _R10(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 100 >= 50: _R10(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 100 >= 40: _R10(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 100 >= 30: _R10(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 100 >= 20: _R10(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 100 >= 10: _R10(_type_, _val_): CompilerEndIf  
  
  CompilerIf (_count_) % 10 >= 9: _R1(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 10 >= 8: _R1(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 10 >= 7: _R1(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 10 >= 6: _R1(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 10 >= 5: _R1(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 10 >= 4: _R1(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 10 >= 3: _R1(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 10 >= 2: _R1(_type_, _val_): CompilerEndIf
  CompilerIf (_count_) % 10 >= 1: _R1(_type_, _val_): CompilerEndIf  
EndMacro

; ---- example ----

Restore values
For i = 1 To 134
  Read.s x.s
  Debug Str(i) + ": " + x
Next i

DataSection
  values:
  Times(s, "foo", 23)
  Times(s, "bar", 111)
EndDataSection


Re: Repeat / Duplicate for DataSection

Posted: Wed Jan 02, 2013 6:27 pm
by Tenaja
freak wrote:The following code is crossplatform (no asm needed) and works for all types. It can repeat 0-999 times. The macro can be extended easily to support more, but I don't see the sense in repeating the same value in a datasection more than 1000 times :)
Thanks! Is there a reason to avoid asm in this situation? Are the assembler commands above not cross platform?

Re: Repeat / Duplicate for DataSection

Posted: Wed Jan 02, 2013 6:31 pm
by freak
I just prefer a PB only solution if there is one. It will correctly handle ascii/unicode switches or 32bit/64bit differences. Also you don't have to worry about NASM/FASM differences.

Re: Repeat / Duplicate for DataSection

Posted: Thu Jan 03, 2013 4:12 am
by Shield
Now that's a pretty nifty solution... :)