; Cond.inc ; Conditional structure macros using short jumps ; Select JUMPS/NOJUMPS for automatic far jumps as needed ; Written for Borland Turbo Assembler using ideal mode ; condition may be any CPU flag valid for conditional jump opcode ; ; IfBeg ; code ;;If code ; ElseBeg ;;Start of ELSE portion, optional jmp size ; code ;;Optional condition check for ORIF ; OrIf ;;Optional branch back to IF code if true ; code ;;Actual ELSE code ; IfEnd ; ; UntilBeg ; code ;;Always do this ; UntilEnd ;;Loop back if condition is false ; ; WhileBeg ; condition test ;;Set CPU flags for condition test ; WhileDo ; code ;;Do this while condition is true ; WhileEnd ; ; LoopBeg ;;CX must hold initial counter value ; code ; LoopEnd ; ; LoopBeg z ;;CX must hold initial counter value ; jcxz LoopEnd ; code ; LoopEnd ; ; CheckNest ;;Display error if macros not properly nested and terminated ;?@macros are used by main conditional macros ?@sp equ 0 ;;Stack pointer ?@val equ 0 ;;Label index macro ?@pchk val, sp ;;Print unterminated conditional error %out Unterminated conditional before ??@&val %out sp value(s) on stack err Stack unbalanced ;;Force assembler error too endm macro ?@pdec val, sp ;;Print index underflow error message %out Nested conditional error before ??@&val %out sp value(s) on stack err Stack unbalanced ;;Force assembler error too endm macro ?@push1 sp, val ifb ?@stk&sp equ %?@val else ?@stk&sp equ %(val) endif endm macro ?@push val ?@push1 %?@sp, val ?@sp equ %(?@sp+1) endm macro ?@pop1 sp ?@rv equ %(?@stk&sp) ;;Return value endm macro ?@pop sp ifnb ?@pop1 sp else if ?@sp ?@sp equ %(?@sp-1) ?@pop1 %?@sp else ?@pdec %?@val, %?@sp ;;Stack underflow endif endif endm macro ?@inc ?@val equ %(?@val+1) endm macro ?@lblv val ;;Set label ??@&val: endm macro ?@lbl val ;;Set label using current val ifb ?@lblv %?@val else ?@lblv val endif endm macro ?@op op, val op ??@&val endm macro ?@negcond cond ?@instr instr , if ?@instr eq 1 ?@ncnd substr ,2 ;;Remove leading 'n' else ?@ncnd catstr , ;;Attach leading 'n' endif ?@jcnd catstr ,?@ncnd endm ;------------------------------------- ; IfBeg ; code for IF ; ElseBeg ; optional additional condition test ; OrIf ; code for ELSE ; IfEnd ;------------------------------------- macro ifbeg cond ?@push ;;If routine exits to here ?@inc ?@negcond cond ?@op %?@jcnd, %?@val ?@push ?@inc ?@lbl %?@val ;;ORIF branches here ?@push ?@inc endm macro orif cond ?@pop %(?@sp-1) ;;Exit address ifb ?@op jmp, %?@rv else ?@op j&cond, %?@rv endif endm macro elsebeg type ?@pop %(?@sp-3) ;;Exit address ifb ?@op , %?@rv else ?@op , %?@rv endif ?@pop %(?@sp-2) ;;Else address ?@lbl %?@rv ?@push1 %(?@sp-2), 0fffffh ;;Flag else address as used endm macro ifend ?@pop ;;Drop ORIF value ?@pop ;;ELSE value if ?@rv eq 0fffffh ;;ELSE present if eq ?@pop ?@lbl %?@rv ;;Exit address for ELSE else ?@lbl %?@rv ;;IF branches here ?@pop ;;Drop final label endif endm ;--------------------------- ; Loop macros ; CX must hold initial value ; LoopBeg ; code ; LoopEnd ;--------------------------- macro loopbeg z ?@push ;;Exit address in case of JCXZ ifnb ?@op jcxz, %?@val endif ?@inc ?@lbl ?@push ?@inc endm macro loopend ?@pop ?@op loop, %?@rv ?@pop ?@lbl %?@rv endm ;--------------------- ; UntilBeg ; code ; UntilEnd ;--------------------- macro untilend cond ?@negcond cond ?@pop ?@op %?@jcnd, %?@rv endm macro untilbeg ?@lbl ?@push ?@inc endm ;-------------------- ; WhileBeg ; condition test ; WhileDo ; code ; WhileEnd ;-------------------- macro whiledo cond ?@negcond cond ?@pop %(?@sp-2) ;;Exit address ?@op %?@jcnd, %?@rv endm macro whilebeg ?@push ;;Exit address ?@inc ?@lbl ;;WhileEnd branches here ?@push ?@inc endm macro whileend ?@pop ?@op jmp, %?@rv ?@pop ?@lbl %?@rv endm ;------------------------------------------------ ; Display error if conditions not properly nested ;------------------------------------------------ macro CheckNest ;;Error message if not properly nested if ?@sp ne 0 ?@pchk %?@val, %?@sp endif endm