Skip to content

Instantly share code, notes, and snippets.

@adragomir
Created May 2, 2014 06:04
Show Gist options
  • Select an option

  • Save adragomir/9af66bef63d86bd90150 to your computer and use it in GitHub Desktop.

Select an option

Save adragomir/9af66bef63d86bd90150 to your computer and use it in GitHub Desktop.
; 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