flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > CALL return result support for HLL macros [fasmg] |
Author |
|
Beege 25 Nov 2019, 04:33
Heres an easy addon I made for the HLL macros to support some call return functionality. Its got a couple restrictions but works good for cleaning up code if you got a bunch of .elseif statements depending on a call result.
The restrictrictions are that you can only have one call per .if/.while/.repeat and the call needs to be the first condition that is following one of the following patterns regarding the parentheses. The macro just adds the call and replaces the condition with eax then passes on to original jcondexpr macro so any additional conditions specified after the call work as they normally would. All the patterns below that have parentheses also support boolean if wanted and could have additional check conditions added on to them and also support the negation operator as in the examples: Code: .if (callconv _add, a,b) = c .if callconv(_add, a,b) = c .if (callconv(_add, a,b) = c) no parentheses needed for boolean only: .if callconv _add, a,b Examples/testing: Code: mov ebx, 3 mov esi, 5 .if (stdcall _add,5,5) ; boolean check .endif .if (stdcall _add,5,5) = 10; compare check .endif .if (stdcall _add,5,5) = 10 & (ebx=5 | esi) & esi=5 ; compare + additional .endif .if (stdcall _add,5,5) & (ebx=5 | esi) & esi=5 ; boolean + additional .endif .if stdcall(_add,5,5) .endif .if stdcall(_add,5,5) = 10 .endif .if stdcall(_add,5,5) = 10 & (ebx | esi=4) & esi=5 .endif .if stdcall(_add,5,5) & (ebx | esi=4) & esi=5 .endif .if (stdcall(_add,5,5)) .endif .if (stdcall(_add,5,5) = 10) .endif .if (stdcall(_add,5,5) = 10) & (ebx | esi=4) & esi=5 .endif .if (stdcall(_add,5,5)) & (ebx | esi=4) & esi=5 .endif .if stdcall _add,5,5 ; boolean .endif .if ~(stdcall _add,5,-5) .endif .if ~stdcall(_add,5,5) <> 10 .endif .if ~stdcall(_add,5, stdcall _add, ebx, stdcall _add,esi,stdcall _add,-5,5) <> 13 & (ebx=33|esi=5) & esi=5 .endif xor ebx, ebx .while (stdcall _add,1,ebx) < 10 inc ebx .endw xor ebx, ebx .repeat inc ebx .until stdcall(_add,1,ebx) > 10 proc _add, i1, i2 mov eax, dword[i1] add eax, dword[i2] ret endp Please let me know if you see any issues or some syntax Im not thinking about. Improvements are very much welcome as well. Thanks Edit: Fixes and added support for negation operator and no parentheses boolean only pattern.
Last edited by Beege on 08 Dec 2019, 04:37; edited 2 times in total |
|||||||||||
25 Nov 2019, 04:33 |
|
Tomasz Grysztar 25 Nov 2019, 09:26
Beege wrote: I dont exactly understand why I had to use "rawmatch" here to detect the calls when it didnt have to be used in proc32.inc. The RAWMATCH is very rarely the right directive to use, because it strips the text of all the context information, and therefore it is applicable only to some specific corner case. When you really need to use RAWMATCH, you should know why. Apart from context-stripping (which is the main feature of RAWMATCH) it also differs from MATCH in that it does not replace symbolic variables with their values before matching. Perhaps this was the source of the problem? If you need to not replace values before matching, you can do it the same way that was used in fasm 1 - with a proxy variable made with DEFINE (note that it needs to be DEFINE and not EQU, because EQU replaces symbolic values before assignment, so it would gain us nothing): Code: local PROXY define PROXY full_condition match =( =stdcall? rest, PROXY Finally, I may recommend a trick that actually utilizes the fact that MATCH replaces symbolic variables with their values. By defining symbolic constants in a special namespace you can easily detect all of the calling convention words with just a single MATCH: Code: define __callconv define __callconv.stdcall? *stdcall define __callconv.invoke? *invoke define __callconv.ccall? *ccall define __callconv.cinvoke? *cinvoke define __callconv.call? *call macro _ifex jmplbl, full_condition& local callfound,newcond callfound = 0 match *any, __callconv.full_condition callfound = 1 else match (tail, full_condition match *any, __callconv.tail callfound = 1 end match end match define newcond full_condition ; ... |
|||
25 Nov 2019, 09:26 |
|
Beege 03 Dec 2019, 04:15
Quote:
Tomasz, this issue I ran into where MATCH can not detect keyword "stdcall" (and lead me down the RAWMATCH path) is currently effecting the original stdcall macro defined in proc32.inc in the same way. This can be seen if you try and do a nested call. The other call conventions are fine, its just stdcall Code: stdcall _add, 3, stdcall _add,3,3 ccall _add, 3, ccall _add,3,3 gives a listing/disassembly of: Code: 00000005: 6A 03 6A 24 E8 16 00 00 00 stdcall _retme, stdcall _retme, 3 0: 6a 03 push 0x3 2: 6a 24 push 0x24 4: e8 16 00 00 00 call 0x1f 0000000E: 6A 03 E8 0F 00 00 00 50 E8 09 00 00 00 83 C4 08 ccall _retme, ccall _retme, 3 0: 6a 03 push 0x3 2: e8 0f 00 00 00 call 0x16 7: 50 push eax 8: e8 09 00 00 00 call 0x16 d: 83 c4 08 add esp,0x8 A proxy variable could be used to fix this , but my guess is renaming the symbol for push_string macro will end up being fix here. That or Im down a wrong path again and incorrect about all of this. . |
|||
03 Dec 2019, 04:15 |
|
Tomasz Grysztar 03 Dec 2019, 08:22
Beege wrote: A proxy variable could be used to fix this , but my guess is renaming the symbol for push_string macro will end up being fix here. |
|||
03 Dec 2019, 08:22 |
|
Beege 04 Dec 2019, 03:48
Tomasz Grysztar wrote: Both methods would fix it, but I think I'm going to change the definition in proc32.inc because this way you may still be able to define aliases. Fixed with one word! Thats sweet! and way less modifications than what I was thinking had to happen. Thank you for the easy fix I was looking over all the match statements in proc32.inc searching for stdcall and noticed lines 252 and 255 both are matching a literal c. Are these meant to say =ccall? EDIT: NOPE! Found in documentation "The name of procedure can be also followed by either the stdcall or c keyword to define the calling convention it uses." |
|||
04 Dec 2019, 03:48 |
|
Beege 08 Dec 2019, 04:57
First post has been updated with primary macro below with all the recommendations and also added support for negation operator plus one more pattern requiring no parentheses if you only need a boolean check.
Code: macro _ifex jmplbl, cond& local cond_proxy,neg,callfound ;check if first token is "~" (negation) operator match ~negcond, cond define cond_proxy negcond neg equ ~ else define cond_proxy cond neg equ end match ;search for call convention usage from __callconv keyword list callfound = 0 match head tail, cond_proxy match *any, __callconv.head callfound = 1 else match (, head match *any, __callconv.tail callfound = 1 end match end match end match ;execute call and swap call with eax if callfound = 1 ;cc = call convention ;fa = function to call with arguments ;ov = condition operator and value to compare and/or additional conditions ;rc = remaining conditions match (cc(fa)ov)rc, cond_proxy ; .if (stdcall(_add,5,5) = 10) & (ebx | esi=4) & esi=5 cc fa jcondexpr jmplbl,1,(neg eax ov rc) ; else match (cc(fa)ov), cond_proxy ; .if (stdcall(_add,5,5) = 10) cc fa jcondexpr jmplbl,1,(neg eax ov) ; else match (cc(fa)), cond_proxy ; .if (stdcall(_add,5,5)) cc fa jcondexpr jmplbl,1,(neg eax) ; else match (cc fa)ov, cond_proxy; .if (stdcall _add,5,5) = 10 & (ebx | esi=4) & esi=5 cc fa jcondexpr jmplbl,1,(neg eax ov) else match (cc fa), cond_proxy ; .if (stdcall _add,5,5) cc fa jcondexpr jmplbl,1,(neg eax) else match cc(fa)ov, cond_proxy ; .if stdcall(_add,5,5) = 10 & (ebx | esi=4) & esi=5 cc fa jcondexpr jmplbl,1,(neg eax ov) else match cc(fa), cond_proxy ; .if stdcall(_add,5,5) cc fa jcondexpr jmplbl,1,(neg eax) else match cc fa, cond_proxy ; .if stdcall _add,5,5 ; boolean only cc fa jcondexpr jmplbl,1,(neg eax) end match else jcondexpr jmplbl,1,cond end if end macro |
|||
08 Dec 2019, 04:57 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.