Здравстауйте, мне понадобилось определить, на сколько push и pop изменяют esp, что-то вроде: Код (Text): delta equ n push something ;delta=n+4 Всё было бы просто, но fasm поддерживает подобные конструкции: Код (Text): push param1 param2 param3 ... pop param1 param2 param3 ... Я пытался использовать irps при переопределении push и pop, но он при использовании чего-нибудь вроде [mem] считает это разными словами: "[", "mem", "]". Кто-нибудь знает, как это делается?
Вобще-то фасм ничего подобного не поддерживает, просто у тебя где-то описан макрос, меняющий push и pop. Соответственно просто переопредели его, или замени совсем Код (Text): purge push,pop !r.32 fix <eax,ebx,ecx,edx,esi,edi,esp,ebp> !r.16 fix <ax,bx,cx,dx,si,di,sp,bp,cs,ds,es,fs,gs> %esp = 0 macro push [p] { if p in !r.32 %esp=%esp+4 else if p in !r.16 %esp=%esp+2 else end if } Правда в таком виде невозможно отличить push dword x от push word x, но если это принципиально - сделай нормальный разбор параметров match. Но быстро это работать не будет.
xRom2 Поддерживает. qwe8013 Проще всего, наверное, запихать в virtual и декодировать инструкции. Такой себе микродизассемблер в директивах fasm.
xRom2 Попробуйте собрать такой код: Код (Text): use32 push eax edx dword [esi] всё нормально собирается, так что всё-таки поддерживает, в общем-то в этом и проблема.
Действительно, я проверял с запятыми, а он вишь как. Ну все равно - замени команду макросом, и в нем сделай нормальную форму передачи аргументов, тогда пуш можно будет использовать ТОЛЬКО с параметрами, переданными через запятую, что в принципе и правильно.
В общем проблема решена: Код (Text): format PE gui entry start section 'qweasd' readable writeable executable %esp = 0 macro the_push arg { local ..start,push@x ..start: push arg load push@x byte from ..start if push@x=66h %esp=%esp+2 else %esp=%esp+4 end if } macro push args { local _qwe_,comma,no_reg _qwe_ equ comma equ no_reg equ 0 irps reg,args \{ match =0,no_reg \\{ no_reg equ 1 comma equ match =eax,reg \\\{ no_reg equ 0 comma equ , \\\} match =ecx,reg \\\{ no_reg equ 0 comma equ , \\\} match =edx,reg \\\{ no_reg equ 0 comma equ , \\\} match =ebx,reg \\\{ no_reg equ 0 comma equ , \\\} match =esp,reg \\\{ no_reg equ 0 comma equ , \\\} match =ebp,reg \\\{ no_reg equ 0 comma equ , \\\} match =esi,reg \\\{ no_reg equ 0 comma equ , \\\} match =edi,reg \\\{ no_reg equ 0 comma equ , \\\} match =ax,reg \\\{ no_reg equ 0 comma equ , \\\} match =cx,reg \\\{ no_reg equ 0 comma equ , \\\} match =dx,reg \\\{ no_reg equ 0 comma equ , \\\} match =bx,reg \\\{ no_reg equ 0 comma equ , \\\} match =sp,reg \\\{ no_reg equ 0 comma equ , \\\} match =bp,reg \\\{ no_reg equ 0 comma equ , \\\} match =si,reg \\\{ no_reg equ 0 comma equ , \\\} match =di,reg \\\{ no_reg equ 0 comma equ , \\\} \\} match =],reg \\{ no_reg equ 0 comma equ , \\} _qwe_ equ _qwe_ reg match =,,comma \\{ the_push _qwe_ _qwe_ equ \\} \} } macro the_pop arg { local ..start,pop@x ..start: pop arg load pop@x byte from ..start if pop@x=66h %esp=%esp-2 else %esp=%esp-4 end if } macro pop args { local _qwe_,comma,no_reg _qwe_ equ comma equ no_reg equ 0 irps reg,args \{ match =0,no_reg \\{ no_reg equ 1 comma equ match =eax,reg \\\{ no_reg equ 0 comma equ , \\\} match =ecx,reg \\\{ no_reg equ 0 comma equ , \\\} match =edx,reg \\\{ no_reg equ 0 comma equ , \\\} match =ebx,reg \\\{ no_reg equ 0 comma equ , \\\} match =esp,reg \\\{ no_reg equ 0 comma equ , \\\} match =ebp,reg \\\{ no_reg equ 0 comma equ , \\\} match =esi,reg \\\{ no_reg equ 0 comma equ , \\\} match =edi,reg \\\{ no_reg equ 0 comma equ , \\\} match =ax,reg \\\{ no_reg equ 0 comma equ , \\\} match =cx,reg \\\{ no_reg equ 0 comma equ , \\\} match =dx,reg \\\{ no_reg equ 0 comma equ , \\\} match =bx,reg \\\{ no_reg equ 0 comma equ , \\\} match =sp,reg \\\{ no_reg equ 0 comma equ , \\\} match =bp,reg \\\{ no_reg equ 0 comma equ , \\\} match =si,reg \\\{ no_reg equ 0 comma equ , \\\} match =di,reg \\\{ no_reg equ 0 comma equ , \\\} \\} match =],reg \\{ no_reg equ 0 comma equ , \\} _qwe_ equ _qwe_ reg match =,,comma \\{ the_pop _qwe_ _qwe_ equ \\} \} } ret_addr equ esp+%esp start: mov eax,[ret_addr] push di eax mov eax,[ret_addr] pop ebx mov eax,[ret_addr] push word [esp] mov eax,[ret_addr] pop bx mov eax,[ret_addr] lea esp,[ret_addr] retn
qwe8013 Круто решена. push 1 2 3 тоже правильно отработает? А как насчёт push dword 1 2 word 3? А если так: push $ $ $? А так: @@: push word rva @B $$ %t? А ещё (по секрету) можно написать push label_1 label_2 label_3, да ещё и атрибутики (rva, dword) добавить можно.
l_inc Вы правы, я чего-то тупанул, так что пришлось всё-таки писать как вы в #3 рекомендовали, и вот что получилось: Код (Text): format PE gui entry start section 'qweasd' readable writeable executable %esp = 0 macro push arg { local push@x,_qwe_,_end_,sib,mod00,mod01,mod10;,mod11 sib equ (push@x and 00000111b)=00000100b mod00 equ (push@x and 11000000b)=00000000b mod01 equ (push@x and 11000000b)=01000000b mod10 equ (push@x and 11000000b)=10000000b ;mod11 equ (push@x and 11000000b)=11000000b _qwe_=$ push arg _end_=$ while _qwe_<_end_ is16=0 load push@x byte from _qwe_ _qwe_=_qwe_+1 while (push@x=0F0h) | (push@x=0F2h) | (push@x=0F3h) | (push@x=2Eh) | (push@x=36h) | (push@x=3Eh) | (push@x=26h) | (push@x=64h) | (push@x=65h) | (push@x=66h) ;push@x in <0F0h,0F2h,0F3h,2Eh,36h,3Eh,26h,64h,65h,66h> does not work, why? if push@x=66h is16=1 end if load push@x byte from _qwe_ _qwe_=_qwe_+1 end while ;push@x=opcode if push@x=0Fh _qwe_=_qwe_+1 else if push@x=0FFh load push@x byte from _qwe_ _qwe_=_qwe_+1 ;push@x=modrm ;_qwe_=modrm+1 if mod00 if sib load push@x byte from _qwe_ _qwe_=_qwe_+1 ;push@x=sib if (push@x and 00000111b)=00000101b _qwe_=_qwe_+4 end if else if (push@x and 00000111b)=00000101b;r/m=101b _qwe_=_qwe_+4 else ; end if else if mod01 if sib _qwe_=_qwe_+2 else _qwe_=_qwe_+1 end if else if mod10 if sib _qwe_=_qwe_+5 else _qwe_=_qwe_+4 end if else;mod11 ;_qwe_ points to next instruction end if else if push@x=6Ah _qwe_=_qwe_+1 else if push@x=68h if is16=1 _qwe_=_qwe_+2 else _qwe_=_qwe_+4 end if else ;push r(32/16)/seg end if ;;;;;;;;;;;;;;;;;;;;;;;; if is16=0 %esp=%esp+4 else %esp=%esp+2 end if end while } macro pop arg { local pop@x,_qwe_,_end_,sib,mod00,mod01,mod10;,mod11 sib equ (pop@x and 00000111b)=00000100b mod00 equ (pop@x and 11000000b)=00000000b mod01 equ (pop@x and 11000000b)=01000000b mod10 equ (pop@x and 11000000b)=10000000b ;mod11 equ (pop@x and 11000000b)=11000000b _qwe_=$ pop arg _end_=$ while _qwe_<_end_ is16=0 load pop@x byte from _qwe_ _qwe_=_qwe_+1 while (pop@x=0F0h) | (pop@x=0F2h) | (pop@x=0F3h) | (pop@x=2Eh) | (pop@x=36h) | (pop@x=3Eh) | (pop@x=26h) | (pop@x=64h) | (pop@x=65h) | (pop@x=66h) ;pop@x in <0F0h,0F2h,0F3h,2Eh,36h,3Eh,26h,64h,65h,66h> does not work, why? if pop@x=66h is16=1 end if load pop@x byte from _qwe_ _qwe_=_qwe_+1 end while ;pop@x=opcode if pop@x=0Fh _qwe_=_qwe_+1 else if pop@x=08Fh load pop@x byte from _qwe_ _qwe_=_qwe_+1 ;pop@x=modrm ;_qwe_=modrm+1 if mod00 if sib load pop@x byte from _qwe_ _qwe_=_qwe_+1 ;pop@x=sib if (pop@x and 00000111b)=00000101b _qwe_=_qwe_+4 end if else if (pop@x and 00000111b)=00000101b;r/m=101b _qwe_=_qwe_+4 else ; end if else if mod01 if sib _qwe_=_qwe_+2 else _qwe_=_qwe_+1 end if else if mod10 if sib _qwe_=_qwe_+5 else _qwe_=_qwe_+4 end if else;mod11 ;_qwe_ points to next instruction end if else if pop@x=6Ah _qwe_=_qwe_+1 else if pop@x=68h if is16=1 _qwe_=_qwe_+2 else _qwe_=_qwe_+4 end if else ;push r(32/16)/seg end if ;;;;;;;;;;;;;;;;;;;;;;;; if is16=0 %esp=%esp-4 else %esp=%esp-2 end if end while } ret_addr equ esp+%esp start: mov eax,[ret_addr] push word [esp] mov eax,[ret_addr] push @f mov eax,[ret_addr] pop bx mov eax,[ret_addr] push 10 rva start word [esp] mov eax,[ret_addr] pop cx dx mov eax,[ret_addr] pop edi mov eax,[ret_addr] pop bp ebx mov eax,[ret_addr] @@: retn Зря я на самом деле префиксы проверял (кроме 66h), всё-равно при использовании префикса он использует оригинальный push/pop.
qwe8013 Нунифигасебе надекодировали. Вряд ли до этого руки дойдут, но таки добавлю себе в конец todo list'а реализацию дизассемблера длин в директивах fasm. Потому что оператор in проверяет равенство, как оператор eq, а не как оператор =.