; Файл COMMONIB.INC ; ═════════════════════════════════════════════════════════════════════ ; CPU686 = 1 ; Часто используемые константы Yes equ 1 ; Да No equ 0 ; Нет null equ 0 ; символ Null nill equ -1 ; символ Nill variable equ 0 ; Означает в ряде наборов макросов переменный размер CR equ 0ah, 0dh ; Возврат каретки MsgEnd equ CR, '$' ; Конец сообщения ДОС Bell equ 7h ; Символ гудка в ДОСе ; ───────────────────────────────────────────────────────────────────── tmpvar=0 ; Временные переменные tmpvar1=0 tmpvar2=0 tmpvar3=0 ; ═════════════════════════════════════════════════════════════════════ ; Макросы общего назначения ; ───────────────────────────────────────────────────────────────────── ; Макросы проверки: является ли указанное имя именем регистра ЦП? ; Макросы возвращают переменную output=Yes, если input является именем регистра ; В противном случае, переменной output присваивается значение No ; Макрос IsItReg? возвращает в качестве ответа размер регистра ; 1 -- байт 4 -- двойное слово ; 2 -- слово No -- Имя регистра не задано IsItReg?d macro input, output ; d - регистр размером в двойное слово output=No irp P, ifidni

, output=Yes endif endm endm IsItReg?w macro input, output ; w - регистр размером в слово output=No irp P, ifidni

, output=Yes endif endm endm IsItReg?b macro input, output ; b - регистр размером в байт output=No irp P, ifidni

, output=Yes endif endm endm IsItReg? macro input, output ; является ли input именем регистра. IsItReg?d input, tmpvar if tmpvar EQ No output=No IsItReg?w input, tmpvar if tmpvar EQ No output=No IsItReg?b input, tmpvar if tmpvar EQ No output=No else output=1 endif else output=2 endif else output=4 endif endm ;────────────────────────────────────────────────────────────────────── ; Макросы вызывает сообщение об ошибке, если указанный параметр не регистр ErrIfNotReg macro reg:req IsItReg? Reg, tmpvar errif tmpvar EQ No "Параметр макроса должен быть именем регистра" endm ErrIfNotDReg macro reg:req IsItReg?d Reg, tmpvar errif tmpvar EQ No "Параметр макроса должен быть именем 32-битного регистра" endm ErrIfNotWReg macro reg:req IsItReg?w Reg, tmpvar errif tmpvar EQ No "Параметр макроса должен быть именем 16-битного регистра" endm ErrIfNotbReg macro reg:req IsItReg?b Reg, tmpvar errif tmpvar EQ No "Параметр макроса должен быть именем 8-битного регистра" endm ; ───────────────────────────────────────────────────────────────────── ; Макрос переносит переменную в регистр только в том случае, если ; её имя не совпадает с именем регистра movreg macro Reg:Req, Var:Req ifdifi , mov Reg, Var endif endm ; ───────────────────────────────────────────────────────────────────── ; Вспомогательный макрос, помещающий в память или регистр reg ссылку nill movnill macro reg IsItReg? reg, tmpvar if tmpvar EQ No mov reg, nill else xor reg, reg dec reg endif endm ; ───────────────────────────────────────────────────────────────────── ; Вспомогательный макрос, помещающий в память или регистр reg ссылку null movnull macro reg IsItReg? reg, tmpvar if tmpvar EQ NO mov reg, 0h else xor reg, reg endif endm ; ───────────────────────────────────────────────────────────────────── ; Вспомогательный макрос, помещающий в память или регистр reg единицу movone macro reg IsItReg? reg, tmpvar if tmpvar EQ No mov reg, 1 else xor reg, reg inc reg endif endm ; ───────────────────────────────────────────────────────────────────── ; Следующий макрос выполняет операцию reg=max(reg, par1, par2, par3) ; reg -- имя регистра, обязателен ; par1, par2, par3 -- переменные в памяти, регистры или константы. Любой из них ; может быть пустым. ; Сравниваются числа без знака setmax и со знаком isetmax. setmax macro reg:req, par1, par2, par3 local X1, X2, X3 ErrIfNotReg reg ifnb cmp reg, par1 ja X1 mov reg, par1 X1: endif ifnb cmp reg, par2 ja X2 mov reg, par2 X2: endif ifnb cmp reg, par3 ja X3 mov reg, par3 X3: endif endm isetmax macro reg:req, par1, par2, par3 local X1, X2, X3 ErrIfNotReg reg ifnb cmp reg, par1 jg X1 mov reg, par1 X1: endif ifnb cmp reg, par2 jg X2 mov reg, par2 X2: endif ifnb cmp reg, par3 jg X3 mov reg, par3 X3: endif endm ; ───────────────────────────────────────────────────────────────────── ; Следующий макрос выполняет операцию reg=min(reg, par1, par2, par3) ; reg -- имя регистра, обязателен ; par1, par2, par3 -- переменные в памяти, регистры или константы. Любой из них ; может быть пустым. ; Сравниваются числа без знака setmin и со знаком isetmin. setmin macro reg:req, par1, par2, par3 local X1, X2, X3 ErrIfNotReg reg ifnb cmp reg, par1 jb X1 mov reg, par1 X1: endif ifnb cmp reg, par2 jb X2 mov reg, par2 X2: endif ifnb cmp reg, par3 jb X3 mov reg, par3 X3: endif endm isetmin macro reg:req, par1, par2, par3 local X1, X2, X3 ErrIfNotReg reg ifnb cmp reg, par1 jl X1 mov reg, par1 X1: endif ifnb cmp reg, par2 jl X2 mov reg, par2 X2: endif ifnb cmp reg, par3 jl X3 mov reg, par3 X3: endif endm ;============================================ ; Перемещает строку в памяти. ; esi -- источник ; edi -- приёмник ; DF -- направление переноса, как во всех командах копирования строк ; SizeBytes -- константа (число байт, которые нужно переместить) ; Если параметр save_ecx пустой, и длина SizeBytes больше 27 байт, ecx портится ; Если save_ecx не пуст, то при длине больше 27 байт, ecx сохраняется в стеке. ; При длине меньше 28 байт, ecx не используется movstr macro SizeBytes:req, save_ecx if SizeBytes GE 1ch ifnb push ecx endif mov ecx, SizeBytes shr 2 rep movsd ifnb pop ecx endif elseif SizeBytes GE 18h movsd movsd movsd movsd movsd movsd elseif SizeBytes GE 14h movsd movsd movsd movsd movsd elseif SizeBytes GE 10h movsd movsd movsd movsd elseif SizeBytes GE 0ch movsd movsd movsd elseif SizeBytes GE 8 movsd movsd elseif SizeBytes GE 4 movsd endif if (SizeBytes and 2) EQ 2 movsw endif if (SizeBytes and 1) EQ 1 movsb endif endm ;────────────────────────────────────────────────────────────────────── ; Макрос перемещает байт, слово или двойное слово в памяти через EAX ; Adr1, Adr2 -- адреса операндов (adr2 -- источник) ; s -- размер перемещаемых операндов (byte/word/dword) ; Выход: al/ax/eax содержит adr2 movmax macro adr1:req, adr2:req, s:req ifidni , mov al, adr2 mov adr1, al elseifidni , mov ax, adr2 movreg adr1, ax elseifidni , mov eax, adr2 mov adr1, eax else .err "Неправильно задан аргумент s" endif endm moval macro adr1:req, adr2:req mov al, byte ptr adr2 mov byte ptr adr1, al endm movax macro adr1:req, adr2:req mov ax, word ptr adr2 mov word ptr adr1, ax endm moveax macro adr1:req, adr2:req mov eax, dword ptr adr2 mov dword ptr adr1, eax endm ;────────────────────────────────────────────────────────────────────── ; Макрос перемещает двойное слово в памяти через стек ; Adr1, Adr2 -- адреса операндов (adr2 -- источник) movmst macro adr1:req, adr2:req push dword ptr adr2 pop dword ptr adr1 endm ;────────────────────────────────────────────────────────────────────── ; Макрос выполняет обмен двух байт, слов или двойных слов в памяти через eax ; Adr1, Adr2 -- адреса операндов ; s -- размер перемещаемых операндов (byte/word/dword) ; Выход: al/ax/eax содержит то же, что и adr1 xchgmax macro adr1:req, adr2:req, s:req ifidni , mov al, adr2 xchg adr1, al mov adr2, al elseifidni , mov ax, adr2 xchg adr1, ax mov adr2, ax elseifidni , mov eax, adr2 xchg adr1, eax mov adr2, eax else .err "Не правильно задан аргумент s" endif endm xchgal macro adr1:req, adr2:req mov al, byte ptr adr2 xchg al, byte ptr adr1 mov byte ptr adr2, al endm xchgax macro adr1:req, adr2:req mov ax, word ptr adr2 xchg ax, word ptr adr1 mov word ptr adr2, ax endm xchgeax macro adr1:req, adr2:req mov eax, dword ptr adr2 xchg eax, dword ptr adr1 mov dword ptr adr2, eax endm ;────────────────────────────────────────────────────────────────────── ; Макрос перемещает двойное слово в памяти через стек ; Adr1, Adr2 -- адреса операндов xchgmst macro adr1:req, adr2:req push dword ptr adr2 push dword ptr adr1 pop dword ptr adr2 pop dword ptr adr1 endm ;============================================ ; Следующие макросы предназначены для имитации команд старших моделей ifndef CPU686 cmovz macro dest, op local NxtOp jnz NxtOp mov dest, op NxtOp: endm cmove equ cmovz cmovnz macro dest, op local NxtOp jz NxtOp mov dest, op NxtOp: endm cmovne equ cmovnz cmovs macro dest, op local NxtOp jns NxtOp mov dest, op NxtOp: endm cmovns macro dest, op local NxtOp js NxtOp mov dest, op NxtOp: endm cmovc macro dest, op local NxtOp jnc NxtOp mov dest, op NxtOp: endm cmovb equ cmovc cmovnae equ cmovc cmovnc macro dest, op local NxtOp jc NxtOp mov dest, op NxtOp: endm cmovnb equ cmovnc cmovae equ cmovnc cmovo macro dest, op local NxtOp jno NxtOp mov dest, op NxtOp: endm cmovno macro dest, op local NxtOp jo NxtOp mov dest, op NxtOp: endm cmovp macro dest, op local NxtOp jnp NxtOp mov dest, op NxtOp: endm cmovnp macro dest, op local NxtOp jp NxtOp mov dest, op NxtOp: endm cmovl macro dest, op local NxtOp jnl NxtOp mov dest, op NxtOp: endm cmovnge equ cmovl cmovle macro dest, op local NxtOp jg NxtOp mov dest, op NxtOp: endm cmovng equ cmovle cmovg macro dest, op local NxtOp jng NxtOp mov dest, op NxtOp: endm cmovnle equ cmovg cmovge macro dest, op local NxtOp jl NxtOp mov dest, op NxtOp: endm cmovnl equ cmovge cmovbe macro dest, op local NxtOp ja NxtOp mov dest, op NxtOp: endm cmovna equ cmovbe cmova macro dest, op local NxtOp jbe NxtOp mov dest, op NxtOp: endm cmovnbe equ cmova endif ; Конец файла COMMONIB.INC