.XLIST ; MSYSTEM.MAC ; Система макрокоманд языка ассемблер IBM PC ; Автор : Конюхов Д.Л. ; Дата : 10.03.92 NULL = 0 NIL = 0FFFFh TRUE = 0 FALSE = 1 CLC_TRUE EQU clc STC_FALSE EQU stc ;--- Программа --- PROG macro Name ifnb title Name else title @FileName endif endm BEGIN macro STARS,ORGS,BEGS,L ifnb org ORGS endif ifnb &STARS&: endif ifnb ifb jmp short BEGS else jmp near ptr BEGS endif endif endm ;--- Константы --- $gen macro p1 p1 endm $DEFINE macro p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14 $gen endm ;--- Переменные --- MPUBLIC macro p1 irp $$item, PUBLIC $$item endm endm MEXTRN macro p1 irp $$item, $extrn &$$item endm endm $extrn macro p1, p2 EXTRN &p2:&p1 endm COMMON macro Variable irp $$item, $publicv &$$item $variable &$$item endm endm $publicv macro p1, p2, p3 PUBLIC p2 endm PRIVATE macro Variable irp $$item, $variable &$$item endm endm $variable macro p1, p2, p3 ifidni , ifnb p2 db p3 else p2 db 0 endif elseifidni , ifnb p2 dw p3 else p2 dw 0 endif elseifidni , ifnb p2 dd p3 else p2 dd 0 endif elseifidni , ifnb p2 dq p3 else p2 dq 0 endif elseifidni , p2 label near elseifidni , p2 label far else p2 p1 p3 endif endm ;--- Ветвления и циклы --- GOTO macro Mark, L ifb jmp short Mark else jmp near ptr Mark endif endm MARKER macro Mark &Mark&: endm $isn macro p1 $$cntn=0 $$not=0 irpc $$item,p1 ifidni <$$item>, $$not=1 endif $$cntn=$$cntn+1 endm endm $ifn macro rel, mark $isn ife $$not jn&rel mark else $$cnt1=0 ife $$cntn-2 irpc $$item,rel $$cnt1=$$cnt1+1 ife $$cnt1-2 $if_mark mark,$$item endif endm else irpc $$item,rel $$cnt1=$$cnt1+1 ife $$cnt1-2 $$cnt1=0 irpc $$char,rel $$cnt1=$$cnt1+1 ife $$cnt1-3 $if_mark mark,$$item,$$char endif endm endif endm endif endif endm $if_mark macro mark, ch1, ch2 j&ch1&ch2 mark endm $cmp macro reg, arg ifnb $reg reg $arg arg purge $arg endif endm $reg macro reg1,reg2 ifnb mov reg1,reg2 endif $arg macro arg1,arg2 ifnb mov arg1,arg2 endif cmp reg1,arg1 endm endm IF_YES macro condition,then_go,L local $$mark1,$$mark2 $$or=0 $$and=0 irp $$item, $if_yes then_go,$$mark1,$$mark2,L,&$$item endm endm $if_yes macro lbl,mark1,mark2,L,p1,p2,p3,p4 ifnb $if_yes4 lbl,mark1,mark2,L,,,, elseifnb $if_yes3 lbl,mark1,mark2,L,,, elseifnb $if_yes2 lbl,mark1,mark2,L,, elseifnb $if_yes1 lbl,mark1,mark2,L, endif endm $if_yes4 macro lbl,mark1,mark2,L,reg,rel,arg,log $cmp , $if_yes2 lbl,mark1,mark2,L,, endm $if_yes2 macro lbl,mark1,mark2,L,rel,log ifidni , $$or=1 ifb j&rel lbl else j&rel mark2 endif elseifidni , $$and=1 ifb $ifn ,mark1 else $ifn ,mark1 endif endif endm $if_yes3 macro lbl,mark1,mark2,L,reg,rel,arg $cmp , $if_yes1 lbl,mark1,mark2,L, endm $if_yes1 macro lbl,mark1,mark2,L,rel ifb j&rel lbl else $ifn ,mark1 endif $yes_or$and lbl,mark1,mark2,L endm $yes_or$and macro lbl,mark1,mark2,L ifnb if $$or mark2: endif jmp near ptr lbl endif mark1: endm IF_NOT macro condition,then_go,L local $$mark1,$$mark2 $$or=0 $$and=0 irp $$item, $if_not then_go,$$mark1,$$mark2,L,&$$item endm endm $if_not macro lbl,mark1,mark2,L,p1,p2,p3,p4 ifnb $if_not4 lbl,mark1,mark2,L,,,, elseifnb $if_not3 lbl,mark1,mark2,L,,, elseifnb $if_not2 lbl,mark1,mark2,L,, elseifnb $if_not1 lbl,mark1,mark2,L, endif endm $if_not4 macro lbl,mark1,mark2,L,reg,rel,arg,log $cmp , $if_not2 lbl,mark1,mark2,L,, endm $if_not2 macro lbl,mark1,mark2,L,rel,log ifidni , $$or=1 ifb j&rel mark1 else j&rel mark1 endif elseifidni , $$and=1 ifb $ifn ,lbl else $ifn ,mark2 endif endif endm $if_not3 macro lbl,mark1,mark2,L,reg,rel,arg $cmp , $if_not1 lbl,mark1,mark2,L, endm $if_not1 macro lbl,mark1,mark2,L,rel ifb $ifn ,lbl else j&rel mark1 endif $not_or$and lbl,mark1,mark2,L endm $not_or$and macro lbl,mark1,mark2,L ifnb if $$and mark2: endif jmp near ptr lbl endif mark1: endm $$number = 0 $$number1 = 0 ;--- ВЕТВЛЕНИЯ --- $$count_co = 0 $$level_co = 0 $savelev_co macro num $$levco_&num = $$count_co $$number = $$count_co endm $plus_co macro $$count_co = $$count_co + 1 $$level_co = $$level_co + 1 $savelev_co %$$level_co endm $restlev_co macro num $$number = $$levco_&num endm $minus_co macro $restlev_co %$$level_co $$level_co = $$level_co - 1 endm IF$ macro condition, L $plus_co $if , %$$number, L endm $if macro condition, num, L if_not , $$&num&if, L endm ELSE$ macro L $minus_co $$number1=$$number $plus_co $else %$$number1, %$$number, L endm $else macro num1, num2, L goto $$&num2&if, L $$&num1&if: endm ENDIF$ macro $minus_co $endif %$$number endm $endif macro num $$&num&if: endm SWITCH macro reg, par_list, L $plus_co $$cnt = 0 irp $$item, $$cnt = $$cnt + 1 $switch1 <$$item>,, L endm endm $switch1 macro item_list, reg, L irp $$char, cmp reg,$$char $switch2 %$$number, %$$cnt, L endm endm $switch2 macro num, cnt, L local $$mark ifb jz $$&num&cnt&ca else jnz $$mark jmp near ptr $$&num&cnt&ca $$mark: endif endm CASE macro cnt, L $restlev_co %$$level_co $case %$$number, cnt, L endm $case macro num, cnt, L ifb jmp short $$&num&ec else jmp near ptr $$&num&ec endif $$&num&cnt&ca: endm ENDCASE macro $minus_co $endcase %$$number endm $endcase macro num $$&num&ec: endm ;--- ЦИКЛЫ --- $$count_do = 0 $$level_do = 0 $savelev_do macro num $$levdo_&num = $$count_do $$number = $$count_do endm $plus_do macro $$count_do = $$count_do + 1 $$level_do = $$level_do + 1 $savelev_do %$$level_do endm $restlev_do macro num $$number = $$levdo_&num endm $minus_do macro $restlev_do %$$level_do $$level_do = $$level_do - 1 endm DO macro Count LoadValue , $plus_do $do %$$number endm $do macro num $$&num&be: endm ENDDO macro L $minus_do ifb $enddo1 %$$number else $enddo2 %$$number endif endm $enddo1 macro num loop $$&num&be $$&num&en: endm $enddo2 macro num dec CX jz $$&num&en jmp near ptr $$&num&be $$&num&en: endm WHILE macro condition, L $plus_do $while ,L,%$$number endm $while macro condition,L,num $$&num&be: if_not ,$$&num&en,L endm ENDWH macro L $minus_do $endwh %$$number,L endm $endwh macro num, L goto $$&num&be, L $$&num&en: endm CONTINUE macro L $restlev_do %$$level_do $continue %$$number, L endm $continue macro num, L goto $$&num&be, L endm BREAK macro L $restlev_do %$$level_do $break %$$number, L endm $break macro num, L goto $$&num&en, L endm REPEAT macro $plus_do $repeat %$$number endm $repeat macro num $$&num&be: endm UNTIL macro condition, L $minus_do $until , L, %$$number endm $until macro condition, L, num if_not , $$&num&be, L $$&num&en: endm FOR macro reg, n1, n2, step, L, revers $plus_do LoadValue , ifb ifnb sub reg, step else dec reg endif else ifnb add reg, step else inc reg endif endif $for %$$number,,, L ifb ifnb add reg, step else inc reg endif else ifnb sub reg, step else dec reg endif endif endm $for macro num, reg, n2, L local $$mark $$&num&be: $cmp , ifnb jnz $$mark jmp near ptr $$&num&en $$mark: else jz $$&num&en endif endm ENDFOR macro L $minus_do $endfor %$$number, L endm $endfor macro num, L goto $$&num&be, L $$&num&en: endm CYCLE macro $plus_do $cycle %$$number, be endm $cycle macro num, lev $$&num&lev: endm ENDCYC macro $minus_do $cycle %$$number, en endm ;--- Подпрограммы --- offset_stack = 0 size_stack = 0 FUNC macro Name, Parameters, Registers, LocalVars, Publics ifnb $publicf name endif $proc name $parameters $stack ,name $push_regs endm $stack macro LocalVars, p1, p2 if size_stack InitStack elseifnb InitStack endif $return macro if size_stack RestStack ret size_stack elseifnb RestStack ret else ret endif endm endm ENDF macro ValueRetr $vretr $pop_regs purge $pop_regs $return purge $return $endf purge $endf endm EXIT macro ValueRetr $vretr $pop_regs $return endm $vretr macro p1 ifnb IRP $$item, $retr &$$item endm endif endm $retr macro p1,p2,p3 if (.TYPE p1) AND 00010000b LoadValue , elseifidni , LoadValue , elseifidni , LoadValue , elseifidni , ifb ifnb LoadValue , LoadValue , endif else LoadValue , LoadValue , endif elseifidni , LoadValue , LoadValue , LoadValue , LoadValue , elseifidni , LoadValue , elseifidni , ifb ifnb LoadValue , LoadValue , endif else LoadValue , LoadValue , endif endif endm $publicf macro p1, p2 ifb PUBLIC _&p1 else PUBLIC _&p2 endif endm $proc macro p1, p2 ifb _&p1 PROC near offset_stack = 4 else ifidni , _&p2 PROC far offset_stack = 6 elseifidni , _&p2 PROC near offset_stack = 4 endif endif $endf macro ifb _&p1 ENDP else _&p2 ENDP endif endm endm $parameters macro $$param size_stack=0 ifnb <$$param> irp $$item,<$$param> $param &$$item %offset_stack+size_stack endm endif endm $param macro p1, p2, p3 if (.TYPE p1) AND 00010000b p2 EQU p1 elseifidni , p2 EQU [BP]+p3 size_stack = size_stack + 2 elseifidni , p2 EQU [BP]+p3 size_stack = size_stack + 2 elseifidni , p2 EQU [BP]+p3 size_stack = size_stack + 4 elseifidni , p2 EQU [BP]+p3 size_stack = size_stack + 8 elseifidni , p2 EQU [BP]+p3 size_stack = size_stack + 2 elseifidni , p2 EQU [BP]+p3 size_stack = size_stack + 4 endif endm $push_regs macro p1 ifnb IRP $$item, push $$item endm endif $pop_regs macro ifnb $$cnt1=0 irp $$item, $$cnt1=$$cnt1+1 endm irp $$item, $$cnt2=0 irp $$item, $$cnt2=$$cnt2+1 ife $$cnt1-$$cnt2 pop $$item $$cnt1=$$cnt1-1 endif endm endm endif endm endm MFUNC macro Name, Parameters, Returns, External $mfunc ,,,Name endm $mfunc macro Parameters,Returns,External,Cal,Name ifb $mfunc1 ,,, else $mfunc1 ,,,, endif endm $mfunc1 macro Name,Parameters,Returns,External,Cal $$call&Name = 1 &name macro Pars, Rets $pars , if $$call&Name $$call&Name = 0 $external Name,External,Cal endif $call Name,External,Cal $rets , endm endm $pars macro Parameters,Pars ifnb $$mcnt=0 irp $$none, $$mcnt=$$mcnt+1 endm irp $$none, $$mcnt1=0 irp $$item, $$mcnt1=$$mcnt1+1 ife $$mcnt1-$$mcnt $$mcnt2=0 irp $$char, $$mcnt2=$$mcnt2+1 ife $$mcnt2-$$mcnt $load &$$item,&$$char $$mcnt=$$mcnt-1 exitm endif endm exitm endif endm endm endif endm $rets macro Returns,Rets ifnb $$mcnt1=0 irp $$item, $$mcnt1=$$mcnt1+1 $$mcnt2=0 irp $$char, $$mcnt2=$$mcnt2+1 ife $$mcnt2-$$mcnt1 $save &$$item,&$$char endif endm endm endif endm $external macro p1,p2,p3 ifnb ifnb EXTRN _&p1:&p3 else EXTRN _&p1:NEAR endif endif endm $call macro p1,p2,p3 ifnb call p3 ptr _&p1 else call near ptr _&p1 endif endm $load macro p1,p2,p3,p4 if (.TYPE p1) AND 00010000b LoadValue , elseifidni , PushValueDB elseifidni , PushValueDW elseifidni , PushValueDD , elseifidni , PushValueDQ , elseifidni , PushAddrNear , elseifidni , PushAddrFar , endif endm $save macro p1,p2,p3 if (.TYPE p1) AND 00010000b SaveValue , elseifidni , SaveValue , elseifidni , SaveValue , elseifidni , ifb ifnb SaveValue , SaveValue , endif else SaveValue , SaveValue , endif elseifidni , SaveValue , SaveValue , SaveValue , SaveValue , elseifidni , SaveValue , elseifidni , ifb ifnb SaveValue , SaveValue , endif else SaveValue , SaveValue , endif endif endm CheckSegReg macro Register IsSegReg = 0 if (.TYPE Register) and 00010000b irp Reg, ifidni , <&Reg&> IsSegReg = 1 exitm endif endm endif endm LoadAddress macro RSeg, ValueSeg, ROfs, ValueOfs ifidni , <@> lea ROfs, ValueOfs elseifidni , <*> mov ROfs, ValueOfs elseifidni , <**> l&RSeg ROfs, ValueOfs else ifnb ifdifi , CheckSegReg if IsSegReg push ValueSeg pop RSeg else if (.TYPE ValueSeg) and 00010000b mov RSeg, ValueSeg else mov ax, ValueSeg mov RSeg, ax endif endif endif endif ifnb ifdifi , mov ROfs, ValueOfs endif endif endif endm SaveAddress macro ValueOfs, ROfs, ValueSeg, RSeg ifidni , <@> mov ValueOfs, ROfs elseifidni , <*> mov ValueOfs, ROfs elseifidni , <**> mov word ptr ValueOfs, ROfs mov ax, RSeg mov word ptr ValueOfs+2, ax else ifnb ifdifi , mov ValueOfs, ROfs endif endif ifnb ifdifi , CheckSegReg if IsSegReg push RSeg pop ValueSeg else if (.TYPE ValueSeg) and 00010000b mov ValueSeg, RSeg else mov ax, RSeg mov ValueSeg, ax endif endif endif endif endif endm LoadValue macro Reg, Value ifnb ifdifi , mov Reg, Value endif endif endm SaveValue macro Value, Reg ifnb ifdifi , mov Value, Reg endif endif endm CheckTwoPoint macro Value IsTwoPoint=0 $$cnt=0 irpc $$char,Value $$cnt=$$cnt+1 ifidni <$$char>,<:> ife $$cnt-3 IsTwoPoint=1 exitm endif endif endm endm PushSegReg macro Value $$cnt=0 irpc $$char,Value ife $$cnt irpc $$item,Value ife $$cnt-1 PushReg $$char,$$item endif $$cnt=$$cnt+1 endm endif endm endm PushReg macro ch1,ch2 push &ch1&ch2 endm PushAddrNear macro Value, ValueOfs ifidni , <@> lea ax, ValueOfs push ax elseifidni , <*> PushValueDW else PushValueDW endif endm PushAddrFar macro ValueSeg, ValueOfs ifidni , <@> CheckTwoPoint ife IsTwoPoint push ds else PushSegReg endif lea ax, ValueOfs push ax elseifidni , <*> CheckTwoPoint ife IsTwoPoint push ds else PushSegReg endif PushValueDW elseifidni , <**> les ax, ValueOfs push es push ax else PushValueDW PushValueDW endif endm PushValueDB macro Value if (.TYPE Value) and 00010000b push Value else LoadValue , push ax endif endm PushValueDW macro Value if (.TYPE Value) and 00010000b push Value else mov ax, Value push ax endif endm PushValueDD macro ValueHight, ValueLow ifb mov AX, word ptr ValueHight+2 push AX mov AX, word ptr ValueHight push AX else PushValueDW PushValueDW endif endm PushValueDQ macro Value push word ptr Value+6 push word ptr Value+4 push word ptr Value+2 push word ptr Value endm ;--- Вектор --- FINT macro Name, Registers name PROC far $push_regs $endi macro Return Return name ENDP endm endm ENDI macro Return $pop_regs purge $pop_regs $endi purge $endi endm ;--- Прерывания --- INTR macro Name, Parameters, Returns, Interrupt, Function, UnderFunc &Name macro Pars, Rets $mpars , $fun , int Interrupt $mrets , endm endm $fun macro Function, UnderFunc ifnb ifnb mov AX, Function*100h+UnderFunc else mov AL, UnderFunc endif else ifnb mov AH, Function endif endif endm $mpars macro Parameters,Pars ifnb $$cnt1 = 0 irp $$item, $$cnt1 = $$cnt1 + 1 $$cnt2 = 0 irp $$char, $$cnt2 = $$cnt2 + 1 ife $$cnt2 - $$cnt1 $mload &$$item,&$$char exitm endif endm endm endif endm $mrets macro Returns,Rets ifnb $$cnt1 = 0 irp $$item, $$cnt1 = $$cnt1 + 1 $$cnt2 = 0 irp $$char, $$cnt2 = $$cnt2 + 1 ife $$cnt2 - $$cnt1 $msave &$$item,&$$char exitm endif endm endm endif endm $mload macro p1,p2,p3,p4,p5,p6 ifb LoadValue , else LoadAddress ,,, endif endm $msave macro p1,p2,p3,p4,p5,p6 ifb SaveValue , else SaveAddress ,,, endif endm MINTR macro Interrupt, Parameters, Returns irp $$item, LoadValue &$$item endm int Interrupt irp $$item, SaveValue &$$item endm endm ;--- Стек --- InitStack macro LocalVars push bp mov bp, sp ifnb sub sp, LocalVars endif endm RestStack macro LocalVars ifnb add sp, LocalVars endif pop bp endm .LIST