flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > Some questions about Fasm preprocessor... |
Author |
|
vid 29 Dec 2005, 19:16
The_Grey_Beast wrote: How can you signal Fasm an error has occured? Like in C you can use #error, but is there something similar in Fasm? There is no such feature, because you need to specify in which compialtion stage error should happen. You can signal it during preprocessing, during parsing and during assembling, with some code that causes error in that stage. To cause preprocessor error you can use "macro}", for parsing error some undefined instruction like "sdkgsdkijgksdjfgdkjgkjg", for assembling error some invalid instruction/directive operands: "mov a,b,c,d,e,f,g,h,__undefined_symbol". (You need to understand how FASM compilation process work to know what happens in each stage) Question 2: There is no way to do this, symbol is conidered as entity, it cannot be divided. .... well, there is very ugly way to accmomplish this with "load" feature, but i rather won't even show it... btw, this was much easier question than first one... Question 3: You need to escape "#" operator too, because you must know during which macro unroll it happens. See this code: Code: macro a arg{ match x, arg \{ _#x: _\#x: \} } a name Code: _x: _name: |
|||
29 Dec 2005, 19:16 |
|
Borsuc 29 Dec 2005, 20:36
Thanks alot
Regarding first question: Wouldn't it be nice to have such directive? like .err, or %err, etc? Regarding second question: this method also works, without load directive: ah equ a h al equ a l bh equ b h bl equ b l ... should've used irps again, but... Is this a reliable method, I mean, without bugs, etc.. Regarding third question: Thanks ALOT.. it works |
|||
29 Dec 2005, 20:36 |
|
vid 29 Dec 2005, 21:52
1. During which part should it work - preprocessing, parsing or assembling. And when you understand FASM's multi-pass assembling mechanism, you will find out that it isn't possible.
2. hehe, yes. This is the "art" of fasm's preprocessor, you can find simple soltion. What do you need it for? There can be even more simple and straightforward way. |
|||
29 Dec 2005, 21:52 |
|
Borsuc 29 Dec 2005, 22:26
vid wrote: hehe, yes. This is the "art" of fasm's preprocessor, you can find simple soltion. What do you need it for? There can be even more simple and straightforward way. I'd like to do something like a packed instruction. pkmov ah:5, al:3, bx:5 will actually compile mov ax, ( 5 shl 8 ) + 5 mov bx, 5 of course, the value after the ':' symbol must be a numeric constant. this packs a list of constants into 'optimized' instructions. this code pkmov ch:4, dx:1, ah:5, bx:3, al:1 will compile mov ch, 4 mov dx, 1 mov ax, ( 5 shl 8 ) + 1 mov bx, 3 the examples should be pretty self-explanatory, 'cause I can't explain better in words. of course, this is just my 'ideal' macro. derivations and ideas are welcome.. my macro doesn't even work, so I don't think it's well-built The method with equ should be like this: irps r, a b c d \{ r\#h equ r h r\#l equ r l \} of course, it must be used again before closing macro, to restore the symbolic constants. This, apparently, right now works for the ah/al packing method (i.e packs it into 16-bit register like ax).. I dunno how to do it for eax, like: pkmov eax:10, ah:2 should replace the high-byte in the 16-bit register for eax (ah) with 2, because it's defined after eax:10.. something like: mov eax, 10 mov ah, 2 but packed into one instruction... something like: mov eax, (10 and 0xFFFF00FF) + ( 2 shl 8 ) i know it may be confusing, but that's why I asked the question in the first place.. if there's an obvious solution, this question might be stupid. thanks again |
|||
29 Dec 2005, 22:26 |
|
Tomasz Grysztar 29 Dec 2005, 23:28
Very interesting idea for a macro... Here's how I tried to implement it, using generally much more "classical" fasm methods, with only one "match" to allow the syntax you needed. I made it work just like in your examples, this:
Code: pkmov ch:4, dx:1, ah:5, bx:3, al:1 generates the instructions: Code: mov ax,501h mov ch,4 mov dx,1 mov bx,3 and this: Code: pkmov eax:10, ah:2 generates the: Code: mov eax,20Ah And here are the macros: Code: macro store@pkmov code,reg,value { if reg in <al,bl,cl,dl> value@pkmov = byte value offset@pkmov = 0 bytemask@pkmov = 1 bitmask@pkmov = 0FFh else if reg in <ah,bh,ch,dh> value@pkmov = byte value offset@pkmov = 1 bytemask@pkmov = 1 bitmask@pkmov = 0FFh else if reg in <ax,bx,cx,dx,si,di,sp,bp> value@pkmov = word value offset@pkmov = 0 bytemask@pkmov = 11b bitmask@pkmov = 0FFFFh else value@pkmov = dword value offset@pkmov = 0 bytemask@pkmov = 1111b bitmask@pkmov = 0FFFFFFFFh end if if mask@pkmov and 1111b shl (code*4) r#code#@pkmov = ( r#code#@pkmov and not (bitmask@pkmov shl (offset@pkmov*8)) ) or (value@pkmov shl (offset@pkmov*8)) else r#code#@pkmov = value@pkmov shl (offset@pkmov*8) end if mask@pkmov = mask@pkmov or bytemask@pkmov shl (code*4+offset@pkmov) } macro make@pkmov code,reg32,reg16,reg8h,reg8l { valuemask@pkmov = (mask@pkmov shr (code*4)) and 1111b if valuemask@pkmov = 1 & (~ reg8l eq ) mov reg8l,r#code#@pkmov else if valuemask@pkmov = 10b & (~ reg8h eq) mov reg8h,r#code#@pkmov shr 8 else if valuemask@pkmov & ~ valuemask@pkmov and 1100b mov reg16,r#code#@pkmov else if valuemask@pkmov mov reg32,r#code#@pkmov end if } macro pkmov [def] { common mask@pkmov = 0 forward match reg:value, def \{ if reg in <eax,ax,ah,al> store@pkmov 0,reg,value else if reg in <ecx,cx,ch,cl> store@pkmov 1,reg,value else if reg in <edx,dx,dh,dl> store@pkmov 2,reg,value else if reg in <ebx,bx,bh,bl> store@pkmov 3,reg,value else if reg in <esi,si> store@pkmov 4,reg,value else if reg in <edi,di> store@pkmov 5,reg,value else if reg in <esp,sp> store@pkmov 6,reg,value else if reg in <ebp,bp> store@pkmov 7,reg,value end if \} common make@pkmov 0,eax,ax,ah,al make@pkmov 1,ecx,cx,ch,cl make@pkmov 2,edx,dx,dh,dl make@pkmov 3,ebx,bx,bh,bl make@pkmov 4,esi,si make@pkmov 5,edi,di make@pkmov 6,esp,sp make@pkmov 7,ebp,bp } The last macro can be also made shorter this way: Code: regs0@pkmov equ eax,ax,ah,al regs1@pkmov equ ecx,cx,ch,cl regs2@pkmov equ edx,dx,dh,dl regs3@pkmov equ ebx,bx,bh,bl regs4@pkmov equ esi,si regs5@pkmov equ edi,di regs6@pkmov equ esp,sp regs7@pkmov equ ebp,bp macro pkmov [def] { common mask@pkmov = 0 forward match reg:value, def \{ rept 8 i:0 \\{ if reg in <regs\\#i\\#@pkmov> store@pkmov i,reg,value end if \\} \} common rept 8 i:0 \{ match regs, regs\#i\#@pkmov \\{ make@pkmov i,regs \\} \} } but I'm not sure whether it's really better. |
|||
29 Dec 2005, 23:28 |
|
vid 30 Dec 2005, 00:46
someone is killing time behind computer instead of sleeping in late night... tell me about it
|
|||
30 Dec 2005, 00:46 |
|
Tomasz Grysztar 30 Dec 2005, 15:54
Well, went to bed just about the time you wrote it.
And, by the way: vid wrote:
This will cause an error in assembly stage. I actually tried to reduce the errors signalized at parsing stage to minimum, to prevent problems with incorrect expressions etc. inside the "if" blocks. Yeah, this can be also solved with the partial "if" processing by the parser - I'm working on this, as it seems the parser should even be able to skip parsing the whole "if" blocks in some cases. But the other reason for moving signaling the errors into assembly stage is that the errors will occurs more accordingly to their order in source. So generally the most of the errors you can get are either from preprocessor or later from the assembler. So, after so massive rewrite and update of preprocessor during the recent versions, I may move to redesign some parts or even the whole of the parser - and this time with the rule in mind, that parser shouldn't signalize any errors on its own at all. The parsing stage has to be the transparent transition from the preprocessing to assembly, and for the fasm's user only knowledge of those two should be important. But, back to the errors topic - even though there shouldn't be any errors signalized by the parser stage, you've got some different type of errors singnalized by assembler - the "critical" ones, that are signalized immediately when encountered, and "recoverable" ones, that are not signalized when assembler plans to do one more pass (so it may happen they get fixed in the next pass). The illegal instruction from your sample is the "critical" error, while something like "times x nop" where value of "x" is -1 is an example of "recoverable" error. More on this topic you can find here: http://board.flatassembler.net/topic.php?t=3805 |
|||
30 Dec 2005, 15:54 |
|
Tomasz Grysztar 30 Dec 2005, 21:56
I have started the promised parser improvements and now I just realized that with the errors I have actually to do the opposite: if I want parser to be able to skip parsing the "if" blocks that can be determined to have false conditions during the parsing stage, I have to move the "structural" errors signalizing (like cross-nesting of "if" and "repeat") into the parser. So I bet we will still have some parser-specific errors.
I will try it and see what results it gives. So far I have made parser to precalculate the parts of logical expressions that can be determined at the parsing stage ("eq", "eqtype" and "in" operators) and reduce them to minimal forms. This allowed also to optimize and clean up the logical expression calculator that is later used by assembler - look out for the 1.65.0 dev. release to check it out. |
|||
30 Dec 2005, 21:56 |
|
Borsuc 31 Dec 2005, 14:30
Tomasz Grysztar wrote: Very interesting idea for a macro... Here's how I tried to implement it, using generally much more "classical" fasm methods, with only one "match" to allow the syntax you needed. I made it work just like in your examples, this: Cool thanks one more question: the equ defines symbolic constants.. but it also replaces the symbolic constants with their values on the right side of equ before defining them. this makes growing list of symbols possible. but, isn't there an alternative to it, without replacing the symbolic constants, thus: Code: a equ something b equ a b c d ; initially, I would like to pass this as "a b c d" ; without replacing a with something... match a b c d, b { display `a#`b#`c#`d } this code displays 'somethingbcd', and it's not what I wanted, of course... I would like to pass b as parameter to irps, for example, but without replacing symbolic constants... I tried with macro directive, but match doesn't work there. Code: a equ something macro b { a b c d } match a b c d, b { display `a#`b#`c#`d } apparently, the match directive does not replace b with macro definition at this stage.. is there a way to accomplish this (maybe a nasty trick ). thanks again for your help |
|||
31 Dec 2005, 14:30 |
|
Tomasz Grysztar 31 Dec 2005, 16:30
I am aware of this problem and there is no solution for it yet.
|
|||
31 Dec 2005, 16:30 |
|
Borsuc 31 Dec 2005, 17:24
Maybe a new directive should work? should be simple to do (simpler than the standard equ at least )
like const? or define? dunno, just some names or try unrolling macros at match directive? |
|||
31 Dec 2005, 17:24 |
|
Tomasz Grysztar 01 Jan 2006, 10:42
Macroinstructions as implemented by fasm are supposed to replace the instruction mnemonics and are recognized only as the whole instructions, and produce multiple lines from the single line which invokes them. For this reason fasm cannot recognize macro inside the arguments/other line contents.
So for solving this problem the only possible solution is some alternative to "equ" that wouldn't replace symbolic constants in the value before assigning it. "define" might be the right choice, however I haven't yet proposed it since till this discussion nobody else complained about this problem and I didn't want to breed too much directives when not really necessary. On the other hand, I would be able to improve the "struct" macro and fix some of its issues with the directive like that - so I guess I will now seriosly consider adding it in the next release. |
|||
01 Jan 2006, 10:42 |
|
Borsuc 02 Jan 2006, 12:40
something like this works: b equ 'a b c d'
quoted strings are not replaced with symbolic constants, but I can't find a way to 'unquote' the string... the ` operator seems to only 'add' quotes to a name, but wouldn't be nice to have it 'remove' quotes if there is a quoted string. I know, most assemblers/compilers don't do this, but why not make Fasm better? It's a simple feature, and should be no problem adding some cmps to see if string is quoted string (in fasm's source code, I mean ) .. something like this: Code: b equ 'a b c d' match any, b { irps r, `any \{ ... \} } alternatively, it could also be declared as: Code: b equ 'a b c d' b equ `b without the need to use the ` operator everywhere is there a reason not to make ` operator 'unquote' quoted strings? seems there is no way to 're' define some constants to original values with equ.. when you define something, that name cannot be used in other equ's (I mean literally), because it would be replaced. or try adding the = symbol like in match - make it mean something literally, without replacing symbolic constants. == should be used for literal = symbol. something like: Code: b equ =a =b =c =d will actually make b be a b c d. this works without new directive. should not be that hard, since match uses this syntax.. it's similar to it or are these ideas stupid struc improvements would be nice. good luck |
|||
02 Jan 2006, 12:40 |
|
Tomasz Grysztar 02 Jan 2006, 13:19
I did mean improvements of the "struct" macro, not the "struc" directive.
There no way to "unquote" the string, and it would be quite problematic, but there's now the "define" directive in fasm 1.65... (see below). As to restoring the symbolic constants to the original values, the oldest solution was like this: Code: _x equ x x equ something different ; ... x equ _x ; restores the original value And also check out the restore directive! But now with fasm 1.65 it can be just: Code: define x x |
|||
02 Jan 2006, 13:19 |
|
Borsuc 02 Jan 2006, 13:31
Sorry about struc confusion.. I mistyped it. I know struc is not even a macro, it's a preprocessor directive, isn't it? I meant the Win32 struct macro. sorry
how does define work.. does it push like equ (i mean, does it work with restore?). Code: x equ something define x something else restore x will x contain something from equ previous? If you haven't done documentation for define (didn't check it), I can help out. Sure, only if you want. Keep up the good work |
|||
02 Jan 2006, 13:31 |
|
Tomasz Grysztar 02 Jan 2006, 13:34
Yes, the DEFINE makes the same kind of definition like EQU, so RESTORE will work just like if you used EQU instead. The only difference is that DEFINE takes the literal value.
|
|||
02 Jan 2006, 13:34 |
|
Borsuc 02 Jan 2006, 13:45
Cool Thanks
fix idea was also nice. |
|||
02 Jan 2006, 13:45 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.