Created
May 2, 2014 06:04
-
-
Save adragomir/9af66bef63d86bd90150 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ; supermacros.asm | |
| ; High-level constructs for NASM | |
| ; v0.5.0 - 01.05.2014 | |
| ; Take note that these macros are written in CamelCase. This is to distinguish | |
| ;then from assembly instructions, which are typically written all in one case. | |
| ; Functions =================================================================== | |
| ; Begin a function, or rather, the variable declaration part. Functions are | |
| ;global by default. Use LocalFunc to make a function that is not visible | |
| ;outside of its resident file. | |
| %macro Func 1 ; name | |
| global %1 | |
| %1: | |
| %push FuncVarList | |
| %assign ArgCount 0 | |
| %assign LocCount 0 | |
| %endmacro | |
| ; Identical to Func, only the function will not be visible ouside of the file | |
| ;that contains it. | |
| %macro LocalFunc 1 ;name | |
| %1: | |
| %push FuncVarList | |
| %assign ArgCount 0 | |
| %assign LocCount 0 | |
| %endmacro | |
| ; Define a name for a stack argument. These are be listed in the same order as | |
| ;they are in a C function prototype, that is, left-to-right. | |
| %macro Arg 2 ; name, size | |
| %ifctx FuncVarList | |
| %xdefine %1 [ebp+(ArgCount+8)] | |
| %assign ArgCount ArgCount + %2 | |
| %else | |
| %fatal "`Arg' must be inside function variable list" | |
| %endif | |
| %endmacro | |
| ; Define a name for a local variable and increase the space to be | |
| ;allocated on the stack. | |
| %macro Loc 2 ; name, size | |
| %ifctx FuncVarList | |
| %xdefine %1 [ebp-(LocCount+8)] | |
| %assign LocCount LocCount + %2 | |
| %else | |
| %fatal "`Loc' must be inside function variable list" | |
| %endif | |
| %endmacro | |
| ; Begin the code section of a function. The stack frame is created and space | |
| ;for stack variable is allocated, if neccesary. | |
| %macro Body 0 | |
| %ifctx FuncVarList | |
| %repl FuncBody | |
| push ebp | |
| mov ebp, esp | |
| %if LocCount > 0 | |
| sub ebp, LocCount | |
| %endif | |
| %else | |
| %fatal "`Body' must be after function argument list" | |
| %endif | |
| %endmacro | |
| ; Set EAX to the return value (if given) and return from the function. If a | |
| ;function does not have a Return, it could potentially run off the end into | |
| ;the great abyss of unused memory. | |
| %macro Return 0-1 eax ; value | |
| %ifctx FuncBody | |
| %repl FuncBodyReturn | |
| %endif | |
| %ifctx FuncBodyReturn | |
| %if %1 != eax | |
| mov eax, %1 | |
| %endif | |
| mov esp, ebp | |
| pop ebp | |
| %if LocCount > 0 | |
| ret LocCount | |
| %else | |
| ret | |
| %endif | |
| %else | |
| %fatal "`Return' must be inside function body" | |
| %endif | |
| %endmacro | |
| ; End the code section of a function. | |
| %macro EndFunc 0 | |
| %ifctx FuncBodyReturn | |
| %pop | |
| %elifctx FuncBody | |
| %warning "function without a `Return'" | |
| %else | |
| %fatal "`Endfunc' must follow `Body'" | |
| %endif | |
| %endmacro | |
| ; Repeat Loops ================================================================ | |
| ; Start a Repeat loop. Jump back with a While, Until, or Forever. | |
| %macro Repeat 0 | |
| %push Repeat | |
| %$DO: | |
| %endmacro | |
| ; If the condition is true, jump back to the corresponding Do. | |
| %macro While 1 ; condition | |
| %ifctx Repeat | |
| j%1 %$DO | |
| %$BRK: | |
| %pop | |
| %else | |
| %fatal "`While' must match a `Repeat'" | |
| %endif | |
| %endmacro | |
| ; If the condition isn't true, jump back to the corresponding Do. | |
| %macro Until 1 | |
| %ifctx Repeat | |
| jn%1 %$DO | |
| %$BRK: | |
| %pop | |
| %else | |
| %fatal "`Until' must match a `Repeat'" | |
| %endif | |
| %endmacro | |
| ; Unconditionally jump back to the corresponding Do. | |
| %macro Forever 0 | |
| %ifctx Repeat | |
| jmp %$DO | |
| %$BRK: | |
| %pop | |
| %else | |
| %fatal "`Forever' must match a `Repeat'" | |
| %endif | |
| %endmacro | |
| ; If the condition is true, jump out of the corresponding Repeat loop. | |
| %macro BreakIf 1 | |
| %ifctx Repeat | |
| j%1 %$BRK | |
| %else | |
| %fatal "`BreakIf' must be inside `Repeat' loop" | |
| %endif | |
| %endmacro | |
| ; If the condition isn't true, jump out of the corresponding Repeat loop. | |
| %macro BreakUnless 1 | |
| %ifctx Repeat | |
| jn%1 %$BRK | |
| %else | |
| %fatal "`BreakUnless' must be inside `Repeat' loop" | |
| %endif | |
| %endmacro | |
| ; Unconditionall jump out of the corresponding Repeat loop. | |
| %macro Break 0 | |
| %ifctx Repeat | |
| jmp %$BRK | |
| %else | |
| %fatal "`Break' must be inside `Repeat' loop" | |
| %endif | |
| %endmacro | |
| ; If Blocks =================================================================== | |
| ; Start an If block. If you're programming in assembly, I expect you know how | |
| ;to use an If...EndIf or an If...Else...EndIf structure. | |
| %macro If 1 ; condition | |
| %push If | |
| jn%1 %$IFN | |
| %endmacro | |
| %macro Else 0 | |
| %ifctx If | |
| %repl IfElse | |
| jmp %$IFE | |
| %$IFN: | |
| %else | |
| %fatal "`Else' must follow `If'" | |
| %endif | |
| %endmacro | |
| %macro EndIf 0 | |
| %ifctx If | |
| %$IFN: | |
| %pop | |
| %ifctx IfElse | |
| %$IFE: | |
| %pop | |
| %else | |
| %fatal "`EndEf' must follow an `If' or an `Else'" | |
| %endmacro |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment