flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
revolution 20 Apr 2011, 02:07
To count the items you can enumerate the list with forward and/or reverse.
To get a specific item from the list you also enumerate and then set a label to just the desired item. But you can't do it the way you show above. fasm doesn't support macro functions. Use a the macro loop directives, forward and reverse. |
|||
![]() |
|
revolution 20 Apr 2011, 02:13
|
|||
![]() |
|
LocoDelAssembly 20 Apr 2011, 02:27
Code: list equ list.count equ 0 macro append item { match any, list \{ list equ list,item \} match , list \{ list equ item \} ; Keep count here so we don't have to make expensive re-calculations when needed rept 1 n:list.count+1\{list.count equ n\} } append 3 append 6 append 2 append 9 macro getItem index*, out* ; Index lower bound is 1. Exceeding upper bound returns last element { local _list match any, list \{_list equ any, END\} rept index\{ match item=,any,_list\\{ out equ item _list equ any \\} \} } macro getListSize out* { match value, list.count\{out equ value\} } ; In both cases, the pseudo IntToStr will fail with values greater than 9 getItem 3, output display 'The 3rd element is: ', output+'0', 13, 10 getListSize output display 'Number of elements in the list is: ', output+'0', 13, 10 |
|||
![]() |
|
SPTH 20 Apr 2011, 02:29
Thank you revolution for the incredible fast answere.
I found a quite beautiful way to determine the elements in a list Code: testlist equ 13,14,15,16 virtual ls: db testlist len = $ - ls end virtual but I will try it with your forward and reverse suggestions too, maybe that can be done even more easy. Thanks for the suggestion to the second question. I hope this works. If yes, I'll post my solution, otherwise I will continue asking ;) [edit] Thanks also to you LocoDelAssembly, have not seen your answere before! Awesome that this board is so active, even at this time. I'm going to try the suggestions now! [/edit] Last edited by SPTH on 20 Apr 2011, 03:16; edited 1 time in total |
|||
![]() |
|
LocoDelAssembly 20 Apr 2011, 02:43
SPTH wrote:
![]() |
|||
![]() |
|
revolution 20 Apr 2011, 02:45
But LocoDelAssembly's answer was considerably more comprehensive, as usual. And I forgot about rept
![]() |
|||
![]() |
|
LocoDelAssembly 20 Apr 2011, 02:53
Still, your (or Tomasz's? or I didn't understand at all?) idea of using numbers could be better:
Code: list equ list.count equ 0 macro append item { rept 1 n:list.count+1\{ list.count equ n list\#n equ item \} } macro getItem index*, out* ; Index lower bound is 1 { match value, list#index \{out equ value\} } macro getListSize out* { match value, list.count\{out equ value\} } append 3 append 6 append 2 append 9 append 7 ; In both cases, the pseudo IntToStr will fail with values greater than 9 getItem 3, output display 'The 3rd element is: ', output+'0', 13, 10 getListSize output display 'Number of elements in the list is: ', output+'0', 13, 10 |
|||
![]() |
|
SPTH 20 Apr 2011, 03:14
LocoDelAssembly wrote:
This is exacty what I need, thank you! I tried to understand the code, the way you count is cool rept 1 n:list.count+1, counting one time starting from the desired value - clever how one works with that macro language. I really like such stuff :) Unfortunatly I dont really get the main part: Code: rept index\{ match item=,any,_list\\{ out equ item ; at least this line is clear ;) _list equ any \\} \} i see that you repeat it 'index'-times. and each time the _list will be decreased by the first element. But I dont get how this happens. Could you please give a short explanation?! What exactly is this match doing? Ah I see there is a second solution. I'll analyse that one now! Thanks alot to both of you! Fast answeres makes coding even more fun ;) |
|||
![]() |
|
SPTH 20 Apr 2011, 03:19
LocoDelAssembly wrote: Still, your (or Tomasz's? or I didn't understand at all?) idea of using numbers could be better: Haha this is exactly the workaround that I tried before posting here. I could not make it work - match does not like me so far... :) |
|||
![]() |
|
SPTH 20 Apr 2011, 03:28
The second solution with the definition of new symbols does not work if I will use it like this:
Code: nnn equ 3 getItem nnn, output It gives an error: "Undefined symbol listnnn". The compiler somehow does not translate the value. It works for the first solution - so I'll use the first one. And I'm reading about forward and reverse now. Thanks again! |
|||
![]() |
|
revolution 20 Apr 2011, 03:56
SPTH wrote: The second solution with the definition of new symbols does not work if I will use it like this: Code: match abc,nnn {getItem abc, output} |
|||
![]() |
|
LocoDelAssembly 20 Apr 2011, 04:22
SPTH wrote: Could you please give a short explanation?! What exactly is this match doing? So, suppose the index is two, then this would happen Code: ;First iteration any equ 6,2,9 ; <- The equ here doesn't really happen, it is just for the explanation out equ 3 _list equ 6,2,9 ; Notice I'm using the exact value as "_list equ any" would be indirect and hence not representing the real behavior ; Second and last iteration any equ 2,9 out equ 6 ; Overwrites previous item value (still recoverable with "restore item") _list equ 2,9 Hope I didn't make a mistake in the explanation. |
|||
![]() |
|
SPTH 20 Apr 2011, 05:29
LocoDelAssembly - I think I understand it now, got confused by the three variables.
OK, I have nearly finished what I want (filling a list and returning a random element) - but there is a problem. In macro GetRndElement RndElement* , the RndNum cant be used as argument for getListItem... This needs the whole code i guess to understand it, but its mainly copy-paste from here ;) Code: RndSymbol=%t AND 0xFFFFFFFF macro NewRndSymbol { RndSymbol = ((RndSymbol*214013+2531011) AND 0xFFFFFFFF) } macro getListSize list*, out* { local start virtual start: db list out = $ - start end virtual } macro getListItem list*, index*, out* { local _list match any, list \{_list EQU any, END\} rept index \{ match item=,any,_list \\{ out EQU item _list EQU any \\} \} } FillList.list EQU macro FillList number* { db 0x1 ; this has to be written to the output every time it runs... match any, FillList.list \{ FillList.list EQU FillList.list,number \} match , FillList.list \{ FillList.list EQU number \} } macro GetRndElement RndElement* { NewRndSymbol getListSize FillList.list, size RndNum EQU (RndSymbol MOD size) display 'RndNumber: ',RndNum+'0', 13,10 ; RndNum EQU 3 ; If i uncomment this, it works! ; match rnd, RndNum \{ getListItem FillList.list, rnd, RndElement \} ; not work eighter getListItem FillList.list, RndNum, RndElement } ; Filling the list FillList 'a' FillList 'b' FillList 'c' FillList 'd' FillList 'e' ; Listsize - works! getListSize FillList.list, size display 'ListSize: ',size+'0' display 13,10 ; Get 3rd List item - works! num EQU 3 getListItem FillList.list, num, element display 'list[',num+'0',']: ', element display 13,10 ; Get random list item GetRndElement RndItem display 'Element: ',RndItem Any idea why there is an error message "Invalid value", and how this can be solved? Anything I tried did not work. Thanks alot for your help! |
|||
![]() |
|
LocoDelAssembly 20 Apr 2011, 06:10
Unfortunately, %t (and using "=" rather than equ or define) won't work with preprocessor features as them are interpreted at different stages.
Still, if the list will be of numbers or strings only and you can tolerate having the value available not earlier than the assembler stage then something like this could be done: Code: list equ list.count equ 0 macro append item { match any, list \{ list equ list,item \} match , list \{ list equ item \} ; Keep count here so we don't have to make expensive re-calculations when needed rept 1 n:list.count+1\{list.count equ n\} } macro getItem index*, out* ; Index lower bound is 1. Exceeding upper bound returns last element { local _list match any, list \{_list equ any, END\} rept index\{ match item=,any,_list\\{ out equ item _list equ any \\} \} } macro getListSize out* { match value, list.count\{out equ value\} } macro getRandomItem out* ; NOTE: Output only usable at the assembler stage { ;assuming the list is made of numbers virtual at 0 dq list load output qword from ((%t shl 3) and $7FFF'FFFF) mod $ end virtual } append 3 append 6 append 2 append 9 append 7 ; In both cases, the pseudo IntToStr will fail with values greater than 9 getRandomItem output display 'The random element is: ', output+'0', 13, 10 getListSize output display 'Number of elements in the list is: ', output+'0', 13, 10 PS: And actually, lists of heterogeneous types would still be possible, but append would need an extra parameter to assist in type detection. |
|||
![]() |
|
SPTH 20 Apr 2011, 06:53
Hmm, ok i thought that something like that would be the cause of the problem.
Your solution works quite good (its only numbers, i just need that random elements late, ...). The only thing is that I need to generate 100s of random elements from a list - and %t seems to change only every second. That means I need to include some kind of LCG or something like that (just as I did before). I hope this works with your solution too. Unfortunatly I have no time at the moment, but I will try it in a few hours. Thanks again! |
|||
![]() |
|
SPTH 20 Apr 2011, 18:52
I tried it now, it works very good, also with a LCG. And its much smaller than the direct attempt before.
Thanks for that! |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.