Возможности макрогенератора Текстовый препроцессор
Макроопределение - набор нескольких команд ассемблера, сгруппированных вместе под некоторым именем, и выполняющих некоторое законченное действие. Макровызов или макрокоманда, встречающаяся в тексте программы на языке ассемблера, вызывает замещение её на набор команд, вошедших в макроопределение. Макроподстановка – процесс замены макрокоманды на набор команд из макроопределения. Макрорасширение – набор команд вставленных в текст программы вместо макрокоманды. Если макроопределение описано, макрокоманда его вызова может встречаться в любом месте программы model small stack data *(+ str1 db 5 dup('string_1'),'$ E 67 5F 31) code 9 write macro str 10 mov ah,09h 11 lea dx,str 12 int 21h 13 endm main proc B8 0000s mov E D8 mov ds,ax write str B4 09 mov ah,09h BA 0000r lea dx,str A CD 21 int 21h exit C B8 4C00 MOV AX,04C00h F CD 21 INT 21h main endp
.model tiny.code org256 Mainproc mov dl,* mov ah,2 int 21h ret Mainendp endmain.model tiny.code org 256 Putstar macro mov ah,2 mov dl,* int 21h endm Mainproc putstar ret Mainendp endmain Построение простейшего макроопределения
Макроопределения с параметром Putstar macro mov dl,* mov ah,2 int 21h endm Putchar macro chr puch ax push dx mov ah,2 mov dl,chr int 21h pop dx pop ax endm.code org 256 Mainprocfar Putchar * ret Mainendp endmain.code Mainproc Putchar * puch ax push dx mov ah,2 mov dl,* int 21h pop dx pop ax ret Mainendp endmain
Формат макроса Макроопределение Имяmacro [арг1[:тип][,арг2[:тип]…]] список операторов endm Тип аргументов REQ – при вызове всегда требуется явное указание соответствующего параметра. = – если соответствующий пара- метр при вызове явно не указан, то подразумевается неявная инициализация его приведенным значением. Макрокоманда Имя [парам1[,парам2…]]
Символы, имеющие специальный смысл ;; - комментарии макроопределения не попа- дающие в макрорасширение (в отличие от ;) & - ограничитель имени макро аргумента % - признак вычисляемого константного выражения - ограничитель значения макропараметра ! – отмена специального смысла символа Local метка – предписывает генерировать в макроподстановке не повторяющиеся метки.
Пример Marray macro name,size,type:= Named&typesize dup(0) endm P equ 10 Q equ 2 Marrayarray1,%P*Q,w array1 dw20 dup(0) Marrayarray2,P*Q array2 dbP*Q dup(0)
Пример Absax macro localmet,fin cmpax,8000h jefin Met:negax jsmet Fin:nop endp … mov ax,2 absax mov ax,-5 absax mov ax,2 cmpax,8000h je??0000 ??0001:neg ax js??0001 ??0000:nop mov ax,-5 cmpax,8000h je??0002 ??0003:neg ax js??0003 ??0002:nop
Библиотеки макроопределений INCLUDE path:\file_name - включить содержимое файла в текст программы PURGE name - указывает имена макроопределений, которые не должны использоваться при компиляции данной программы Директива EXITM – прекращение процесса макрогенерации
Условные директивы IF*** xxxxx [ELSE операторы1операторы3] [ELSEIF*** ENDIF операторы2] IF выражение T: операторы1 F:операторы2 IFE выражение F: операторы1 T:операторы2 IFB : операторы1 *:операторы2 IFNB *: операторы1 :операторы2 IFIDN(I), =: операторы1 :операторы2 IFDIF(I), : операторы1 =:операторы2 IFDEF имя : операторы1 =:операторы2 IFNDEF имя :операторы1 =:операторы2 LT, LE EQ, NE GT, GE Без учета регистра
Пример.startmacro a movds,ax ifnb assume moves,ax endif endm.start mov mov ds,ax ….start + movds,ax assume moves,ax …
Директивы повторения 1 REPT выражение … ENDM.data k=0 rept 4 dbk k=k+1 endm WHILE условие … ENDM.data k=4 while k gt 1 dbk k=k-1 endm k=0 dbk k=k+1 dbk k=k+1 dbk k=k+1 dbk k=k+1 k=4 dbk k=k-1 dbk k=k-1 dbk k=k-1
Директивы повторения 2 IRP параметр, … ENDM SaveRegmacro RegList irp reg, push reg endm endm SaveReg IRPreg, pushreg ENDM IRPC параметр, строка … ENDM LoadRegmacro List irpc reg,List pop reg&&x endm endm LoadRegcba IRPCreg,cba popreg&x ENDM push ax push bx push cx pop cx pop bx pop ax
.ERRxx n - условная директива увеличения значения счетчика числа ошибок. Может сообщать код ошибки n. (хх – те же символы, что и в IFxx) %OUT текст – выводит на стандартный вывод текст сообщения об ошибке. GOTO :met – директива безусловного перехода макрогенератора к строке макроопределения с внутренней меткой :met.
Пример pushallmacror1,r2,r3,r4,r5,r6,r7,r8 ifnb pushr1 pushallr2,r3,r4,r5,r6,r7,r8 endif endm … pushallax,bx,cx … pushallax,bx,cx,dx,sp,bp,si,di Pushall ax,bx,cxPush ax Pushall bx,cxPush bx Pushall cxPush cx Pushall
Файл print.h.486.data cwrdw? rqlabelqword rdlabeldword rabdt? adr_rabddrab+8
Пролог основной программы.start macroa movds,ax ifnb moves,ax endif endm
Переход на новую строку newlinemacro pushax pushdx movah,2 movdl,13 int21h movdl,10 int21h popdx popax endm
Вывод текста из сегмента данных (должен заканчиваться знаком $) pr_str macro str pushax pushdx movah,9 leadx,str int21h popdx popax endm
Вывод k символов pr_char macroc,k:= pushax movah,2 ifdifi, pushdx mov dl,c endif ifidni, pushcx movcx,bx elseif k gt 1 pushcx movcx,k endif int 21h ifidni, loop$-2 popcx elseif k gt 1 loop$-2 popcx endif ifdifi, popdx endif popax endm
pr_int macrox,m:= localm1,m2,m3,m4,m5,m6,m7,m8,fin pusha if type x eq 1 push ax mov ah,x sar ax,8 mov word ptr rab,ax pop ax fild word ptr rab else fild x; Загрузили в стек FPU целое число endif Вывод целого числа со знаком
fbstprab; Выгрузили в память в BCD формате lesdi,adr_rab; Старший байт - байт знака и ovfl mov al,[di+1] xor al,0ffh; Если =FFh - переполнение jnz short m1 pr_char'*',5; печатаем звездочки jmp fin m1:moval,[di+1] testal,80h; Проверка знака jzshort m2 pr_char'-'; Печатаем минус, если число
repe scasb; Пропускаем старшие нули jz short m5 mov bx,cx inc bx shl bx,1 sub bl,m; для дробной части ja short m6 jz short m8 neg bl; печатаем ведущие нули pr_char'0',bx m8:mov bh,1 m6:movdl,[di+1]; Первый не нулевой байт shr dl,4 jnz short m3 test bh,1 jz short m cx,di
repe scasb; Пропускаем старшие нули jz short m5 mov bx,cx inc bx shl bx,1 sub bl,m; для дробной части ja short m6 jz short m8 neg bl; печатаем ведущие нули pr_char'0',bx m8:mov bh,1 m6:movdl,[di+1]; Первый не нулевой байт shr dl,4 jnz short m3 test bh,1 jz short m bx
repe scasb; Пропускаем старшие нули jz short m5 mov bx,cx inc bx shl bx,1 sub bl,m; для дробной части ja short m6 jz short m8 neg bl; печатаем ведущие нули pr_char'0',bx m8:mov bh,1 m6:movdl,[di+1]; Первый не нулевой байт shr dl,4 jnz short m3 test bh,1 jz short m
m3:adddl,48; Цифра в старшем полубайте не нуль pr_chardl m7:movdl,[di+1] and dl,0fh; Цифра из младшего полубайта add dl,48 pr_chardl jcxz short fin; Переход если этот байт единственн. mov si,di m4:lodsb mov dl,al shr dl,4; Старший полубайт текущего байта add dl,48 pr_chardl
m3:adddl,48; Цифра в старшем полубайте не нуль pr_chardl m7:movdl,[di+1] and dl,0fh; Цифра из младшего полубайта add dl,48 pr_chardl jcxz short fin; Переход если этот байт единственн. mov si,di m4:lodsb mov dl,al shr dl,4; Старший полубайт текущего байта add dl,48 pr_chardl si
m3:adddl,48; Цифра в старшем полубайте не нуль pr_chardl m7:movdl,[di+1] and dl,0fh; Цифра из младшего полубайта add dl,48 pr_chardl jcxz short fin; Переход если этот байт единственн. mov si,di m4:lodsb mov dl,al shr dl,4; Старший полубайт текущего байта add dl,48 pr_chardl si
mov dl,al and dl,0fh ; Младший полубайт текущего байта add dl,48 pr_chardl loopm4 jmp short fin m5:pr_char '0',m; Печать нулевого числа fin:cld popa endm
print macrotp,x,after:= localm,m1,k ifidni, pr_int x ; Вывод целого числа со знаком elseifidni, push ax; Вывод целого без знака k= (type x) /2 while k lt 3 mov word ptr rab + 2*k,0 k=k+1 endm Основное макроопределение print
if type x eq 1 mov al,x mov byte ptr rq,al elseif type x eq 2 mov ax,x mov word ptr rq,ax elseif type x eq 4 mov eax,x mov dword ptr rq,eax else Display "Error Type of Unsigned Parameter &x".err exitm endif pop ax pr_int rq
elseifidni, fstcw cwr; Вывод вещественного числа push cwr and cwr,0f3ffh; Установить режим отбрасывания or cwr,0c00h; дробной части fldcw cwr fld x; Загрузить в стек FPU вещественное число fist rd; сохранить в памяти целую часть push rd cmp rd,0 jnzshort m1 ftst fstsw ax sahf jae short m1 pr_char '-'
m1:pr_intrd; и вывести её pr_char'.'; Вывести десятичную точку pop rd fisubrd; Вычислить дробную часть ftst fstswax sahf jashort m fchs ; Изменить знак в случае отрицательного числа m: k=0 rept 5 movword ptr rab + k,0 k=k+2 endm
if (after mod 2) eq 1 movbyte ptr rab+(after shr 1),10h else movbyte ptr rab+(after shr 1),1 endif; Определили сомножитель для выделения fbld rab; цифр после запятой fmul popcwr; Восстановить прежний режим работы FPU fldcw cwr fistp rd ; Сохранить целое число составленное из цифр, pr_int rd,after; стоящих после запятой и вывести его else Display"Error First Parameter".err endif endm
Вычисление функции x y fpwmacrox,y,z local cnt k= (type x) - 1 mov al,byte ptr (x+k) test al,80h jz short cnt.exit 1 cnt:finit fldy fldx fyl2x fldst frndint fxch fsub st,st(1) f2xm1 fld1 fadd fscale ffree st(1) ifnb fstp z else fstp x endif endm X Y
Вычисление функции x y fpwmacrox,y,z local cnt k= (type x) - 1 mov al,byte ptr (x+k) test al,80h jz short cnt.exit 1 cnt:finit fldy fldx fyl2x fldst frndint fxch fsub st,st(1) f2xm1 fld1 fadd fscale ffree st(1) ifnb fstp z else fstp x endif endm Y* log 2 X
Вычисление функции x y fpwmacrox,y,z local cnt k= (type x) - 1 mov al,byte ptr (x+k) test al,80h jz short cnt.exit 1 cnt:finit fldy fldx fyl2x fldst frndint fxch fsub st,st(1) f2xm1 fld1 fadd fscale ffree st(1) ifnb fstp z else fstp x endif endm Y* log 2 X
Вычисление функции x y fpwmacrox,y,z local cnt k= (type x) - 1 mov al,byte ptr (x+k) test al,80h jz short cnt.exit 1 cnt:finit fldy fldx fyl2x fldst frndint fxch fsub st,st(1) f2xm1 fld1 fadd fscale ffree st(1) ifnb fstp z else fstp x endif endm Y* log 2 X [Y* log 2 X]
Вычисление функции x y fpwmacrox,y,z local cnt k= (type x) - 1 mov al,byte ptr (x+k) test al,80h jz short cnt.exit 1 cnt:finit fldy fldx fyl2x fldst frndint fxch fsub st,st(1) f2xm1 fld1 fadd fscale ffree st(1) ifnb fstp z else fstp x endif endm [Y* log 2 X] {Y* log 2 X}
Вычисление функции x y fpwmacrox,y,z local cnt k= (type x) - 1 mov al,byte ptr (x+k) test al,80h jz short cnt.exit 1 cnt:finit fldy fldx fyl2x fldst frndint fxch fsub st,st(1) f2xm1 fld1 fadd fscale ffree st(1) ifnb fstp z else fstp x endif endm [Y* log 2 X] 2 {Y*log 2 X} -1
Вычисление функции x y fpwmacrox,y,z local cnt k= (type x) - 1 mov al,byte ptr (x+k) test al,80h jz short cnt.exit 1 cnt:finit fldy fldx fyl2x fldst frndint fxch fsub st,st(1) f2xm1 fld1 fadd fscale ffree st(1) ifnb fstp z else fstp x endif endm [Y* log 2 X] 2 {Y*log 2 X}
Вычисление функции x y fpwmacrox,y,z local cnt k= (type x) - 1 mov al,byte ptr (x+k) test al,80h jz short cnt.exit 1 cnt:finit fldy fldx fyl2x fldst frndint fxch fsub st,st(1) f2xm1 fld1 fadd fscale ffree st(1) ifnb fstp z else fstp x endif endm [Y* log 2 X] 2 {Y*log 2 X} *2 [Y*log 2 X]
Вычисление функции x y fpwmacrox,y,z local cnt k= (type x) - 1 mov al,byte ptr (x+k) test al,80h jz short cnt.exit 1 cnt:finit fldy fldx fyl2x fldst frndint fxch fsub st,st(1) f2xm1 fld1 fadd fscale ffree st(1) ifnb fstp z else fstp x endif endm [Y* log 2 X] 2 {Y*log 2 X}+[Y*log 2 X]
Вычисление функции x y fpwmacrox,y,z local cnt k= (type x) - 1 mov al,byte ptr (x+k) test al,80h jz short cnt.exit 1 cnt:finit fldy fldx fyl2x fldst frndint fxch fsub st,st(1) f2xm1 fld1 fadd fscale ffree st(1) ifnb fstp z else fstp x endif endm [Y* log 2 X] 2 Y*log 2 X
Вычисление функции x y fpwmacrox,y,z local cnt k= (type x) - 1 mov al,byte ptr (x+k) test al,80h jz short cnt.exit 1 cnt:finit fldy fldx fyl2x fldst frndint fxch fsub st,st(1) f2xm1 fld1 fadd fscale ffree st(1) ifnb fstp z else fstp x endif endm XYXY
Пример.model small.stack256 include print.h.data xdd-0.05 ydw-1234 zdb100 wdd code mainproc.start fpww,x printreal,w newline printreal,x,6 newline printint,y newline printunsign,y newline printunsign,z newline.exit 0 mainendp endmain
Пример irpp, irpcu,ab incu&&p endm endm irpcu,ab incu&h endm irpcu,ab incu&l endm incah incbh incal incbl
Пример irpс u,& irpp, x&u&pax,ax endm endm irpp, x&pax,ax endm xorax,ax