1) Подскажите, как в MASM на макро написать подобие INVOKE (цепочка PUSH'ей раскручивающая с конца строки и CALL), сам INVOKE по ряду причин использовать не могу 2) как используя макро IRPC можно анализировать по два символа, меня интересует, как в макрос, преобразующий ASCII-строку в UNICODE-строку Код (Text): du macro string irpc c,<string> if '&c' gt 127 db ('&c'- 0B0h),4 else dw '&c' endif endm dw 0 endm обнаружив, что '&c'=='\' -- впихнуть анализ '\t', '\n' и т.п.
Вот когда-то давно писал, gl функций. Код (Text): option NOKEYWORD:<invoke> ;это обязательно в начале исходника pushm MACRO args:VARARG TEX TEXTEQU <> address TEXTEQU <> FOR item,<args> IF @SizeStr(<item>) GE 6 TEX SUBSTR <item>,1,4 address SUBSTR <item>, 6, @SizeStr(<item>) - 5 IFIDN TEX,<addr> lea eax,address push eax ELSEIFIDN TEX,<ADDR> lea eax,address push eax ELSEIFIDN TEX,<Addr> lea eax,address push eax ELSE push item ENDIF ELSE push item ENDIF ENDM ENDM cntstr = 0 push_psrt MACRO args:VARARG LOCAL labelic,callic,defstr labelic CATSTR <locastr_>,@CatStr(%cntstr) callic CATSTR <call >,labelic %callic ;; defstr CATSTR <db '>,<args>,<',0> ;; %defstr db args,0 labelic CATSTR labelic,<:> %labelic cntstr = cntstr+1 ENDM invoke MACRO a,args:VARARG txt TEXTEQU <> IsFloat TEXTEQU <> IsAddr TEXTEQU <> % FOR item, <args> txt CATSTR <item>,<!,>,txt ENDM txt SUBSTR txt, 1, @SizeStr( %txt ) - 1 % FOR item, <txt> IsFloat SUBSTR <item>,1,1 IFIDN IsFloat,<'> push_psrt item ELSEIFIDN IsFloat,<0> IF @SizeStr(item) GE 3 IsFloat SUBSTR <item>,2,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSE push item ENDIF ELSEIFIDN IsFloat,<1> IF @SizeStr(item) GE 3 IsFloat SUBSTR <item>,2,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSE push item ENDIF ELSEIFIDN IsFloat,<2> IF @SizeStr(item) GE 3 IsFloat SUBSTR <item>,2,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSE push item ENDIF ELSEIFIDN IsFloat,<3> IF @SizeStr(item) GE 3 IsFloat SUBSTR <item>,2,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSE push item ENDIF ELSEIFIDN IsFloat,<4> IF @SizeStr(item) GE 3 IsFloat SUBSTR <item>,2,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSE push item ENDIF ELSEIFIDN IsFloat,<5> IF @SizeStr(item) GE 3 IsFloat SUBSTR <item>,2,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSE push item ENDIF ELSEIFIDN IsFloat,<6> IF @SizeStr(item) GE 3 IsFloat SUBSTR <item>,2,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSE push item ENDIF ELSEIFIDN IsFloat,<7> IF @SizeStr(item) GE 3 IsFloat SUBSTR <item>,2,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSE push item ENDIF ELSEIFIDN IsFloat,<8> IF @SizeStr(item) GE 3 IsFloat SUBSTR <item>,2,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSE push item ENDIF ELSEIFIDN IsFloat,<9> IF @SizeStr(item) GE 3 IsFloat SUBSTR <item>,2,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSE push item ENDIF ELSEIFIDN IsFloat,<-> IF @SizeStr(item) GE 4 IsFloat SUBSTR <item>,2,1 IFIDN IsFloat,<0> IsFloat SUBSTR <item>,3,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSEIFIDN IsFloat,<1> IsFloat SUBSTR <item>,3,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSEIFIDN IsFloat,<2> IsFloat SUBSTR <item>,3,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSEIFIDN IsFloat,<3> IsFloat SUBSTR <item>,3,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSEIFIDN IsFloat,<4> IsFloat SUBSTR <item>,3,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSEIFIDN IsFloat,<5> IsFloat SUBSTR <item>,3,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSEIFIDN IsFloat,<6> IsFloat SUBSTR <item>,3,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSEIFIDN IsFloat,<7> IsFloat SUBSTR <item>,3,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSEIFIDN IsFloat,<8> IsFloat SUBSTR <item>,3,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSEIFIDN IsFloat,<9> IsFloat SUBSTR <item>,3,1 IFIDN IsFloat,<.> db 68h REAL4 item ELSE push item ENDIF ELSE push item ENDIF ELSE push item ENDIF ELSE pushm item ENDIF ENDM call a ENDM
Существует директива IFIDNI, которая нечувствительна к регистру. Я для себя в своё время написал макробиблиотеку с весьма продвинутыми макросами, в частности для работы с UNICODE. Вот простой пример программы, использующеё эти макросы: Код (Text): .386p .model flat,stdcall include windows.inc include kernel32.inc include kdvbase.inc ;моя макробиблиотека includelib kernel32.lib ENCODING "utf8" ;указываем кодировку этого текста ;для корректного отображения кириллицы ;если текст набран в DOS-кодировке, ;то нужно указать "cp866", также заложил ;возможность других кодовых таблиц .data wszUni dw L("Непосредственно объявленная UNICODE-строка\n"),0 ;макрос L() для непосредственного объявления строки UNICODE .code Start proc invoke MessageBoxW, 0,WSZ("ПРЕВЕД МЕДВЕД\x31\r\n"+)\ WSZ("Новая строка :)"),\ WSZ("Сообщение в UNICODE"),MB_OK invoke MessageBoxW, 0,offset wszUni,\ WSZ("Сообщение в UNICODE"),MB_OK ;макрос WSZ() для объявления строки UNICODE "по ходу", ;строка объявляется только один раз (используется хеширование), ;макрос возвращает строчку <offset Name>, где Name - хэш-имя строки invoke ExitProcess,0 Start endp end Start Тут лишь очень малая часть макросов из всех, которые находятся в kdvbase.inc. Вот думаю, выкладывать ли это в сеть...
Замена INVOKE Код (Text): .586 .model flat include windows.inc includelib user32.lib extern _imp__MessageBoxA@16:dword ;------------------------------------------------------------------- OPTION NOKEYWORD: <invoke> invoke MACRO Fn,args:VARARG LOCAL txt,arg ;меняем порядок аргументов на обратный, каждый аргумент разделяем запятой txt TEXTEQU <>;инициируем переменную txt как пустую строку IRP arg,<args>;директива IRP делает одну копию указанных операторов ;для каждого из параметров, входящих в стоящий в угловых скобках список txt CATSTR <arg>, <!,>, txt;"склеиваем" новую строку аргументов ;оператор ! указывает, что указанный "символ" нужно трактовать именно, как ;литеральный, для того, чтобы запятая воспринемалась не как разделитель ;операторов, а как символ (!, = ",") ENDM % IRP arg,<txt>;оператор % используется в тех случаях, когда нужно ;в макрос передать результат выражения push arg; PUSH'им каждый аргумент в порядке обратном указанному ENDM call _imp__&Fn;оператор & указывает на границу формального параметра ENDM ;---------------------------------------------------------------------- .code start: invoke MessageBoxA@16, eax, offset MsgBoxText, offset MsgCaption,\ MB_OK or MB_ICONASTERISK retn MsgCaption db "Iczelion Tutorial #2:MessageBox",0 MsgBoxText db "Win32 Assembly with masm is Great!",0 end start
макрос, преобразующий ASCII-строку в UNICODE-строку в MASM Код (Text): du macro string local bslash bslash = 0 irpc c,<string> if bslash eq 0 if '&c' eq "/" bslash = 1 elseif '&c'gt 127 db ('&c'- 0B0h),4;; кириллица else dw '&c';; латиница endif else bslash = 0 if '&c' eq "n";; управляющие символы DW 0Dh,0Ah elseif '&c' eq "/" dw '/' elseif '&c' eq "r" dw 0Dh elseif '&c' eq "l" dw 0Ah elseif '&c' eq "s" dw 20h elseif '&c' eq "c" dw 3Bh elseif '&c' eq "t" dw 9 endif endif endm dw 0;; ноль, завершающий UNICODE-строку endm
Локальные макро-переменные не следует использовать без необходимости. Вторую строку лучше убрать. Код (Text): local bslash
s_d_f можно конечно bslash объявить как глобальную константу, но ведь макрос DU может быть вызван из нескольких мест, local bslash сделана по подобию Strings.mac by Four-F (см. STRINGA MACRO)
Это легко проверяется на практике. Никаких проблем не будет. Локальные полезны только в редких случаях при рекурсии. Просто у меня были проблемы именно из-за того что я слишком часто использовал LOCAL, без необходимости. Потом пришлось их удалять.
Как я посмотрю, нормальные и надёжные макросы по UNICODE (и не только) никому не нужны. Жаль, а уже хотел было выложить...
LShadow77 А вы ожидали голосования по поводу выкладывать или не выкладывать kdvbase.inc ? P.S. продолжая вашу мысль: и у меня, и у s_d_f макросы ненормальные и ненадёжные?
Это ваша мысль и только ваша (я свою не продолжал)! А насчёт голосования, кстати, неплохая идея. Чем каждый ассемблерщик изобретал велосипед, не лучше было бы организовать конкурс макробиблиотек (моих, ваших, s_d_f и др. пользователей) и опубликовать лучшую на сайте?
To Heap (в смысле До кучи Код (Text): .586 .model flat, stdcall option casemap :none ; To get unicode support include \masm32\macros\ucmacros.asm include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib include \masm32\include\user32.inc includelib \masm32\lib\user32.lib .data ; WSTR gets you a unicode string definition WSTR wstrTitle, "Hello" WSTR wstrMessage, "World" .code main: invoke MessageBoxW, NULL, ADDR wstrMessage, ADDR wstrTitle, MB_OK invoke ExitProcess, eax end main