flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > My Master Macro File |
Author |
|
baldr 14 Apr 2013, 11:51
alwaysnub,
Those USE_X macroinstructions can be defined in a batch: Code: irps bit_mode, 16 32 64 { macro USE_#bit_mode \{ USE#bit_mode Bit_Mode equ bit_mode \} } You may use rept for calculations more often: rept 1 .ParamOffset:Bit_Mode/4 { ParamOffset equ .ParamOffset } can replace all those ParamOffset equ X in PROC macro. Moreover, you may move definition of ParamOffset in USE_X macros altogether (since PROC depends on Bit_Mode being defined, and those macros are only ones that do so). ENDP macro could use bpReg that is defined in PROC macro to shorten its definition (rept could be used too, see previous paragraph). While it's perfectly sane to mix preprocessor's and assembler's directive (sometimes it is unavoidable, and it saves a lot of backslashing), you must exactly understand what happens. Your indenting in PCALL macro, for example, may be misleading: Code: macro PCALL ProcName,[arg] ;Directly call procedure. { common if ~ arg eq reverse PUSH arg common end if CALL ProcName } Code: macro pcall name, [arg] { common match args, arg \{; "if ~ arg eq" irp \arg, args \\{ \\reverse push \arg \\} \} call name } Code: macro PICALL ProcPointer,[arg] ;Indirectly call procedure. { common PCALL [ProcPointer], arg } It may be better to split second argument of JMPCOND (namely arg; I mean ":" delimiter) before main loop, than to collect instruction symbol-wise inside that loop. Also JMPCOND macro name may lead to wrong conclusion that in result it will jump if condition is met (while doing just opposite). Anyway, proper matchbox can simplify it: Code: macro convert op, cc, target, expr { match v1 op v2, expr \{ cmp v1, v2 j#cc target restore DONE DONE equ YES \} } macro JMP!COND target, [expr*] { common DONE equ NO convert =<==, g, target, expr convert >==, l, target, expr convert =<>, e, target, expr match =NO, DONE \{ convert =<, ge, target, expr convert >, le, target, expr convert ==, ne, target, expr \} restore DONE } Code: struc equ! expr { rept 1 value:expr \{ restore . . equ value \} } macro increment name { name equ! name+1 } |
|||
14 Apr 2013, 11:51 |
|
alwaysnub 15 Apr 2013, 04:53
Quote: Those USE_X macroinstructions can be defined in a batch: Yea, and its saves space. I also noticed while playing around if i define the macros as USE16, USE32 or USE64, it will override their original operation, i think this is a good aproach because one does not have to worry about typing USE_16 instead of USE16. Quote: test your example before posting! It's missing comma between Var1:WORD and Var2:WORD in PROC macro invocation. ... my bad Here is the updated file based on baldr suggestions: Code: ;Condition operators are, ; = (equal), < (less), > (greater), <= (less or equal), >= (greater or equal), <> (not equal). irps Bits, 16 32 64 { macro USE#Bits \{ USE#Bits Bit_Mode equ Bits \} } struc equ! expr { rept 1 newExpr:expr \{ restore . . equ newExpr \} } macro equ_increment Name,Increment { Name equ! Name+Increment } macro .if [arg] { __IF equ local ..endif __ENDIF equ ..endif local ..else __ELSE equ ..else JMP!COND __ELSE,arg } macro .else { JMP __ENDIF __ELSE: restore __IF __IF equ , } macro .elseif [arg] { JMP __ENDIF __ELSE: restore __ELSE local ..else __ELSE equ ..else JMP!COND __ELSE,arg } macro .endif { if __IF eq __ELSE: end if __ENDIF: restore __ELSE restore __ENDIF restore __IF } macro .while [arg] { local ..while __WHILE equ ..while local ..endw __ENDW equ ..endw __WHILE: .break equ JMP __ENDW if ~ arg eq JMP!COND __ENDW,arg end if .continue equ JMP __WHILE } macro .breakif [arg] { JMPCOND __ENDW,arg } macro .continueif [arg] { JMPCOND __WHILE,arg } macro .endw { JMP __WHILE __ENDW: restore .continue restore .break restore __ENDW restore __WHILE } macro JccMatchBox op, CC, label, expr { match v1 op v2, expr \{ CMP v1,v2 J#CC label restore DONE DONE equ YES \} } macro JMP!COND label,arg { DONE equ NO JccExpr equ arg match JccArg:PreInstruction, arg \{ PreInstruction restore JccExpr JccExpr equ JccArg \} JccMatchBox =<==, G, label, JccExpr JccMatchBox >==, L, label, JccExpr JccMatchBox =<>, E, label, JccExpr match =NO, DONE \{ JccMatchBox =<, GE, label, JccExpr JccMatchBox >, LE, label, JccExpr JccMatchBox ==, NE, label, JccExpr \} restore JccExpr restore DONE } macro JMPCOND label,arg { DONE equ NO JccExpr equ arg match JccArg:PreInstruction, arg \{ PreInstruction restore JccExpr JccExpr equ JccArg \} JccMatchBox =<==, LE, label, JccExpr JccMatchBox >==, GE, label, JccExpr JccMatchBox =<>, NE, label, JccExpr match =NO, DONE \{ JccMatchBox =<, L, label, JccExpr JccMatchBox >, G, label, JccExpr JccMatchBox ==, E, label, JccExpr \} restore JccExpr restore DONE } macro PROC ProcName,[arg] { common ProcName: match =16, Bit_Mode \{ PUSH BP MOV BP,SP bpReg equ BP \} match =32, Bit_Mode \{ PUSH EBP MOV EBP,ESP bpReg equ EBP \} match =64, Bit_Mode \{ PUSH RBP MOV RBP,RSP bpReg equ RBP \} ParamNamesToFix equ rept 1 PrmOffsetX:Bit_Mode/4 \{ ParamOffset equ PrmOffsetX \} forward match argName:argType, arg \{ match =WORD, argType \\{ ParamNamesToFix equ ParamNamesToFix\argName argName equ bpReg+ParamOffset equ_increment ParamOffset,2 \\} match =DWORD, argType \\{ ParamNamesToFix equ ParamNamesToFix\argName argName equ bpReg+ParamOffset equ_increment ParamOffset,4 \\} match =QWORD, argType \\{ ParamNamesToFix equ ParamNamesToFix\argName argName equ bpReg+ParamOffset equ_increment ParamOffset,8 \\} \} } macro ENDP { POP bpReg rept 1 PrmOffsetX:Bit_Mode/4 \{ RET ParamOffset-PrmOffsetX \} restore bpReg restore ParamOffset match Params, ParamNamesToFix \{ irps argName, Params \\{ restore argName \\} \} } macro PCALL ProcName,[arg] { common match args, arg \{ irp \arg, args \\{ \\reverse PUSH \arg \\} \} CALL ProcName } macro PICALL ProcPointer,[arg] { PCALL [ProcPointer],arg } Example usage: Code: USE16 ORG 0 PCALL MyFunction2, WORD BX, WORD 0 PROC MyFunction, Var1:WORD, Var2:WORD MOV AX,WORD [Var2] .while AX < 10 : INC AX .continueif AX < 6 .breakif AX > 6 .endw ENDP PROC MyFunction2, Var2:WORD, Var1:WORD MOV AX,WORD [Var2] .while .if AX > 111 .break .else .continue .endif .endw ENDP |
|||
15 Apr 2013, 04:53 |
|
baldr 15 Apr 2013, 06:55
alwaysnub wrote: I also noticed while playing around if i define the macros as USE16, USE32 or USE64, it will override their original operation, i think this is a good aproach because one does not have to worry about typing USE_16 instead of USE16. That recurring restore/equ combo encourages wrapping it in macro (struc macro, to be exact, — then you can write symbol reequ value). local and restore preprocessor directives accept multiple arguments. Multiple matches at start of PROC macro can be reduced to something like this: Code: match bit_mode, Bit_Mode { match head/=bit_mode bp sp/tail, //16 bp sp/32 ebp esp/64 rbp rsp// \{ push bp mov bp, sp bpReg equ bp \} } Matches inside match argName:argType, arg block are different only in equ_increment's second argument. You may define symbolic constants like sizeof.WORD equ 2, then use equ_increment ParamOffset, sizeof.#argType, with proper backslashing. BTW, there is no need of backslash before argName in that blocks. Make more use of equ! macro (hint: search for rept 1 outside of it). |
|||
15 Apr 2013, 06:55 |
|
alwaysnub 16 Apr 2013, 03:11
Quote: There is one subtlety: preprocessor symbols (e.g. macro names) are case-sensitive, while assembler directives aren't. Thus one can use use16 to have original directive behavior, and USE16 to invoke your macro. oh... I did not notice that, in that case i made it more likely to mess up. lol Ether way, both ways work, people will just have to watch what they type. Here is the updated file: Code: irps Bits, 16 32 64 { macro USE#Bits \{ use#Bits Bit_Mode equ Bits \} } sizeof.BYTE equ 1 sizeof.WORD equ 2 sizeof.DWORD equ 4 sizeof.QWORD equ 8 struc reequ value { restore . . equ value } struc equ! expr { rept 1 newExpr:expr \{ restore . . equ newExpr \} } macro equ_increment Name,Increment { Name equ! Name+Increment } macro equ_decrement Name,Decrement { Name equ! Name-Decrement } macro .if [arg] { __IF equ local ..endif __ENDIF equ ..endif local ..else __ELSE equ ..else JMP!COND __ELSE,arg } macro .else { JMP __ENDIF __ELSE: __IF reequ , } macro .elseif [arg] { JMP __ENDIF __ELSE: restore __ELSE local ..else __ELSE equ ..else JMP!COND __ELSE,arg } macro .endif { if __IF eq __ELSE: end if __ENDIF: restore __ELSE restore __ENDIF restore __IF } macro .while [arg] { local ..while __WHILE equ ..while local ..endw __ENDW equ ..endw __WHILE: .break equ JMP __ENDW if ~ arg eq JMP!COND __ENDW,arg end if .continue equ JMP __WHILE } macro .breakif [arg] { JMPCOND __ENDW,arg } macro .continueif [arg] { JMPCOND __WHILE,arg } macro .endw { JMP __WHILE __ENDW: restore .continue restore .break restore __ENDW restore __WHILE } macro JccMatchBox op, CC, label, expr { match v1 op v2, expr \{ CMP v1,v2 J#CC label DONE reequ YES \} } macro JMP!COND label,arg { DONE equ NO JccExpr equ arg match JccArg:PreInstruction, arg \{ PreInstruction JccExpr reequ JccArg \} JccMatchBox =<==, G, label, JccExpr JccMatchBox >==, L, label, JccExpr JccMatchBox =<>, E, label, JccExpr match =NO, DONE \{ JccMatchBox =<, GE, label, JccExpr JccMatchBox >, LE, label, JccExpr JccMatchBox ==, NE, label, JccExpr \} restore JccExpr restore DONE } macro JMPCOND label,arg { DONE equ NO JccExpr equ arg match JccArg:PreInstruction, arg \{ PreInstruction JccExpr reequ JccArg \} JccMatchBox =<==, LE, label, JccExpr JccMatchBox >==, GE, label, JccExpr JccMatchBox =<>, NE, label, JccExpr match =NO, DONE \{ JccMatchBox =<, L, label, JccExpr JccMatchBox >, G, label, JccExpr JccMatchBox ==, E, label, JccExpr \} restore JccExpr restore DONE } macro PROC ProcName,[arg] { common ProcName: match Bits, Bit_Mode \{ match Head/=Bits BP SP/Tail, //16 BP SP/32 EBP ESP/64 RBP RSP// \\{ PUSH BP MOV BP,SP bpReg equ BP \\} \} ParamNamesToFix equ ParamOffset equ! Bit_Mode/4 forward match argName:argType, arg \{ ParamNamesToFix equ ParamNamesToFix\argName argName equ bpReg+ParamOffset equ_increment ParamOffset,sizeof.\#argType \} } macro ENDP { POP bpReg RET ParamOffset-Bit_Mode/4 restore bpReg restore ParamOffset match Params, ParamNamesToFix \{ irps argName, Params \\{ restore argName \\} \} } macro PCALL ProcName,[arg] { common match args, arg \{ irp \arg, args \\{ \\reverse PUSH \arg \\} \} CALL ProcName } macro PICALL ProcPointer,[arg] { PCALL [ProcPointer],arg } I wont be posting any more updates. If baldr or someone has suggestions, then you'll have to make the changes based on what they say. Unless a bug is found i think the macro file is great for all os and non-os projects as it is. |
|||
16 Apr 2013, 03:11 |
|
alwaysnub 17 Apr 2013, 01:35
NOTE: FOUND A BUG!
Posting updated file because of bad code. notes about bug: The name PreInstruction in JMP!COND is misleading, its an instruction that gets executed after every loop. however, it was being executed once befor the loop ever started. Code: irps Bits, 16 32 64 { macro USE_#Bits \{ use#Bits Bit_Mode equ Bits \} } sizeof.BYTE equ 1 sizeof.WORD equ 2 sizeof.DWORD equ 4 sizeof.QWORD equ 8 struc reequ value { restore . . equ value } struc equ! expr { rept 1 newExpr:expr \{ restore . . equ newExpr \} } macro equ_increment Name,Increment { Name equ! Name+Increment } macro equ_decrement Name,Decrement { Name equ! Name-Decrement } macro .if [arg] { __IF equ local ..endif __ENDIF equ ..endif local ..else __ELSE equ ..else JMP!COND __ELSE,arg } macro .else { JMP __ENDIF __ELSE: __IF reequ , } macro .elseif [arg] { JMP __ENDIF __ELSE: restore __ELSE local ..else __ELSE equ ..else JMP!COND __ELSE,arg } macro .endif { if __IF eq __ELSE: end if __ENDIF: restore __ELSE restore __ENDIF restore __IF } macro .while [arg] { local ..while __WHILE equ ..while local ..endw __ENDW equ ..endw __WHILE: JccExpr equ arg if ~ arg eq match JccArg:AfterInstruction, arg \{ local ..over __OVER equ ..over JMP __OVER restore __WHILE local ..while __WHILE equ ..while __WHILE: AfterInstruction __OVER: JccExpr reequ JccArg restore __OVER \} JMP!COND __ENDW,JccExpr end if .break equ JMP __ENDW .continue equ JMP __WHILE } macro .breakif [arg] { JMPCOND __ENDW,arg } macro .continueif [arg] { JMPCOND __WHILE,arg } macro .endw { JMP __WHILE __ENDW: restore JccExpr restore .continue restore .break restore __ENDW restore __WHILE } macro JccMatchBox op, CC, label, expr { match v1 op v2, expr \{ CMP v1,v2 J#CC label DONE reequ YES \} } macro JMP!COND label,arg { DONE equ NO JccMatchBox =<==, G, label, arg JccMatchBox >==, L, label, arg JccMatchBox =<>, E, label, arg match =NO, DONE \{ JccMatchBox =<, GE, label, arg JccMatchBox >, LE, label, arg JccMatchBox ==, NE, label, arg \} restore DONE } macro JMPCOND label,arg { DONE equ NO JccMatchBox =<==, LE, label, arg JccMatchBox >==, GE, label, arg JccMatchBox =<>, NE, label, arg match =NO, DONE \{ JccMatchBox =<, L, label, arg JccMatchBox >, G, label, arg JccMatchBox ==, E, label, arg \} restore DONE } macro PROC ProcName,[arg] { common ProcName: match Bits, Bit_Mode \{ match Head/=Bits BP SP/Tail, //16 BP SP/32 EBP ESP/64 RBP RSP// \\{ PUSH BP MOV BP,SP bpReg equ BP \\} \} ParamNamesToFix equ ParamOffset equ! Bit_Mode/4 forward match argName:argType, arg \{ ParamNamesToFix equ ParamNamesToFix\argName argName equ bpReg+ParamOffset equ_increment ParamOffset,sizeof.\#argType \} } macro ENDP { POP bpReg RET ParamOffset-Bit_Mode/4 restore bpReg restore ParamOffset match Params, ParamNamesToFix \{ irps argName, Params \\{ restore argName \\} \} } macro PCALL ProcName,[arg] { common match args, arg \{ irp \arg, args \\{ \\reverse PUSH \arg \\} \} CALL ProcName } macro PICALL ProcPointer,[arg] { PCALL [ProcPointer],arg } |
|||
17 Apr 2013, 01:35 |
|
uart777 18 Apr 2013, 06:51
Just some notes:
Your procedures (PROC) are always inserted in the executable even if unused. If my library did this, minimal example would be 170K+! In LANGUAGE.INC>"function", notice the "if used name" (ProcName:) at the beginning and the "end if" in "endf". In JMP!COND: Code: JccMatchBox =<==, G, label, JccExpr JccMatchBox =<>, E, label, JccExpr JccMatchBox =<, GE, label, JccExpr Code: JccMatchBox <==, G, label, JccExpr JccMatchBox <>, E, label, JccExpr JccMatchBox <, GE, label, JccExpr "call" can be redefined and extended to accept parameters: Code: macro pushr [p] { common if ~p eq reverse pushd p common end if } macro call f, [p] { common pushr p call f } macro callp f, [p] { common call [f], p } |
|||
18 Apr 2013, 06:51 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.