Не претендую на создание чего-то нового и гениального, но макросы довольно полезные. Часть из того, что я сделал, уже делали другие. Тем не менее, большинство макросов придумано и сделано мною с нуля, остальной код переписан по-своему Вот эти макросы (полный вариант, только заголовки): Код (ASM): ;############################################ ;## ## ;## -= EXTRA MACROSES (FULL EDITION) =- ## ;## МАКРОСЫ ДЛЯ MASM/TASM (16/32) ## ;## Полный вариант ## ;## [ v1.00 :: 09.01.2017 ] ## ;## ## ;## (c) 2017 by Jin X (jin.x@sources.ru) ## ;## http://xk7.ru/p/a/i ## ;## ## ;############################################ xmacro_ver = 100h ; версия данного файла (word: старший байт - целая часть, младший - дробная) ;------------------------------------------------------------------------------- @ equ <offset> $b equ <byte ptr> $w equ <word ptr> $d equ <dword ptr> $f equ <fword ptr> $q equ <qword ptr> $t equ <tbyte ptr> $s equ <short> $n equ <near> $f equ <far> ; Выполнение инструкций/директив/макросов, заданных одной строкой _ macro p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 ;------------------------------------------------------------------------------- ;-- УСЛОВНЫЕ МАКРОСЫ ----------------------------------------------------------- ;------------------------------------------------------------------------------- ; Если cond, исполнить do1; иначе do0 ifel macro cond:req, do1, do0 ifdo equ <ifel> ifn equ <ife> ; Если НЕ cond, исполнить do1; иначе do0 ifnel macro cond:req, do1, do0 ifeel equ <ifnel> ; Если cond1, исполнить do1; иначе если cond2, исполнить do2; иначе do0 ifelif macro cond1:req, do1, cond2:req, do2, do0 ; ifdef id (если идентификатор определён), исполнить do1; иначе do0 ifdefel macro id:req, do1, do0 ; ifndef id (если идентификатор НЕ определён), исполнить do1; иначе do0 ifndefel macro id:req, do1, do0 ; ifb exp (если выражение пустое), исполнить do1; иначе do0 ifbel macro exp, do1, do0 ; Если выражение exp пустое или состоит из пробелов, исполнить do1; иначе do0 ifbbel macro exp, do1, do0 ; ifnb exp (если выражение НЕпустое), исполнить do1; иначе do0 ifnbel macro exp, do1, do0 ; Если выражение exp НЕпустое и НЕ состоит из пробелов, исполнить do1; иначе do0 ifnbbel macro exp, do1, do0 ; ifidn exp1, exp2 (если значения совпадают С учётом регистра символов), исполнить do1; иначе do0 ifidnel macro exp1:req, exp2:req, do1, do0 ; ifidni cond (если значения совпадают БЕЗ учёта регистра символов), исполнить do1; иначе do0 ifidniel macro exp1:req, exp2:req, do1, do0 ; ifidn exp1, exp2 (если значения различаются С учётом регистра символов), исполнить do1; иначе do0 ifdifel macro exp1:req, exp2:req, do1, do0 ; ifidni cond (если значения различаются БЕЗ учёта регистра символов), исполнить do1; иначе do0 ifdifiel macro exp1:req, exp2:req, do1, do0 ; Если cond1 или cond2 (условие cond2 проверяется только в том случае, если cond1 не выполнилось), исполнить do1; иначе do0 iforel macro cond1:req, cond2:req, do1, do0 ; Если cond1 и cond2 (условие cond2 проверяется только в том случае, если cond1 выполнилось), исполнить do1; иначе do0 ifandel macro cond1:req, cond2:req, do1, do0 ; Аналогично ifel, но условие подставляется слитно с if, например: ifelx <def debug>, <int 3>, nop ifelx macro cond:req, do1, do0 ifx equ <ifelx> ; Аналогично ifnel, но условие подставляется слитно с if, например: ifnelx <def debug>, nop, <int 3> ifnelx macro cond:req, do1, do0 ifeelx equ <ifnelx> ; Аналогично ifelif, но условия подставляются слитно с if, например: ifelifx <def debug>, <int 3>, <idn <spec>, <stosb>>, stosb, nop ifelifx macro cond1:req, do1, cond2:req, do2, do0 ; Аналогично iforel, но условия подставляются слитно с if iforelx macro cond1:req, cond2:req, do1, do0 ; Аналогично ifandel, но условия подставляются слитно с if ifandelx macro cond1:req, cond2:req, do1, do0 ;------------------------------------------------------------------------------- ; Установить значение var = true, если выполняется хотя бы одно из условий cX; иначе установить var = false setifor macro var:req, c1:req, c2:req, c3, c4, c5, c6, c7, c8 ; Установить значение var = true, если выполняются все условия cX; иначе установить var = false setifand macro var:req, c1:req, c2:req, c3, c4, c5, c6, c7, c8 ; Установить значение var1 = true, а var2 = false, если выполняется условие cond (которые подставляются слитно с if); иначе установить var1 = false, а var2 = true setifelx macro cond:req, var1, var2 ; Установить значение var = true, если выполняется хотя бы одно из условий cX (которые подставляются слитно с if); иначе установить var = false setiforx macro var:req, c1:req, c2:req, c3, c4, c5, c6, c7, c8 ; Установить значение var = true, если выполняются все условия cX (которые подставляются слитно с if); иначе установить var = false setifandx macro var:req, c1:req, c2:req, c3, c4, c5, c6, c7, c8 ;------------------------------------------------------------------------------- ; Если идентификатор value определён, установить значение const = value, иначе установить значение _const = defval defdef macro const:req, value:req, defval:req ; Если константа const определена, установить значение _const = const, иначе установить значение _const = defval _defdef macro const:req, defval:req ;------------------------------------------------------------------------------- ; Вывод сообщения txt об ошибке (одинаковый синтаксис для MASM и TASM) ?err macro txt ; Вывод сообщения txt об ошибке при выполнении условия cond ?errif macro cond:req, txt ; Аналогично ?errif, но условие подставляется слитно с if, например: ?errifx <ndef ok>, <Error message> ?errifx macro cond:req, txt ;------------------------------------------------------------------------------- ; Следующие идентификаторы определены для более удобного использования вложенных условных директив компиляции, например: ; if abc ; ?if def ; ??if ghi ; ... ; ??endif ; ?endif ; endif ?if equ <if> ?ifdef equ <ifdef> ?ifndef equ <ifndef> ?ifb equ <ifb> ?ifnb equ <ifnb> ?ifidn equ <ifidn> ?ifidni equ <ifidni> ?ifdif equ <ifdif> ?ifdifi equ <ifdifi> ?if1 equ <if1> ?if2 equ <if2> ?else equ <else> ?elseif equ <elseif> ?elseifdef equ <elseifdef> ?elseifndef equ <elseifndef> ?elseifb equ <elseifb> ?elseifnb equ <elseifnb> ?elseifidn equ <elseifidn> ?elseifidni equ <elseifidni> ?elseifdif equ <elseifdif> ?elseifdifi equ <elseifdifi> ?elseif1 equ <elseif1> ?elseif2 equ <elseif2> ?endif equ <endif> ??if equ <if> ??ifdef equ <ifdef> ??ifndef equ <ifndef> ??ifb equ <ifb> ??ifnb equ <ifnb> ??ifidn equ <ifidn> ??ifidni equ <ifidni> ??ifdif equ <ifdif> ??ifdifi equ <ifdifi> ??if1 equ <if1> ??if2 equ <if2> ??else equ <else> ??elseif equ <elseif> ??elseifdef equ <elseifdef> ??elseifndef equ <elseifndef> ??elseifb equ <elseifb> ??elseifnb equ <elseifnb> ??elseifidn equ <elseifidn> ??elseifidni equ <elseifidni> ??elseifdif equ <elseifdif> ??elseifdifi equ <elseifdifi> ??elseif1 equ <elseif1> ??elseif2 equ <elseif2> ??endif equ <endif> Продолжение следует (весь код не помещается в одно сообщение)... Полный код см. в аттаче
Продолжение... Код (ASM): ;=============================================================================== ;------------------------------------------------------------------------------- ;-- ОПРЕДЕЛЕНИЕ ЗНАЧЕНИЙ КОНСТАНТ ---------------------------------------------- ;------------------------------------------------------------------------------- false = 0 true = not false ; Установка isTASM = true и isMASM = false, если текущий компилятор - TASM, иначе наоборот setifelx <def ??Version>, isTASM, isMASM ; Установка идентификатора @32Bit (32-битный режим) в MASM ifdo isMASM, <@32Bit = (@WordSize eq 4)> ; Разрешены ли инструкции/регистры процессоров (в TASM @Cpu = 0 в режиме .586) @186 = (@Cpu and 2) or (@Cpu eq 0) @286 = (@Cpu and 3) or (@Cpu eq 0) @386 = (@Cpu and 8) or (@Cpu eq 0) @486 = (@Cpu and 10h) or (@Cpu eq 0) @586 = (@Cpu and 20h) or (@Cpu eq 0) @686 = @Cpu and 40h ; Включить режим оптимизации и использования локальных меток, начинающихся на @@ ifdo isTASM, <_ smart, locals> ; Проверка требуемой версии данного include-файла, заданной через константу xmacro_ver_req или xmac_ver_req ifx <def xmacro_ver_req>, <?errif <xmacro_ver_req gt xmacro_ver>, <Version of 'xmacro.inc' is less than required :(>> ifx <def xmac_ver_req>, <?errif <xmac_ver_req gt xmacro_ver>, <Version of 'xmacro.inc' is less than required :(>> ;=============================================================================== ;------------------------------------------------------------------------------- ;-- МАКРОСЫ, ОПИСЫВАЮЩИЕ ИЛИ УПРОЩАЮЩИЕ ИСПОЛЬЗОВАНИЕ ИНСТРУКЦИЙ ПРОЦЕССОРА ---- ;------------------------------------------------------------------------------- ; Недокументированная инструкция salc (setalc) salc macro setalc equ <salc> ; Инструкция rdtsc if isTASM rdtsc macro endif ;------------------------------------------------------------------------------- ; Прыжок через 1 байт; если указан 1-байтовый регистр reg, его значение изменяется, но сохраняются флаги, иначе изменяются флаги, но сохраняются регистры jmp_1 macro reg ; Прыжок через 2 байта; если указан 2-байтовый регистр reg, его значение изменяется, но сохраняются флаги, иначе изменяются флаги, но сохраняются регистры jmp_2 macro reg ; Прыжок через 4 байта; если указан 4-байтовый регистр reg, его значение изменяется, но сохраняются флаги, иначе изменяются флаги, но сохраняются регистры jmp_4 macro reg jmps equ <jmp short> jmpn equ <jmp near> ; jmp far seg:ofs (если seg:ofs не указан, генерируется только 1 байт опкода) jmpf macro seg, ofs ; call far seg:ofs (если seg:ofs не указан, генерируется только 1 байт опкода) callf macro seg, ofs ; call int (pushf + callf) calli macro seg, ofs ; Определяет nop'ы в количестве cnt штук nops macro cnt:req ;------------------------------------------------------------------------------- ; Выполнение присвоения значения регистру с помощью mov или xor (если src = 0) ; Чтобы передать в параметре src константу, необходимо поставить перед ней % (movx ax,%val), иначе xor не выполнится movx macro dst:req, src:req ; Выполнение сравнение регистра с помощью cmp или test (если src = 0) ; Чтобы передать в параметре src константу, необходимо поставить перед ней % (cmpx ax,%val), иначе test не выполнится cmpx macro dst:req, src:req ; Выполнение присвоения op = val через стек movp macro op:req, val:req ; Выполнение присвоения op = val через временный регистр temp (по умолчанию ax; например, movt ds,@data или movt es,0A000h,dx) movt macro op:req, val:req, temp:=<ax> ; Обмен значениями op1 и op2 через стек ; Макрос не проверяет соответствие разрядности операндов !!! xchgp macro op1:req, op2:req ; Сохранение регистров в одну строку: push ax bx cx dx pushx macro regs:vararg ; Восстановление регистров в одну строку: pop dx cx bx ax popx macro regs:vararg ; Восстановление регистров в обратном порядке: popb ax bx cx dx popb macro regs:vararg ; Запись ip (адрес следующей строки) в op, используя стек ; Макрос не проверяет соответствие разрядности кода и операнда !!! getip macro op:req ; Запись флагов в op, используя стек ; Макрос не проверяет соответствие разрядности флагов и операнда !!! getf macro op:req ; Запись слова флагов в op, используя стек ; Макрос не проверяет соответствие разрядности флагов и операнда !!! getfw macro op:req ; Запись двойного слова флагов в op, используя стек ; Макрос не проверяет соответствие разрядности флагов и операнда !!! getfd macro op:req ; Запись op в регистр флагов, используя стек ; Макрос не проверяет соответствие разрядности флагов и операнда !!! setf macro op:req ; Запись слова op в регистр флагов, используя стек ; Макрос не проверяет соответствие разрядности флагов и операнда !!! setfw macro op:req ; Запись двойного слова op в регистр флагов, используя стек ; Макрос не проверяет соответствие разрядности флагов и операнда !!! setfd macro op:req ; Установка флага ZF=ZR=1 (влияет и на другие флаги: CF=0, PF=1, AF=0, SF=0, OF=0) stz macro ; Получить абсолютное (положительное) значение op (минимальное отрицательное значение остаётся неизменным, при этом SF=1, OF=1, иначе SF=0, SF=0) absx macro op:req ; Получить абсолютное (положительное) значение регистра al (значение -128 остаётся неизменным, при этом SF=1, OF=1, иначе SF=0, SF=0) ; Работает быстрее, чем absx; при этом: ah = 0 и CF=0, если исходное значение al положительное, иначе ah = -1, CF=1 absal macro ; Получить абсолютное (положительное) значение регистра ax (значение -32768 остаётся неизменным, при этом SF=1, OF=1, иначе SF=0, SF=0) ; Работает быстрее, чем absx; при этом: dx = 0 и CF=0, если исходное значение ax положительное, иначе dx = -1, CF=1 absax macro ; Получить абсолютное (положительное) значение регистра ax (значение -2147483648 остаётся неизменным, при этом SF=1, OF=1, иначе SF=0, SF=0) ; Работает быстрее, чем absx; при этом: edx = 0 и CF=0, если исходное значение eax положительное, иначе edx = -1, CF=1 abseax macro ;------------------------------------------------------------------------------- ; lodsb/lodsw/lodsd с использованием сегментов, отличных от ds: ; lodsb_seg, lodsw_seg, lodsd_seg с названием сегментного регистра в качестве аргумента (например, lodsb_seg es) ; lodsb_es, lodsb_cs, lodsb_ss, lodsb_fs, lodsb_gs, ; lodsw_es, lodsw_cs, lodsw_ss, lodsw_fs, lodsw_gs, ; lodsd_es, lodsd_cs, lodsd_ss, lodsd_fs, lodsd_gs без аргументов ; outsb/outsw/outsd с использованием сегментов, отличных от ds: ; outsb_seg, outsw_seg, outsd_seg с названием сегментного регистра в качестве аргумента (например, outsb_seg es) ; outsb_es, outsb_cs, outsb_ss, outsb_fs, outsb_gs, ; outsw_es, outsw_cs, outsw_ss, outsw_fs, outsw_gs, ; outsd_es, outsd_cs, outsd_ss, outsd_fs, outsd_gs без аргументов ;------------------------------------------------------------------------------- ; Вызов прерывания no с установкой регистров reg1 = val1, reg2 = val2... ; Если указан только reg1 без val1, то значение reg1 заносится в ah (или ax, если число > 0FFh) ; Например: intfn 16h,0 или intfn 15h,ah,86h,cx,0,dx,10000 intfn macro no:req, reg1:req, val1, reg2, val2, reg3, val3, reg4, val4, reg5, val5 Также имеется краткий вариант, в котором отсутствует примерно половина этих макросов (специфических). p.s. Что-то вся вёрстка поехала (включая пустые строки). Какой-то глюк на форуме, видимо...
Обновление: версия 1.01. xmacro.inc: Код (Text): -= ИСТОРИЯ ВЕРСИЙ =- v1.01 (26.01.2017) [+] Добавлены идентификаторы $ax, $bx, $cx, $dx, $si, $di, $bp, $sp, $word, j$cxz, cwdq$, pushf$, popf$. [+] Добавлен псевдоним ifndo. [*] В макросы defdef и _defdef добавлен дополнительный параметр, позволяющий делать проверку ещё одной константы. [*] В макросы ?err, ?errif, ?errifx добавлен дополнительный параметр, позволяющий добавлять к сообщению 3 восклицательных знака. [*] Исправлен баг в макросе movt. v1.00 (09.01.2017) [!] Самая первая версия. xmac.inc: Код (Text): -= ИСТОРИЯ ВЕРСИЙ =- v1.01 (26.01.2017) [+] Добавлены идентификаторы $ax, $bx, $cx, $dx, $si, $di, $bp, $sp, $word, j$cxz, cwdq$, pushf$, popf$. [+] Добавлены макросы iforel, ifandel, iforelx, ifandelx (из полной редакции). [+] Добавлен псевдоним ifndo. [*] В макросы defdef и _defdef добавлен дополнительный параметр, позволяющий делать проверку ещё одной константы. [*] В макросы ?err, ?errif, ?errifx добавлен дополнительный параметр, позволяющий добавлять к сообщению 3 восклицательных знака. [-] Из данной редакции удалены макросы movt, movp, xchgp, calli, outsXXX, intfn. [-] Из данной редакции удалена проверка xmacro_ver_req (поскольку это могло явиться причиной сообщения об ошибке при включении обеих редакций). v1.00 (09.01.2017) [!] Самая первая версия.
Обновление: версия 1.02. Код (Text): -= ИСТОРИЯ ВЕРСИЙ =- v1.02 (01.02.2017) [+] Добавлен макрос loopx, генерирующий dec + jnz (jns). [*] (В ПОЛНОЙ РЕДАКЦИИ) В макросе movt значение параметра temp по умолчанию изменено с ax на $ax. [*] В макросе ?err для добавления ' !!!' в конец сообщения параметр exclam должен быть <> 0 (до этого достаточно было задать любое значение, в т.ч. 0).
И снова обновление: версия 1.03. Код (Text): -= ИСТОРИЯ ВЕРСИЙ =- v1.03 (08.03.2017) [+] Добавлены макросы doif, doifn и doifx, работающие аналогично ifdo, ifndo и ifx, но позволяющие указывать параметр do без <угловых скобок> (ifdo, ifndo и ifx сохранены для обратной совместимости). [+] Добавлены макросы doifset, doifnset, doifsete и ifsetel, проверяющие и определение идентификатора, и его значение. [+] Добавлены макросы aligndata, aligncode, alignd, alignc, alignds, aligncs. [+] Добавлен идентификатор dw$, определяющий dw или dd в зависимости от разрядности кода. [+] Добавлены идентификаторы proto = procdesc и invoke = call для TASM. [+] По умолчанию данный include-файл включает директивы locals и smart для TASM; если нужно их отключить, установите константу xnodir = 1 ДО включения файла. [+] Требуемую версию данного include-файла можно теперь проверять не только через константу xmacro_ver_req, но и через макрос check_xmacro_ver (после подключения файла), что исключает возможность опечатки. [*] Сделаны некоторые перестановки и изменения в макросах (например, ifel переписан без использования вложенных макросов, что должно увеличить скорость и упростить обнаружение ошибок в коде). (изменения приведены для полной версии xmacro.inc).
Jin X, посмотри пример с обработкой условно неограниченного (:VARARG) количества параметров (полезно для твоего макро "_"): Код (Text): xcall Macro procedure,parameters:VARARG Local param,reversed reversed TEXTEQU <> % For param,<parameters> reversed CATSTR <param>,<!,>,reversed EndM % For param,<reversed> push param EndM call procedure EndM
UbIvItS, пробовал немного, а что? Jupiter, спасибо за пример. Я пробовал VARARG + IRP, но такой вариант не работал. Посмотрю такой вариант. Главное, чтобы он работал и с TASM тоже (а там FOR'а нет, только IRP)... p.s. А что % в данном примере даёт? Сейчас у меня другая проблема возникла, см. ниже (в "истории версий" под знаком [!])...
Скорое обновление: версия 1.04. Код (Text): -= ИСТОРИЯ ВЕРСИЙ =- v1.04 (10.03.2017) [!] Обнаружен баг, который появился вместе с макросами doifXXX в предыдущей версии (1.03), и я пока не знаю как его исправить (если знаете, напишите мне) !!! MASM выдаёт ошибку при совместном использовании макросов doifXXX и _ с параметрами, содержащими запятые в угловых скобках (например, doif x, _ <mov ax,bx>), параметр макроса _ разделяется на несколько, будто угловых скобок нет (данный пример работает аналогично doif x, _ mov ax,bx; т.е. макрос _ получает 2 параметра: mov ax и bx). Пока я вижу только два варианта решения данной проблемы: 1. использовать макросы ifXXX, заключая также и макрос _ в угловые скобки (ifdo x, <_ <mov ax,bx>>) - это ЛУЧШИЙ ВАРИАНТ, 2. использовать двойные угловые скобки (doif x, _ <<mov ax,bx>>), однако этот вариант НЕ работает в TASM, что плохо, учитывая, что данный include-файл является универсальным для TASM и MASM. p.s. Эта проблема проявляется у макросов doifXXX не только с макросом _, но и с другими, принимающими несколько параметров, которые могут содержать запятые (например, doif x, ?errif <hello, world>). [+] Добавлены макросы ifnsetel и ifseteel (в дополнение к ifsetel) и псевдонимы для всех 3-х макросов: ifset, ifnset и ifsete. [+] Добавлен макрос fastnops и константа fastnopsprefix, а макрос aligncode получил дополнительный параметр prefix и использует (так же, как и alignc и aligncs) nop'ы с префиксами. [*] Исправлена ошибка в макросе ifsetel, возникающая при использовании угловых скобок в do1 и/или do0. [*] Макрос _ расширен до 16 параметров. [*] Макрос ifelif переписан без использования вложенных макросов, в других макросах doif-подобные макросы заменены на ifdo-подобные. (изменения приведены для полной редакции xmacro.inc, в сокращённой xmac.inc их чуть меньше).
перед директивой for указан знак процента (%). Обычно он означает, что текст интерпретируется как выражение Jin X, перечитай пожалуйста Макросы Пильщиков пишет о ТАСМе, Соколенко, Зубков и Edmond о МАСМе
под линем как-то органичней что ль. хотя, конечно, дело привычки c другой стороны -- под линем больше возможностей для оптимизации кодов.
GCC inline asm + сишный препроцессор рулят. Код (C++): #define OP2_ALIGN(OP) \ /* Align destination */ \ __ASM_EMIT("1:") \ __ASM_EMIT("test $0x0f, %[dst]") \ __ASM_EMIT("jz 2f") \ __ASM_EMIT("movss 0x00(%[dst]), %%xmm0") \ __ASM_EMIT("movss 0x00(%[src]), %%xmm4") \ __ASM_EMIT(OP "ss %%xmm4, %%xmm0") \ __ASM_EMIT("movss %%xmm0, 0x00(%[dst])") \ __ASM_EMIT("add $0x04, %[src]") \ __ASM_EMIT("add $0x04, %[dst]") \ __ASM_EMIT("dec %[count]") \ __ASM_EMIT("jnz 1b") \ __ASM_EMIT("jmp 20000f") \ __ASM_EMIT("2:") #define OP2_CORE(OP, MV_SRC) \ __ASM_EMIT("sub $0x10, %[count]") \ __ASM_EMIT("jb 2f") \ /* 16x blocks */ \ __ASM_EMIT("1:") \ __ASM_EMIT("movaps 0x00(%[dst]), %%xmm0") \ __ASM_EMIT("movaps 0x10(%[dst]), %%xmm1") \ __ASM_EMIT("movaps 0x20(%[dst]), %%xmm2") \ __ASM_EMIT("movaps 0x30(%[dst]), %%xmm3") \ __ASM_EMIT(MV_SRC " 0x00(%[src]), %%xmm4") \ __ASM_EMIT(MV_SRC " 0x10(%[src]), %%xmm5") \ __ASM_EMIT(MV_SRC " 0x20(%[src]), %%xmm6") \ __ASM_EMIT(MV_SRC " 0x30(%[src]), %%xmm7") \ __ASM_EMIT(OP "ps %%xmm4, %%xmm0") \ __ASM_EMIT(OP "ps %%xmm5, %%xmm1") \ __ASM_EMIT(OP "ps %%xmm6, %%xmm2") \ __ASM_EMIT(OP "ps %%xmm7, %%xmm3") \ __ASM_EMIT("movaps %%xmm0, 0x00(%[dst])") \ __ASM_EMIT("movaps %%xmm1, 0x10(%[dst])") \ __ASM_EMIT("movaps %%xmm2, 0x20(%[dst])") \ __ASM_EMIT("movaps %%xmm3, 0x30(%[dst])") \ __ASM_EMIT("add $0x40, %[src]") \ __ASM_EMIT("add $0x40, %[dst]") \ __ASM_EMIT("sub $0x10, %[count]") \ __ASM_EMIT("jae 1b") \ /* 8x blocks */ \ __ASM_EMIT("2:") \ __ASM_EMIT("add $0x10, %[count]") \ __ASM_EMIT("test $8, %[count]") \ __ASM_EMIT("jz 3f") \ __ASM_EMIT("movaps 0x00(%[dst]), %%xmm0") \ __ASM_EMIT("movaps 0x10(%[dst]), %%xmm1") \ __ASM_EMIT(MV_SRC " 0x00(%[src]), %%xmm4") \ __ASM_EMIT(MV_SRC " 0x10(%[src]), %%xmm5") \ __ASM_EMIT(OP "ps %%xmm4, %%xmm0") \ __ASM_EMIT(OP "ps %%xmm5, %%xmm1") \ __ASM_EMIT("movaps %%xmm0, 0x00(%[dst])") \ __ASM_EMIT("movaps %%xmm1, 0x10(%[dst])") \ __ASM_EMIT("add $0x20, %[src]") \ __ASM_EMIT("add $0x20, %[dst]") \ /* 4x blocks */ \ __ASM_EMIT("3:") \ __ASM_EMIT("test $4, %[count]") \ __ASM_EMIT("jz 4f") \ __ASM_EMIT("movaps 0x00(%[dst]), %%xmm0") \ __ASM_EMIT(MV_SRC " 0x00(%[src]), %%xmm4") \ __ASM_EMIT(OP "ps %%xmm4, %%xmm0") \ __ASM_EMIT("movaps %%xmm0, 0x00(%[dst])") \ __ASM_EMIT("add $0x10, %[src]") \ __ASM_EMIT("add $0x10, %[dst]") \ /* 1x blocks */ \ __ASM_EMIT("4:") \ __ASM_EMIT("and $3, %[count]") \ __ASM_EMIT("jz 20000f") \ __ASM_EMIT("5:") \ __ASM_EMIT("movss 0x00(%[dst]), %%xmm0") \ __ASM_EMIT("movss 0x00(%[src]), %%xmm4") \ __ASM_EMIT(OP "ss %%xmm4, %%xmm0") \ __ASM_EMIT("movss %%xmm0, 0x00(%[dst])") \ __ASM_EMIT("add $0x04, %[src]") \ __ASM_EMIT("add $0x04, %[dst]") \ __ASM_EMIT("dec %[count]") \ __ASM_EMIT("jnz 5b") void add2(float *dst, const float *src, size_t count) { __asm__ __volatile__ ( __ASM_EMIT("test %[count], %[count]") __ASM_EMIT("jz 20000f") OP2_ALIGN("add") __ASM_EMIT("test $0x0f, %[src]") __ASM_EMIT("jnz 10001f") OP2_CORE("add", "movaps") __ASM_EMIT("jmp 20000f") __ASM_EMIT("10001:") OP2_CORE("add", "movups") __ASM_EMIT("20000:") : [dst] "+r" (dst), [src] "+r" (src), [count] "+r" (count) : : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" ); } void sub2(float *dst, const float *src, size_t count) { __asm__ __volatile__ ( __ASM_EMIT("test %[count], %[count]") __ASM_EMIT("jz 20000f") OP2_ALIGN("sub") __ASM_EMIT("test $0x0f, %[src]") __ASM_EMIT("jnz 10001f") OP2_CORE("sub", "movaps") __ASM_EMIT("jmp 20000f") __ASM_EMIT("10001:") OP2_CORE("sub", "movups") __ASM_EMIT("20000:") : [dst] "+r" (dst), [src] "+r" (src), [count] "+r" (count) : : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" ); } void mul2(float *dst, const float *src, size_t count) { __asm__ __volatile__ ( __ASM_EMIT("test %[count], %[count]") __ASM_EMIT("jz 20000f") OP2_ALIGN("mul") __ASM_EMIT("test $0x0f, %[src]") __ASM_EMIT("jnz 10001f") OP2_CORE("mul", "movaps") __ASM_EMIT("jmp 20000f") __ASM_EMIT("10001:") OP2_CORE("mul", "movups") __ASM_EMIT("20000:") : [dst] "+r" (dst), [src] "+r" (src), [count] "+r" (count) : : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" ); } void div2(float *dst, const float *src, size_t count) { __asm__ __volatile__ ( __ASM_EMIT("test %[count], %[count]") __ASM_EMIT("jz 20000f") OP2_ALIGN("div") __ASM_EMIT("test $0x0f, %[src]") __ASM_EMIT("jnz 10001f") OP2_CORE("div", "movaps") __ASM_EMIT("jmp 20000f") __ASM_EMIT("10001:") OP2_CORE("div", "movups") __ASM_EMIT("20000:") : [dst] "+r" (dst), [src] "+r" (src), [count] "+r" (count) : : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" ); } #undef OP2_CORE #undef OP2_ALIGN
???????????????????????????????????????????????????????????????????????????????? У Пильщикова в книге масм, в той что у меня точно !!!
Rockphorr, ссылка на Макрсы, а там использовалась книга Пильщикова "Программирование на языке ассемблера IBM PC" – издательство "ДИАЛОГ-МИФИ", год издания 1994, 288 страниц. Приведены фрагменты из 11 главы "Макросредства". Книга написана на основе диалекта TASM.
Jupiter, Mikl___, я так и не понял что значит этот % применительно в For (а не к константе). Можете объяснить?
лучше всего скачать масм6.11 и запустить справку там все разжевано насколько помню это костыль влияющий на глубину разбора выражений при макрозаменах
Короче, понял я, как здесь % работает. Он интерпретирует в строке <reversed> слово reversed как значение локальной переменной, а не как строку (без % это будет просто строка <reversed>). А вот для <parameters> этого делать необязательно, т.к. переменные циклов подставляются всегда даже без %. Работает и в tasm, и в masm, что интересно! Скоро пришлю новую версию xmacro, кстати! Очень много новых макросов и изменений там будет!
Код (ASM): ; поместить в память или регистр float-значение из памяти или регистра или непосредственного значения float_set MACRO flt_this:req, param:req LOCAL first, break echo param IFIDN <param>, <0.0> and flt_this, 0 echo is_zero ELSEIFIDN <param>, <0.> and flt_this, 0 echo is_zero ELSE break = 0 ; если param регистр FOR arg,<eax,ebx,ecx,edx,esp,ebp,esi,edi> IFIDNI <arg>,<param> mov flt_this, param break = 1 echo is_register EXITM ENDIF ENDM IF break EQ 0 ; если param непосредственое float значения first SUBSTR <param>,1,1 echo first FOR arg,<0,1,2,3,4,5,6,7,8,9,-> IFIDN <arg>,<first> ;;@SUBSTR(<param>,1,1) movflt flt_this, param break = 1 echo is_float_const EXITM ENDIF ENDM ENDIF IF break EQ 0 mov eax, param mov flt_this, eax echo is_memory ENDIF ENDIF ENDM Вот макрос, спотыкается на first SUBSTR <param>,1,1 В first передаётся какая-то ерунда и далее макрос не правильно работает. Не пойму что за проблема. Этот макрос вложен в других макросы. Код (ASM): Fvector4_set MACRO vec_this:req, vec_x:req, vec_y:req, vec_z:req, vec_w:req float_set vec_this.x, vec_x float_set vec_this.y, vec_y float_set vec_this.z, vec_z float_set vec_this.w, vec_w ENDM
Не ошибка в IFIDN <arg>,<first>, если строки arg и first равны, то эта команда всё равно даёт ложь, то есть не срабатывает. Код (ASM): ; поместить непосредственое float значение в память или регистр. movflt MACRO param:req, const:req mov dword ptr param, 0 org $-4 dd const ENDM З.Ы. А наконец-то разобрался, надо так IFIDN first,<arg>