fasm/0000755000175000017500000000000014533376755012314 5ustar privalovprivalovfasm/examples/0000755000175000017500000000000014533376740014124 5ustar privalovprivalovfasm/examples/elfexe/0000755000175000017500000000000014533376740015374 5ustar privalovprivalovfasm/examples/elfexe/dynamic/0000755000175000017500000000000014533376740017020 5ustar privalovprivalovfasm/examples/elfexe/dynamic/elf.inc0000644000175000017500000000421214533376740020260 0ustar privalovprivalov macro Elf32_Sym name,value,size,bind,type,other,shndx { dd name+0 dd value+0 dd size+0 db (bind+0) shl 4 + (type+0) db other+0 dw shndx+0 } virtual at 0 Elf32_Sym sizeof.Elf32_Sym = $ end virtual macro Elf32_Rel offset,symbol,type { dd offset+0 dd (symbol+0) shl 8 + (type+0) } virtual at 0 Elf32_Rel sizeof.Elf32_Rel = $ end virtual macro Elf32_Rela offset,symbol,type,addend { dd offset+0 dd (symbol+0) shl 8 + (type+0) dd addend+0 } virtual at 0 Elf32_Rela sizeof.Elf32_Rela = $ end virtual macro Elf64_Sym name,value,size,bind,type,other,shndx { dd name+0 db (bind+0) shl 4 + (type+0) db other+0 dw shndx+0 dq value+0 dq size+0 } virtual at 0 Elf64_Sym sizeof.Elf64_Sym = $ end virtual macro Elf64_Rel offset,symbol,type { dq offset+0 dq (symbol+0) shl 32 + (type+0) } virtual at 0 Elf64_Rel sizeof.Elf64_Rel = $ end virtual macro Elf64_Rela offset,symbol,type,addend { dq offset+0 dq (symbol+0) shl 32 + (type+0) dq addend+0 } virtual at 0 Elf64_Rela sizeof.Elf64_Rela = $ end virtual DT_NULL = 0 DT_NEEDED = 1 DT_HASH = 4 DT_STRTAB = 5 DT_SYMTAB = 6 DT_RELA = 7 DT_RELASZ = 8 DT_RELAENT = 9 DT_STRSZ = 10 DT_SYMENT = 11 DT_REL = 17 DT_RELSZ = 18 DT_RELENT = 19 STB_LOCAL = 0 STB_GLOBAL = 1 STB_WEAK = 2 STT_NOTYPE = 0 STT_OBJECT = 1 STT_FUNC = 2 STT_SECTION = 3 STT_FILE = 4 R_386_NONE = 0 R_386_32 = 1 R_386_PC32 = 2 R_386_GOT32 = 3 R_386_PLT32 = 4 R_386_COPY = 5 R_386_GLOB_DAT = 6 R_386_JMP_SLOT = 7 R_386_RELATIVE = 8 R_386_GOTOFF = 9 R_386_GOTPC = 10 R_X86_64_NONE = 0 R_X86_64_64 = 1 R_X86_64_PC32 = 2 R_X86_64_GOT32 = 3 R_X86_64_PLT32 = 4 R_X86_64_COPY = 5 R_X86_64_GLOB_DAT = 6 R_X86_64_JUMP_SLOT = 7 R_X86_64_RELATIVE = 8 R_X86_64_GOTPCREL = 9 R_X86_64_32 = 10 R_X86_64_32S = 11 R_X86_64_16 = 12 R_X86_64_PC16 = 13 R_X86_64_8 = 14 R_X86_64_PC8 = 15 R_X86_64_DPTMOD64 = 16 R_X86_64_DTPOFF64 = 17 R_X86_64_TPOFF64 = 18 R_X86_64_TLSGD = 19 R_X86_64_TLSLD = 20 R_X86_64_DTPOFF32 = 21 R_X86_64_GOTTPOFF = 22 R_X86_64_TPOFF32 = 23 R_X86_64_PC64 = 24 R_X86_64_GOTOFF64 = 25 R_X86_64_GOTPC32 = 26 fasm/examples/elfexe/dynamic/hello.asm0000644000175000017500000000043214533376740020624 0ustar privalovprivalov format ELF executable 3 entry start include 'import32.inc' include 'proc32.inc' interpreter '/lib/ld-linux.so.2' needed 'libc.so.6' import printf,exit segment readable executable start: cinvoke printf,msg cinvoke exit segment readable writeable msg db 'Hello world!',0xA,0 fasm/examples/elfexe/dynamic/hello64.asm0000644000175000017500000000045014533376740020776 0ustar privalovprivalov format ELF64 executable 3 entry start include 'import64.inc' interpreter '/lib64/ld-linux-x86-64.so.2' needed 'libc.so.6' import printf,exit segment readable executable start: lea rdi,[msg] xor eax,eax call [printf] call [exit] segment readable writeable msg db 'Hello world!',0xA,0 fasm/examples/elfexe/dynamic/import32.inc0000644000175000017500000000240714533376740021175 0ustar privalovprivalov include 'elf.inc' macro interpreter [library] { segment interpreter readable db library,0 } macro needed [library] { local str match needed,needed@dynamic \{ define needed@dynamic needed,str:library \} match ,needed@dynamic \{ define needed@dynamic str:library \} } define needed@dynamic macro import [name] { common local strtab,strsz,symtab,rel,relsz,hash segment dynamic readable match needed,needed@dynamic \{ irp item,needed \\{ match str:library,item \\\{ dd DT_NEEDED,str-strtab \\\} \\} \} dd DT_STRTAB,strtab dd DT_STRSZ,strsz dd DT_SYMTAB,symtab dd DT_SYMENT,sizeof.Elf32_Sym dd DT_REL,rel dd DT_RELSZ,relsz dd DT_RELENT,sizeof.Elf32_Rel dd DT_HASH,hash dd DT_NULL,0 segment readable writeable symtab: Elf32_Sym forward local fstr Elf32_Sym fstr-strtab,0,0,STB_GLOBAL,STT_FUNC,0,0 common rel: local counter counter = 1 forward Elf32_Rel name,counter,R_386_32 counter = counter+1 common relsz = $-rel hash: dd 1,counter dd 0 repeat counter if %=counter dd 0 else dd % end if end repeat strtab db 0 forward fstr db `name,0 common match needed,needed@dynamic \{ irp item,needed \\{ match str:library,item \\\{ str db library,0 \\\} \\} \} strsz = $-strtab forward name dd 0 } fasm/examples/elfexe/dynamic/import64.inc0000644000175000017500000000242414533376740021201 0ustar privalovprivalov include 'elf.inc' macro interpreter [library] { segment interpreter readable db library,0 } macro needed [library] { local str match needed,needed@dynamic \{ define needed@dynamic needed,str:library \} match ,needed@dynamic \{ define needed@dynamic str:library \} } define needed@dynamic macro import [name] { common local strtab,strsz,symtab,rel,relsz,hash segment dynamic readable match needed,needed@dynamic \{ irp item,needed \\{ match str:library,item \\\{ dq DT_NEEDED,str-strtab \\\} \\} \} dq DT_STRTAB,strtab dq DT_STRSZ,strsz dq DT_SYMTAB,symtab dq DT_SYMENT,sizeof.Elf64_Sym dq DT_RELA,rela dq DT_RELASZ,relasz dq DT_RELAENT,sizeof.Elf64_Rela dq DT_HASH,hash dq DT_NULL,0 segment readable writeable symtab: Elf64_Sym forward local fstr Elf64_Sym fstr-strtab,0,0,STB_GLOBAL,STT_FUNC,0,0 common rela: local counter counter = 1 forward Elf64_Rela name,counter,R_X86_64_64 counter = counter+1 common relasz = $-rela hash: dd 1,counter dd 0 repeat counter if %=counter dd 0 else dd % end if end repeat strtab db 0 forward fstr db `name,0 common match needed,needed@dynamic \{ irp item,needed \\{ match str:library,item \\\{ str db library,0 \\\} \\} \} strsz = $-strtab forward name dq 0 } fasm/examples/elfexe/dynamic/proc32.inc0000644000175000017500000001723314533376740020631 0ustar privalovprivalov ; Macroinstructions for defining and calling procedures macro stdcall proc,[arg] ; directly call STDCALL procedure { common if ~ arg eq reverse pushd arg common end if call proc } macro invoke proc,[arg] ; indirectly call STDCALL procedure { common if ~ arg eq reverse pushd arg common end if call [proc] } macro ccall proc,[arg] ; directly call CDECL procedure { common size@ccall = 0 if ~ arg eq reverse pushd arg size@ccall = size@ccall+4 common end if call proc if size@ccall add esp,size@ccall end if } macro cinvoke proc,[arg] ; indirectly call CDECL procedure { common size@ccall = 0 if ~ arg eq reverse pushd arg size@ccall = size@ccall+4 common end if call [proc] if size@ccall add esp,size@ccall end if } macro proc [args] ; define procedure { common match name params, args> \{ define@proc name, \{ prologue name,flag,parmbytes,localbytes,reglist \} virtual at parmbase@proc match =,args, params \{ defargs@proc args \} match =args@proc args, args@proc params \{ defargs@proc args \} parmbytes = $-(parmbase@proc) end virtual name # % = parmbytes/4 all@vars equ current = 0 macro locals \{ virtual at localbase@proc+current macro label def \\{ match . type,def> \\\{ deflocal@proc .,label, \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} macro finish@proc \{ localbytes = current match close:reglist, close@proc: \\{ close name,flag,parmbytes,localbytes,reglist \\} end if \} } macro defargs@proc [arg] { common if ~ arg eq forward local ..arg,current@arg match argname:type, arg \{ current@arg equ argname label ..arg type argname equ ..arg if dqword eq type dd ?,?,?,? else if tbyte eq type dd ?,?,? else if qword eq type | pword eq type dd ?,? else dd ? end if \} match =current@arg,current@arg \{ current@arg equ arg arg equ ..arg ..arg dd ? \} common args@proc equ current@arg forward restore current@arg common end if } macro deflocal@proc name,def,[val] { name def val } macro deflocal@proc name,def,[val] { common match vars, all@vars \{ all@vars equ all@vars, \} all@vars equ all@vars name forward local ..var,..tmp ..var def val match =?, val \{ ..tmp equ \} match any =?, val \{ ..tmp equ \} match any (=?), val \{ ..tmp equ \} match =label, def \{ ..tmp equ \} match tmp : value, ..tmp : val \{ tmp: end virtual initlocal@proc ..var,def value virtual at tmp\} common match first rest, ..var, \{ name equ first \} } struc label type { label . type } macro initlocal@proc name,def { virtual at name def size@initlocal = $ - name end virtual position@initlocal = 0 while size@initlocal > position@initlocal virtual at name def if size@initlocal - position@initlocal < 2 current@initlocal = 1 load byte@initlocal byte from name+position@initlocal else if size@initlocal - position@initlocal < 4 current@initlocal = 2 load word@initlocal word from name+position@initlocal else current@initlocal = 4 load dword@initlocal dword from name+position@initlocal end if end virtual if current@initlocal = 1 mov byte [name+position@initlocal],byte@initlocal else if current@initlocal = 2 mov word [name+position@initlocal],word@initlocal else mov dword [name+position@initlocal],dword@initlocal end if position@initlocal = position@initlocal + current@initlocal end while } macro endp { purge ret,locals,endl finish@proc purge finish@proc restore regs@proc match all,args@proc \{ restore all \} restore args@proc match all,all@vars \{ restore all \} } macro local [var] { common locals forward done@local equ match varname[count]:vartype, var \{ match =BYTE, vartype \\{ varname rb count restore done@local \\} match =WORD, vartype \\{ varname rw count restore done@local \\} match =DWORD, vartype \\{ varname rd count restore done@local \\} match =PWORD, vartype \\{ varname rp count restore done@local \\} match =QWORD, vartype \\{ varname rq count restore done@local \\} match =TBYTE, vartype \\{ varname rt count restore done@local \\} match =DQWORD, vartype \\{ label varname dqword rq count+count restore done@local \\} match , done@local \\{ virtual varname vartype end virtual rb count*sizeof.\#vartype restore done@local \\} \} match :varname:vartype, done@local:var \{ match =BYTE, vartype \\{ varname db ? restore done@local \\} match =WORD, vartype \\{ varname dw ? restore done@local \\} match =DWORD, vartype \\{ varname dd ? restore done@local \\} match =PWORD, vartype \\{ varname dp ? restore done@local \\} match =QWORD, vartype \\{ varname dq ? restore done@local \\} match =TBYTE, vartype \\{ varname dt ? restore done@local \\} match =DQWORD, vartype \\{ label varname dqword dq ?,? restore done@local \\} match , done@local \\{ varname vartype restore done@local \\} \} match ,done@local \{ var restore done@local \} common endl } fasm/examples/elfexe/hello.asm0000644000175000017500000000045414533376740017204 0ustar privalovprivalov ; fasm demonstration of writing simple ELF executable format ELF executable 3 entry start segment readable executable start: mov eax,4 mov ebx,1 mov ecx,msg mov edx,msg_size int 0x80 mov eax,1 xor ebx,ebx int 0x80 segment readable writeable msg db 'Hello world!',0xA msg_size = $-msg fasm/examples/elfexe/hello64.asm0000644000175000017500000000130014533376740017345 0ustar privalovprivalov ; fasm demonstration of writing 64-bit ELF executable ; (thanks to František Gábriš) ; syscall numbers: /usr/src/linux/include/asm-x86_64/unistd.h ; parameters order: ; r9 ; 6th param ; r8 ; 5th param ; r10 ; 4th param ; rdx ; 3rd param ; rsi ; 2nd param ; rdi ; 1st param ; eax ; syscall_number ; syscall format ELF64 executable 3 segment readable executable entry $ mov edx,msg_size ; CPU zero extends 32-bit operation to 64-bit ; we can use less bytes than in case mov rdx,... lea rsi,[msg] mov edi,1 ; STDOUT mov eax,1 ; sys_write syscall xor edi,edi ; exit code 0 mov eax,60 ; sys_exit syscall segment readable writeable msg db 'Hello 64-bit world!',0xA msg_size = $-msg fasm/examples/elfobj/0000755000175000017500000000000014533376740015365 5ustar privalovprivalovfasm/examples/elfobj/msgdemo.asm0000644000175000017500000000062414533376740017524 0ustar privalovprivalov ; fasm demonstration of assembling object files ; compile the program using commands like: ; fasm msgdemo.asm msgdemo.o ; fasm writemsg.asm writemsg.o ; ld msgdemo.o writemsg.o -o msgdemo format ELF section '.text' executable public _start _start: extrn writemsg mov esi,msg call writemsg mov eax,1 xor ebx,ebx int 0x80 section '.data' writeable msg db "Elves are coming!",0xA,0 fasm/examples/elfobj/writemsg.asm0000644000175000017500000000027714533376740017736 0ustar privalovprivalov format ELF section '.text' executable public writemsg writemsg: mov ecx,esi find_end: lodsb or al,al jnz find_end mov edx,esi sub edx,ecx mov eax,4 mov ebx,1 int 0x80 ret fasm/examples/libcdemo/0000755000175000017500000000000014533376740015702 5ustar privalovprivalovfasm/examples/libcdemo/ccall.inc0000644000175000017500000000046614533376740017461 0ustar privalovprivalov macro ccall proc,[arg] { common local size size = 0 mov ebp,esp if ~ arg eq forward size = size + 4 common sub esp,size end if and esp,-16 if ~ arg eq add esp,size reverse pushd arg common end if call proc mov esp,ebp } fasm/examples/libcdemo/libcdemo.asm0000644000175000017500000000062214533376740020162 0ustar privalovprivalov ; fasm example of using the C library in Unix systems ; compile the source with commands like: ; fasm libcdemo.asm libcdemo.o ; gcc libcdemo.o -o libcdemo ; strip libcdemo format ELF include 'ccall.inc' section '.text' executable public main extrn printf extrn getpid main: call getpid ccall printf, msg,eax ret section '.data' writeable msg db "Current process ID is %d.",0xA,0 fasm/fasm0000755000175000017500000032115314533375770013171 0ustar privalovprivalovELFt44 (kkkk2k2C%7[%7 $\77 p2+l2x2+t2 ]NG1̀GáGأ7%7d 7k.Iy~2@ANG1̀GáG+7s61һd t&1һ R.X2ɉ|0;{k*72227f2d Iti773<-t%=2u 52=2u:52FuIt3 t@s7%>uItЃ3{ twf2IJ=2t727À>uIt3W=7M=7_f뱀>u IX3521¬< tt,0r< wk p rNÉGs0<=t< tt Gsuì< tt GsNGs0É%|21۸-̀t2 7 ut2˸-̀p2+t2t2x2l2ظ̀73t$ʬ"B<=tt(t u [output] optional settings: -m set the limit in kilobytes for the available memory -p set the maximum allowed number of passes -d = define symbolic variable -s dump symbolic information for debugging ( kilobytes memory) passes, seconds, bytes. h-h#hh h hh=2hh(h;hOhghxhhhyhoheh[h Qh/ GhJ =hn 3h )h h h  h 6 1h6=353v G uð'Nf'fÿ6!=3t53v t G G !h6gh!`h*!Yh8!RhE!Khb!Dhy!=h!6h!/h!(h!!h!h "h" hZ"h/"=20!=2 52 ;=$3)؉C̋52;=$3|3-2%3=3t=3%t39t0=l2t22x2212$33 34252SHFP:^=l2z;=p2 < tĻ4t9'tQ"tLfĪ41ɬف|)ˈKOf< t<;[<\t*녰"D8u8tNO)؉C^!< <;f\fN<\u< <"<'<;Ļ4tN=l2+zz 52h=l2z=4t323  t5 t/RӋ tӉ Z=4tڡ32d=2ÍwQV2R5p2V1P01 Yp2J)9p2Z1ɉA=2Ыȫ)ث1SRZ[~t~uяp2Q4tf;f;=p20< t< tĻ4tA'"fĪ41ɬف)ˈKOf< rt<;<\tq<< t$< t< ou< }Nw< nNh"< t{< twts<to8u8tNO)؉C< < << < <;f\fN<\uC<< < < < <"<'<;Ļ4tQC< t< t<tVtR< t< t#<;T< t< tt<u/< t N< tN$< < t<u0Yÿ54תW_5t GÊ&:'rw 8ur t ߃ԉ։ 4* Ë$É+|2=QV52f>;u4uA>u5VTf:u&4BBB=fix~524u503F<rW_rB;0rC;2^ 52ά<:<v<u'4FF=equ3O;RV5252-2N*rY1J + 2w{=2rJ  22:f;f^r Z 2BWw)_G:B^ZFe N)΍nst>:FZJ 9t;uC\9t;:u C;:uCE)z WP9tr t|J |$)ϋr_^F)503^YUWV$<u6v1f__f;u(f;Du!U]r1u3  tZ1OuPŁ 1ʼn t,1Ouȋ tzv t4$ u^_][_]1۸ŝ28rWV1ttQɿGYŁ 1 ͻ3  tX1ŃIu tt7zu: t+u%Ћ2;22^_rË2;221BIuы2;22^_rÃRV52F;N[I)ىZJ <FƍO)rJ 0<2B FƉr4$ 4231<{!N<t<[< FƬ<:t5<=t1<*u<,t<&t<]uլ '<{ 4Fŀ>t<)tO052=2F돭V123B ^r4$ 4<{gD3"33334$ 42352=3t;t<{t<"t <uN52<{3Ь<,t&<"t<t<=u<t<"tFڬҭ0Q<r t BY<,t33<t$<"t <{t uí3tNՊF-3Cr=3J R"֬<tj<"t3<{t:u)Í;p23ssfí3t 3)))tÊF-3fNfibZVW30_D;p2"ȫ^)$G;p2oK 2t Ct[0҉<`tr<#<t<;t <"t!0u߉Éò>\t IJ"OIF)Fٻ4׉F0F<uf̍_$>\uFIK<"<`t׍_1t<#tA)w"ªȫ99Quݍ}N)X"Wt t"t<9t>uF>\t WFIt4uĀ>"t5>`uF<`t<"t%<uF>\uFI t<#t F<`<#g<t<;<"t0uò >\뿲"5252253rBRrB 231<{F<[u F33<,t<]t<&N;,uC뼀;,C3먬ȡ3K 12>*t>:t>=uF52 4`F 2r 4;&t @5NB )Jzu2 tB ËB )8Ft=3w1<:t<=t<*u<,=1 4>,F#<,=3t<{ 1525225332=3=3t02P352F;,uCX52F33Z ;t;"tCCBÀ;t;{u4<  R3j tBvNtZ53R52FȋD$}ZJ BC K t ;ju $uXN΀>>{?<t<,;52| ;p2Zrbr6rC\;tu;52;tZC\r 9ZC\;trrۉr;52t <t<"tËFF;52t&<,t<t <=t tCtKÊ<t<"t 8tÍ[vËKKuÉƉÀ;,j1525225332VWR;<$t!7F1GB O)J Z_^54 4535252525252P52<{t)v52t<{t<;\߹5222 21393t3<}N=2G;p2zD$ tȫ$2)$@x;txuP@$X諉ȫ2 4 SQ4tf;f;p2<}5-<t <;%4ߪ<"uŋVW4 tFjsN _XGY[%4F3s5193tL_XJR t~)C193tVR)xZ^r9wÉ@PcX_QJR r G;3t ,GYW)YX3%t I'1QRZYA; 3,G}ٰ-ffWȹʚ;10Ru tt01ҹ X u[)؈C_^F>.u\$ t<tNOFNOD$8;8u;\$VW{wN)f;_^Ƭ<t<;t<"tuíGPXY[<}tA522 2223X$%44ì<G;0Qȡ3z 2@=l;-p2-İf?V2 2^+B B02<:r+uA#<[rua<{r00Y<}<,O<C0p3C=3tP3#=3t03 35222 2;52tJ=3tA|3;3t233H=t35222 2Q r t $ztދYYȉŻ2 t1 uSUr'2;2l2r][Ë2;2G21BBB  uʃ1랬<"<VW23Ct[u;<$t\t /tOt$LPZOsI-2>t#UWhPt$t$PZ"]s։4$WPZ <$u^O)N54%4X$%44p22t2212223335l2=252;2~Q~;G344>WN<:tB<=t` <uVQtN sZY^} sl_f1_S ~:t GF0Gu_ G0Ff1YZ_PSVN G^[XW_°ffЪfQ ff fH f fH't"<:rN3v;52y=3t X2S0=2É+|2=R52fP3fQ f z대>UWFF5 _s?°ffЪfQ tft f t==3f;\$ 3XZfQ   W04$^<0t3<1t; $W04$k^<0t<1 $ $=3f|$Q tg<WF# _fQ $u4°ffЪBW"04$^  $},$$ $;5252>uEFF<:t W_s -tfQ t@ft9f t2fH tSf t<t <;t<"t +|2=52fP3븀>uWFF_s롬fQ tft f t=3f;\$u 3XZfQ 23H Q =3%f|$Q tZ<WFC_fQ $u0$23Q D,$$5-$ $3fdf-fH ff2ff3f2f2tf~1t f@t 4;2<:4<,<=<|<&<~<>h<<q<)j<[<]T<{:<}:<#&<`<;tN=4t<-N<WuPFFs$2>?)_NH_f>+f%f=`_<<<}<<<X<y>WFFss __°ffЪ()>:u봀 4>VFF][t G0>VFF[tG0>FVFVQW 44_r <u fY^ff[SVW_Z[<sևFf(fȫ0V>"tY>VNf(fȫff^>%FF0>">:<Ff(f0VWU_^<I?VQ+Y^u0OD_>"uLF\SQVW0XZY[9ljFf(fssf0e(-)À>(u]+|2=VWF3P@>= F>>t>=FF04PzX404Pa>:uV<]t<,t N)f),f룰]}[f>u6V^>:^u)SW6_^r<u0u0WB_p >(uF4 4=3+ 3=3>)u 3_^=3t 3À>.t"r tK2À~@txÀ>uAUFW_5G9utrG։]0Ít*]Ê<"t?rw:Gt |FGVZ w[rV]]_ t<}Ǎ<5w-r'f<r <t=4t^À=4u^뷍\Vwprk&&(*VwDr? t%}Ǎ<5wr^f_^΍\Á!>@t>.~.=2W=x2)QV52);=2f^Y_SVȈC^[;Xu Sx2ÃuxF4<@tI%ta>$t>?upukFÃt5w]FvF~$t~%tE1øøøøf~%%u"ÃwFt̬4(t?G1rS tGÃufuuGGGGGfF50303<)tN!á2EWVf<u:r0<u,tQtI sDt?<#t;<%t7<&t3<'t/^ _u<iGøZ_GO<jtVr50303^=GC1<"U<ȉ5,3<$t ,0< VNG;$.f;0x(N'tI>_tD1ҋ҉Gr*r&Gr!rrG,0r.< w*WrF9w<'t<_t,0r< w =X5,3NN0;5,3$<'t4<_t0,0<w1҈N@tÀ s ̀ GtN부t0;5,3<'t]<_tY,0<1҈N?w-u<w'tw W 빀 GNtN;5,3^í0GrFـ@t s  G؃WV<-t<+t<u;Ȁv2V0<.t+t>-u F>uFAIut^3<t <+t531ҿ<3WW 3<.t[+t>-uSՃF,0< sk <3 t$ uQ OYQ Y<33G 3G GtWsG GfG_ G G Ӌ؃ӋG؃G t)G GGG6ËG1GG G  _ GuGG G O1G WsG_  GGÁ{tOtGC;G}GNGߋS [W _sG G GGËCGCGC G Q+KS+k CSYËo / o tGuGo g OG03W<F|t&t+tupZN<1tJ<0t6WЪ[<0t2<1uŪ0<0t9<1tWЪ[<1t<0u0롋<$뗉0!r<$1r <$0r_À>~uF~u>u>U3RZ3]uuFW)t4É1҉3tC,t>>t ;4$sHC4)9u(u>>t ;4$s'"4F;4$u^_Uά<,t;4$u^_2^_13f2x3332$3t22x2(352=21\3`3333t33 3333343gsx2;(3t@2392;p2@t(f 2f;Hu@tf+Hfu ` 3@t2f 2`@ uf;Hu@t @tf;Ht 3@@t8`@u'f 2@uf;Hu@t @tf;Ht 3 H=3u<3 tR2= 3u3 t@u 3-$f2f2f;2R=Ë3tC +CC$3CC$,9$331;CCCC{CC á$3-9<f<<<t<t<g3I2%4=2tC=3u:$3CC9-$3{3C3C>Aǽì3Ӊ10ɋ-3>+E>U>Mz%& 3>E u4K Sk +Sͣ\3`3-3 c ;;SSċ-3>m 3>U>m32C $0C :K K :k k ;k k t ;SSf 2fK2ScCt9f;Kʼs r fAf+KtCtf 2f;Ku 3ÀKíFo~P 3&[0Ɋ-3Jc ;;SSĠ32C $0C :K K :k k 1;S S td3;SSf 2fK2SCtff;KuC߻Kc s r6fAf+KCCf 2f;K 3KZif 2@tf;HY@ u 3fPfffPfH2P3K 0%3%3F$4<tNì<(>.t$ 3P3+CCC uK XK 3)SKz"d3S=3a;=2U=J-t3=< F3<:tN<uf<%3>t 3F<(SQK>. $ņffY[c-3c ;;SSċh3 3P<'M\FP>u<3%43%83<*r VW޿43_^34383[f1<:<(3+KK>ubf~):uZF>(F@MfHf; 2uu@ zf2fCKbS>. 3~#]&=3u =311ʉ>+Eu2 3>;Ew$Ã=3u523 33 À=3<(>. =3t32r 3r3B u9w; 3wÀ>t<(E13 3!=3I4383<GJVW43_^; 3/;3#3<(>u)FW=$3);<$=$31_FW=$3 =$3H_;=$3ٴ<,tN$3 t,529t"F)΃tuV贰^;5$3uËN V=252tz1۬;=(3st.ti>:uF535333+|2=V 4393t 3^X33[m(sO<(u.b< -h3:N-3>E 310>+E>U>M 3>f]>fM>m߆fQP3C u 39t=3K >u0f~(LNKK K S4ׄ+F[X 3уSKCk3C 6(3;2C(3Ë(3;x2t f;tf 3K { 2K3+CCÀ>x~)nFF@MfHf; 2u{@ tpf2fCKNC tSc _3VrJB );$3]))B)ZZ^=3523 33S-[C 3{VW+ (3s~(3_^Ë3+CCC C t]K VWQR$3@H)ȣ$3|C C+C t)sNOsf1SSZY_^4><(԰>.Mt~f3C3Cs2C4ٱ3393vC3C3s<wf=y4kf 3Cs2CS u*-<3J[C38[4C23s5f= ΰ4Š<u<u)f~Q u!07fQ C2CXZ<` 4HfQ 9{/<uf~Q uMs1<E4֯$f= t f=Q  f=Q 5323"s<ue2>u>ufFf=dtՃf=tLf= tPf=Q tTf= t$f=H u>ufFf=t f= tf=Q u3á32 v'lb$r>u f~Q u$ì<lfFf=f=f= f=Q f=@42(3t<;x2sff=t7f= t=f=Q t52C2eL2(3S[aS;=$3&>(FN!;uvFF tK>u*FPV;=$3T$<,t<k[XHtP;=$3ȫPVT$[XHt4>uF 5>uF ;=$3$<,MNEO<(ttmF;$3=FË-3>E t; 3t3= 3À 33<(tt w&fFO;$30fFt~<(t:t%Éހ>.z PF<(3P>.[%fX3X%f<(t:t F%ffÉހ>.PF<(v3P>.ժ %X3X$ft~<(tH<(t.Ff~FfFf?7f=-fLfffAf@f wV f 1ҋFsGWf1tf@^ ff f 1F ff AP>:3F<()3P>.#ЫX3X#fff(ݨFt1茣P1Ҁ>:u&F>(F>.+S[)$#>,u)F>(F>.SRZ[;$$0)Yɧ;=$3עĢ<,IN|VW20@t@u;<$t\t /tOt$ZsI2RVt$t$t$Z蹡Zs:u։4$WZ螡f^ì<(>.;$3W=3t1ssfX<(>>.D;$3W=3t.eD<4;$3(W=3t. إ;$3̥W=3K.A{;$3oW=3K<<(ޥ>.W7+#;$3W=3.J -3>+M>}>} t@=3t,=3u t3u>];;Cvx=mH!EAX;$3LW=3t-w=3 23 3ssf:< ݥ=323 3=033> >. $3 9< <<!<<v<<+<)<]6 C GC 8up 0fGgCG C 33:3 3-3>E u;03u3-3>E t 303=3+2P0310-3>+E>U>mz Ы>E>M f>EG3@뺡31 薞Ы ttՃttI Mf=2w 3 3fg 1 =3b23 33G0c G ttuO;KtA ċOKc GCG C z f VފO GO G ^tG8FuN wu7F8F uN bu"F À~uFN À~ &F N 0c G t#t8u 0O;Kt ؈ċOKc )GCG C z=3u+ f .VފO GO G ^x$f tf{u1ɋ  rVR0ۀ~ tV҃V  t=~t ^ )~ t ^ W҃W ~t tF' g 'Vt҃V uӈ^ Zf tSf~tOn f8F uF~ t+n f8jF uF ^Z^f;W?;7VRZf tJ~tF f?F ~ tF f?F ^(VWV~ ^WO !!S K WO  SK WO 11S0K G WWr2 uuSu!K @tw s-S3{ u9K 9u19u-1Cq C#;u C ;P?FG WWsO TSu3@s,Vs sS^ s^C Cfa tWW f; t1uL GuA u;vzf t u׹ Gu1t1҉WW 8t _  t _ _ 110ɇWO )WO zfx3<<<[t3u>%x3r08G tG 2@41)W_ z|%x3r08G tG 2P4@0t3u(t3̚ tIW #0G uf=3t3t3t Gu8w uG8u1ۃ?uu=3^~ t V҃V 7f tW҃W uF1F1^SF1wf'9wr9s +Ws)щʉ[+PR)1wt)Pg)D$X')D$$ZXZXt҃ utVV Nuӈ^ Ã=2t.=3u%$3@@ 9$3Ffgfg 3<<[tj11f~f^V҉  ss fCfffMfffAf5f r f 1fstfC u L^  ډW 1f~tpf^fFffsf@f s f%fCffff,f fffAf f1fsf@ftf%fCf f ^ ff ؉1G 1f~tkf^F s@s %fCffuf- fffAfXf1s@t%fC 7^  ؉1G F1Ffgfg 3 3tOW t u=r Åu=s11҃=3u523 3 3Ã=3u523 33 3<rW t u=rÅy=n3 3H<u%3;WC: 32ËW t Å3 3<u"W t Á3 3W3 3fP3G t u W uÃ=3u23 313舘<(3<t}<tm<t`<tR<tAה3WfGd3G 3G 33`11x1334C334,33433 4>.:Gh3G 3G 3<tk<t<tw u<@%33t:8t6f=t f=a=3u3;Wt=3u11Ɋ 3-3fWGW G W ft t8< <<%3t8<<< t/֒=4_<$8t=4WË;W:W t uuYÈtJtE t@Eu2=3@t)=3u =3f;;Wuɀ=43$<<<bΑ=3@HuDDt,t'=3@t"Eu =3t뒀Eu=3u뀀Ettq` \O0t)<t =3@u(<u$%3t8 $f;]t>f;]ِ>f;Mΐ3>E>U>])33 h3 d3ut2>} 8t ft=3t3>;Mt33>} t>} 03~>|t>&tFuPh[Ft PX[ PX3 3(uG  uG Gd3G 3_ WO0>~uF4P<g<<P<C<<05<12<(mh=3PR5d3SQ<<<&<|F3>(:\$u$t d3;\$u; $t%; $t=3uP[f$Y]=3=tX=3$=3ht=3>tI=3E =3v<te<3 t3<<t<< ">f~(F53tĬ<8-t33<<k<i%t3,V-t33<<.-t33<I<3<<,3< <4<@"ʆ3<t<%t33<t<$3<{Ff2fPH؋2S;(32C2C <#ff(st3S3<t<%t3ff(؅t2B ;(3.2Z<<ņԆF0<:tN<u f<vh3%3̉J1113t3=3t=-3>E u0=3tw=3=3=3!à3<<< "Ët2W׹1=2_fB fB3PSf3:2+2ff fCf;ufCf+;(3҃2[Xì<NtFÉ+2)1RSa[+2=°>uF3е3113h3o<(ƒ=3tCt2fB<:<(=3t2fB=3u523 3؊ì<(CV>:t&f=3Rt2fBc=3tt2fB<:<(=3t2fB-t3=3跆&<(=3t2fB t2%t3r2H@fBJȣ2=23)LJ=2)0+=2fMZfz3fB2ȉ %fFf ufNfBfr2H@52NF)fB fB ֈf B fB 2V|0É3 V1 󫸀f@fMZBfBBB fB fJfBMZN ;=$3,1@fV0m{NV@({)fV0I{NI Vufщ)tr!QIA;$31Yzz)ff%fFJ BfV)F<^É11zP01z $Gff%fF fFN<@)vfF fMZFffF fHfFffFfFfFF@$3)9~1Yzy^1f3Lf33 3@%3t3tf3d3>>>te(LF>.~FR~ ~~ ~fVftBFf~ff)ыFd~%ds@f1Z 3-t3 Yf(}>.Q~RW=3t3u 333_Z=3~>uff(~}F-3 t;3t&+=3=2+23=2ʼnt3t1fPEf3fBB9B=B@3BHf3fB\fu B8BE>M>f]>}%t3sJ %t3 sJ_ %t3 sJ %t3 sJ_]vPSs[X-t3K(RT+39vZ؀ 3W߹1_C ff(zVt|1CVW߉_^c${21+C >]>E 3 t3t >E 3@t3u+B4>]%x3r!>E +B0J4>]%x3r>E >E>M>}<t <tKNsFt3uLxD|ˆDŽŒ f{SRZ[묬< y< yC$1{ C$넋32+Cu%t3rC ÉC;= 3uz8r=3% 3+kJ.lxt3u>9%x3r083tRt3u12+B4B(%x3r083t 2+A0Q4t>A(鵽<(\w>.wt3u_V2B`>,u/<(*w>.w02Bd;B`wUBdB`=@Bd8=3x 2A`Qd>,uN<(v>.4w=3w 2AhQl;Qdwռ;A`wǼAhydA`=Ah頼<(Gv>.vt3uFA2Bh>,k<(v>.v2Bl;Bh}v<=3 w 2ApQt>,<(u>.4v=3v 2AxQ|;Qtvջ;ApvǻPSt3t =3t=3tJ3+CC 23;(3t2C=3tC C[X<<tË2bJ^@-x3r 3%33+3w1=3ǣ3V1ɇ 352)Ɖ5233F9r()tf1fЁ9sfFĊf⺉33^)À>Fff(tt=3t(f=2u%3=3;=$3[sVS52F ;(38s Kns19sf9Fus9F ls 9F^st)°5nV mr|NVN ;(3rmsV FN4fyt9rf9tf9t9rf9t0mU;52r1=3G;$3(r1Jp11ۋ521҃>tWf>tG t1ff; wr5ff  u& t1ff; wrff  u~F t%ӡ3f@ G;$3qث1s52>t!f>uF9~ 9‰~Fځt"ӡ3f@G;$34qث1륋53Nf gQW+3VG;$3p1o11ۋ521҃>V9num'f>t_ t21ff; w&rMff  u>f>uÃf~u t1ff; wrff  u$x^Ftw t#Ӌ$f@ G;$39pث1H52>t2V9nu"kf>uF9~ 9‹$x^FtɁt Ӌ$f@G;$3oث1XYfI53FVЍ4W;4$Nf QW+3VG;$3Xo1zm152>t>V9nu.F9~9} ‹$43^Ft뽁t#Ӌ$f@G;$3nث43XYfID;53WFNȍP t=Q+3f1fG;$3mnff t ff߃Y^;4$r+3tf1fZ[CKQ+53sG;$3nF 1Y9r[U3+HH 04iN;=$3mh+3t )0]9r^h+33f2BPk2B3fBk(JD3Jt4>F%t3r<lCem C%t3kF<(k>.KlS[J9l 1l= &lB SC mg{бC%t3K0鯱3S)ЉC 1 39u;3u׀KÀ=3tUSPt3u =3=31lo=3td=3tY=3 lHS%t3s3[))؃3Pt3u { k { k2 ;(3i2C3@Cd3CX[=3t |32+=2=2=2  3;(3xi1fLt3tfdfC%t3sKSng[C3fC5|311;52tss= ߉@AfN ͉V@z tR:s:r@막 @똋|3{ uX=3tO;2u|3 Êt2t >tiC%t3g HgCiCH  CfC y)Љ+=2=2%22_`e2Y 2`ezVv twW_^.flaCt^É)ЉCA^t3 ;$3e1ELFBBBBBB(4B.(3 Bf>Bf>Bt2|3à ;(3d2133C{CCzӉZB t3#B C;$3Fd1ELFBBBBB>B4@B:@3@Bf> Bf> +%t3d2C ;(3c23f3c1{CC}ӉZB t3tB ff( dst>t'>u\F,4cCPeCF<(c>.DdS[J2d *dC e뚃{Ct3ʩCt3dS3=3tV=3tMP=3t,hdt3=3 t32d m{ !d3[))P=3F?%t3 [=3t |32É+ 2كt3u0W-5|3=21t3tt ga^Ct=f2f;Cu1S tDC8ob@t3uWbfP3a=bfPfFt3u:C $;Cla3da1C { t  1{ t  C 3C"aCC 0AFt3u1F0F1A 20Rt3t9t_t3u'{ t C .rel)և3 t(0ɀ{t C.rela)և3Ը.flaftf띉z 2+21)t3u'ȉC 3f@_fC2f@ _fC0%ȉC(3f@^fC>f@^fC<1(t3t1ɉF~ tFtF$?1F3+2F 1F1yA <$;52t|tvtZ1BZ 됫t3t'9<$tt3tHt3u 0+2$)3ȫAt3u 00;52X2)أ2 t3t( 0#2B+23@3@t3u 00 0B+22B +B11tabB.symBB .strB 322V4\52) 2:W\ t3>(u!F>.\R=3]ZB3>u-f(5\>.\R=3I]3ZB* f=2t 31%3fCC-3ckk +2B%3 210+33SK=|3 t3>(u!F>.[R=3\ZB3@%3>u3f(5[>.[R!=3I\33ZB68f=2t 31%3fC0C-3 3ckKkK+2BJ2xuC t3tC ì<(|Z>.Zt3u2B餠J2CS鎠%t3:Zt3TPck݋324;|3r|3 3cfC>t6>uzfYtYtĄc[cŀ; [f 324;|3s 8"Z #fCPr td|Z;u =3uJ+2C%ЉCC 10у>E>U>M3J1ɇ 3tAICC K)+21릡31=3u";=|3u 33Ã%333K24+2+C;= 3u ;u=3C)ЉC% 3C;t=3u;t;Qt3CC%?PRfn݋3k82@;|3r 3cfC0>t6>uzfWtWtĄc#Ycŀ;Yf 32@;|3s 8"X8#fC0Pr td|ZX;u =3u'+ 2KȃCSCS1ɇ 3t,AQICSCSK+ 2ȃ331΃=3u(;=|3u 333Ã%333Kk82@+2+C;= 3u ;u=3C()ЉC % 3CS;t!=3u;t!;Qt3C(C(%t3u0S23B4fB,Ѓ4;|3t 3 23B @fB8k8Ѓ@;|3t 3À=3@U=3@U=3@U=3uћİffƛ=3@sU=3tߪ骛=3@u=3@NUİHf鉛=3@6UHGİfmG婢 4jU$3Z 4D 47XT<(THy胾İf=3@TP >(uF03<T À=3TXf鳚3bX<<[\TXRSQ<,KT;X<(t1<9TW3Y[Z<t Y3ZL3<r?tB<ti<<S=3*TIY=3T74333Y[Z3_ԙX蒽f4333Y[Z=3u=3uf=43rf=43s3_|3i_kXq4333Y[Z=3u=3u=43r=43s3?_躽љ9t脼=3u3ìU3<,RV<t7<(t_<[RV3<tW3S3GU33<t W3Xq3<t=<tw<<"R=3QRpW)=3:RcŠ33t3XЪ3ЪV諻fŠ33=3u=3u fr%fst/3Wf f铗3WЪ36WVwŠ33=3u=3u rst3=W3V=3u523 333T<t2<[PT3<trU3XNSÈ<t U3 33T<<<[%PrTRSQ<,PT<(<O<0r<@;S3Y[Zt!3QU3"uRDu-wOw<t=3ur U[3fUY陕Tn[3=3@O9UfOa=3@uňul3 ttðO0~T3TY"uDDu)wN<C=3ur0TZ3#TZ3-T3,13Y[Z%3t XN3(3<r>C=3>3B>3w=3@>3cB<t.<[>B<,>A3y>PAe>ì<,P>A3=3@*>oA3<,!>B<[>`B3<t<>wC3bAt=<(=Ч=3u=3>&>P3<,=At=<(==3u=[ȪffЪ镃=3@B= =3@3=B yBB%43Ntc<t_At t =<(<=3u=3=M==3uf tfBff3B=3@uAkAaAW3?3<,`<03PG@<[I< 3@X3At<t3333ŀ=3@;3?3<,;3?<[;@3<t <t< t;@@A}3?<<[|;?RSQ3P3<,^;N?<(t=<L;<C;XY[Z<tr@3S33t<;z43XY[Z<t2r+l@=43t3 G3=43t3F3=f3<,:s><(t4<q:<h:<t?333t<>:S解[<t*?t3a@ЪC3t3<@Ъ333=<<[9>RSQ<,9<3<,93Pv=<(t%<t9<k9XY[Z>3=3t<P9躢43XY[Z>cEer<3<,9P<33PS<,83<<(t#<8<8[XN>33t<8'[X$>>Ъ~33;3P<,v83_<<tI<[]8<X%3t&8O8tA83= <tNe;[88t t8v=l=33;37<,73;<t-<[7;=3t =37<i:~7<)333B;<<[<7;PSQ<,+7>(t$>u~(tV:3Y[Z<03P:<(63t<6N43XtE<Y[Z3B|9ì<,6>(t!>u~(t93;503PSZ:<(\63t<U6迟43[X;3<43_|33r3;y;093<,59<t<[5:ì9â33r=355M33n9<t2<[l593<tr:32w(8>,tÈ<t :33F>(3>u ~($8<<[489RSQ>,t 3S:Y[Z33F8<(43<t2<tp<4=349=34L9nf43=3u=3u f|f=|UY[Z3i@nz9t43=3u=3u |=|Y[Z3iX@-zY[Z3k@z3N'7À>,t?933nF7<(33<t3<tw<3=338S=33S8S[[f€=3u=3u f|f=|`3i{9fϭfVyn8S[[€=3u=3u |=|3i49艭y3k9Ъx52<,2P36<(tA<t2<"2X<t"<t<~273b8xx3t<O2蹛X<t%<t<72738ЪPx䪈ЪEx5<(t^<1<"1<,1351<t"<t<19737ww3t<1¬<,134l1<t%<t<d163H7Ъ}w檈Ъrw333333A54t303%44<(x3<<[0=304 3t!<<<tb<t6< tw0=3tC=3t=3=3 tn=3N0=3@-0=3t$}5=3!03q5H5ڀ=3t=3t =3tހ=3@/*5=3/53/2È<t5<t</=3@w/==3@e/4&4>./N蝣;:=32/3<<t"<tq/=3=3@tS=3@. =3ufGrPƒq =3@3`t=3@.К\љ9^sİft{=3tfG(3rՀ=3g/J3fut-3蘝À=3t"w=3t=3u =r6s1À=3-=3u =3.s=sÃ=3s23 3Ċs=3-=3@-33耗PF<(q-3P5d3>.-3<t<tEQ-=3u4=z2,3fӧfd3X3X迧fFsQW22蠧̢3%41=3,0<(,>.(-3<<t"<tx,=3=3@tZ=3@,蔘=3ufG*6rWƒq =3@|%3fir=3@*,Qљ9@sĠ3f2r=3tfGrҀ=3,f%3ffq=3@+=3t(3g=3 t3g =3@e+3/=3W+H/<(J+>.+3<<t"<tl.+=3=3@tN=3@ +=3ufGf=3tP3XÀ=3@*kљ9蚖=3tfGB듬g.<[i*. **=3*S<,=*-.<[/*|.Z *}*89*\*S*<t<t=3@*5=3@)51H/3%)h-<[j)- ))&t$Ft)=3@])V5=3@G)551.V3,<[(F- P)H)'t$Gt5)=3@(4=3@(4=3)3,<[(, ((3PS<,_(O,<[Q(, ((ZX=3(38H(k(b(<t<t=3@( 4=3@'31W- +<['+  (('t$Gt'=3@'3=3@'}3=3'<,L'<C'<":'l=3u0'<'<"'<, '*<[&J+ T'L'&t$Ft9'=3@&2=3@&216,ng*<[&* &&#t$Ct&=3@&}2=3@n&\2+׀=3g2&$3%33)<t#<[%J*3<t%+)À%$3%33)<u(È+V333r)<[t%)3<t< t d%*=3@A%=3@2%=3r*33X(3<, %03|*(<t#<[$8)3t<$(${333(<[$(sGG =3@j$İfj33J(<t<<[H$(RSQ<,7$r'3Y[Z<t )3]'3<,$;'Æ3<t g)3't 3A$Ȣ33t#))i))i33Ǣ3n'<[p#'%33t8\#u()&tt [thi333'<t <[#R'3tq(6&È](33ج&<tT<[t N%3""`&3<t<t"a3U&Ê%3tet`t=t53<,>".&<0"%""3<, "%<!%3Āfh3%<[!&3<t<t !33y3~%<tn<[|!%3<t<t< t%h!333'3<t 3<t3!33$À=3s 333$<[ '%3<t!<t<t% 333<t$r 3<t 33X3L3Q$<[S $3t < tF 333މ$<t ֳ#ì<,#<#fffffff f݈Ɖ#<tffe*#ƀffeG37G$G$G$G$G3ݢ3 #<["o#=3G33٬"<[:#3t <t33"<t$<["3t <tx!f=ffdGİfd߈¬L"<N!Ā>,t Ԉfrd.F"<!ԈfHd33!<!3<,!<t<["h!q33!<A!O3<,}3f!<t<(t <[t_ӆ4333$p3 3v#43Uc33H t=3@33<, <u =3tMpSQR0Ɇ 3<,  3<(~43ZY[(b"b3<,H8 C<(1襅â33 <33<,<t,<[+ =3=3 =33 3333pl<n:%3f3<,N><t<[<33~<t$<[R333f.33333333{<}^33<,bR<tz<[P=3t383;3%3,uF<K,=â33f33s<3f333C33#&RI3333<<[3=3t383w3<,]M<O03%3f333<u33<,333<3<,< 3f33</83<,hX<Z3f33Ps3t*=3@3<,<:3f33<33<,<t(<[=3t =3h-}-3333@<B#33<,'<t6<[b=3t=3t=3Vͽ0t8鈿33f333<A33333333=338333:3<3<,<t<[ dE3343<63<,n^<t<[\VH43hV333f338k33 33f3: 33343D<tW<[=3t =3RSQ3<,o_<aB3Y[ZP3<,7'<) 3[<<=3@3:333f<33<,<t(<[=3t =3) 3333Q:<td<[83:3t =3#<uzRSQ3<, < 3Y[Z-%=3wt=3@ut u3P<, < 7X3=3u33$\ 333 3+< 33<, <t0<[ 6=3(3:3 À=3t@ 2 3+3"3333pK<M .3<,9 3"<t0<[ m=33:3 ޷鬹38333f5 ,03%33 3<[ %3t :%3 ^봴뮴333C<[E t B 3 33ffGffت=Qff2Q33f333<[ <, < T:%3 3s333333S<[U 3:3tE <,2 3< 33833 <[ 9<,  t 03颵3>tM>tH f= <, f= =3u<,t f=e ff3O3]8 <:  3<,&  <[ e 3f33x < 33<, <t.<(0ۆ3rEN3s F333x` <bC 33<,G7 <9 À>,t 3nIN33383, 3t=3@<,3 <t1<[ 3t<t 3 n賶 È<t 3 $3433834 <[t><2{ 3<, <[] 3 3C RSQ<, 3Y[Z3M 鯲33833r3<< oA .3333 À=3@tD63333 <t=<[H 3<t<t ? 3J 鬱 È<u< c3f333Ǭv <[x 3t<l3<3x? <t'<[= <,/j33뼬gP%<, D3 [3鮲=3@t=3À=33y3<,<t<[+3:3x3<,UE<[G3<7P33T tt'=3@$=3t=3@ =3 tg XIf=9=3@t~P33]3<,Kf=<)33Ǣ3]Èа=3@3333#ÈP鍰<()lffЪH<(3<@t.< t#n-3qfHnn-3q˜9uffmHq =3@TffЫMH%33333<,<[t<~陭3f33O3<t0<[3<,nG3EA3<,K<t7<[9< $3333<,<[~]tT<,<( 3 l3=3T<]t8t =3f G=3:2=3@u34ll3f t:3q333<,.y33<,3P<[`i~]t}<,<(3PSQR5h3=<]m 3 l3=3h3ZY[X3tߊ30t3333?À>,F%f=<, f=3333ÈP303P<,n^<[`3t<@TW[X 3;gu s 8-ZD LD3%333<[03鲩3H 3H3%333<@=3t=3@_h3f3H3f3383#<t0<[!nRSQ<,K3Y[ZߨB3<, Æ3T鏪 B<$tw<r t# 3@:%3t=3%3ô 3و$ QLj t?$ 4$<r=3@둈 t 0<u.3fĀ 3:%3t=3%33<[u%33<u f3À%3%4g~]l3€=3u]=3wTf uL=3@uFh3d3l3-3jl3;l3td 3fÀ%3%333$<`u ,`3$,F(43t =3@|63<<<,B743t =3@ Pr#=3 3i026%4343D(4360Ɇ 3<[t5< 3'u 3t8tQ>{F<k<^3u&$u33̬$3$*33%3(Ĭ$8 3@<}Xt!3=3u9t :3à3=3u<t< t<@t؝t:3t=3u+SQR<,<(yW43ZY[À>{uz3PF<F7$-3 3 <}>{u03 F< 3<}3 3t=3u =3@uo>,uj~{ud3 3@3t/ 3<v$3<-f<]<0T<}Kôf%3 3< 3 3 3f%3 33f 3 333 3033<33u3<[ 3 4<,$3d 33f33 3 33?똀 3 33B<p'$<, $3黙 3%3333 3#3<,<[錗38f몀 333 33f33~X<tr<[V3 3H<,5%<'/#"3=3%3 33Җ 30?433%3: 30ɀ 3 3f 3-333<t< 3=3 3u3.s 3ff 3ff-3 3 3V3<t> 3 30 3 30f0Ɉ%338 3 3 3 33f3:>3f3f 3 33f3f 33 333C33u<,['3<,HÀ=3<&$â3 333<tm<3<['<,3%33t8重r 3t3fì]3<,t<t<t,\<[J땬,Ê%33à38v:%3!<t<w&ʎ3f龎 3=3@3鞎33<,뉀 3 3Q3<,aJ 3 3B3<,c]383333 33%3hT& 3 303:! 3 3 3ش80 3V3f-3 33%33 3À 3 3 30ɴ:X=3s Q3<,4dzÀ>,F<uF<(3F383<r 3 363343I343H343 333:00 3 30Ɉ 333f33 3B3<,00Ɇ 3<[ 3< 3<,V0Ɇ 3<tH^<[tW 3N]3Āp%3, 33X} 3J3QqX3M<i@ 333f33s 333<, <[t< 30* 3 333f33r 3333' 3 3}b3<,P03Ȁ%3P+<t-<[)vX3:3 :%3tX3雉 3 338333<tg<[ 3 d:3|S03P<,VP3Ȁ%3Xì@:3#<͈ 3M  3 3+' 3   3 3@3f38 333 3:%33@u=3t=3Yt b0%3P<,A1<t@<[/|X%333383@t <`rG<3 :%3twÈ 3~7 3 333 3 3 3 3 33f333 3 3 3P{<,033sXpX銀3t<@8tÀ 3@À 3 3f3 3f3f3 380=$ 3 3<t8<[J<,%3 3%3 ^0Ɇ 3<, 3t8t 3 3 3 3 3 3 3 33%333 3 <X33tT<,~鋀 3 3 3 3%333 3 3<,pj 3<,]3F<[t;<DÀt8B=3u^33<}<O} 33 3<u? 3<, 3<,<[c}<[u<,ga 3<,TN 33$}3f33P 3<]3t=3@3<,~ 3 33f33<t=3@33<,hb~ 3e 3 3 <3<,*0Ɇ 3Q<[`X33t%3t8>,t3 %3 3F3:3$:3:3<tM <u323t"3t38^5{:%3K"{{ 43'3z 3 3 3 <[0w<,03P3Xƀ 3Ʊ 33 3 3 n<[\%33t8Y3@t =3u8) z33833 3<>3<,<t<[y o{3<t<=3@ 3333383 3N<P3<,<-333f3383 3 r%?x*z<,<u 33383 3蝖rr/exr-/z3 3)43Fh<($RSQh643Y[Z333:3 3r 82.p3 $%33 33 33<@y 33 33U<W3<,C0Ɇ 3+<t+<[QuX3t<&hO 3<,#333À 33 33 3333 D 333433343333 4333%33 33433333 33 3<,<[<`3<,kV0Ɇ 3R^ 3<[t<u)GÆ3v 3${ u0ۆ3=3303N锬H<,V0Ɇ 3^ 3<u3t=3303N3338333 3n3<,\V3>+uF>()@=3@<3<,"R3@s4=<$`t`u@<?=3@-333=3@3<A3uJ=4tA=3u8r0s+<t S=3ur 3p3%38to:tt3 uugŠ3%30 GÀ=3 u %3fttt    ð%3 %3gĊ%30G$34%3GÀ=3@tШA3@4ÈG3%3@t =3@0G34%3G3=3=3u%38:gb%30%30G(3$%3 %3 G3$3u%3v %33 t 33@t Gð%3V%3I͉p3 t71Ɋ 3u 3t'1urs 33INCLUDE  +-/*=<>()[]{}:,|&~#`;\defineincludeirpirpsirpvmacromatch postponepurgereptrestorerestrucstruccommon#forward:localQreverseZfileline: +-*/andmodorshlshrxor+-bsfbsrnotpltrvaalignasatdefineddefinitedupeqeqtypefrominonptr relativetousedbytedwordqwordword,/)WRrRPfzahalax bhblbp%bx#chclcs2cx!dhdi'dlds4dx"es1fs5gs6k0Pk1Qk2Rk3Sk4Tk5Uk6Vk7WmsAmz nxpe0r8r9rd!rn ru"rz#si&sp$ss3stbplcr0cr1cr2cr3cr4cr5cr6cr7cr8cr9 dildlldr0dr1dr2dr3dr4dr5dr6dr7dr8dr9eax@ebpEebxCecxAediGedxBefi eipelfPesiFespDfarguimm0mm1mm2mm3mm4mm5mm6mm7r10r11r12r13r14r15r8br8dHr8lr8w(r9br9dIr9lr9w)raxrbprbxrcxrdirdxriprsirspsae0silsplst0st1st2st3st4st5st6st7tr0@tr1Atr2Btr3Ctr4Dtr5Etr6Ftr7Gwdm1to21to41to8bnd0`bnd1abnd2bbnd3cbytecodecoff@cr10 cr11 cr12 cr13 cr14cr15datadr10dr11dr12dr13dr14dr15ms64Inearnotepe64zaEU\J LM NNbtiifQ injawjbrjcrjetjgjl|jopjpzjsxjztorZeaaa7caadeaameaas?cadcZeaddZeand Zebnddbsfbsrbtcibtribtsicbw-dcdqTdclc dcld dcli dcmc dcmp8Zecqoldcwd-ddaa'cdas/cdeczdiv!iendH err1fld>fst>hlt dinczinslintdjaesjbevjge}jle~jmpjnavjnbsjncsjneujng~jnl}jnoqjnp{jnsyjnzujpezjpo{larlds}leaW}les}lfs}lgs}lsllss}ltrmovimul!ineg!inopnot!iorg-outȇpopwporśrcl:~rcr:~repdret§|rol:~ror:~rsmdsal:~sar:~sbbZeshl:~shr:~stc dstd dsti dstrsub(Zeud0ud1ud2 dxor0ZeadcxfadoxandnYarpl{blci&blcsblsiblsrbzhicallcdqeldclac]clgi]cltsdclwbcmps?cwdeTddata@dppdAdpps@else emmswdfabs!faddfbldkfchs fcomfcos?fdivfeniZfildfistfld1(fldz.fmulfnopfsin>fstp>fsubftst$fxam%fxch heap2idiv!iimulEinsbl dinsdmTdinswm-dint1 dint3 dintocinvddiretcdjcxz$jnaerjnbewjnge|jnlekorbE)kordE2korqE9korwE@lahf dlgdtpminsb8pminsd9pminswśpminubśpminud;pminuw:pmuldq(pmulhwśpmulld@pmullwśpopcntnpsadbwśpshufbpshufdf;pshufw-psignbpsignd psignw pslldqpsmashJpsrldqpsubsbśpsubswśpswapd%public2pushad`Gdpushaw` dpushfdGdpushfqdpushfw-drdmsrq2drdpkru]rdrandrdseedrdsspd rdsspqrdtscp]repeatsetalccsetnaezsetnbezsetngezsetnlezsfenceshufpd[shufpsHskinitslwpcbsqrtpdQbsqrtpsQOsqrtsdQsqrtssQuswapgsPsysretdt1mskctpausefumwaitvaddpdXtvaddpsXvaddsdXvaddssX3vandpdTvandpsTvcmppdvcmpps%vcmpsd+vcmpss?vdivpd^tvdivps^vdivsd^vdivss^3vlddquvmaxpd_{vmaxps_vmaxsd_vmaxss_:vmcall]vmfunc]vminpd]{vminps]vminsd]vminss]:vmloadکvmovsdvmovssvmread{vmsave۩vmulpdYtvmulpsYvmulsdYvmulssY3vmxoff]vpabsb+vpabsdvpabsqXvpabsw+vpaddb9vpaddd vpaddqԦvpaddw9vpanddvpandnVvpandq۟vpavgb9vpavgw9vpcmovvpcmpbvpcmpdvpcmpqvpcmpwvpcombvpcomdvpcomqvpcomwvpermbMvpermd6vpermqKvpermwFvppermwvproldvprolqvprordvprorqvprotb vprotd vprotq vprotw vpshab vpshad vpshaq vpshaw vpshlb vpshld vpshlq vpshlw vpslld\vpsllqQvpsllw`vpsrad\vpsraqJvpsraw`vpsrld\vpsrlqQvpsrlw`vpsubb9vpsubd vpsubqvpsubw9vptest vpxordvpxorqvrcppsSvrcpssSOvsubpd\tvsubps\vsubsd\vsubss\3vxorpdWvxorpsWwbinvd dwrmsrq0dwrpkru]wrussdwrussqtxabortxbegin1xgetbv]xrstorxsavecxsavesxsetbv]blcfillblendpd blendps blsfillclflushYcmovnaeBcmovnbeGcmovngeLcmovnleOcmpeqpdcmpeqpscmpeqsdܢcmpeqsscmplepdcmplepscmplesdܢcmplesscmpltpdcmpltpscmpltsdܢcmpltsscmpxchgkdisplayendbr32endbr64fcmovbeifcmovnbmfcmovnemfcmovnumfdecstp6fincstp7fldenvdtfldenvwifnsavedfnsavewfnstenv\frndint2vpminsb82vpminsd9vpminsq9_vpminsw9vpminub9vpminud;vpminuq;_vpminuw:2vpmovdb1vpmovdw3vpmovqb2vpmovqd5vpmovqw4vpmovwb0vpmuldq(fvpmulhw9vpmulld@vpmullq@_vpmullw9vprolvdvprolvq_vprorvdvprorvq_vpsadbw9vpshlddqvpshldqqvpshldwp vpshrddsvpshrdqsvpshrdwr vpshufb2vpshufdpvpsignbvpsignd vpsignw vpslldqvpsllvdGvpsllvqGvvpsllvwFvpsravdFvpsravqFovpsravwFvpsrldqvpsrlvdEvpsrlvqEvvpsrlvwFvpsubsb9vpsubsw9vshufpdkvshufpsvsqrtpdQRvsqrtpsQvsqrtsdQvsqrtssQ3vtestpd vtestps xrstorsxsave64 addsubpdbaddsubpsblendvpdblendvpscldemote_clrssbsyŻcmpneqpdcmpneqpscmpneqsdܢcmpneqsscmpnlepdcmpnlepscmpnlesdܢcmpnlesscmpnltpdcmpnltpscmpnltsdܢcmpnltsscmpordpdcmpordpscmpordsdܢcmpordsscvtdq2pd cvtdq2ps[Ocvtpd2dqcvtpd2pi-cvtpd2psZbcvtpi2pd*cvtpi2ps*cvtps2dq[bcvtps2pdZcvtps2pi- cvtsd2si-fcvtsd2ssZcvtsi2sd*ncvtsi2ss*ecvtss2sdZucvtss2si-Vfcmovnbemfnstenvdtfnstenvwifxsave64 insertps!kortestb kortestdkortestqkortestw kshiftlb2kshiftld3kshiftlq3kshiftlw2kshiftrb0kshiftrd1kshiftrq1kshiftrw0kunpckbwK)kunpckdqK9kunpckwdK@maskmovq$monitorxmovmskpdmovmskpsmovntdqa*movshdup,movsldup,packssdwkśpacksswbcśpackusdw+packuswbgśpblendvbpfrcpit1%pfrcpit2%pfrsqit1%pmovmskb׸pmovsxbd!Fpmovsxbq"Opmovsxbw =pmovsxdq%jpmovsxwd#Xpmovsxwq$apmovzxbd1Fpmovzxbq2Opmovzxbw0=pmovzxdq5jpmovzxwd3Xpmovzxwq4apmulhrsw prefetchrdfsbase¶rdgsbase¶rstorsspsetssbsy賻sha1msg1ɼsha1msg2ʼsysenter4dsysexitq5dumonitorunpckhpdbunpckhpsOunpcklpdbunpcklpsOvblendpd ^vblendps ^vcmpeqpdvcmpeqps%vcmpeqsd+vcmpeqss?vcmpgepd vcmpgeps %vcmpgesd +vcmpgess ?vcmpgtpdvcmpgtps%vcmpgtsd+vcmpgtss?vcmplepdvcmpleps%vcmplesd+vcmpless?vcmpltpdvcmpltps%vcmpltsd+vcmpltss?vfmaddpdivfmaddpshvfmaddsdkvfmaddssjvfmsubpdmvfmsubpslvfmsubsdovfmsubssnvldmxcsrvmlaunch]vmovddupvmovdqu8ovmovhlpsAvmovlhpsAvmovntdqZvmovntpd+Svmovntps+avmpsadbwB^vmresume]vpaddusb9vpaddusw9vpalignrvpblendd^vpblendw^vpcmpeqbtzvpcmpeqdvvvpcmpeqq)dvpcmpeqwuzvpcmpgtbdzvpcmpgtdfvvpcmpgtq7dvpcmpgtwezvpcmplebvpcmpledvpcmpleqvpcmplewvpcmpltbvpcmpltdvpcmpltqvpcmpltwvpcomeqbvpcomeqdvpcomeqqvpcomeqwvpcomgebvpcomgedvpcomgeqvpcomgewvpcomgtbvpcomgtdvpcomgtqvpcomgtwvpcomlebvpcomledvpcomleqvpcomlewvpcomltbvpcomltdvpcomltqvpcomltwvpdpbusdPvpdpwssdRvpermi2buMvpermi2dvvpermi2qv_vpermi2wuFvpermt2b}Mvpermt2d~vpermt2q~_vpermt2w}FvphaddbdPvphaddbqPvphaddbwPvphadddqPvphaddswvphaddwdPvphaddwqPvphsubbwPvphsubdqPvphsubswvphsubwdPvplzcntdDvplzcntqDXvpmacsdd`vpmacswd`vpmacsww`vpmaddwd9vpmovb2m)Ovpmovd2m9Ovpmovm2b(vpmovm2d8vpmovm2q8vpmovm2w(vpmovq2m9Hvpmovsdb!vpmovsdw#vpmovsqb"vpmovsqd%vpmovsqw$vpmovswb vpmovw2m)Hvpmulhuw9vpmuludqvpopcntbTvpopcntdUAvpopcntqUvpopcntwTvpshldvdqvpshldvqq_vpshldvwpFvpshrdvdsvpshrdvqs_vpshrdvwHFvpshufhwvpshuflwvpsubusb9vpsubusw9vptestmb&vptestmd'vptestmq'vptestmw&vrangepdPvrangepsPvrangesdQvrangessQvrcp14pdLvrcp14psLAvrcp14sdM\vrcp14ssMwvrcp28pdʕvrcp28psʩvrcp28sdUvrcp28sspvroundpd WvroundpsWvroundsd 6vroundss 2vrsqrtpsRvrsqrtssROvstmxcsrvucomisd.vucomiss.vzeroallwwbnoinvd dwrfsbase¶wrgsbase¶xacquiredxreleasedxrstor64 xsavec64xsaveoptxsaves64cmpxchg8b@cvttpd2dqbcvttpd2pi,cvttps2dq[,cvttps2pi, cvttsd2si,fcvttss2si,Vextractpsfxrstor64 gf2p8mulbϵmovdir64bBpclmulqdqpcmpestriapcmpestrm`pcmpistricpcmpistrmbpmaddubswprefetchwpunpckhbwhśpunpckhdqjśpunpckhwdiśpunpcklbw`śpunpckldqbśpunpcklwdaśpvalidateDrmpadjustJrmpupdateDsha1nexteȼsha1rnds4useavx256useavx512vaddsubpdVvaddsubpshvblendmpdevblendmpsevblendvpdKEvblendvpsJEvcmpneqpdvcmpneqps%vcmpneqsd+vcmpneqss?vcmpngepd vcmpngeps %vcmpngesd +vcmpngess ?vcmpngtpd vcmpngtps %vcmpngtsd +vcmpngtss ?vcmpnlepdvcmpnleps%vcmpnlesd+vcmpnless?vcmpnltpdvcmpnltps%vcmpnltsd+vcmpnltss?vcmpordpdvcmpordps%vcmpordsd+vcmpordss?vcvtdq2pdvcvtdq2ps[vcvtpd2dqvcvtpd2psZvcvtpd2qq{Kvcvtph2psvcvtps2dq[vcvtps2pdZvcvtps2phvcvtps2qq{vcvtqq2pdvcvtqq2ps[vcvtsd2si-_vcvtsd2ssZvcvtsi2sd*vcvtsi2ss*vcvtss2sdZ:vcvtss2si-|vdbpsadbwBvexpandpdXvexpandpsvfnmaddpdyvfnmaddpsxvfnmaddsd{vfnmaddsszvfnmsubpd}vfnmsubps|vfnmsubsdvfnmsubss~vgetexppdBvgetexppsB:vgetexpsdCUvgetexpssCpvinsertps!vmovdqa32ovmovdqa64ovmovdqu16ovmovdqu32ovmovdqu64ovmovmskpdvmovmskpsvmovntdqa*+vmovshdupvmovsldupvp4dpwssdR.vpackssdwk vpacksswbc9vpackusdw+vpackuswbg9vpblendmbfMvpblendmddvpblendmqd_vpblendmwfFvpblendvbLEvpcmpleubvpcmpleudvpcmpleuq~vpcmpleuwvpcmpltubvpcmpltudvpcmpltuq~vpcmpltuwvpcmpneqbvpcmpneqdvpcmpneqqvpcmpneqwvpcmpnlebvpcmpnledvpcmpnleqvpcmpnlewvpcmpnltbvpcmpnltdvpcmpnltqvpcmpnltwvpcomequbvpcomequdvpcomequqvpcomequwvpcomgeubvpcomgeudvpcomgeuqvpcomgeuwvpcomgtubvpcomgtudvpcomgtuqvpcomgtuwvpcomleubvpcomleudvpcomleuqvpcomleuwvpcomltubvpcomltudvpcomltuqvpcomltuwvpcomneqbvpcomneqdvpcomneqqvpcomneqwvpdpbusdsQvpdpwssdsSvpermi2pdw_vpermi2pswvpermilpdVvpermilpsavpermt2pd_vpermt2psvpexpandbbvpexpanddvpexpandqXvpexpandwbXvphaddubdPvphaddubqPvphaddubwPvphaddudqPvphadduwdPvphadduwqPvpmacsdqh`vpmacsdql`vpmacssdd`vpmacsswd`vpmacssww`vpmadcswd`vpmovmskb vpmovsxbd!Qvpmovsxbq"Mvpmovsxbw Uvpmovsxdq%Uvpmovsxwd#Uvpmovsxwq$Qvpmovusdbvpmovusdwvpmovusqbvpmovusqdvpmovusqwvpmovuswbvpmovzxbd1Qvpmovzxbq2Mvpmovzxbw0Uvpmovzxdq5Uvpmovzxwd3Uvpmovzxwq4Qvpmulhrsw 2vptestnmb&vptestnmd'vptestnmq'vptestnmw&vreducepdVvreducepsVvreducesdWvreducessWvscalefpd, vscalefps,1vscalefsd-Nvscalefss-ivunpckhpdvunpckhpsvunpcklpdvunpcklpsxrstors64aesdeclastߵaesenclastݵclflushoptcmpunordpdcmpunordpscmpunordsdܢcmpunordsscmpxchg16b@loadall286dloadall386dmaskmovdqu(phminposuwAprefetcht0kprefetcht1kprefetcht2kpunpckhqdqmbpunpcklqdqlbsha256msg1̼sha256msg2ͼvcmptruepdvcmptrueps%vcmptruesd+vcmptruess?vcvtpd2udqyvcvtpd2uqqyKvcvtps2udqyvcvtps2uqqyvcvtsd2usiyOvcvtss2usiylvcvttpd2dqvcvttpd2qqz[vcvttps2dq[|vcvttps2qqzvcvttsd2si,fvcvttss2si,vcvtudq2pdzvcvtudq2pszvcvtuqq2pdzvcvtuqq2pszvcvtusi2sd{vcvtusi2ss{vextractps vfpclasspdfFvfpclasspsfSvfpclasssdgYvfpclassssgfvgatherdpduvgatherdps|vgatherqpduvgatherqps|vgetmantpd&vgetmantps&vgetmantsd'vgetmantss'vgf2p8mulb2vmaskmovpd-vmaskmovps,vp4dpwssdsS.vpclmulqdqvpcmpestria:vpcmpestrm`:vpcmpistric:vpcmpistrmb:vpcmpnequbvpcmpnequdvpcmpnequq~vpcmpnequwvpcmpnleubvpcmpnleudvpcmpnleuq~vpcmpnleuwvpcmpnltubvpcmpnltudvpcmpnltuq~vpcmpnltuwvpcomnequbvpcomnequdvpcomnequqvpcomnequwvpcomtruebvpcomtruedvpcomtrueqvpcomtruewvperm2f128vperm2i128Fvpermil2pdI vpermil2psH vpgatherdd|vpgatherdquvpgatherqd|vpgatherqquvpmacssdqh`vpmacssdql`vpmadcsswd`vpmaddubsw2vpmaskmovdvpmaskmovqvpternlogd%vpternlogq%vpunpckhbwh9vpunpckhdqj vpunpckhwdi9vpunpcklbw`9vpunpckldqb vpunpcklwda9vrsqrt14pdNvrsqrt14psNAvrsqrt14sdO\vrsqrt14ssOwvrsqrt28pd̕vrsqrt28ps̩vrsqrt28sdUvrsqrt28sspvshuff32x4#vshuff64x2#vshufi32x4Cvshufi64x2Cvzeroupperwxsaveopt64 pclmulhqhdqpclmullqhdqprefetchntakprefetchwt1saveprevssp곻sha256rnds2˥vaesdeclastߥvaesenclastݥvcmpeq_ospdvcmpeq_osps%vcmpeq_ossd+vcmpeq_osss?vcmpeq_uqpdvcmpeq_uqps%vcmpeq_uqsd+vcmpeq_uqss?vcmpeq_uspdvcmpeq_usps%vcmpeq_ussd+vcmpeq_usss?vcmpfalsepd vcmpfalseps %vcmpfalsesd +vcmpfalsess ?vcmpge_oqpdvcmpge_oqps%vcmpge_oqsd+vcmpge_oqss?vcmpgt_oqpdvcmpgt_oqps%vcmpgt_oqsd+vcmpgt_oqss?vcmple_oqpdvcmple_oqps%vcmple_oqsd+vcmple_oqss?vcmplt_oqpdvcmplt_oqps%vcmplt_oqsd+vcmplt_oqss?vcmpord_spdvcmpord_sps%vcmpord_ssd+vcmpord_sss?vcmpunordpdvcmpunordps%vcmpunordsd+vcmpunordss?vcompresspdvcompresspsvcvttpd2udqxvcvttpd2uqqx[vcvttps2udqxevcvttps2uqqxvcvttsd2usixVvcvttss2usixsvfixupimmpdTvfixupimmpsTvfixupimmsdUvfixupimmssUvfmadd132pdvfmadd132psvfmadd132sdvfmadd132ssvfmadd213pdvfmadd213psvfmadd213sdvfmadd213ssvfmadd231pdvfmadd231psvfmadd231sdvfmadd231ssvfmaddsubpd]vfmaddsubps\vfmsub132pdvfmsub132psvfmsub132sdvfmsub132ssvfmsub213pdvfmsub213psvfmsub213sdvfmsub213ssvfmsub231pdvfmsub231psvfmsub231sdvfmsub231ssvfmsubaddpd_vfmsubaddps^vinsertf128zvinserti1288zvmaskmovdquvpcomfalsebvpcomfalsedvpcomfalseqvpcomfalsewvpcompressbcvpcompressdvpcompressqvpcompresswcvpcomtrueubvpcomtrueudvpcomtrueuqvpcomtrueuwvpconflictdĻvpconflictqXvphminposuwA vpmadd52huq_vpmadd52luq_vpscatterddvpscatterdqvpscatterqdvpscatterqqvpunpckhqdqmvpunpcklqdqlvrndscalepd vrndscalepsvrndscalesd vrndscaless vscatterdpdvscatterdpsvscatterqpdvscatterqpspclmulhqhqdqpclmulhqlqdqpclmullqhqdqpclmullqlqdqvbroadcastsdvbroadcastssvcmpneq_oqpd vcmpneq_oqps %vcmpneq_oqsd +vcmpneq_oqss ?vcmpneq_ospdvcmpneq_osps%vcmpneq_ossd+vcmpneq_osss?vcmpneq_uspdvcmpneq_usps%vcmpneq_ussd+vcmpneq_usss?vcmpnge_uqpdvcmpnge_uqps%vcmpnge_uqsd+vcmpnge_uqss?vcmpngt_uqpdvcmpngt_uqps%vcmpngt_uqsd+vcmpngt_uqss?vcmpnle_uqpdvcmpnle_uqps%vcmpnle_uqsd+vcmpnle_uqss?vcmpnlt_uqpdvcmpnlt_uqps%vcmpnlt_uqsd+vcmpnlt_uqss?vextractf128vextracti1289vfnmadd132pdvfnmadd132psvfnmadd132sdvfnmadd132ssvfnmadd213pdvfnmadd213psvfnmadd213sdvfnmadd213ssvfnmadd231pdvfnmadd231psvfnmadd231sdvfnmadd231ssvfnmsub132pdvfnmsub132psvfnmsub132sdvfnmsub132ssvfnmsub213pdvfnmsub213psvfnmsub213sdvfnmsub213ssvfnmsub231pdvfnmsub231psvfnmsub231sdvfnmsub231ssvinsertf32x4ovinsertf32x8]vinsertf64x2hvinsertf64x4Vvinserti32x48ovinserti32x8:]vinserti64x28hvinserti64x4:VvpbroadcastbxvpbroadcastdX vpbroadcastqY vpbroadcastwyvpclmulhqhdqvpclmullqhdqvpcomfalseubvpcomfalseudvpcomfalseuqvpcomfalseuwvpermilmo2pdvpermilmo2psvpermilmz2pdvpermilmz2psvpermiltd2pdvpermiltd2psvpshufbitqmbgf2p8affineqbvcmptrue_uspdvcmptrue_usps%vcmptrue_ussd+vcmptrue_usss?vcmpunord_spdvcmpunord_sps%vcmpunord_ssd+vcmpunord_sss?vextractf32x4vextractf32x8vextractf64x2vextractf64x4vextracti32x49vextracti32x8;vextracti64x29vextracti64x4;vgatherpf0dpdvgatherpf0dps/vgatherpf0qpdvgatherpf0qps+vgatherpf1dpdvgatherpf1dps/vgatherpf1qpdvgatherpf1qps+vpclmulhqlqdqvpclmullqlqdqvbroadcastf128vbroadcasti128Zvcmpfalse_ospdvcmpfalse_osps%vcmpfalse_ossd+vcmpfalse_osss?vfmaddsub132pdvfmaddsub132psvfmaddsub213pdvfmaddsub213psvfmaddsub231pdvfmaddsub231psvfmsubadd132pdvfmsubadd132psvfmsubadd213pdvfmsubadd213psvfmsubadd231pdvfmsubadd231psvgf2p8affineqbvpmultishiftqb_vscatterpf0dpdvscatterpf0dps/vscatterpf0qpdvscatterpf0qps+vscatterpf1dpdvscatterpf1dps/vscatterpf1qpdvscatterpf1qps+aeskeygenassistvbroadcastf32x2vbroadcastf32x4vbroadcastf32x8vbroadcastf64x2vbroadcastf64x4vbroadcasti32x2Yvbroadcasti32x4Zvbroadcasti32x8[vbroadcasti64x2Zvbroadcasti64x4[vpbroadcastmb2q*vpbroadcastmw2d:gf2p8affineinvqbvaeskeygenassist:vgf2p8affineinvqb WWdb dddfdpdqdt dudw!rbrdrf"rp"rqyrt rwvfileout of memoryout of stack spacesource file not foundcode cannot be generatedformat limitations exceededinvalid definition providedwrite failedfile not founderror reading fileinvalid file formatinvalid macro argumentsincomplete macrounexpected charactersinvalid argumentillegal instructioninvalid operandinvalid size of operandoperand size not specifiedoperand sizes do not matchinvalid size of address valueaddress sizes do not agreedisallowed combination of registersnot encodable with long immediaterelative jump out of rangeinvalid expressioninvalid addressinvalid valuevalue out of rangeundefined symbolsymbolout of scopeinvalid use of symbolname too longinvalid namereserved word used as symbolsymbol already definedmissing end quotemissing end directiveunexpected instructionextra characters on linesection is not aligned enoughsetting already specifieddata already definedtoo many repeatserror directive encountered in source fileassertion failedfasm/fasm.txt0000644000175000017500000102675614533376740014016 0ustar privalovprivalov ,''' ,,;,, ,,,, ,,,,, ,,, ,, ; ; ; ; ; ; ; ,''''; '''', ; ; ; ; ',,,,;, ,,,,,' ; ; ; flat assembler 1.73 Programmer's Manual Table of contents ----------------- Chapter 1 Introduction 1.1 Compiler overview 1.1.1 System requirements 1.1.2 Executing compiler from command line 1.1.3 Compiler messages 1.1.4 Output formats 1.2 Assembly syntax 1.2.1 Instruction syntax 1.2.2 Data definitions 1.2.3 Constants and labels 1.2.4 Numerical expressions 1.2.5 Jumps and calls 1.2.6 Size settings Chapter 2 Instruction set 2.1 The x86 architecture instructions 2.1.1 Data movement instructions 2.1.2 Type conversion instructions 2.1.3 Binary arithmetic instructions 2.1.4 Decimal arithmetic instructions 2.1.5 Logical instructions 2.1.6 Control transfer instructions 2.1.7 I/O instructions 2.1.8 Strings operations 2.1.9 Flag control instructions 2.1.10 Conditional operations 2.1.11 Miscellaneous instructions 2.1.12 System instructions 2.1.13 FPU instructions 2.1.14 MMX instructions 2.1.15 SSE instructions 2.1.16 SSE2 instructions 2.1.17 SSE3 instructions 2.1.18 AMD 3DNow! instructions 2.1.19 The x86-64 long mode instructions 2.1.20 SSE4 instructions 2.1.21 AVX instructions 2.1.22 AVX2 instructions 2.1.23 Auxiliary sets of computational instructions 2.1.24 AVX-512 instructions 2.1.25 Other extensions of instruction set 2.2 Control directives 2.2.1 Numerical constants 2.2.2 Conditional assembly 2.2.3 Repeating blocks of instructions 2.2.4 Addressing spaces 2.2.5 Other directives 2.2.6 Multiple passes 2.3 Preprocessor directives 2.3.1 Including source files 2.3.2 Symbolic constants 2.3.3 Macroinstructions 2.3.4 Structures 2.3.5 Repeating macroinstructions 2.3.6 Conditional preprocessing 2.3.7 Order of processing 2.4 Formatter directives 2.4.1 MZ executable 2.4.2 Portable Executable 2.4.3 Common Object File Format 2.4.4 Executable and Linkable Format Chapter 1 Introduction ----------------------- This chapter contains all the most important information you need to begin using the flat assembler. If you are experienced assembly language programmer, you should read at least this chapter before using this compiler. 1.1 Compiler overview Flat assembler is a fast assembly language compiler for the x86 architecture processors, which does multiple passes to optimize the size of generated machine code. It is self-compilable and versions for different operating systems are provided. All the versions are designed to be used from the system command line and they should not differ in behavior. 1.1.1 System requirements All versions require the x86 architecture 32-bit processor (at least 80386), although they can produce programs for the x86 architecture 16-bit processors, too. DOS version requires an OS compatible with MS DOS 2.0 and either true real mode environment or DPMI. Windows version requires a Win32 console compatible with 3.1 version. 1.1.2 Executing compiler from command line To execute flat assembler from the command line you need to provide two parameters - first should be name of source file, second should be name of destination file. If no second parameter is given, the name for output file will be guessed automatically. After displaying short information about the program name and version, compiler will read the data from source file and compile it. When the compilation is successful, compiler will write the generated code to the destination file and display the summary of compilation process; otherwise it will display the information about error that occurred. The source file should be a text file, and can be created in any text editor. Line breaks are accepted in both DOS and Unix standards, tabulators are treated as spaces. In the command line you can also include "-m" option followed by a number, which specifies how many kilobytes of memory flat assembler should maximally use. In case of DOS version this options limits only the usage of extended memory. The "-p" option followed by a number can be used to specify the limit for number of passes the assembler performs. If code cannot be generated within specified amount of passes, the assembly will be terminated with an error message. The maximum value of this setting is 65536, while the default limit, used when no such option is included in command line, is 100. It is also possible to limit the number of passes the assembler performs, with the "-p" option followed by a number specifying the maximum number of passes. There are no command line options that would affect the output of compiler, flat assembler requires only the source code to include the information it really needs. For example, to specify output format you specify it by using the "format" directive at the beginning of source. 1.1.3 Compiler messages As it is stated above, after the successful compilation, the compiler displays the compilation summary. It includes the information of how many passes was done, how much time it took, and how many bytes were written into the destination file. The following is an example of the compilation summary: flat assembler version 1.72 (16384 kilobytes memory) 38 passes, 5.3 seconds, 77824 bytes. In case of error during the compilation process, the program will display an error message. For example, when compiler can't find the input file, it will display the following message: flat assembler version 1.72 (16384 kilobytes memory) error: source file not found. If the error is connected with a specific part of source code, the source line that caused the error will be also displayed. Also placement of this line in the source is given to help you finding this error, for example: flat assembler version 1.72 (16384 kilobytes memory) example.asm [3]: mob ax,1 error: illegal instruction. It means that in the third line of the "example.asm" file compiler has encountered an unrecognized instruction. When the line that caused error contains a macroinstruction, also the line in macroinstruction definition that generated the erroneous instruction is displayed: flat assembler version 1.72 (16384 kilobytes memory) example.asm [6]: stoschar 7 example.asm [3] stoschar [1]: mob al,char error: illegal instruction. It means that the macroinstruction in the sixth line of the "example.asm" file generated an unrecognized instruction with the first line of its definition. 1.1.4 Output formats By default, when there is no "format" directive in source file, flat assembler simply puts generated instruction codes into output, creating this way flat binary file. By default it generates 16-bit code, but you can always turn it into the 16-bit or 32-bit mode by using "use16" or "use32" directive. Some of the output formats switch into 32-bit mode, when selected - more information about formats which you can choose can be found in 2.4. All output code is always in the order in which it was entered into the source file. 1.2 Assembly syntax The information provided below is intended mainly for the assembly language programmers that have been using some other assembly compilers before. If you are beginner, you should look for the assembly programming tutorials. Flat assembler by default uses the Intel syntax for the assembly instructions, although you can customize it using the preprocessor capabilities (macroinstructions and symbolic constants). It also has its own set of the directives - the instructions for compiler. All symbols defined inside the sources are case-sensitive. 1.2.1 Instruction syntax Instructions in assembly language are separated by line breaks, and one instruction is expected to fill the one line of text. If a line contains a semicolon, except for the semicolons inside the quoted strings, the rest of this line is the comment and compiler ignores it. If a line ends with "\" character (eventually the semicolon and comment may follow it), the next line is attached at this point. Each line in source is the sequence of items, which may be one of the three types. One type are the symbol characters, which are the special characters that are individual items even when are not spaced from the other ones. Any of the "+-*/=<>()[]{}:,|&~#`" is the symbol character. The sequence of other characters, separated from other items with either blank spaces or symbol characters, is a symbol. If the first character of symbol is either a single or double quote, it integrates any sequence of characters following it, even the special ones, into a quoted string, which should end with the same character, with which it began (the single or double quote) - however if there are two such characters in a row (without any other character between them), they are integrated into quoted string as just one of them and the quoted string continues then. The symbols other than symbol characters and quoted strings can be used as names, so are also called the name symbols. Every instruction consists of the mnemonic and the various number of operands, separated with commas. The operand can be register, immediate value or a data addressed in memory, it can also be preceded by size operator to define or override its size (table 1.1). Names of available registers you can find in table 1.2, their sizes cannot be overridden. Immediate value can be specified by any numerical expression. When operand is a data in memory, the address of that data (also any numerical expression, but it may contain registers) should be enclosed in square brackets or preceded by "ptr" operator. For example instruction "mov eax,3" will put the immediate value 3 into the EAX register, instruction "mov eax,[7]" will put the 32-bit value from the address 7 into EAX and the instruction "mov byte [7],3" will put the immediate value 3 into the byte at address 7, it can also be written as "mov byte ptr 7,3". To specify which segment register should be used for addressing, segment register name followed by a colon should be put just before the address value (inside the square brackets or after the "ptr" operator). Table 1.1 Size operators /-------------------------\ | Operator | Bits | Bytes | |==========|======|=======| | byte | 8 | 1 | | word | 16 | 2 | | dword | 32 | 4 | | fword | 48 | 6 | | pword | 48 | 6 | | qword | 64 | 8 | | tbyte | 80 | 10 | | tword | 80 | 10 | | dqword | 128 | 16 | | xword | 128 | 16 | | qqword | 256 | 32 | | yword | 256 | 32 | | dqqword | 512 | 64 | | zword | 512 | 64 | \-------------------------/ Table 1.2 Registers /-----------------------------------------------------------------\ | Type | Bits | | |=========|======|================================================| | | 8 | al cl dl bl ah ch dh bh | | General | 16 | ax cx dx bx sp bp si di | | | 32 | eax ecx edx ebx esp ebp esi edi | |---------|------|------------------------------------------------| | Segment | 16 | es cs ss ds fs gs | |---------|------|------------------------------------------------| | Control | 32 | cr0 cr2 cr3 cr4 | |---------|------|------------------------------------------------| | Debug | 32 | dr0 dr1 dr2 dr3 dr6 dr7 | |---------|------|------------------------------------------------| | FPU | 80 | st0 st1 st2 st3 st4 st5 st6 st7 | |---------|------|------------------------------------------------| | MMX | 64 | mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 | |---------|------|------------------------------------------------| | SSE | 128 | xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7 | |---------|------|------------------------------------------------| | AVX | 256 | ymm0 ymm1 ymm2 ymm3 ymm4 ymm5 ymm6 ymm7 | |---------|------|------------------------------------------------| | AVX-512 | 512 | zmm0 zmm1 zmm2 zmm3 zmm4 zmm5 zmm6 zmm7 | |---------|------|------------------------------------------------| | Opmask | 64 | k0 k1 k2 k3 k4 k5 k6 k7 | |---------|------|------------------------------------------------| | Bounds | 128 | bnd0 bnd1 bnd2 bnd3 | \-----------------------------------------------------------------/ 1.2.2 Data definitions To define data or reserve a space for it, use one of the directives listed in table 1.3. The data definition directive should be followed by one or more of numerical expressions, separated with commas. These expressions define the values for data cells of size depending on which directive is used. For example "db 1,2,3" will define the three bytes of values 1, 2 and 3 respectively. The "db" and "du" directives also accept the quoted string values of any length, which will be converted into chain of bytes when "db" is used and into chain of words with zeroed high byte when "du" is used. For example "db 'abc'" will define the three bytes of values 61, 62 and 63. The "dp" directive and its synonym "df" accept the values consisting of two numerical expressions separated with colon, the first value will become the high word and the second value will become the low double word of the far pointer value. Also "dd" accepts such pointers consisting of two word values separated with colon, and "dt" accepts the word and quad word value separated with colon, the quad word is stored first. The "dt" directive with single expression as parameter accepts only floating point values and creates data in FPU double extended precision format. Any of the above directive allows the usage of special "dup" operator to make multiple copies of given values. The count of duplicates should precede this operator and the value to duplicate should follow - it can even be the chain of values separated with commas, but such set of values needs to be enclosed with parenthesis, like "db 5 dup (1,2)", which defines five copies of the given two byte sequence. The "file" is a special directive and its syntax is different. This directive includes a chain of bytes from file and it should be followed by the quoted file name, then optionally numerical expression specifying offset in file preceded by the colon, and - also optionally - comma and numerical expression specifying count of bytes to include (if no count is specified, all data up to the end of file is included). For example "file 'data.bin'" will include the whole file as binary data and "file 'data.bin':10h,4" will include only four bytes starting at offset 10h. The data reservation directive should be followed by only one numerical expression, and this value defines how many cells of the specified size should be reserved. All data definition directives also accept the "?" value, which means that this cell should not be initialized to any value and the effect is the same as by using the data reservation directive. The uninitialized data may not be included in the output file, so its values should be always considered unknown. Table 1.3 Data directives /----------------------------\ | Size | Define | Reserve | | (bytes) | data | data | |=========|========|=========| | 1 | db | rb | | | file | | |---------|--------|---------| | 2 | dw | rw | | | du | | |---------|--------|---------| | 4 | dd | rd | |---------|--------|---------| | 6 | dp | rp | | | df | rf | |---------|--------|---------| | 8 | dq | rq | |---------|--------|---------| | 10 | dt | rt | \----------------------------/ 1.2.3 Constants and labels In the numerical expressions you can also use constants or labels instead of numbers. To define the constant or label you should use the specific directives. Each label can be defined only once and it is accessible from the any place of source (even before it was defined). Constant can be redefined many times, but in this case it is accessible only after it was defined, and is always equal to the value from last definition before the place where it's used. When a constant is defined only once in source, it is - like the label - accessible from anywhere. The definition of constant consists of name of the constant followed by the "=" character and numerical expression, which after calculation will become the value of constant. This value is always calculated at the time the constant is defined. For example you can define "count" constant by using the directive "count = 17", and then use it in the assembly instructions, like "mov cx,count" - which will become "mov cx,17" during the compilation process. There are different ways to define labels. The simplest is to follow the name of label by the colon, this directive can even be followed by the other instruction in the same line. It defines the label whose value is equal to offset of the point where it's defined. This method is usually used to label the places in code. The other way is to follow the name of label (without a colon) by some data directive. It defines the label with value equal to offset of the beginning of defined data, and remembered as a label for data with cell size as specified for that data directive in table 1.3. The label can be treated as constant of value equal to offset of labeled code or data. For example when you define data using the labeled directive "char db 224", to put the offset of this data into BX register you should use "mov bx,char" instruction, and to put the value of byte addressed by "char" label to DL register, you should use "mov dl,[char]" (or "mov dl,ptr char"). But when you try to assemble "mov ax,[char]", it will cause an error, because fasm compares the sizes of operands, which should be equal. You can force assembling that instruction by using size override: "mov ax,word [char]", but remember that this instruction will read the two bytes beginning at "char" address, while it was defined as a one byte. The last and the most flexible way to define labels is to use "label" directive. This directive should be followed by the name of label, then optionally size operator (it can be preceded by a colon) and then - also optionally "at" operator and the numerical expression defining the address at which this label should be defined. For example "label wchar word at char" will define a new label for the 16-bit data at the address of "char". Now the instruction "mov ax,[wchar]" will be after compilation the same as "mov ax,word [char]". If no address is specified, "label" directive defines the label at current offset. Thus "mov [wchar],57568" will copy two bytes while "mov [char],224" will copy one byte to the same address. The label whose name begins with dot is treated as local label, and its name is attached to the name of last global label (with name beginning with anything but dot) to make the full name of this label. So you can use the short name (beginning with dot) of this label anywhere before the next global label is defined, and in the other places you have to use the full name. Label beginning with two dots are the exception - they are like global, but they don't become the new prefix for local labels. The "@@" name means anonymous label, you can have defined many of them in the source. Symbol "@b" (or equivalent "@r") references the nearest preceding anonymous label, symbol "@f" references the nearest following anonymous label. These special symbol are case-insensitive. 1.2.4 Numerical expressions In the above examples all the numerical expressions were the simple numbers, constants or labels. But they can be more complex, by using the arithmetical or logical operators for calculations at compile time. All these operators with their priority values are listed in table 1.4. The operations with higher priority value will be calculated first, you can of course change this behavior by putting some parts of expression into parenthesis. The "+", "-", "*" and "/" are standard arithmetical operations, "mod" calculates the remainder from division. The "and", "or", "xor", "shl", "shr", "bsf", "bsr" and "not" perform the same bit-logical operations as assembly instructions of those names. The "rva" and "plt" are special unary operators that perform conversions between different kinds of addresses, they can be used only with few of the output formats and their meaning may vary (see 2.4). The arithmetical and bit-logical calculations are processed as if they operated on infinite precision 2-adic numbers, and assembler signalizes an overflow error if because of its limitations it is not table to perform the required calculation, or if the result is too large number to fit in either signed or unsigned range for the destination unit size. The numbers in the expression are by default treated as a decimal, binary numbers should have the "b" letter attached at the end, octal number should end with "o" letter, hexadecimal numbers should begin with "0x" characters (like in C language) or with the "$" character (like in Pascal language) or they should end with "h" letter. Also quoted string, when encountered in expression, will be converted into number - the first character will become the least significant byte of number. The numerical expression used as an address value can also contain any of general registers used for addressing, they can be added and multiplied by appropriate values, as it is allowed for the x86 architecture instructions. The numerical calculations inside address definition by default operate with target size assumed to be the same as the current bitness of code, even if generated instruction encoding will use a different address size. There are also some special symbols that can be used inside the numerical expression. First is "$", which is always equal to the value of current offset, while "$$" is equal to base address of current addressing space. The other one is "%", which is the number of current repeat in parts of code that are repeated using some special directives (see 2.2) and zero anywhere else. There's also "%t" symbol, which is always equal to the current time stamp. Any numerical expression can also consist of single floating point value (flat assembler does not allow any floating point operations at compilation time) in the scientific notation, they can end with the "f" letter to be recognized, otherwise they should contain at least one of the "." or "E" characters. So "1.0", "1E0" and "1f" define the same floating point value, while simple "1" defines an integer value. Table 1.4 Arithmetical and bit-logical operators by priority /-------------------------\ | Priority | Operators | |==========|==============| | 0 | + - | |----------|--------------| | 1 | * / | |----------|--------------| | 2 | mod | |----------|--------------| | 3 | and or xor | |----------|--------------| | 4 | shl shr | |----------|--------------| | 5 | not | |----------|--------------| | 6 | bsf bsr | |----------|--------------| | 7 | rva plt | \-------------------------/ 1.2.5 Jumps and calls The operand of any jump or call instruction can be preceded not only by the size operator, but also by one of the operators specifying type of the jump: "short", "near" or "far". For example, when assembler is in 16-bit mode, instruction "jmp dword [0]" will become the far jump and when assembler is in 32-bit mode, it will become the near jump. To force this instruction to be treated differently, use the "jmp near dword [0]" or "jmp far dword [0]" form. When operand of near jump is the immediate value, assembler will generate the shortest variant of this jump instruction if possible (but will not create 32-bit instruction in 16-bit mode nor 16-bit instruction in 32-bit mode, unless there is a size operator stating it). By specifying the jump type you can force it to always generate long variant (for example "jmp near 0") or to always generate short variant and terminate with an error when it's impossible (for example "jmp short 0"). 1.2.6 Size settings When instruction uses some memory addressing, by default the smallest form of instruction is generated by using the short displacement if only address value fits in the range. This can be overridden using the "word" or "dword" operator before the address inside the square brackets (or after the "ptr" operator), which forces the long displacement of appropriate size to be made. In case when address is not relative to any registers, those operators allow also to choose the appropriate mode of absolute addressing. Instructions "adc", "add", "and", "cmp", "or", "sbb", "sub" and "xor" with first operand being 16-bit or 32-bit are by default generated in shortened 8-bit form when the second operand is immediate value fitting in the range for signed 8-bit values. It also can be overridden by putting the "word" or "dword" operator before the immediate value. The similar rules applies to the "imul" instruction with the last operand being immediate value. Immediate value as an operand for "push" instruction without a size operator is by default treated as a word value if assembler is in 16-bit mode and as a double word value if assembler is in 32-bit mode, shorter 8-bit form of this instruction is used if possible, "word" or "dword" size operator forces the "push" instruction to be generated in longer form for specified size. "pushw" and "pushd" mnemonics force assembler to generate 16-bit or 32-bit code without forcing it to use the longer form of instruction. Chapter 2 Instruction set -------------------------- This chapter provides the detailed information about the instructions and directives supported by flat assembler. Directives for defining labels were already discussed in 1.2.3, all other directives will be described later in this chapter. 2.1 The x86 architecture instructions In this section you can find both the information about the syntax and purpose the assembly language instructions. If you need more technical information, look for the Intel Architecture Software Developer's Manual. Assembly instructions consist of the mnemonic (instruction's name) and from zero to three operands. If there are two or more operands, usually first is the destination operand and second is the source operand. Each operand can be register, memory or immediate value (see 1.2 for details about syntax of operands). After the description of each instruction there are examples of different combinations of operands, if the instruction has any. Some instructions act as prefixes and can be followed by other instruction in the same line, and there can be more than one prefix in a line. Each name of the segment register is also a mnemonic of instruction prefix, altough it is recommended to use segment overrides inside the square brackets instead of these prefixes. 2.1.1 Data movement instructions "mov" transfers a byte, word or double word from the source operand to the destination operand. It can transfer data between general registers, from the general register to memory, or from memory to general register, but it cannot move from memory to memory. It can also transfer an immediate value to general register or memory, segment register to general register or memory, general register or memory to segment register, control or debug register to general register and general register to control or debug register. The "mov" can be assembled only if the size of source operand and size of destination operand are the same. Below are the examples for each of the allowed combinations: mov bx,ax ; general register to general register mov [char],al ; general register to memory mov bl,[char] ; memory to general register mov dl,32 ; immediate value to general register mov [char],32 ; immediate value to memory mov ax,ds ; segment register to general register mov [bx],ds ; segment register to memory mov ds,ax ; general register to segment register mov ds,[bx] ; memory to segment register mov eax,cr0 ; control register to general register mov cr3,ebx ; general register to control register "xchg" swaps the contents of two operands. It can swap two byte operands, two word operands or two double word operands. Order of operands is not important. The operands may be two general registers, or general register with memory. For example: xchg ax,bx ; swap two general registers xchg al,[char] ; swap register with memory "push" decrements the stack frame pointer (ESP register), then transfers the operand to the top of stack indicated by ESP. The operand can be memory, general register, segment register or immediate value of word or double word size. If operand is an immediate value and no size is specified, it is by default treated as a word value if assembler is in 16-bit mode and as a double word value if assembler is in 32-bit mode. "pushw" and "pushd" mnemonics are variants of this instruction that store the values of word or double word size respectively. If more operands follow in the same line (separated only with spaces, not commas), compiler will assemble chain of the "push" instructions with these operands. The examples are with single operands: push ax ; store general register push es ; store segment register pushw [bx] ; store memory push 1000h ; store immediate value "pusha" saves the contents of the eight general register on the stack. This instruction has no operands. There are two version of this instruction, one 16-bit and one 32-bit, assembler automatically generates the appropriate version for current mode, but it can be overridden by using "pushaw" or "pushad" mnemonic to always get the 16-bit or 32-bit version. The 16-bit version of this instruction pushes general registers on the stack in the following order: AX, CX, DX, BX, the initial value of SP before AX was pushed, BP, SI and DI. The 32-bit version pushes equivalent 32-bit general registers in the same order. "pop" transfers the word or double word at the current top of stack to the destination operand, and then increments ESP to point to the new top of stack. The operand can be memory, general register or segment register. "popw" and "popd" mnemonics are variants of this instruction for restoring the values of word or double word size respectively. If more operands separated with spaces follow in the same line, compiler will assemble chain of the "pop" instructions with these operands. pop bx ; restore general register pop ds ; restore segment register popw [si] ; restore memory "popa" restores the registers saved on the stack by "pusha" instruction, except for the saved value of SP (or ESP), which is ignored. This instruction has no operands. To force assembling 16-bit or 32-bit version of this instruction use "popaw" or "popad" mnemonic. 2.1.2 Type conversion instructions The type conversion instructions convert bytes into words, words into double words, and double words into quad words. These conversions can be done using the sign extension or zero extension. The sign extension fills the extra bits of the larger item with the value of the sign bit of the smaller item, the zero extension simply fills them with zeros. "cwd" and "cdq" double the size of value AX or EAX register respectively and store the extra bits into the DX or EDX register. The conversion is done using the sign extension. These instructions have no operands. "cbw" extends the sign of the byte in AL throughout AX, and "cwde" extends the sign of the word in AX throughout EAX. These instructions also have no operands. "movsx" converts a byte to word or double word and a word to double word using the sign extension. "movzx" does the same, but it uses the zero extension. The source operand can be general register or memory, while the destination operand must be a general register. For example: movsx ax,al ; byte register to word register movsx edx,dl ; byte register to double word register movsx eax,ax ; word register to double word register movsx ax,byte [bx] ; byte memory to word register movsx edx,byte [bx] ; byte memory to double word register movsx eax,word [bx] ; word memory to double word register 2.1.3 Binary arithmetic instructions "add" replaces the destination operand with the sum of the source and destination operands and sets CF if overflow has occurred. The operands may be bytes, words or double words. The destination operand can be general register or memory, the source operand can be general register or immediate value, it can also be memory if the destination operand is register. add ax,bx ; add register to register add ax,[si] ; add memory to register add [di],al ; add register to memory add al,48 ; add immediate value to register add [char],48 ; add immediate value to memory "adc" sums the operands, adds one if CF is set, and replaces the destination operand with the result. Rules for the operands are the same as for the "add" instruction. An "add" followed by multiple "adc" instructions can be used to add numbers longer than 32 bits. "inc" adds one to the operand, it does not affect CF. The operand can be a general register or memory, and the size of the operand can be byte, word or double word. inc ax ; increment register by one inc byte [bx] ; increment memory by one "sub" subtracts the source operand from the destination operand and replaces the destination operand with the result. If a borrow is required, the CF is set. Rules for the operands are the same as for the "add" instruction. "sbb" subtracts the source operand from the destination operand, subtracts one if CF is set, and stores the result to the destination operand. Rules for the operands are the same as for the "add" instruction. A "sub" followed by multiple "sbb" instructions may be used to subtract numbers longer than 32 bits. "dec" subtracts one from the operand, it does not affect CF. Rules for the operand are the same as for the "inc" instruction. "cmp" subtracts the source operand from the destination operand. It updates the flags as the "sub" instruction, but does not alter the source and destination operands. Rules for the operands are the same as for the "sub" instruction. "neg" subtracts a signed integer operand from zero. The effect of this instructon is to reverse the sign of the operand from positive to negative or from negative to positive. Rules for the operand are the same as for the "inc" instruction. "xadd" exchanges the destination operand with the source operand, then loads the sum of the two values into the destination operand. The destination operand may be a general register or memory, the source operand must be a general register. All the above binary arithmetic instructions update SF, ZF, PF and OF flags. SF is always set to the same value as the result's sign bit, ZF is set when all the bits of result are zero, PF is set when low order eight bits of result contain an even number of set bits, OF is set if result is too large for a positive number or too small for a negative number (excluding sign bit) to fit in destination operand. "mul" performs an unsigned multiplication of the operand and the accumulator. If the operand is a byte, the processor multiplies it by the contents of AL and returns the 16-bit result to AH and AL. If the operand is a word, the processor multiplies it by the contents of AX and returns the 32-bit result to DX and AX. If the operand is a double word, the processor multiplies it by the contents of EAX and returns the 64-bit result in EDX and EAX. "mul" sets CF and OF when the upper half of the result is nonzero, otherwise they are cleared. Rules for the operand are the same as for the "inc" instruction. "imul" performs a signed multiplication operation. This instruction has three variations. First has one operand and behaves in the same way as the "mul" instruction. Second has two operands, in this case destination operand is multiplied by the source operand and the result replaces the destination operand. Destination operand must be a general register, it can be word or double word, source operand can be general register, memory or immediate value. Third form has three operands, the destination operand must be a general register, word or double word in size, source operand can be general register or memory, and third operand must be an immediate value. The source operand is multiplied by the immediate value and the result is stored in the destination register. All the three forms calculate the product to twice the size of operands and set CF and OF when the upper half of the result is nonzero, but second and third form truncate the product to the size of operands. So second and third forms can be also used for unsigned operands because, whether the operands are signed or unsigned, the lower half of the product is the same. Below are the examples for all three forms: imul bl ; accumulator by register imul word [si] ; accumulator by memory imul bx,cx ; register by register imul bx,[si] ; register by memory imul bx,10 ; register by immediate value imul ax,bx,10 ; register by immediate value to register imul ax,[si],10 ; memory by immediate value to register "div" performs an unsigned division of the accumulator by the operand. The dividend (the accumulator) is twice the size of the divisor (the operand), the quotient and remainder have the same size as the divisor. If divisor is byte, the dividend is taken from AX register, the quotient is stored in AL and the remainder is stored in AH. If divisor is word, the upper half of dividend is taken from DX, the lower half of dividend is taken from AX, the quotient is stored in AX and the remainder is stored in DX. If divisor is double word, the upper half of dividend is taken from EDX, the lower half of dividend is taken from EAX, the quotient is stored in EAX and the remainder is stored in EDX. Rules for the operand are the same as for the "mul" instruction. "idiv" performs a signed division of the accumulator by the operand. It uses the same registers as the "div" instruction, and the rules for the operand are the same. 2.1.4 Decimal arithmetic instructions Decimal arithmetic is performed by combining the binary arithmetic instructions (already described in the prior section) with the decimal arithmetic instructions. The decimal arithmetic instructions are used to adjust the results of a previous binary arithmetic operation to produce a valid packed or unpacked decimal result, or to adjust the inputs to a subsequent binary arithmetic operation so the operation will produce a valid packed or unpacked decimal result. "daa" adjusts the result of adding two valid packed decimal operands in AL. "daa" must always follow the addition of two pairs of packed decimal numbers (one digit in each half-byte) to obtain a pair of valid packed decimal digits as results. The carry flag is set if carry was needed. This instruction has no operands. "das" adjusts the result of subtracting two valid packed decimal operands in AL. "das" must always follow the subtraction of one pair of packed decimal numbers (one digit in each half-byte) from another to obtain a pair of valid packed decimal digits as results. The carry flag is set if a borrow was needed. This instruction has no operands. "aaa" changes the contents of register AL to a valid unpacked decimal number, and zeroes the top four bits. "aaa" must always follow the addition of two unpacked decimal operands in AL. The carry flag is set and AH is incremented if a carry is necessary. This instruction has no operands. "aas" changes the contents of register AL to a valid unpacked decimal number, and zeroes the top four bits. "aas" must always follow the subtraction of one unpacked decimal operand from another in AL. The carry flag is set and AH decremented if a borrow is necessary. This instruction has no operands. "aam" corrects the result of a multiplication of two valid unpacked decimal numbers. "aam" must always follow the multiplication of two decimal numbers to produce a valid decimal result. The high order digit is left in AH, the low order digit in AL. The generalized version of this instruction allows adjustment of the contents of the AX to create two unpacked digits of any number base. The standard version of this instruction has no operands, the generalized version has one operand - an immediate value specifying the number base for the created digits. "aad" modifies the numerator in AH and AL to prepare for the division of two valid unpacked decimal operands so that the quotient produced by the division will be a valid unpacked decimal number. AH should contain the high order digit and AL the low order digit. This instruction adjusts the value and places the result in AL, while AH will contain zero. The generalized version of this instruction allows adjustment of two unpacked digits of any number base. Rules for the operand are the same as for the "aam" instruction. 2.1.5 Logical instructions "not" inverts the bits in the specified operand to form a one's complement of the operand. It has no effect on the flags. Rules for the operand are the same as for the "inc" instruction. "and", "or" and "xor" instructions perform the standard logical operations. They update the SF, ZF and PF flags. Rules for the operands are the same as for the "add" instruction. "bt", "bts", "btr" and "btc" instructions operate on a single bit which can be in memory or in a general register. The location of the bit is specified as an offset from the low order end of the operand. The value of the offset is the taken from the second operand, it either may be an immediate byte or a general register. These instructions first assign the value of the selected bit to CF. "bt" instruction does nothing more, "bts" sets the selected bit to 1, "btr" resets the selected bit to 0, "btc" changes the bit to its complement. The first operand can be word or double word. bt ax,15 ; test bit in register bts word [bx],15 ; test and set bit in memory btr ax,cx ; test and reset bit in register btc word [bx],cx ; test and complement bit in memory "bsf" and "bsr" instructions scan a word or double word for first set bit and store the index of this bit into destination operand, which must be general register. The bit string being scanned is specified by source operand, it may be either general register or memory. The ZF flag is set if the entire string is zero (no set bits are found); otherwise it is cleared. If no set bit is found, the value of the destination register is undefined. "bsf" scans from low order to high order (starting from bit index zero). "bsr" scans from high order to low order (starting from bit index 15 of a word or index 31 of a double word). bsf ax,bx ; scan register forward bsr ax,[si] ; scan memory reverse "shl" shifts the destination operand left by the number of bits specified in the second operand. The destination operand can be byte, word, or double word general register or memory. The second operand can be an immediate value or the CL register. The processor shifts zeros in from the right (low order) side of the operand as bits exit from the left side. The last bit that exited is stored in CF. "sal" is a synonym for "shl". shl al,1 ; shift register left by one bit shl byte [bx],1 ; shift memory left by one bit shl ax,cl ; shift register left by count from cl shl word [bx],cl ; shift memory left by count from cl "shr" and "sar" shift the destination operand right by the number of bits specified in the second operand. Rules for operands are the same as for the "shl" instruction. "shr" shifts zeros in from the left side of the operand as bits exit from the right side. The last bit that exited is stored in CF. "sar" preserves the sign of the operand by shifting in zeros on the left side if the value is positive or by shifting in ones if the value is negative. "shld" shifts bits of the destination operand to the left by the number of bits specified in third operand, while shifting high order bits from the source operand into the destination operand on the right. The source operand remains unmodified. The destination operand can be a word or double word general register or memory, the source operand must be a general register, third operand can be an immediate value or the CL register. shld ax,bx,1 ; shift register left by one bit shld [di],bx,1 ; shift memory left by one bit shld ax,bx,cl ; shift register left by count from cl shld [di],bx,cl ; shift memory left by count from cl "shrd" shifts bits of the destination operand to the right, while shifting low order bits from the source operand into the destination operand on the left. The source operand remains unmodified. Rules for operands are the same as for the "shld" instruction. "rol" and "rcl" rotate the byte, word or double word destination operand left by the number of bits specified in the second operand. For each rotation specified, the high order bit that exits from the left of the operand returns at the right to become the new low order bit. "rcl" additionally puts in CF each high order bit that exits from the left side of the operand before it returns to the operand as the low order bit on the next rotation cycle. Rules for operands are the same as for the "shl" instruction. "ror" and "rcr" rotate the byte, word or double word destination operand right by the number of bits specified in the second operand. For each rotation specified, the low order bit that exits from the right of the operand returns at the left to become the new high order bit. "rcr" additionally puts in CF each low order bit that exits from the right side of the operand before it returns to the operand as the high order bit on the next rotation cycle. Rules for operands are the same as for the "shl" instruction. "test" performs the same action as the "and" instruction, but it does not alter the destination operand, only updates flags. Rules for the operands are the same as for the "and" instruction. "bswap" reverses the byte order of a 32-bit general register: bits 0 through 7 are swapped with bits 24 through 31, and bits 8 through 15 are swapped with bits 16 through 23. This instruction is provided for converting little-endian values to big-endian format and vice versa. bswap edx ; swap bytes in register 2.1.6 Control transfer instructions "jmp" unconditionally transfers control to the target location. The destination address can be specified directly within the instruction or indirectly through a register or memory, the acceptable size of this address depends on whether the jump is near or far (it can be specified by preceding the operand with "near" or "far" operator) and whether the instruction is 16-bit or 32-bit. Operand for near jump should be "word" size for 16-bit instruction or the "dword" size for 32-bit instruction. Operand for far jump should be "dword" size for 16-bit instruction or "pword" size for 32-bit instruction. A direct "jmp" instruction includes the destination address as part of the instruction (and can be preceded by "short", "near" or "far" operator), the operand specifying address should be the numerical expression for near or short jump, or two numerical expressions separated with colon for far jump, the first specifies selector of segment, the second is the offset within segment. The "pword" operator can be used to force the 32-bit far call, and "dword" to force the 16-bit far call. An indirect "jmp" instruction obtains the destination address indirectly through a register or a pointer variable, the operand should be general register or memory. See also 1.2.5 for some more details. jmp 100h ; direct near jump jmp 0FFFFh:0 ; direct far jump jmp ax ; indirect near jump jmp pword [ebx] ; indirect far jump "call" transfers control to the procedure, saving on the stack the address of the instruction following the "call" for later use by a "ret" (return) instruction. Rules for the operands are the same as for the "jmp" instruction, but the "call" has no short variant of direct instruction and thus it not optimized. "ret", "retn" and "retf" instructions terminate the execution of a procedure and transfers control back to the program that originally invoked the procedure using the address that was stored on the stack by the "call" instruction. "ret" is the equivalent for "retn", which returns from the procedure that was executed using the near call, while "retf" returns from the procedure that was executed using the far call. These instructions default to the size of address appropriate for the current code setting, but the size of address can be forced to 16-bit by using the "retw", "retnw" and "retfw" mnemonics, and to 32-bit by using the "retd", "retnd" and "retfd" mnemonics. All these instructions may optionally specify an immediate operand, by adding this constant to the stack pointer, they effectively remove any arguments that the calling program pushed on the stack before the execution of the "call" instruction. "iret" returns control to an interrupted procedure. It differs from "ret" in that it also pops the flags from the stack into the flags register. The flags are stored on the stack by the interrupt mechanism. It defaults to the size of return address appropriate for the current code setting, but it can be forced to use 16-bit or 32-bit address by using the "iretw" or "iretd" mnemonic. The conditional transfer instructions are jumps that may or may not transfer control, depending on the state of the CPU flags when the instruction executes. The mnemonics for conditional jumps may be obtained by attaching the condition mnemonic (see table 2.1) to the "j" mnemonic, for example "jc" instruction will transfer the control when the CF flag is set. The conditional jumps can be short or near, and direct only, and can be optimized (see 1.2.5), the operand should be an immediate value specifying target address. Table 2.1 Conditions /-----------------------------------------------------------\ | Mnemonic | Condition tested | Description | |==========|=======================|========================| | o | OF = 1 | overflow | |----------|-----------------------|------------------------| | no | OF = 0 | not overflow | |----------|-----------------------|------------------------| | c | | carry | | b | CF = 1 | below | | nae | | not above nor equal | |----------|-----------------------|------------------------| | nc | | not carry | | ae | CF = 0 | above or equal | | nb | | not below | |----------|-----------------------|------------------------| | e | ZF = 1 | equal | | z | | zero | |----------|-----------------------|------------------------| | ne | ZF = 0 | not equal | | nz | | not zero | |----------|-----------------------|------------------------| | be | CF or ZF = 1 | below or equal | | na | | not above | |----------|-----------------------|------------------------| | a | CF or ZF = 0 | above | | nbe | | not below nor equal | |----------|-----------------------|------------------------| | s | SF = 1 | sign | |----------|-----------------------|------------------------| | ns | SF = 0 | not sign | |----------|-----------------------|------------------------| | p | PF = 1 | parity | | pe | | parity even | |----------|-----------------------|------------------------| | np | PF = 0 | not parity | | po | | parity odd | |----------|-----------------------|------------------------| | l | SF xor OF = 1 | less | | nge | | not greater nor equal | |----------|-----------------------|------------------------| | ge | SF xor OF = 0 | greater or equal | | nl | | not less | |----------|-----------------------|------------------------| | le | (SF xor OF) or ZF = 1 | less or equal | | ng | | not greater | |----------|-----------------------|------------------------| | g | (SF xor OF) or ZF = 0 | greater | | nle | | not less nor equal | \-----------------------------------------------------------/ The "loop" instructions are conditional jumps that use a value placed in CX (or ECX) to specify the number of repetitions of a software loop. All "loop" instructions automatically decrement CX (or ECX) and terminate the loop (don't transfer the control) when CX (or ECX) is zero. It uses CX or ECX whether the current code setting is 16-bit or 32-bit, but it can be forced to us CX with the "loopw" mnemonic or to use ECX with the "loopd" mnemonic. "loope" and "loopz" are the synonyms for the same instruction, which acts as the standard "loop", but also terminates the loop when ZF flag is set. "loopew" and "loopzw" mnemonics force them to use CX register while "looped" and "loopzd" force them to use ECX register. "loopne" and "loopnz" are the synonyms for the same instructions, which acts as the standard "loop", but also terminate the loop when ZF flag is not set. "loopnew" and "loopnzw" mnemonics force them to use CX register while "loopned" and "loopnzd" force them to use ECX register. Every "loop" instruction needs an operand being an immediate value specifying target address, it can be only short jump (in the range of 128 bytes back and 127 bytes forward from the address of instruction following the "loop" instruction). "jcxz" branches to the label specified in the instruction if it finds a value of zero in CX, "jecxz" does the same, but checks the value of ECX instead of CX. Rules for the operands are the same as for the "loop" instruction. "int" activates the interrupt service routine that corresponds to the number specified as an operand to the instruction, the number should be in range from 0 to 255. The interrupt service routine terminates with an "iret" instruction that returns control to the instruction that follows "int". "int3" mnemonic codes the short (one byte) trap that invokes the interrupt 3. "into" instruction invokes the interrupt 4 if the OF flag is set. "bound" verifies that the signed value contained in the specified register lies within specified limits. An interrupt 5 occurs if the value contained in the register is less than the lower bound or greater than the upper bound. It needs two operands, the first operand specifies the register being tested, the second operand should be memory address for the two signed limit values. The operands can be "word" or "dword" in size. bound ax,[bx] ; check word for bounds bound eax,[esi] ; check double word for bounds 2.1.7 I/O instructions "in" transfers a byte, word, or double word from an input port to AL, AX, or EAX. I/O ports can be addressed either directly, with the immediate byte value coded in instruction, or indirectly via the DX register. The destination operand should be AL, AX, or EAX register. The source operand should be an immediate value in range from 0 to 255, or DX register. in al,20h ; input byte from port 20h in ax,dx ; input word from port addressed by dx "out" transfers a byte, word, or double word to an output port from AL, AX, or EAX. The program can specify the number of the port using the same methods as the "in" instruction. The destination operand should be an immediate value in range from 0 to 255, or DX register. The source operand should be AL, AX, or EAX register. out 20h,ax ; output word to port 20h out dx,al ; output byte to port addressed by dx 2.1.8 Strings operations The string operations operate on one element of a string. A string element may be a byte, a word, or a double word. The string elements are addressed by SI and DI (or ESI and EDI) registers. After every string operation SI and/or DI (or ESI and/or EDI) are automatically updated to point to the next element of the string. If DF (direction flag) is zero, the index registers are incremented, if DF is one, they are decremented. The amount of the increment or decrement is 1, 2, or 4 depending on the size of the string element. Every string operation instruction has short forms which have no operands and use SI and/or DI when the code type is 16-bit, and ESI and/or EDI when the code type is 32-bit. SI and ESI by default address data in the segment selected by DS, DI and EDI always address data in the segment selected by ES. Short form is obtained by attaching to the mnemonic of string operation letter specifying the size of string element, it should be "b" for byte element, "w" for word element, and "d" for double word element. Full form of string operation needs operands providing the size operator and the memory addresses, which can be SI or ESI with any segment prefix, DI or EDI always with ES segment prefix. "movs" transfers the string element pointed to by SI (or ESI) to the location pointed to by DI (or EDI). Size of operands can be byte, word, or double word. The destination operand should be memory addressed by DI or EDI, the source operand should be memory addressed by SI or ESI with any segment prefix. movs byte [di],[si] ; transfer byte movs word [es:di],[ss:si] ; transfer word movsd ; transfer double word "cmps" subtracts the destination string element from the source string element and updates the flags AF, SF, PF, CF and OF, but it does not change any of the compared elements. If the string elements are equal, ZF is set, otherwise it is cleared. The first operand for this instruction should be the source string element addressed by SI or ESI with any segment prefix, the second operand should be the destination string element addressed by DI or EDI. cmpsb ; compare bytes cmps word [ds:si],[es:di] ; compare words cmps dword [fs:esi],[edi] ; compare double words "scas" subtracts the destination string element from AL, AX, or EAX (depending on the size of string element) and updates the flags AF, SF, ZF, PF, CF and OF. If the values are equal, ZF is set, otherwise it is cleared. The operand should be the destination string element addressed by DI or EDI. scas byte [es:di] ; scan byte scasw ; scan word scas dword [es:edi] ; scan double word "stos" places the value of AL, AX, or EAX into the destination string element. Rules for the operand are the same as for the "scas" instruction. "lods" places the source string element into AL, AX, or EAX. The operand should be the source string element addressed by SI or ESI with any segment prefix. lods byte [ds:si] ; load byte lods word [cs:si] ; load word lodsd ; load double word "ins" transfers a byte, word, or double word from an input port addressed by DX register to the destination string element. The destination operand should be memory addressed by DI or EDI, the source operand should be the DX register. insb ; input byte ins word [es:di],dx ; input word ins dword [edi],dx ; input double word "outs" transfers the source string element to an output port addressed by DX register. The destination operand should be the DX register and the source operand should be memory addressed by SI or ESI with any segment prefix. outs dx,byte [si] ; output byte outsw ; output word outs dx,dword [gs:esi] ; output double word The repeat prefixes "rep", "repe"/"repz", and "repne"/"repnz" specify repeated string operation. When a string operation instruction has a repeat prefix, the operation is executed repeatedly, each time using a different element of the string. The repetition terminates when one of the conditions specified by the prefix is satisfied. All three prefixes automatically decrease CX or ECX register (depending whether string operation instruction uses the 16-bit or 32-bit addressing) after each operation and repeat the associated operation until CX or ECX is zero. "repe"/"repz" and "repne"/"repnz" are used exclusively with the "scas" and "cmps" instructions (described below). When these prefixes are used, repetition of the next instruction depends on the zero flag (ZF) also, "repe" and "repz" terminate the execution when the ZF is zero, "repne" and "repnz" terminate the execution when the ZF is set. rep movsd ; transfer multiple double words repe cmpsb ; compare bytes until not equal 2.1.9 Flag control instructions The flag control instructions provide a method for directly changing the state of bits in the flag register. All instructions described in this section have no operands. "stc" sets the CF (carry flag) to 1, "clc" zeroes the CF, "cmc" changes the CF to its complement. "std" sets the DF (direction flag) to 1, "cld" zeroes the DF, "sti" sets the IF (interrupt flag) to 1 and therefore enables the interrupts, "cli" zeroes the IF and therefore disables the interrupts. "lahf" copies SF, ZF, AF, PF, and CF to bits 7, 6, 4, 2, and 0 of the AH register. The contents of the remaining bits are undefined. The flags remain unaffected. "sahf" transfers bits 7, 6, 4, 2, and 0 from the AH register into SF, ZF, AF, PF, and CF. "pushf" decrements "esp" by two or four and stores the low word or double word of flags register at the top of stack, size of stored data depends on the current code setting. "pushfw" variant forces storing the word and "pushfd" forces storing the double word. "popf" transfers specific bits from the word or double word at the top of stack, then increments "esp" by two or four, this value depends on the current code setting. "popfw" variant forces restoring from the word and "popfd" forces restoring from the double word. 2.1.10 Conditional operations The instructions obtained by attaching the condition mnemonic (see table 2.1) to the "set" mnemonic set a byte to one if the condition is true and set the byte to zero otherwise. The operand should be an 8-bit be general register or the byte in memory. setne al ; set al if zero flag cleared seto byte [bx] ; set byte if overflow "salc" instruction sets the all bits of AL register when the carry flag is set and zeroes the AL register otherwise. This instruction has no arguments. The instructions obtained by attaching the condition mnemonic to "cmov" mnemonic transfer the word or double word from the general register or memory to the general register only when the condition is true. The destination operand should be general register, the source operand can be general register or memory. cmove ax,bx ; move when zero flag set cmovnc eax,[ebx] ; move when carry flag cleared "cmpxchg" compares the value in the AL, AX, or EAX register with the destination operand. If the two values are equal, the source operand is loaded into the destination operand. Otherwise, the destination operand is loaded into the AL, AX, or EAX register. The destination operand may be a general register or memory, the source operand must be a general register. cmpxchg dl,bl ; compare and exchange with register cmpxchg [bx],dx ; compare and exchange with memory "cmpxchg8b" compares the 64-bit value in EDX and EAX registers with the destination operand. If the values are equal, the 64-bit value in ECX and EBX registers is stored in the destination operand. Otherwise, the value in the destination operand is loaded into EDX and EAX registers. The destination operand should be a quad word in memory. cmpxchg8b [bx] ; compare and exchange 8 bytes 2.1.11 Miscellaneous instructions "nop" instruction occupies one byte but affects nothing but the instruction pointer. This instruction has no operands and doesn't perform any operation. "ud2" instruction generates an invalid opcode exception. This instruction is provided for software testing to explicitly generate an invalid opcode. This is instruction has no operands. "xlat" replaces a byte in the AL register with a byte indexed by its value in a translation table addressed by BX or EBX. The operand should be a byte memory addressed by BX or EBX with any segment prefix. This instruction has also a short form "xlatb" which has no operands and uses the BX or EBX address in the segment selected by DS depending on the current code setting. "lds" transfers a pointer variable from the source operand to DS and the destination register. The source operand must be a memory operand, and the destination operand must be a general register. The DS register receives the segment selector of the pointer while the destination register receives the offset part of the pointer. "les", "lfs", "lgs" and "lss" operate identically to "lds" except that rather than DS register the ES, FS, GS and SS is used respectively. lds bx,[si] ; load pointer to ds:bx "lea" transfers the offset of the source operand (rather than its value) to the destination operand. The source operand must be a memory operand, and the destination operand must be a general register. lea dx,[bx+si+1] ; load effective address to dx "cpuid" returns processor identification and feature information in the EAX, EBX, ECX, and EDX registers. The information returned is selected by entering a value in the EAX register before the instruction is executed. This instruction has no operands. "pause" instruction delays the execution of the next instruction an implementation specific amount of time. It can be used to improve the performance of spin wait loops. This instruction has no operands. "enter" creates a stack frame that may be used to implement the scope rules of block-structured high-level languages. A "leave" instruction at the end of a procedure complements an "enter" at the beginning of the procedure to simplify stack management and to control access to variables for nested procedures. The "enter" instruction includes two parameters. The first parameter specifies the number of bytes of dynamic storage to be allocated on the stack for the routine being entered. The second parameter corresponds to the lexical nesting level of the routine, it can be in range from 0 to 31. The specified lexical level determines how many sets of stack frame pointers the CPU copies into the new stack frame from the preceding frame. This list of stack frame pointers is sometimes called the display. The first word (or double word when code is 32-bit) of the display is a pointer to the last stack frame. This pointer enables a "leave" instruction to reverse the action of the previous "enter" instruction by effectively discarding the last stack frame. After "enter" creates the new display for a procedure, it allocates the dynamic storage space for that procedure by decrementing ESP by the number of bytes specified in the first parameter. To enable a procedure to address its display, "enter" leaves BP (or EBP) pointing to the beginning of the new stack frame. If the lexical level is zero, "enter" pushes BP (or EBP), copies SP to BP (or ESP to EBP) and then subtracts the first operand from ESP. For nesting levels greater than zero, the processor pushes additional frame pointers on the stack before adjusting the stack pointer. enter 2048,0 ; enter and allocate 2048 bytes on stack 2.1.12 System instructions "lmsw" loads the operand into the machine status word (bits 0 through 15 of CR0 register), while "smsw" stores the machine status word into the destination operand. The operand for both those instructions can be 16-bit general register or memory, for "smsw" it can also be 32-bit general register. lmsw ax ; load machine status from register smsw [bx] ; store machine status to memory "lgdt" and "lidt" instructions load the values in operand into the global descriptor table register or the interrupt descriptor table register respectively. "sgdt" and "sidt" store the contents of the global descriptor table register or the interrupt descriptor table register in the destination operand. The operand should be a 6 bytes in memory. lgdt [ebx] ; load global descriptor table "lldt" loads the operand into the segment selector field of the local descriptor table register and "sldt" stores the segment selector from the local descriptor table register in the operand. "ltr" loads the operand into the segment selector field of the task register and "str" stores the segment selector from the task register in the operand. Rules for operand are the same as for the "lmsw" and "smsw" instructions. "lar" loads the access rights from the segment descriptor specified by the selector in source operand into the destination operand and sets the ZF flag. The destination operand can be a 16-bit or 32-bit general register. The source operand should be a 16-bit general register or memory. lar ax,[bx] ; load access rights into word lar eax,dx ; load access rights into double word "lsl" loads the segment limit from the segment descriptor specified by the selector in source operand into the destination operand and sets the ZF flag. Rules for operand are the same as for the "lar" instruction. "verr" and "verw" verify whether the code or data segment specified with the operand is readable or writable from the current privilege level. The operand should be a word, it can be general register or memory. If the segment is accessible and readable (for "verr") or writable (for "verw") the ZF flag is set, otherwise it's cleared. Rules for operand are the same as for the "lldt" instruction. "arpl" compares the RPL (requestor's privilege level) fields of two segment selectors. The first operand contains one segment selector and the second operand contains the other. If the RPL field of the destination operand is less than the RPL field of the source operand, the ZF flag is set and the RPL field of the destination operand is increased to match that of the source operand. Otherwise, the ZF flag is cleared and no change is made to the destination operand. The destination operand can be a word general register or memory, the source operand must be a general register. arpl bx,ax ; adjust RPL of selector in register arpl [bx],ax ; adjust RPL of selector in memory "clts" clears the TS (task switched) flag in the CR0 register. This instruction has no operands. "lock" prefix causes the processor's bus-lock signal to be asserted during execution of the accompanying instruction. In a multiprocessor environment, the bus-lock signal insures that the processor has exclusive use of any shared memory while the signal is asserted. The "lock" prefix can be prepended only to the following instructions and only to those forms of the instructions where the destination operand is a memory operand: "add", "adc", "and", "btc", "btr", "bts", "cmpxchg", "cmpxchg8b", "dec", "inc", "neg", "not", "or", "sbb", "sub", "xor", "xadd" and "xchg". If the "lock" prefix is used with one of these instructions and the source operand is a memory operand, an undefined opcode exception may be generated. An undefined opcode exception will also be generated if the "lock" prefix is used with any instruction not in the above list. The "xchg" instruction always asserts the bus-lock signal regardless of the presence or absence of the "lock" prefix. "hlt" stops instruction execution and places the processor in a halted state. An enabled interrupt, a debug exception, the BINIT, INIT or the RESET signal will resume execution. This instruction has no operands. "invlpg" invalidates (flushes) the TLB (translation lookaside buffer) entry specified with the operand, which should be a memory. The processor determines the page that contains that address and flushes the TLB entry for that page. "rdmsr" loads the contents of a 64-bit MSR (model specific register) of the address specified in the ECX register into registers EDX and EAX. "wrmsr" writes the contents of registers EDX and EAX into the 64-bit MSR of the address specified in the ECX register. "rdtsc" loads the current value of the processor's time stamp counter from the 64-bit MSR into the EDX and EAX registers. The processor increments the time stamp counter MSR every clock cycle and resets it to 0 whenever the processor is reset. "rdpmc" loads the contents of the 40-bit performance monitoring counter specified in the ECX register into registers EDX and EAX. These instructions have no operands. "wbinvd" writes back all modified cache lines in the processor's internal cache to main memory and invalidates (flushes) the internal caches. The instruction then issues a special function bus cycle that directs external caches to also write back modified data and another bus cycle to indicate that the external caches should be invalidated. This instruction has no operands. "rsm" return program control from the system management mode to the program that was interrupted when the processor received an SMM interrupt. This instruction has no operands. "sysenter" executes a fast call to a level 0 system procedure, "sysexit" executes a fast return to level 3 user code. The addresses used by these instructions are stored in MSRs. These instructions have no operands. 2.1.13 FPU instructions The FPU (Floating-Point Unit) instructions operate on the floating-point values in three formats: single precision (32-bit), double precision (64-bit) and double extended precision (80-bit). The FPU registers form the stack and each of them holds the double extended precision floating-point value. When some values are pushed onto the stack or are removed from the top, the FPU registers are shifted, so ST0 is always the value on the top of FPU stack, ST1 is the first value below the top, etc. The ST0 name has also the synonym ST. "fld" pushes the floating-point value onto the FPU register stack. The operand can be 32-bit, 64-bit or 80-bit memory location or the FPU register, its value is then loaded onto the top of FPU register stack (the ST0 register) and is automatically converted into the double extended precision format. fld dword [bx] ; load single prevision value from memory fld st2 ; push value of st2 onto register stack "fld1", "fldz", "fldl2t", "fldl2e", "fldpi", "fldlg2" and "fldln2" load the commonly used contants onto the FPU register stack. The loaded constants are +1.0, +0.0, lb 10, lb e, pi, lg 2 and ln 2 respectively. These instructions have no operands. "fild" converts the signed integer source operand into double extended precision floating-point format and pushes the result onto the FPU register stack. The source operand can be a 16-bit, 32-bit or 64-bit memory location. fild qword [bx] ; load 64-bit integer from memory "fst" copies the value of ST0 register to the destination operand, which can be 32-bit or 64-bit memory location or another FPU register. "fstp" performs the same operation as "fst" and then pops the register stack, getting rid of ST0. "fstp" accepts the same operands as the "fst" instruction and can also store value in the 80-bit memory. fst st3 ; copy value of st0 into st3 register fstp tword [bx] ; store value in memory and pop stack "fist" converts the value in ST0 to a signed integer and stores the result in the destination operand. The operand can be 16-bit or 32-bit memory location. "fistp" performs the same operation and then pops the register stack, it accepts the same operands as the "fist" instruction and can also store integer value in the 64-bit memory, so it has the same rules for operands as "fild" instruction. "fbld" converts the packed BCD integer into double extended precision floating-point format and pushes this value onto the FPU stack. "fbstp" converts the value in ST0 to an 18-digit packed BCD integer, stores the result in the destination operand, and pops the register stack. The operand should be an 80-bit memory location. "fadd" adds the destination and source operand and stores the sum in the destination location. The destination operand is always an FPU register, if the source is a memory location, the destination is ST0 register and only source operand should be specified. If both operands are FPU registers, at least one of them should be ST0 register. An operand in memory can be a 32-bit or 64-bit value. fadd qword [bx] ; add double precision value to st0 fadd st2,st0 ; add st0 to st2 "faddp" adds the destination and source operand, stores the sum in the destination location and then pops the register stack. The destination operand must be an FPU register and the source operand must be the ST0. When no operands are specified, ST1 is used as a destination operand. faddp ; add st0 to st1 and pop the stack faddp st2,st0 ; add st0 to st2 and pop the stack "fiadd" instruction converts an integer source operand into double extended precision floating-point value and adds it to the destination operand. The operand should be a 16-bit or 32-bit memory location. fiadd word [bx] ; add word integer to st0 "fsub", "fsubr", "fmul", "fdiv", "fdivr" instruction are similar to "fadd", have the same rules for operands and differ only in the perfomed computation. "fsub" subtracts the source operand from the destination operand, "fsubr" subtract the destination operand from the source operand, "fmul" multiplies the destination and source operands, "fdiv" divides the destination operand by the source operand and "fdivr" divides the source operand by the destination operand. "fsubp", "fsubrp", "fmulp", "fdivp", "fdivrp" perform the same operations and pop the register stack, the rules for operand are the same as for the "faddp" instruction. "fisub", "fisubr", "fimul", "fidiv", "fidivr" perform these operations after converting the integer source operand into floating-point value, they have the same rules for operands as "fiadd" instruction. "fsqrt" computes the square root of the value in ST0 register, "fsin" computes the sine of that value, "fcos" computes the cosine of that value, "fchs" complements its sign bit, "fabs" clears its sign to create the absolute value, "frndint" rounds it to the nearest integral value, depending on the current rounding mode. "f2xm1" computes the exponential value of 2 to the power of ST0 and subtracts the 1.0 from it, the value of ST0 must lie in the range -1.0 to +1.0. All these instructions store the result in ST0 and have no operands. "fsincos" computes both the sine and the cosine of the value in ST0 register, stores the sine in ST0 and pushes the cosine on the top of FPU register stack. "fptan" computes the tangent of the value in ST0, stores the result in ST0 and pushes a 1.0 onto the FPU register stack. "fpatan" computes the arctangent of the value in ST1 divided by the value in ST0, stores the result in ST1 and pops the FPU register stack. "fyl2x" computes the binary logarithm of ST0, multiplies it by ST1, stores the result in ST1 and pops the FPU register stack; "fyl2xp1" performs the same operation but it adds 1.0 to ST0 before computing the logarithm. "fprem" computes the remainder obtained from dividing the value in ST0 by the value in ST1, and stores the result in ST0. "fprem1" performs the same operation as "fprem", but it computes the remainder in the way specified by IEEE Standard 754. "fscale" truncates the value in ST1 and increases the exponent of ST0 by this value. "fxtract" separates the value in ST0 into its exponent and significand, stores the exponent in ST0 and pushes the significand onto the register stack. "fnop" performs no operation. These instructions have no operands. "fxch" exchanges the contents of ST0 an another FPU register. The operand should be an FPU register, if no operand is specified, the contents of ST0 and ST1 are exchanged. "fcom" and "fcomp" compare the contents of ST0 and the source operand and set flags in the FPU status word according to the results. "fcomp" additionally pops the register stack after performing the comparison. The operand can be a single or double precision value in memory or the FPU register. When no operand is specified, ST1 is used as a source operand. fcom ; compare st0 with st1 fcomp st2 ; compare st0 with st2 and pop stack "fcompp" compares the contents of ST0 and ST1, sets flags in the FPU status word according to the results and pops the register stack twice. This instruction has no operands. "fucom", "fucomp" and "fucompp" performs an unordered comparison of two FPU registers. Rules for operands are the same as for the "fcom", "fcomp" and "fcompp", but the source operand must be an FPU register. "ficom" and "ficomp" compare the value in ST0 with an integer source operand and set the flags in the FPU status word according to the results. "ficomp" additionally pops the register stack after performing the comparison. The integer value is converted to double extended precision floating-point format before the comparison is made. The operand should be a 16-bit or 32-bit memory location. ficom word [bx] ; compare st0 with 16-bit integer "fcomi", "fcomip", "fucomi", "fucomip" perform the comparison of ST0 with another FPU register and set the ZF, PF and CF flags according to the results. "fcomip" and "fucomip" additionaly pop the register stack after performing the comparison. The instructions obtained by attaching the FPU condition mnemonic (see table 2.2) to the "fcmov" mnemonic transfer the specified FPU register into ST0 register if the given test condition is true. These instructions allow two different syntaxes, one with single operand specifying the source FPU register, and one with two operands, in that case destination operand should be ST0 register and the second operand specifies the source FPU register. fcomi st2 ; compare st0 with st2 and set flags fcmovb st0,st2 ; transfer st2 to st0 if below Table 2.2 FPU conditions /------------------------------------------------------\ | Mnemonic | Condition tested | Description | |==========|==================|========================| | b | CF = 1 | below | | e | ZF = 1 | equal | | be | CF or ZF = 1 | below or equal | | u | PF = 1 | unordered | | nb | CF = 0 | not below | | ne | ZF = 0 | not equal | | nbe | CF and ZF = 0 | not below nor equal | | nu | PF = 0 | not unordered | \------------------------------------------------------/ "ftst" compares the value in ST0 with 0.0 and sets the flags in the FPU status word according to the results. "fxam" examines the contents of the ST0 and sets the flags in FPU status word to indicate the class of value in the register. These instructions have no operands. "fstsw" and "fnstsw" store the current value of the FPU status word in the destination location. The destination operand can be either a 16-bit memory or the AX register. "fstsw" checks for pending unmasked FPU exceptions before storing the status word, "fnstsw" does not. "fstcw" and "fnstcw" store the current value of the FPU control word at the specified destination in memory. "fstcw" checks for pending umasked FPU exceptions before storing the control word, "fnstcw" does not. "fldcw" loads the operand into the FPU control word. The operand should be a 16-bit memory location. "fstenv" and "fnstenv" store the current FPU operating environment at the memory location specified with the destination operand, and then mask all FPU exceptions. "fstenv" checks for pending umasked FPU exceptions before proceeding, "fnstenv" does not. "fldenv" loads the complete operating environment from memory into the FPU. "fsave" and "fnsave" store the current FPU state (operating environment and register stack) at the specified destination in memory and reinitializes the FPU. "fsave" check for pending unmasked FPU exceptions before proceeding, "fnsave" does not. "frstor" loads the FPU state from the specified memory location. All these instructions need an operand being a memory location. For each of these instructions exist two additional mnemonics that allow to precisely select the type of the operation. The "fstenvw", "fnstenvw", "fldenvw", "fsavew", "fnsavew" and "frstorw" mnemonics force the instruction to perform operation as in the 16-bit mode, while "fstenvd", "fnstenvd", "fldenvd", "fsaved", "fnsaved" and "frstord" force the operation as in 32-bit mode. "finit" and "fninit" set the FPU operating environment into its default state. "finit" checks for pending unmasked FPU exception before proceeding, "fninit" does not. "fclex" and "fnclex" clear the FPU exception flags in the FPU status word. "fclex" checks for pending unmasked FPU exception before proceeding, "fnclex" does not. "wait" and "fwait" are synonyms for the same instruction, which causes the processor to check for pending unmasked FPU exceptions and handle them before proceeding. These instructions have no operands. "ffree" sets the tag associated with specified FPU register to empty. The operand should be an FPU register. "fincstp" and "fdecstp" rotate the FPU stack by one by adding or subtracting one to the pointer of the top of stack. These instructions have no operands. 2.1.14 MMX instructions The MMX instructions operate on the packed integer types and use the MMX registers, which are the low 64-bit parts of the 80-bit FPU registers. Because of this MMX instructions cannot be used at the same time as FPU instructions. They can operate on packed bytes (eight 8-bit integers), packed words (four 16-bit integers) or packed double words (two 32-bit integers), use of packed formats allows to perform operations on multiple data at one time. "movq" copies a quad word from the source operand to the destination operand. At least one of the operands must be a MMX register, the second one can be also a MMX register or 64-bit memory location. movq mm0,mm1 ; move quad word from register to register movq mm2,[ebx] ; move quad word from memory to register "movd" copies a double word from the source operand to the destination operand. One of the operands must be a MMX register, the second one can be a general register or 32-bit memory location. Only low double word of MMX register is used. All general MMX operations have two operands, the destination operand should be a MMX register, the source operand can be a MMX register or 64-bit memory location. Operation is performed on the corresponding data elements of the source and destination operand and stored in the data elements of the destination operand. "paddb", "paddw" and "paddd" perform the addition of packed bytes, packed words, or packed double words. "psubb", "psubw" and "psubd" perform the subtraction of appropriate types. "paddsb", "paddsw", "psubsb" and "psubsw" perform the addition or subtraction of packed bytes or packed words with the signed saturation. "paddusb", "paddusw", "psubusb", "psubusw" are analoguous, but with unsigned saturation. "pmulhw" and "pmullw" performs a signed multiplication of the packed words and store the high or low words of the results in the destination operand. "pmaddwd" performs a multiply of the packed words and adds the four intermediate double word products in pairs to produce result as a packed double words. "pand", "por" and "pxor" perform the logical operations on the quad words, "pandn" peforms also a logical negation of the destination operand before performing the "and" operation. "pcmpeqb", "pcmpeqw" and "pcmpeqd" compare for equality of packed bytes, packed words or packed double words. If a pair of data elements is equal, the corresponding data element in the destination operand is filled with bits of value 1, otherwise it's set to 0. "pcmpgtb", "pcmpgtw" and "pcmpgtd" perform the similar operation, but they check whether the data elements in the destination operand are greater than the correspoding data elements in the source operand. "packsswb" converts packed signed words into packed signed bytes, "packssdw" converts packed signed double words into packed signed words, using saturation to handle overflow conditions. "packuswb" converts packed signed words into packed unsigned bytes. Converted data elements from the source operand are stored in the high part of the destination operand, while converted data elements from the destination operand are stored in the low part. "punpckhbw", "punpckhwd" and "punpckhdq" interleaves the data elements from the high parts of the source and destination operands and stores the result into the destination operand. "punpcklbw", "punpcklwd" and "punpckldq" perform the same operation, but the low parts of the source and destination operand are used. paddsb mm0,[esi] ; add packed bytes with signed saturation pcmpeqw mm3,mm7 ; compare packed words for equality "psllw", "pslld" and "psllq" perform logical shift left of the packed words, packed double words or a single quad word in the destination operand by the amount specified in the source operand. "psrlw", "psrld" and "psrlq" perform logical shift right of the packed words, packed double words or a single quad word. "psraw" and "psrad" perform arithmetic shift of the packed words or double words. The destination operand should be a MMX register, while source operand can be a MMX register, 64-bit memory location, or 8-bit immediate value. psllw mm2,mm4 ; shift words left logically psrad mm4,[ebx] ; shift double words right arithmetically "emms" makes the FPU registers usable for the FPU instructions, it must be used before using the FPU instructions if any MMX instructions were used. 2.1.15 SSE instructions The SSE extension adds more MMX instructions and also introduces the operations on packed single precision floating point values. The 128-bit packed single precision format consists of four single precision floating point values. The 128-bit SSE registers are designed for the purpose of operations on this data type. "movaps" and "movups" transfer a double quad word operand containing packed single precision values from source operand to destination operand. At least one of the operands have to be a SSE register, the second one can be also a SSE register or 128-bit memory location. Memory operands for "movaps" instruction must be aligned on boundary of 16 bytes, operands for "movups" instruction don't have to be aligned. movups xmm0,[ebx] ; move unaligned double quad word "movlps" moves packed two single precision values between the memory and the low quad word of SSE register. "movhps" moved packed two single precision values between the memory and the high quad word of SSE register. One of the operands must be a SSE register, and the other operand must be a 64-bit memory location. movlps xmm0,[ebx] ; move memory to low quad word of xmm0 movhps [esi],xmm7 ; move high quad word of xmm7 to memory "movlhps" moves packed two single precision values from the low quad word of source register to the high quad word of destination register. "movhlps" moves two packed single precision values from the high quad word of source register to the low quad word of destination register. Both operands have to be a SSE registers. "movmskps" transfers the most significant bit of each of the four single precision values in the SSE register into low four bits of a general register. The source operand must be a SSE register, the destination operand must be a general register. "movss" transfers a single precision value between source and destination operand (only the low double word is trasferred). At least one of the operands have to be a SSE register, the second one can be also a SSE register or 32-bit memory location. movss [edi],xmm3 ; move low double word of xmm3 to memory Each of the SSE arithmetic operations has two variants. When the mnemonic ends with "ps", the source operand can be a 128-bit memory location or a SSE register, the destination operand must be a SSE register and the operation is performed on packed four single precision values, for each pair of the corresponding data elements separately, the result is stored in the destination register. When the mnemonic ends with "ss", the source operand can be a 32-bit memory location or a SSE register, the destination operand must be a SSE register and the operation is performed on single precision values, only low double words of SSE registers are used in this case, the result is stored in the low double word of destination register. "addps" and "addss" add the values, "subps" and "subss" subtract the source value from destination value, "mulps" and "mulss" multiply the values, "divps" and "divss" divide the destination value by the source value, "rcpps" and "rcpss" compute the approximate reciprocal of the source value, "sqrtps" and "sqrtss" compute the square root of the source value, "rsqrtps" and "rsqrtss" compute the approximate reciprocal of square root of the source value, "maxps" and "maxss" compare the source and destination values and return the greater one, "minps" and "minss" compare the source and destination values and return the lesser one. mulss xmm0,[ebx] ; multiply single precision values addps xmm3,xmm7 ; add packed single precision values "andps", "andnps", "orps" and "xorps" perform the logical operations on packed single precision values. The source operand can be a 128-bit memory location or a SSE register, the destination operand must be a SSE register. "cmpps" compares packed single precision values and returns a mask result into the destination operand, which must be a SSE register. The source operand can be a 128-bit memory location or SSE register, the third operand must be an immediate operand selecting code of one of the eight compare conditions (table 2.3). "cmpss" performs the same operation on single precision values, only low double word of destination register is affected, in this case source operand can be a 32-bit memory location or SSE register. These two instructions have also variants with only two operands and the condition encoded within mnemonic. Their mnemonics are obtained by attaching the mnemonic from table 2.3 to the "cmp" mnemonic and then attaching the "ps" or "ss" at the end. cmpps xmm2,xmm4,0 ; compare packed single precision values cmpltss xmm0,[ebx] ; compare single precision values Table 2.3 SSE conditions /-------------------------------------------\ | Code | Mnemonic | Description | |======|==========|=========================| | 0 | eq | equal | | 1 | lt | less than | | 2 | le | less than or equal | | 3 | unord | unordered | | 4 | neq | not equal | | 5 | nlt | not less than | | 6 | nle | not less than nor equal | | 7 | ord | ordered | \-------------------------------------------/ "comiss" and "ucomiss" compare the single precision values and set the ZF, PF and CF flags to show the result. The destination operand must be a SSE register, the source operand can be a 32-bit memory location or SSE register. "shufps" moves any two of the four single precision values from the destination operand into the low quad word of the destination operand, and any two of the four values from the source operand into the high quad word of the destination operand. The destination operand must be a SSE register, the source operand can be a 128-bit memory location or SSE register, the third operand must be an 8-bit immediate value selecting which values will be moved into the destination operand. Bits 0 and 1 select the value to be moved from destination operand to the low double word of the result, bits 2 and 3 select the value to be moved from the destination operand to the second double word, bits 4 and 5 select the value to be moved from the source operand to the third double word, and bits 6 and 7 select the value to be moved from the source operand to the high double word of the result. shufps xmm0,xmm0,10010011b ; shuffle double words "unpckhps" performs an interleaved unpack of the values from the high parts of the source and destination operands and stores the result in the destination operand, which must be a SSE register. The source operand can be a 128-bit memory location or a SSE register. "unpcklps" performs an interleaved unpack of the values from the low parts of the source and destination operand and stores the result in the destination operand, the rules for operands are the same. "cvtpi2ps" converts packed two double word integers into the the packed two single precision floating point values and stores the result in the low quad word of the destination operand, which should be a SSE register. The source operand can be a 64-bit memory location or MMX register. cvtpi2ps xmm0,mm0 ; convert integers to single precision values "cvtsi2ss" converts a double word integer into a single precision floating point value and stores the result in the low double word of the destination operand, which should be a SSE register. The source operand can be a 32-bit memory location or 32-bit general register. cvtsi2ss xmm0,eax ; convert integer to single precision value "cvtps2pi" converts packed two single precision floating point values into packed two double word integers and stores the result in the destination operand, which should be a MMX register. The source operand can be a 64-bit memory location or SSE register, only low quad word of SSE register is used. "cvttps2pi" performs the similar operation, except that truncation is used to round a source values to integers, rules for the operands are the same. cvtps2pi mm0,xmm0 ; convert single precision values to integers "cvtss2si" convert a single precision floating point value into a double word integer and stores the result in the destination operand, which should be a 32-bit general register. The source operand can be a 32-bit memory location or SSE register, only low double word of SSE register is used. "cvttss2si" performs the similar operation, except that truncation is used to round a source value to integer, rules for the operands are the same. cvtss2si eax,xmm0 ; convert single precision value to integer "pextrw" copies the word in the source operand specified by the third operand to the destination operand. The source operand must be a MMX register, the destination operand must be a 32-bit general register (the high word of the destination is cleared), the third operand must an 8-bit immediate value. pextrw eax,mm0,1 ; extract word into eax "pinsrw" inserts a word from the source operand in the destination operand at the location specified with the third operand, which must be an 8-bit immediate value. The destination operand must be a MMX register, the source operand can be a 16-bit memory location or 32-bit general register (only low word of the register is used). pinsrw mm1,ebx,2 ; insert word from ebx "pavgb" and "pavgw" compute average of packed bytes or words. "pmaxub" return the maximum values of packed unsigned bytes, "pminub" returns the minimum values of packed unsigned bytes, "pmaxsw" returns the maximum values of packed signed words, "pminsw" returns the minimum values of packed signed words. "pmulhuw" performs a unsigned multiplication of the packed words and stores the high words of the results in the destination operand. "psadbw" computes the absolute differences of packed unsigned bytes, sums the differences, and stores the sum in the low word of destination operand. All these instructions follow the same rules for operands as the general MMX operations described in previous section. "pmovmskb" creates a mask made of the most significant bit of each byte in the source operand and stores the result in the low byte of destination operand. The source operand must be a MMX register, the destination operand must a 32-bit general register. "pshufw" inserts words from the source operand in the destination operand from the locations specified with the third operand. The destination operand must be a MMX register, the source operand can be a 64-bit memory location or MMX register, third operand must an 8-bit immediate value selecting which values will be moved into destination operand, in the similar way as the third operand of the "shufps" instruction. "movntq" moves the quad word from the source operand to memory using a non-temporal hint to minimize cache pollution. The source operand should be a MMX register, the destination operand should be a 64-bit memory location. "movntps" stores packed single precision values from the SSE register to memory using a non-temporal hint. The source operand should be a SSE register, the destination operand should be a 128-bit memory location. "maskmovq" stores selected bytes from the first operand into a 64-bit memory location using a non-temporal hint. Both operands should be a MMX registers, the second operand selects wich bytes from the source operand are written to memory. The memory location is pointed by DI (or EDI) register in the segment selected by DS. "prefetcht0", "prefetcht1", "prefetcht2" and "prefetchnta" fetch the line of data from memory that contains byte specified with the operand to a specified location in hierarchy. The operand should be an 8-bit memory location. "sfence" performs a serializing operation on all instruction storing to memory that were issued prior to it. This instruction has no operands. "ldmxcsr" loads the 32-bit memory operand into the MXCSR register. "stmxcsr" stores the contents of MXCSR into a 32-bit memory operand. "fxsave" saves the current state of the FPU, MXCSR register, and all the FPU and SSE registers to a 512-byte memory location specified in the destination operand. "fxrstor" reloads data previously stored with "fxsave" instruction from the specified 512-byte memory location. The memory operand for both those instructions must be aligned on 16 byte boundary, it should declare operand of no specified size. 2.1.16 SSE2 instructions The SSE2 extension introduces the operations on packed double precision floating point values, extends the syntax of MMX instructions, and adds also some new instructions. "movapd" and "movupd" transfer a double quad word operand containing packed double precision values from source operand to destination operand. These instructions are analogous to "movaps" and "movups" and have the same rules for operands. "movlpd" moves double precision value between the memory and the low quad word of SSE register. "movhpd" moved double precision value between the memory and the high quad word of SSE register. These instructions are analogous to "movlps" and "movhps" and have the same rules for operands. "movmskpd" transfers the most significant bit of each of the two double precision values in the SSE register into low two bits of a general register. This instruction is analogous to "movmskps" and has the same rules for operands. "movsd" transfers a double precision value between source and destination operand (only the low quad word is trasferred). At least one of the operands have to be a SSE register, the second one can be also a SSE register or 64-bit memory location. Arithmetic operations on double precision values are: "addpd", "addsd", "subpd", "subsd", "mulpd", "mulsd", "divpd", "divsd", "sqrtpd", "sqrtsd", "maxpd", "maxsd", "minpd", "minsd", and they are analoguous to arithmetic operations on single precision values described in previous section. When the mnemonic ends with "pd" instead of "ps", the operation is performed on packed two double precision values, but rules for operands are the same. When the mnemonic ends with "sd" instead of "ss", the source operand can be a 64-bit memory location or a SSE register, the destination operand must be a SSE register and the operation is performed on double precision values, only low quad words of SSE registers are used in this case. "andpd", "andnpd", "orpd" and "xorpd" perform the logical operations on packed double precision values. They are analoguous to SSE logical operations on single prevision values and have the same rules for operands. "cmppd" compares packed double precision values and returns and returns a mask result into the destination operand. This instruction is analoguous to "cmpps" and has the same rules for operands. "cmpsd" performs the same operation on double precision values, only low quad word of destination register is affected, in this case source operand can be a 64-bit memory or SSE register. Variant with only two operands are obtained by attaching the condition mnemonic from table 2.3 to the "cmp" mnemonic and then attaching the "pd" or "sd" at the end. "comisd" and "ucomisd" compare the double precision values and set the ZF, PF and CF flags to show the result. The destination operand must be a SSE register, the source operand can be a 128-bit memory location or SSE register. "shufpd" moves any of the two double precision values from the destination operand into the low quad word of the destination operand, and any of the two values from the source operand into the high quad word of the destination operand. This instruction is analoguous to "shufps" and has the same rules for operand. Bit 0 of the third operand selects the value to be moved from the destination operand, bit 1 selects the value to be moved from the source operand, the rest of bits are reserved and must be zeroed. "unpckhpd" performs an unpack of the high quad words from the source and destination operands, "unpcklpd" performs an unpack of the low quad words from the source and destination operands. They are analoguous to "unpckhps" and "unpcklps", and have the same rules for operands. "cvtps2pd" converts the packed two single precision floating point values to two packed double precision floating point values, the destination operand must be a SSE register, the source operand can be a 64-bit memory location or SSE register. "cvtpd2ps" converts the packed two double precision floating point values to packed two single precision floating point values, the destination operand must be a SSE register, the source operand can be a 128-bit memory location or SSE register. "cvtss2sd" converts the single precision floating point value to double precision floating point value, the destination operand must be a SSE register, the source operand can be a 32-bit memory location or SSE register. "cvtsd2ss" converts the double precision floating point value to single precision floating point value, the destination operand must be a SSE register, the source operand can be 64-bit memory location or SSE register. "cvtpi2pd" converts packed two double word integers into the the packed double precision floating point values, the destination operand must be a SSE register, the source operand can be a 64-bit memory location or MMX register. "cvtsi2sd" converts a double word integer into a double precision floating point value, the destination operand must be a SSE register, the source operand can be a 32-bit memory location or 32-bit general register. "cvtpd2pi" converts packed double precision floating point values into packed two double word integers, the destination operand should be a MMX register, the source operand can be a 128-bit memory location or SSE register. "cvttpd2pi" performs the similar operation, except that truncation is used to round a source values to integers, rules for operands are the same. "cvtsd2si" converts a double precision floating point value into a double word integer, the destination operand should be a 32-bit general register, the source operand can be a 64-bit memory location or SSE register. "cvttsd2si" performs the similar operation, except that truncation is used to round a source value to integer, rules for operands are the same. "cvtps2dq" and "cvttps2dq" convert packed single precision floating point values to packed four double word integers, storing them in the destination operand. "cvtpd2dq" and "cvttpd2dq" convert packed double precision floating point values to packed two double word integers, storing the result in the low quad word of the destination operand. "cvtdq2ps" converts packed four double word integers to packed single precision floating point values. For all these instructions destination operand must be a SSE register, the source operand can be a 128-bit memory location or SSE register. "cvtdq2pd" converts packed two double word integers from the source operand to packed double precision floating point values, the source can be a 64-bit memory location or SSE register, destination has to be SSE register. "movdqa" and "movdqu" transfer a double quad word operand containing packed integers from source operand to destination operand. At least one of the operands have to be a SSE register, the second one can be also a SSE register or 128-bit memory location. Memory operands for "movdqa" instruction must be aligned on boundary of 16 bytes, operands for "movdqu" instruction don't have to be aligned. "movq2dq" moves the contents of the MMX source register to the low quad word of destination SSE register. "movdq2q" moves the low quad word from the source SSE register to the destination MMX register. movq2dq xmm0,mm1 ; move from MMX register to SSE register movdq2q mm0,xmm1 ; move from SSE register to MMX register All MMX instructions operating on the 64-bit packed integers (those with mnemonics starting with "p") are extended to operate on 128-bit packed integers located in SSE registers. Additional syntax for these instructions needs an SSE register where MMX register was needed, and the 128-bit memory location or SSE register where 64-bit memory location or MMX register were needed. The exception is "pshufw" instruction, which doesn't allow extended syntax, but has two new variants: "pshufhw" and "pshuflw", which allow only the extended syntax, and perform the same operation as "pshufw" on the high or low quad words of operands respectively. Also the new instruction "pshufd" is introduced, which performs the same operation as "pshufw", but on the double words instead of words, it allows only the extended syntax. psubb xmm0,[esi] ; subtract 16 packed bytes pextrw eax,xmm0,7 ; extract highest word into eax "paddq" performs the addition of packed quad words, "psubq" performs the subtraction of packed quad words, "pmuludq" performs an unsigned multiplication of low double words from each corresponding quad words and returns the results in packed quad words. These instructions follow the same rules for operands as the general MMX operations described in 2.1.14. "pslldq" and "psrldq" perform logical shift left or right of the double quad word in the destination operand by the amount of bytes specified in the source operand. The destination operand should be a SSE register, source operand should be an 8-bit immediate value. "punpckhqdq" interleaves the high quad word of the source operand and the high quad word of the destination operand and writes them to the destination SSE register. "punpcklqdq" interleaves the low quad word of the source operand and the low quad word of the destination operand and writes them to the destination SSE register. The source operand can be a 128-bit memory location or SSE register. "movntdq" stores packed integer data from the SSE register to memory using non-temporal hint. The source operand should be a SSE register, the destination operand should be a 128-bit memory location. "movntpd" stores packed double precision values from the SSE register to memory using a non-temporal hint. Rules for operand are the same. "movnti" stores integer from a general register to memory using a non-temporal hint. The source operand should be a 32-bit general register, the destination operand should be a 32-bit memory location. "maskmovdqu" stores selected bytes from the first operand into a 128-bit memory location using a non-temporal hint. Both operands should be a SSE registers, the second operand selects wich bytes from the source operand are written to memory. The memory location is pointed by DI (or EDI) register in the segment selected by DS and does not need to be aligned. "clflush" writes and invalidates the cache line associated with the address of byte specified with the operand, which should be a 8-bit memory location. "lfence" performs a serializing operation on all instruction loading from memory that were issued prior to it. "mfence" performs a serializing operation on all instruction accesing memory that were issued prior to it, and so it combines the functions of "sfence" (described in previous section) and "lfence" instructions. These instructions have no operands. 2.1.17 SSE3 instructions Prescott technology introduced some new instructions to improve the performance of SSE and SSE2 - this extension is called SSE3. "fisttp" behaves like the "fistp" instruction and accepts the same operands, the only difference is that it always used truncation, irrespective of the rounding mode. "movshdup" loads into destination operand the 128-bit value obtained from the source value of the same size by filling the each quad word with the two duplicates of the value in its high double word. "movsldup" performs the same action, except it duplicates the values of low double words. The destination operand should be SSE register, the source operand can be SSE register or 128-bit memory location. "movddup" loads the 64-bit source value and duplicates it into high and low quad word of the destination operand. The destination operand should be SSE register, the source operand can be SSE register or 64-bit memory location. "lddqu" is functionally equivalent to "movdqu" with memory as source operand, but it may improve performance when the source operand crosses a cacheline boundary. The destination operand has to be SSE register, the source operand must be 128-bit memory location. "addsubps" performs single precision addition of second and fourth pairs and single precision subtracion of the first and third pairs of floating point values in the operands. "addsubpd" performs double precision addition of the second pair and double precision subtraction of the first pair of floating point values in the operand. "haddps" performs the addition of two single precision values within the each quad word of source and destination operands, and stores the results of such horizontal addition of values from destination operand into low quad word of destination operand, and the results from the source operand into high quad word of destination operand. "haddpd" performs the addition of two double precision values within each operand, and stores the result from destination operand into low quad word of destination operand, and the result from source operand into high quad word of destination operand. All these instructions need the destination operand to be SSE register, source operand can be SSE register or 128-bit memory location. "monitor" sets up an address range for monitoring of write-back stores. It need its three operands to be EAX, ECX and EDX register in that order. "mwait" waits for a write-back store to the address range set up by the "monitor" instruction. It uses two operands with additional parameters, first being the EAX and second the ECX register. The functionality of SSE3 is further extended by the set of Supplemental SSE3 instructions (SSSE3). They generally follow the same rules for operands as all the MMX operations extended by SSE. "phaddw" and "phaddd" perform the horizontal additional of the pairs of adjacent values from both the source and destination operand, and stores the sums into the destination (sums from the source operand go into higher part of destination register). They operate on 16-bit or 32-bit chunks, respectively. "phaddsw" performs the same operation on signed 16-bit packed values, but the result of each addition is saturated. "phsubw" and "phsubd" analogously perform the horizontal subtraction of 16-bit or 32-bit packed value, and "phsubsw" performs the horizontal subtraction of signed 16-bit packed values with saturation. "pabsb", "pabsw" and "pabsd" calculate the absolute value of each signed packed signed value in source operand and stores them into the destination register. They operator on 8-bit, 16-bit and 32-bit elements respectively. "pmaddubsw" multiplies signed 8-bit values from the source operand with the corresponding unsigned 8-bit values from the destination operand to produce intermediate 16-bit values, and every adjacent pair of those intermediate values is then added horizontally and those 16-bit sums are stored into the destination operand. "pmulhrsw" multiplies corresponding 16-bit integers from the source and destination operand to produce intermediate 32-bit values, and the 16 bits next to the highest bit of each of those values are then rounded and packed into the destination operand. "pshufb" shuffles the bytes in the destination operand according to the mask provided by source operand - each of the bytes in source operand is an index of the target position for the corresponding byte in the destination. "psignb", "psignw" and "psignd" perform the operation on 8-bit, 16-bit or 32-bit integers in destination operand, depending on the signs of the values in the source. If the value in source is negative, the corresponding value in the destination register is negated, if the value in source is positive, no operation is performed on the corresponding value is performed, and if the value in source is zero, the value in destination is zeroed, too. "palignr" appends the source operand to the destination operand to form the intermediate value of twice the size, and then extracts into the destination register the 64 or 128 bits that are right-aligned to the byte offset specified by the third operand, which should be an 8-bit immediate value. This is the only SSSE3 instruction that takes three arguments. 2.1.18 AMD 3DNow! instructions The 3DNow! extension adds a new MMX instructions to those described in 2.1.14, and introduces operation on the 64-bit packed floating point values, each consisting of two single precision floating point values. These instructions follow the same rules as the general MMX operations, the destination operand should be a MMX register, the source operand can be a MMX register or 64-bit memory location. "pavgusb" computes the rounded averages of packed unsigned bytes. "pmulhrw" performs a signed multiplication of the packed words, round the high word of each double word results and stores them in the destination operand. "pi2fd" converts packed double word integers into packed floating point values. "pf2id" converts packed floating point values into packed double word integers using truncation. "pi2fw" converts packed word integers into packed floating point values, only low words of each double word in source operand are used. "pf2iw" converts packed floating point values to packed word integers, results are extended to double words using the sign extension. "pfadd" adds packed floating point values. "pfsub" and "pfsubr" subtracts packed floating point values, the first one subtracts source values from destination values, the second one subtracts destination values from the source values. "pfmul" multiplies packed floating point values. "pfacc" adds the low and high floating point values of the destination operand, storing the result in the low double word of destination, and adds the low and high floating point values of the source operand, storing the result in the high double word of destination. "pfnacc" subtracts the high floating point value of the destination operand from the low, storing the result in the low double word of destination, and subtracts the high floating point value of the source operand from the low, storing the result in the high double word of destination. "pfpnacc" subtracts the high floating point value of the destination operand from the low, storing the result in the low double word of destination, and adds the low and high floating point values of the source operand, storing the result in the high double word of destination. "pfmax" and "pfmin" compute the maximum and minimum of floating point values. "pswapd" reverses the high and low double word of the source operand. "pfrcp" returns an estimates of the reciprocals of floating point values from the source operand, "pfrsqrt" returns an estimates of the reciprocal square roots of floating point values from the source operand, "pfrcpit1" performs the first step in the Newton-Raphson iteration to refine the reciprocal approximation produced by "pfrcp" instruction, "pfrsqit1" performs the first step in the Newton-Raphson iteration to refine the reciprocal square root approximation produced by "pfrsqrt" instruction, "pfrcpit2" performs the second final step in the Newton-Raphson iteration to refine the reciprocal approximation or the reciprocal square root approximation. "pfcmpeq", "pfcmpge" and "pfcmpgt" compare the packed floating point values and sets all bits or zeroes all bits of the correspoding data element in the destination operand according to the result of comparison, first checks whether values are equal, second checks whether destination value is greater or equal to source value, third checks whether destination value is greater than source value. "prefetch" and "prefetchw" load the line of data from memory that contains byte specified with the operand into the data cache, "prefetchw" instruction should be used when the data in the cache line is expected to be modified, otherwise the "prefetch" instruction should be used. The operand should be an 8-bit memory location. "femms" performs a fast clear of MMX state. This instruction has no operands. 2.1.19 The x86-64 long mode instructions The AMD64 and EM64T architectures (we will use the common name x86-64 for them both) extend the x86 instruction set for the 64-bit processing. While legacy and compatibility modes use the same set of registers and instructions, the new long mode extends the x86 operations to 64 bits and introduces several new registers. You can turn on generating the code for this mode with the "use64" directive. Each of the general purpose registers is extended to 64 bits and the eight whole new general purpose registers and also eight new SSE registers are added. See table 2.4 for the summary of new registers (only the ones that was not listed in table 1.2). The general purpose registers of smallers sizes are the low order portions of the larger ones. You can still access the "ah", "bh", "ch" and "dh" registers in long mode, but you cannot use them in the same instruction with any of the new registers. Table 2.4 New registers in long mode /--------------------------------------------------\ | Type | General | SSE | AVX | |------|---------------------------|-------|-------| | Bits | 8 | 16 | 32 | 64 | 128 | 256 | |======|======|======|======|======|=======|=======| | | | | | rax | | | | | | | | rcx | | | | | | | | rdx | | | | | | | | rbx | | | | | spl | | | rsp | | | | | bpl | | | rbp | | | | | sil | | | rsi | | | | | dil | | | rdi | | | | | r8b | r8w | r8d | r8 | xmm8 | ymm8 | | | r9b | r9w | r9d | r9 | xmm9 | ymm9 | | | r10b | r10w | r10d | r10 | xmm10 | ymm10 | | | r11b | r11w | r11d | r11 | xmm11 | ymm11 | | | r12b | r12w | r12d | r12 | xmm12 | ymm12 | | | r13b | r13w | r13d | r13 | xmm13 | ymm13 | | | r14b | r14w | r14d | r14 | xmm14 | ymm14 | | | r15b | r15w | r15d | r15 | xmm15 | ymm15 | \--------------------------------------------------/ In general any instruction from x86 architecture, which allowed 16-bit or 32-bit operand sizes, in long mode allows also the 64-bit operands. The 64-bit registers should be used for addressing in long mode, the 32-bit addressing is also allowed, but it's not possible to use the addresses based on 16-bit registers. Below are the samples of new operations possible in long mode on the example of "mov" instruction: mov rax,r8 ; transfer 64-bit general register mov al,[rbx] ; transfer memory addressed by 64-bit register The long mode uses also the instruction pointer based addresses, you can specify it manually with the special RIP register symbol, but such addressing is also automatically generated by flat assembler, since there is no 64-bit absolute addressing in long mode. You can still force the assembler to use the 32-bit absolute addressing by putting the "dword" size override for address inside the square brackets. There is also one exception, where the 64-bit absolute addressing is possible, it's the "mov" instruction with one of the operand being accumulator register, and second being the memory operand. To force the assembler to use the 64-bit absolute addressing there, use the "qword" size operator for address inside the square brackets. When no size operator is applied to address, assembler generates the optimal form automatically. mov [qword 0],rax ; absolute 64-bit addressing mov [dword 0],r15d ; absolute 32-bit addressing mov [0],rsi ; automatic RIP-relative addressing mov [rip+3],sil ; manual RIP-relative addressing Also as the immediate operands for 64-bit operations only the signed 32-bit values are possible, with the only exception being the "mov" instruction with destination operand being 64-bit general purpose register. Trying to force the 64-bit immediate with any other instruction will cause an error. If any operation is performed on the 32-bit general registers in long mode, the upper 32 bits of the 64-bit registers containing them are filled with zeros. This is unlike the operations on 16-bit or 8-bit portions of those registers, which preserve the upper bits. Three new type conversion instructions are available. The "cdqe" sign extends the double word in EAX into quad word and stores the result in RAX register. "cqo" sign extends the quad word in RAX into double quad word and stores the extra bits in the RDX register. These instructions have no operands. "movsxd" sign extends the double word source operand, being either the 32-bit register or memory, into 64-bit destination operand, which has to be register. No analogous instruction is needed for the zero extension, since it is done automatically by any operations on 32-bit registers, as noted in previous paragraph. And the "movzx" and "movsx" instructions, conforming to the general rule, can be used with 64-bit destination operand, allowing extension of byte or word values into quad words. All the binary arithmetic and logical instruction have been promoted to allow 64-bit operands in long mode. The use of decimal arithmetic instructions in long mode is prohibited. The stack operations, like "push" and "pop" in long mode default to 64-bit operands and it's not possible to use 32-bit operands with them. The "pusha" and "popa" are disallowed in long mode. The indirect near jumps and calls in long mode default to 64-bit operands and it's not possible to use the 32-bit operands with them. On the other hand, the indirect far jumps and calls allow any operands that were allowed by the x86 architecture and also 80-bit memory operand is allowed (though only EM64T seems to implement such variant), with the first eight bytes defining the offset and two last bytes specifying the selector. The direct far jumps and calls are not allowed in long mode. The I/O instructions, "in", "out", "ins" and "outs" are the exceptional instructions that are not extended to accept quad word operands in long mode. But all other string operations are, and there are new short forms "movsq", "cmpsq", "scasq", "lodsq" and "stosq" introduced for the variants of string operations for 64-bit string elements. The RSI and RDI registers are used by default to address the string elements. The "lfs", "lgs" and "lss" instructions are extended to accept 80-bit source memory operand with 64-bit destination register (though only EM64T seems to implement such variant). The "lds" and "les" are disallowed in long mode. The system instructions like "lgdt" which required the 48-bit memory operand, in long mode require the 80-bit memory operand. The "cmpxchg16b" is the 64-bit equivalent of "cmpxchg8b" instruction, it uses the double quad word memory operand and 64-bit registers to perform the analoguous operation. The "fxsave64" and "fxrstor64" are new variants of "fxsave" and "fxrstor" instructions, available only in long mode, which use a different format of storage area in order to store some pointers in full 64-bit size. "swapgs" is the new instruction, which swaps the contents of GS register and the KernelGSbase model-specific register (MSR address 0C0000102h). "syscall" and "sysret" is the pair of new instructions that provide the functionality similar to "sysenter" and "sysexit" in long mode, where the latter pair is disallowed. The "sysexitq" and "sysretq" mnemonics provide the 64-bit versions of "sysexit" and "sysret" instructions. The "rdmsrq" and "wrmsrq" mnemonics are the 64-bit variants of the "rdmsr" and "wrmsr" instructions. 2.1.20 SSE4 instructions There are actually three different sets of instructions under the name SSE4. Intel designed two of them, SSE4.1 and SSE4.2, with latter extending the former into the full Intel's SSE4 set. On the other hand, the implementation by AMD includes only a few instructions from this set, but also contains some additional instructions, that are called the SSE4a set. The SSE4.1 instructions mostly follow the same rules for operands, as the basic SSE operations, so they require destination operand to be SSE register and source operand to be 128-bit memory location or SSE register, and some operations require a third operand, the 8-bit immediate value. "pmulld" performs a signed multiplication of the packed double words and stores the low double words of the results in the destination operand. "pmuldq" performs a two signed multiplications of the corresponding double words in the lower quad words of operands, and stores the results as packed quad words into the destination register. "pminsb" and "pmaxsb" return the minimum or maximum values of packed signed bytes, "pminuw" and "pmaxuw" return the minimum and maximum values of packed unsigned words, "pminud", "pmaxud", "pminsd" and "pmaxsd" return minimum or maximum values of packed unsigned or signed double words. These instructions complement the instructions computing packed minimum or maximum introduced by SSE. "ptest" sets the ZF flag to one when the result of bitwise AND of the both operands is zero, and zeroes the ZF otherwise. It also sets CF flag to one, when the result of bitwise AND of the destination operand with the bitwise NOT of the source operand is zero, and zeroes the CF otherwise. "pcmpeqq" compares packed quad words for equality, and fills the corresponding elements of destination operand with either ones or zeros, depending on the result of comparison. "packusdw" converts packed signed double words from both the source and destination operand into the unsigned words using saturation, and stores the eight resulting word values into the destination register. "phminposuw" finds the minimum unsigned word value in source operand and places it into the lowest word of destination operand, setting the remaining upper bits of destination to zero. "roundps", "roundss", "roundpd" and "roundsd" perform the rounding of packed or individual floating point value of single or double precision, using the rounding mode specified by the third operand. roundsd xmm0,xmm1,0011b ; round toward zero "dpps" calculates dot product of packed single precision floating point values, that is it multiplies the corresponding pairs of values from source and destination operand and then sums the products up. The high four bits of the 8-bit immediate third operand control which products are calculated and taken to the sum, and the low four bits control, into which elements of destination the resulting dot product is copied (the other elements are filled with zero). "dppd" calculates dot product of packed double precision floating point values. The bits 4 and 5 of third operand control, which products are calculated and added, and bits 0 and 1 of this value control, which elements in destination register should get filled with the result. "mpsadbw" calculates multiple sums of absolute differences of unsigned bytes. The third operand controls, with value in bits 0-1, which of the four-byte blocks in source operand is taken to calculate the absolute differencies, and with value in bit 2, at which of the two first four-byte block in destination operand start calculating multiple sums. The sum is calculated from four absolute differencies between the corresponding unsigned bytes in the source and destination block, and each next sum is calculated in the same way, but taking the four bytes from destination at the position one byte after the position of previous block. The four bytes from the source stay the same each time. This way eight sums of absolute differencies are calculated and stored as packed word values into the destination operand. The instructions described in this paragraph follow the same rules for operands, as "roundps" instruction. "blendps", "blendvps", "blendpd" and "blendvpd" conditionally copy the values from source operand into the destination operand, depending on the bits of the mask provided by third operand. If a mask bit is set, the corresponding element of source is copied into the same place in destination, otherwise this position is destination is left unchanged. The rules for the first two operands are the same, as for general SSE instructions. "blendps" and "blendpd" need third operand to be 8-bit immediate, and they operate on single or double precision values, respectively. "blendvps" and "blendvpd" require third operand to be the XMM0 register. blendvps xmm3,xmm7,xmm0 ; blend according to mask "pblendw" conditionally copies word elements from the source operand into the destination, depending on the bits of mask provided by third operand, which needs to be 8-bit immediate value. "pblendvb" conditionally copies byte elements from the source operands into destination, depending on mask defined by the third operand, which has to be XMM0 register. These instructions follow the same rules for operands as "blendps" and "blendvps" instructions, respectively. "insertps" inserts a single precision floating point value taken from the position in source operand specified by bits 6-7 of third operand into location in destination register selected by bits 4-5 of third operand. Additionally, the low four bits of third operand control, which elements in destination register will be set to zero. The first two operands follow the same rules as for the general SSE operation, the third operand should be 8-bit immediate. "extractps" extracts a single precision floating point value taken from the location in source operand specified by low two bits of third operand, and stores it into the destination operand. The destination can be a 32-bit memory value or general purpose register, the source operand must be SSE register, and the third operand should be 8-bit immediate value. extractps edx,xmm3,3 ; extract the highest value "pinsrb", "pinsrd" and "pinsrq" copy a byte, double word or quad word from the source operand into the location of destination operand determined by the third operand. The destination operand has to be SSE register, the source operand can be a memory location of appropriate size, or the 32-bit general purpose register (but 64-bit general purpose register for "pinsrq", which is only available in long mode), and the third operand has to be 8-bit immediate value. These instructions complement the "pinsrw" instruction operating on SSE register destination, which was introduced by SSE2. pinsrd xmm4,eax,1 ; insert double word into second position "pextrb", "pextrw", "pextrd" and "pextrq" copy a byte, word, double word or quad word from the location in source operand specified by third operand, into the destination. The source operand should be SSE register, the third operand should be 8-bit immediate, and the destination operand can be memory location of appropriate size, or the 32-bit general purpose register (but 64-bit general purpose register for "pextrq", which is only available in long mode). The "pextrw" instruction with SSE register as source was already introduced by SSE2, but SSE4 extends it to allow memory operand as destination. pextrw [ebx],xmm3,7 ; extract highest word into memory "pmovsxbw" and "pmovzxbw" perform sign extension or zero extension of eight byte values from the source operand into packed word values in destination operand, which has to be SSE register. The source can be 64-bit memory or SSE register - when it is register, only its low portion is used. "pmovsxbd" and "pmovzxbd" perform sign extension or zero extension of the four byte values from the source operand into packed double word values in destination operand, the source can be 32-bit memory or SSE register. "pmovsxbq" and "pmovzxbq" perform sign extension or zero extension of the two byte values from the source operand into packed quad word values in destination operand, the source can be 16-bit memory or SSE register. "pmovsxwd" and "pmovzxwd" perform sign extension or zero extension of the four word values from the source operand into packed double words in destination operand, the source can be 64-bit memory or SSE register. "pmovsxwq" and "pmovzxwq" perform sign extension or zero extension of the two word values from the source operand into packed quad words in destination operand, the source can be 32-bit memory or SSE register. "pmovsxdq" and "pmovzxdq" perform sign extension or zero extension of the two double word values from the source operand into packed quad words in destination operand, the source can be 64-bit memory or SSE register. pmovzxbq xmm0,word [si] ; zero-extend bytes to quad words pmovsxwq xmm0,xmm1 ; sign-extend words to quad words "movntdqa" loads double quad word from the source operand to the destination using a non-temporal hint. The destination operand should be SSE register, and the source operand should be 128-bit memory location. The SSE4.2, described below, adds not only some new operations on SSE registers, but also introduces some completely new instructions operating on general purpose registers only. "pcmpistri" compares two zero-ended (implicit length) strings provided in its source and destination operand and generates an index stored to ECX; "pcmpistrm" performs the same comparison and generates a mask stored to XMM0. "pcmpestri" compares two strings of explicit lengths, with length provided in EAX for the destination operand and in EDX for the source operand, and generates an index stored to ECX; "pcmpestrm" performs the same comparision and generates a mask stored to XMM0. The source and destination operand follow the same rules as for general SSE instructions, the third operand should be 8-bit immediate value determining the details of performed operation - refer to Intel documentation for information on those details. "pcmpgtq" compares packed quad words, and fills the corresponding elements of destination operand with either ones or zeros, depending on whether the value in destination is greater than the one in source, or not. This instruction follows the same rules for operands as "pcmpeqq". "crc32" accumulates a CRC32 value for the source operand starting with initial value provided by destination operand, and stores the result in destination. Unless in long mode, the destination operand should be a 32-bit general purpose register, and the source operand can be a byte, word, or double word register or memory location. In long mode the destination operand can also be a 64-bit general purpose register, and the source operand in such case can be a byte or quad word register or memory location. crc32 eax,dl ; accumulate CRC32 on byte value crc32 eax,word [ebx] ; accumulate CRC32 on word value crc32 rax,qword [rbx] ; accumulate CRC32 on quad word value "popcnt" calculates the number of bits set in the source operand, which can be 16-bit, 32-bit, or 64-bit general purpose register or memory location, and stores this count in the destination operand, which has to be register of the same size as source operand. The 64-bit variant is available only in long mode. popcnt ecx,eax ; count bits set to 1 The SSE4a extension, which also includes the "popcnt" instruction introduced by SSE4.2, at the same time adds the "lzcnt" instruction, which follows the same syntax, and calculates the count of leading zero bits in source operand (if the source operand is all zero bits, the total number of bits in source operand is stored in destination). "extrq" extract the sequence of bits from the low quad word of SSE register provided as first operand and stores them at the low end of this register, filling the remaining bits in the low quad word with zeros. The position of bit string and its length can either be provided with two 8-bit immediate values as second and third operand, or by SSE register as second operand (and there is no third operand in such case), which should contain position value in bits 8-13 and length of bit string in bits 0-5. extrq xmm0,8,7 ; extract 8 bits from position 7 extrq xmm0,xmm5 ; extract bits defined by register "insertq" writes the sequence of bits from the low quad word of the source operand into specified position in low quad word of the destination operand, leaving the other bits in low quad word of destination intact. The position where bits should be written and the length of bit string can either be provided with two 8-bit immediate values as third and fourth operand, or by the bit fields in source operand (and there are only two operands in such case), which should contain position value in bits 72-77 and length of bit string in bits 64-69. insertq xmm1,xmm0,4,2 ; insert 4 bits at position 2 insertq xmm1,xmm0 ; insert bits defined by register "movntss" and "movntsd" store single or double precision floating point value from the source SSE register into 32-bit or 64-bit destination memory location respectively, using non-temporal hint. 2.1.21 AVX instructions The Advanced Vector Extensions introduce instructions that are new variants of SSE instructions, with new scheme of encoding that allows extended syntax having a destination operand separate from all the source operands. It also introduces 256-bit AVX registers, which extend up the old 128-bit SSE registers. Any AVX instruction that puts some result into SSE register, puts zero bits into high portion of the AVX register containing it. The AVX version of SSE instruction has the mnemonic obtained by prepending SSE instruction name with "v". For any SSE arithmetic instruction which had a destination operand also being used as one of the source values, the AVX variant has a new syntax with three operands - the destination and two sources. The destination and first source can be SSE registers, and second source can be SSE register or memory. If the operation is performed on single pair of values, the remaining bits of first source SSE register are copied into the the destination register. vsubss xmm0,xmm2,xmm3 ; subtract two 32-bit floats vmulsd xmm0,xmm7,qword [esi] ; multiply two 64-bit floats In case of packed operations, each instruction can also operate on the 256-bit data size when the AVX registers are specified instead of SSE registers, and the size of memory operand is also doubled then. vaddps ymm1,ymm5,yword [esi] ; eight sums of 32-bit float pairs The instructions that operate on packed integer types (in particular the ones that earlier had been promoted from MMX to SSE) also acquired the new syntax with three operands, however they are only allowed to operate on 128-bit packed types and thus cannot use the whole AVX registers. vpavgw xmm3,xmm0,xmm2 ; average of 16-bit integers vpslld xmm1,xmm0,1 ; shift double words left If the SSE version of instruction had a syntax with three operands, the third one being an immediate value, the AVX version of such instruction takes four operands, with immediate remaining the last one. vshufpd ymm0,ymm1,ymm2,10010011b ; shuffle 64-bit floats vpalignr xmm0,xmm4,xmm2,3 ; extract byte aligned value The promotion to new syntax according to the rules described above has been applied to all the instructions from SSE extensions up to SSE4, with the exceptions described below. "vdppd" instruction has syntax extended to four operans, but it does not have a 256-bit version. The are a few instructions, namely "vsqrtpd", "vsqrtps", "vrcpps" and "vrsqrtps", which can operate on 256-bit data size, but retained the syntax with only two operands, because they use data from only one source: vsqrtpd ymm1,ymm0 ; put square roots into other register In a similar way "vroundpd" and "vroundps" retained the syntax with three operands, the last one being immediate value. vroundps ymm0,ymm1,0011b ; round toward zero Also some of the operations on packed integers kept their two-operand or three-operand syntax while being promoted to AVX version. In such case these instructions follow exactly the same rules for operands as their SSE counterparts (since operations on packed integers do not have 256-bit variants in AVX extension). These include "vpcmpestri", "vpcmpestrm", "vpcmpistri", "vpcmpistrm", "vphminposuw", "vpshufd", "vpshufhw", "vpshuflw". And there are more instructions that in AVX versions keep exactly the same syntax for operands as the one from SSE, without any additional options: "vcomiss", "vcomisd", "vcvtss2si", "vcvtsd2si", "vcvttss2si", "vcvttsd2si", "vextractps", "vpextrb", "vpextrw", "vpextrd", "vpextrq", "vmovd", "vmovq", "vmovntdqa", "vmaskmovdqu", "vpmovmskb", "vpmovsxbw", "vpmovsxbd", "vpmovsxbq", "vpmovsxwd", "vpmovsxwq", "vpmovsxdq", "vpmovzxbw", "vpmovzxbd", "vpmovzxbq", "vpmovzxwd", "vpmovzxwq" and "vpmovzxdq". The move and conversion instructions have mostly been promoted to allow 256-bit size operands in addition to the 128-bit variant with syntax identical to that from SSE version of the same instruction. Each of the "vcvtdq2ps", "vcvtps2dq" and "vcvttps2dq", "vmovaps", "vmovapd", "vmovups", "vmovupd", "vmovdqa", "vmovdqu", "vlddqu", "vmovntps", "vmovntpd", "vmovntdq", "vmovsldup", "vmovshdup", "vmovmskps" and "vmovmskpd" inherits the 128-bit syntax from SSE without any changes, and also allows a new form with 256-bit operands in place of 128-bit ones. vmovups [edi],ymm6 ; store unaligned 256-bit data "vmovddup" has the identical 128-bit syntax as its SSE version, and it also has a 256-bit version, which stores the duplicates of the lowest quad word from the source operand in the lower half of destination operand, and in the upper half of destination the duplicates of the low quad word from the upper half of source. Both source and destination operands need then to be 256-bit values. "vmovlhps" and "vmovhlps" have only 128-bit versions, and each takes three operands, which all must be SSE registers. "vmovlhps" copies two single precision values from the low quad word of second source register to the high quad word of destination register, and copies the low quad word of first source register into the low quad word of destination register. "vmovhlps" copies two single precision values from the high quad word of second source register to the low quad word of destination register, and copies the high quad word of first source register into the high quad word of destination register. "vmovlps", "vmovhps", "vmovlpd" and "vmovhpd" have only 128-bit versions and their syntax varies depending on whether memory operand is a destination or source. When memory is destination, the syntax is identical to the one of equivalent SSE instruction, and when memory is source, the instruction requires three operands, first two being SSE registers and the third one 64-bit memory. The value put into destination is then the value copied from first source with either low or high quad word replaced with value from second source (the memory operand). vmovhps [esi],xmm7 ; store upper half to memory vmovlps xmm0,xmm7,[ebx] ; low from memory, rest from register "vmovss" and "vmovsd" have syntax identical to their SSE equivalents as long as one of the operands is memory, while the versions that operate purely on registers require three operands (each being SSE register). The value stored in destination is then the value copied from first source with lowest data element replaced with the lowest value from second source. vmovss xmm3,[edi] ; low from memory, rest zeroed vmovss xmm0,xmm1,xmm2 ; one value from xmm2, three from xmm1 "vcvtss2sd", "vcvtsd2ss", "vcvtsi2ss" and "vcvtsi2d" use the three-operand syntax, where destination and first source are always SSE registers, and the second source follows the same rules and the source in syntax of equivalent SSE instruction. The value stored in destination is then the value copied from first source with lowest data element replaced with the result of conversion. vcvtsi2sd xmm4,xmm4,ecx ; 32-bit integer to 64-bit float vcvtsi2ss xmm0,xmm0,rax ; 64-bit integer to 32-bit float "vcvtdq2pd" and "vcvtps2pd" allow the same syntax as their SSE equivalents, plus the new variants with AVX register as destination and SSE register or 128-bit memory as source. Analogously "vcvtpd2dq", "vcvttpd2dq" and "vcvtpd2ps", in addition to variant with syntax identical to SSE version, allow a variant with SSE register as destination and AVX register or 256-bit memory as source. "vinsertps", "vpinsrb", "vpinsrw", "vpinsrd", "vpinsrq" and "vpblendw" use a syntax with four operands, where destination and first source have to be SSE registers, and the third and fourth operand follow the same rules as second and third operand in the syntax of equivalent SSE instruction. Value stored in destination is the the value copied from first source with some data elements replaced with values extracted from the second source, analogously to the operation of corresponding SSE instruction. vpinsrd xmm0,xmm0,eax,3 ; insert double word "vblendvps", "vblendvpd" and "vpblendvb" use a new syntax with four register operands: destination, two sources and a mask, where second source can also be a memory operand. "vblendvps" and "vblendvpd" have 256-bit variant, where operands are AVX registers or 256-bit memory, as well as 128-bit variant, which has operands being SSE registers or 128-bit memory. "vpblendvb" has only a 128-bit variant. Value stored in destination is the value copied from the first source with some data elements replaced, according to mask, by values from the second source. vblendvps ymm3,ymm1,ymm2,ymm7 ; blend according to mask "vptest" allows the same syntax as its SSE version and also has a 256-bit version, with both operands doubled in size. There are also two new instructions, "vtestps" and "vtestpd", which perform analogous tests, but only of the sign bits of corresponding single precision or double precision values, and set the ZF and CF accordingly. They follow the same syntax rules as "vptest". vptest ymm0,yword [ebx] ; test 256-bit values vtestpd xmm0,xmm1 ; test sign bits of 64-bit floats "vbroadcastss", "vbroadcastsd" and "vbroadcastf128" are new instructions, which broadcast the data element defined by source operand into all elements of corresponing size in the destination register. "vbroadcastss" needs source to be 32-bit memory and destination to be either SSE or AVX register. "vbroadcastsd" requires 64-bit memory as source, and AVX register as destination. "vbroadcastf128" requires 128-bit memory as source, and AVX register as destination. vbroadcastss ymm0,dword [eax] ; get eight copies of value "vinsertf128" is the new instruction, which takes four operands. The destination and first source have to be AVX registers, second source can be SSE register or 128-bit memory location, and fourth operand should be an immediate value. It stores in destination the value obtained by taking contents of first source and replacing one of its 128-bit units with value of the second source. The lowest bit of fourth operand specifies at which position that replacement is done (either 0 or 1). "vextractf128" is the new instruction with three operands. The destination needs to be SSE register or 128-bit memory location, the source must be AVX register, and the third operand should be an immediate value. It extracts into destination one of the 128-bit units from source. The lowest bit of third operand specifies, which unit is extracted. "vmaskmovps" and "vmaskmovpd" are the new instructions with three operands that selectively store in destination the elements from second source depending on the sign bits of corresponding elements from first source. These instructions can operate on either 128-bit data (SSE registers) or 256-bit data (AVX registers). Either destination or second source has to be a memory location of appropriate size, the two other operands should be registers. vmaskmovps [edi],xmm0,xmm5 ; conditionally store vmaskmovpd ymm5,ymm0,[esi] ; conditionally load "vpermilpd" and "vpermilps" are the new instructions with three operands that permute the values from first source according to the control fields from second source and put the result into destination operand. It allows to use either three SSE registers or three AVX registers as its operands, the second source can be a memory of size equal to the registers used. In alternative form the second source can be immediate value and then the first source can be a memory location of the size equal to destination register. "vperm2f128" is the new instruction with four operands, which selects 128-bit blocks of floating point data from first and second source according to the bit fields from fourth operand, and stores them in destination. Destination and first source need to be AVX registers, second source can be AVX register or 256-bit memory area, and fourth operand should be an immediate value. vperm2f128 ymm0,ymm6,ymm7,12h ; permute 128-bit blocks "vzeroall" instruction sets all the AVX registers to zero. "vzeroupper" sets the upper 128-bit portions of all AVX registers to zero, leaving the SSE registers intact. These new instructions take no operands. "vldmxcsr" and "vstmxcsr" are the AVX versions of "ldmxcsr" and "stmxcsr" instructions. The rules for their operands remain unchanged. 2.1.22 AVX2 instructions The AVX2 extension allows all the AVX instructions operating on packed integers to use 256-bit data types, and introduces some new instructions as well. The AVX instructions that operate on packed integers and had only a 128-bit variants, have been supplemented with 256-bit variants, and thus their syntax rules became analogous to AVX instructions operating on packed floating point types. vpsubb ymm0,ymm0,[esi] ; subtract 32 packed bytes vpavgw ymm3,ymm0,ymm2 ; average of 16-bit integers However there are some instructions that have not been equipped with the 256-bit variants. "vpcmpestri", "vpcmpestrm", "vpcmpistri", "vpcmpistrm", "vpextrb", "vpextrw", "vpextrd", "vpextrq", "vpinsrb", "vpinsrw", "vpinsrd", "vpinsrq" and "vphminposuw" are not affected by AVX2 and allow only the 128-bit operands. The packed shift instructions, which allowed the third operand specifying amount to be SSE register or 128-bit memory location, use the same rules for the third operand in their 256-bit variant. vpsllw ymm2,ymm2,xmm4 ; shift words left vpsrad ymm0,ymm3,xword [ebx] ; shift double words right There are also new packed shift instructions with standard three-operand AVX syntax, which shift each element from first source by the amount specified in corresponding element of second source, and store the results in destination. "vpsllvd" shifts 32-bit elements left, "vpsllvq" shifts 64-bit elements left, "vpsrlvd" shifts 32-bit elements right logically, "vpsrlvq" shifts 64-bit elements right logically and "vpsravd" shifts 32-bit elements right arithmetically. The sign-extend and zero-extend instructions, which in AVX versions allowed source operand to be SSE register or a memory of specific size, in the new 256-bit variant need memory of that size doubled or SSE register as source and AVX register as destination. vpmovzxbq ymm0,dword [esi] ; bytes to quad words Also "vmovntdqa" has been upgraded with 256-bit variant, so it allows to transfer 256-bit value from memory to AVX register, it needs memory address to be aligned to 32 bytes. "vpmaskmovd" and "vpmaskmovq" are the new instructions with syntax identical to "vmaskmovps" or "vmaskmovpd", and they performs analogous operation on packed 32-bit or 64-bit values. "vinserti128", "vextracti128", "vbroadcasti128" and "vperm2i128" are the new instructions with syntax identical to "vinsertf128", "vextractf128", "vbroadcastf128" and "vperm2f128" respectively, and they perform analogous operations on 128-bit blocks of integer data. "vbroadcastss" and "vbroadcastsd" instructions have been extended to allow SSE register as a source operand (which in AVX could only be a memory). "vpbroadcastb", "vpbroadcastw", "vpbroadcastd" and "vpbroadcastq" are the new instructions which broadcast the byte, word, double word or quad word from the source operand into all elements of corresponing size in the destination register. The destination operand can be either SSE or AVX register, and the source operand can be SSE register or memory of size equal to the size of data element. vpbroadcastb ymm0,byte [ebx] ; get 32 identical bytes "vpermd" and "vpermps" are new three-operand instructions, which use each 32-bit element from first source as an index of element in second source which is copied into destination at position corresponding to element containing index. The destination and first source have to be AVX registers, and the second source can be AVX register or 256-bit memory. "vpermq" and "vpermpd" are new three-operand instructions, which use 2-bit indexes from the immediate value specified as third operand to determine which element from source store at given position in destination. The destination has to be AVX register, source can be AVX register or 256-bit memory, and the third operand must be 8-bit immediate value. The family of new instructions performing "gather" operation have special syntax, as in their memory operand they use addressing mode that is unique to them. The base of address can be a 32-bit or 64-bit general purpose register (the latter only in long mode), and the index (possibly multiplied by scale value, as in standard addressing) is specified by SSE or AVX register. It is possible to use only index without base and any numerical displacement can be added to the address. Each of those instructions takes three operands. First operand is the destination register, second operand is memory addressed with a vector index, and third operand is register containing a mask. The most significant bit of each element of mask determines whether a value will be loaded from memory into corresponding element in destination. The address of each element to load is determined by using the corresponding element from index register in memory operand to calculate final address with given base and displacement. When the index register contains less elements than the destination and mask registers, the higher elements of destination are zeroed. After the value is successfuly loaded, the corresponding element in mask register is set to zero. The destination, index and mask should all be distinct registers, it is not allowed to use the same register in two different roles. "vgatherdps" loads single precision floating point values addressed by 32-bit indexes. The destination, index and mask should all be registers of the same type, either SSE or AVX. The data addressed by memory operand is 32-bit in size. vgatherdps xmm0,[eax+xmm1],xmm3 ; gather four floats vgatherdps ymm0,[ebx+ymm7*4],ymm3 ; gather eight floats "vgatherqps" loads single precision floating point values addressed by 64-bit indexes. The destination and mask should always be SSE registers, while index register can be either SSE or AVX register. The data addressed by memory operand is 32-bit in size. vgatherqps xmm0,[xmm2],xmm3 ; gather two floats vgatherqps xmm0,[ymm2+64],xmm3 ; gather four floats "vgatherdpd" loads double precision floating point values addressed by 32-bit indexes. The index register should always be SSE register, the destination and mask should be two registers of the same type, either SSE or AVX. The data addressed by memory operand is 64-bit in size. vgatherdpd xmm0,[ebp+xmm1],xmm3 ; gather two doubles vgatherdpd ymm0,[xmm3*8],ymm5 ; gather four doubles "vgatherqpd" loads double precision floating point values addressed by 64-bit indexes. The destination, index and mask should all be registers of the same type, either SSE or AVX. The data addressed by memory operand is 64-bit in size. "vpgatherdd" and "vpgatherqd" load 32-bit values addressed by either 32-bit or 64-bit indexes. They follow the same rules as "vgatherdps" and "vgatherqps" respectively. "vpgatherdq" and "vpgatherqq" load 64-bit values addressed by either 32-bit or 64-bit indexes. They follow the same rules as "vgatherdpd" and "vgatherqpd" respectively. 2.1.23 Auxiliary sets of computational instructions There is a number of additional instruction set extensions related to AVX. They introduce new vector instructions (and sometimes also their SSE equivalents that use classic instruction encoding), and even some new instructions operating on general registers that use the AVX-like encoding allowing the extended syntax with separate destination and source operands. The CPU support for each of these instructions sets needs to be determined separately. The AES extension provides a specialized set of instructions for the purpose of cryptographic computations defined by Advanced Encryption Standard. Each of these instructions has two versions: the AVX one and the one with SSE-like syntax that uses classic encoding. Refer to the Intel manuals for the details of operation of these instructions. "aesenc" and "aesenclast" perform a single round of AES encryption on data from first source with a round key from second source, and store result in destination. The destination and first source are SSE registers, and the second source can be SSE register or 128-bit memory. The AVX versions of these instructions, "vaesenc" and "vaesenclast", use the syntax with three operands, while the SSE-like version has only two operands, with first operand being both the destination and first source. "aesdec" and "aesdeclast" perform a single round of AES decryption on data from first source with a round key from second source. The syntax rules for them and their AVX versions are the same as for "aesenc". "aesimc" performs the InvMixColumns transformation of source operand and store the result in destination. Both "aesimc" and "vaesimc" use only two operands, destination being SSE register, and source being SSE register or 128-bit memory location. "aeskeygenassist" is a helper instruction for generating the round key. It needs three operands: destination being SSE register, source being SSE register or 128-bit memory, and third operand being 8-bit immediate value. The AVX version of this instruction uses the same syntax. The CLMUL extension introduces just one instruction, "pclmulqdq", and its AVX version as well. This instruction performs a carryless multiplication of two 64-bit values selected from first and second source according to the bit fields in immediate value. The destination and first source are SSE registers, second source is SSE register or 128-bit memory, and immediate value is provided as last operand. "vpclmulqdq" takes four operands, while "pclmulqdq" takes only three operands, with the first one serving both the role of destination and first source. The FMA (Fused Multiply-Add) extension introduces additional AVX instructions which perform multiplication and summation as single operation. Each one takes three operands, first one serving both the role of destination and first source, and the following ones being the second and third source. The mnemonic of FMA instruction is obtained by appending to "vf" prefix: first either "m" or "nm" to select whether result of multiplication should be taken as-is or negated, then either "add" or "sub" to select whether third value will be added to the product or subtracted from the product, then either "132", "213" or "231" to select which source operands are multiplied and which one is added or subtracted, and finally the type of data on which the instruction operates, either "ps", "pd", "ss" or "sd". As it was with SSE instructions promoted to AVX, instructions operating on packed floating point values allow 128-bit or 256-bit syntax, in former all the operands are SSE registers, but the third one can also be a 128-bit memory, in latter the operands are AVX registers and the third one can also be a 256-bit memory. Instructions that compute just one floating point result need operands to be SSE registers, and the third operand can also be a memory, either 32-bit for single precision or 64-bit for double precision. vfmsub231ps ymm1,ymm2,ymm3 ; multiply and subtract vfnmadd132sd xmm0,xmm5,[ebx] ; multiply, negate and add In addition to the instructions created by the rule described above, there are families of instructions with mnemonics starting with either "vfmaddsub" or "vfmsubadd", followed by either "132", "213" or "231" and then either "ps" or "pd" (the operation must always be on packed values in this case). They add to the result of multiplication or subtract from it depending on the position of value in packed data - instructions from the "vfmaddsub" group add when the position is odd and subtract when the position is even, instructions from the "vfmsubadd" group add when the position is even and subtstract when the position is odd. The rules for operands are the same as for other FMA instructions. The FMA4 instructions are similar to FMA, but use syntax with four operands and thus allow destination to be different than all the sources. Their mnemonics are identical to FMA instructions with the "132", "213" or "231" cut out, as having separate destination operand makes such selection of operands superfluous. The multiplication is always performed on values from the first and second source, and then the value from third source is added or subtracted. Either second or third source can be a memory operand, and the rules for the sizes of operands are the same as for FMA instructions. vfmaddpd ymm0,ymm1,[esi],ymm2 ; multiply and add vfmsubss xmm0,xmm1,xmm2,[ebx] ; multiply and subtract The F16C extension consists of two instructions, "vcvtps2ph" and "vcvtph2ps", which convert floating point values between single precision and half precision (the 16-bit floating point format). "vcvtps2ph" takes three operands: destination, source, and rounding controls. The third operand is always an immediate, the source is either SSE or AVX register containing single precision values, and the destination is SSE register or memory, the size of memory is 64 bits when the source is SSE register and 128 bits when the source is AVX register. "vcvtph2ps" takes two operands, the destination that can be SSE or AVX register, and the source that is SSE register or memory with size of the half of destination operand's size. The AMD XOP extension introduces a number of new vector instructions with encoding and syntax analogous to AVX instructions. "vfrczps", "vfrczss", "vfrczpd" and "vfrczsd" extract fractional portions of single or double precision values, they all take two operands. The packed operations allow either SSE or AVX register as destination, for the other two it has to be SSE register. Source can be register of the same type as destination, or memory of appropriate size (256-bit for destination being AVX register, 128-bit for packed operation with destination being SSE register, 64-bit for operation on a solitary double precision value and 32-bit for operation on a solitary single precision value). vfrczps ymm0,[esi] ; load fractional parts "vpcmov" copies bits from either first or second source into destination depending on the values of corresponding bits in the fourth operand (the selector). If the bit in selector is set, the corresponding bit from first source is copied into the same position in destination, otherwise the bit from second source is copied. Either second source or selector can be memory location, 128-bit or 256-bit depending on whether SSE registers or AVX registers are specified as the other operands. vpcmov xmm0,xmm1,xmm2,[ebx] ; selector in memory vpcmov ymm0,ymm5,[esi],ymm2 ; source in memory The family of packed comparison instructions take four operands, the destination and first source being SSE register, second source being SSE register or 128-bit memory and the fourth operand being immediate value defining the type of comparison. The mnemonic or instruction is created by appending to "vpcom" prefix either "b" or "ub" to compare signed or unsigned bytes, "w" or "uw" to compare signed or unsigned words, "d" or "ud" to compare signed or unsigned double words, "q" or "uq" to compare signed or unsigned quad words. The respective values from the first and second source are compared and the corresponding data element in destination is set to either all ones or all zeros depending on the result of comparison. The fourth operand has to specify one of the eight comparison types (table 2.5). All these instructions have also variants with only three operands and the type of comparison encoded within the instruction name by inserting the comparison mnemonic after "vpcom". vpcomb xmm0,xmm1,xmm2,4 ; test for equal bytes vpcomgew xmm0,xmm1,[ebx] ; compare signed words Table 2.5 XOP comparisons /-------------------------------------------\ | Code | Mnemonic | Description | |======|==========|=========================| | 0 | lt | less than | | 1 | le | less than or equal | | 2 | gt | greater than | | 3 | ge | greater than or equal | | 4 | eq | equal | | 5 | neq | not equal | | 6 | false | false | | 7 | true | true | \-------------------------------------------/ "vpermil2ps" and "vpermil2pd" set the elements in destination register to zero or to a value selected from first or second source depending on the corresponding bit fields from the fourth operand (the selector) and the immediate value provided in fifth operand. Refer to the AMD manuals for the detailed explanation of the operation performed by these instructions. Each of the first four operands can be a register, and either second source or selector can be memory location, 128-bit or 256-bit depending on whether SSE registers or AVX registers are used for the other operands. vpermil2ps ymm0,ymm3,ymm7,ymm2,0 ; permute from two sources "vphaddbw" adds pairs of adjacent signed bytes to form 16-bit values and stores them at the same positions in destination. "vphaddubw" does the same but treats the bytes as unsigned. "vphaddbd" and "vphaddubd" sum all bytes (either signed or unsigned) in each four-byte block to 32-bit results, "vphaddbq" and "vphaddubq" sum all bytes in each eight-byte block to 64-bit results, "vphaddwd" and "vphadduwd" add pairs of words to 32-bit results, "vphaddwq" and "vphadduwq" sum all words in each four-word block to 64-bit results, "vphadddq" and "vphaddudq" add pairs of double words to 64-bit results. "vphsubbw" subtracts in each two-byte block the byte at higher position from the one at lower position, and stores the result as a signed 16-bit value at the corresponding position in destination, "vphsubwd" subtracts in each two-word block the word at higher position from the one at lower position and makes signed 32-bit results, "vphsubdq" subtract in each block of two double word the one at higher position from the one at lower position and makes signed 64-bit results. Each of these instructions takes two operands, the destination being SSE register, and the source being SSE register or 128-bit memory. vphadduwq xmm0,xmm1 ; sum quadruplets of words "vpmacsww" and "vpmacssww" multiply the corresponding signed 16-bit values from the first and second source and then add the products to the parallel values from the third source, then "vpmacsww" takes the lowest 16 bits of the result and "vpmacssww" saturates the result down to 16-bit value, and they store the final 16-bit results in the destination. "vpmacsdd" and "vpmacssdd" perform the analogous operation on 32-bit values. "vpmacswd" and "vpmacsswd" do the same calculation only on the low 16-bit values from each 32-bit block and form the 32-bit results. "vpmacsdql" and "vpmacssdql" perform such operation on the low 32-bit values from each 64-bit block and form the 64-bit results, while "vpmacsdqh" and "vpmacssdqh" do the same on the high 32-bit values from each 64-bit block, also forming the 64-bit results. "vpmadcswd" and "vpmadcsswd" multiply the corresponding signed 16-bit value from the first and second source, then sum all the four products and add this sum to each 16-bit element from third source, storing the truncated or saturated result in destination. All these instructions take four operands, the second source can be 128-bit memory or SSE register, all the other operands have to be SSE registers. vpmacsdd xmm6,xmm1,[ebx],xmm6 ; accumulate product "vpperm" selects bytes from first and second source, optionally applies a separate transformation to each of them, and stores them in the destination. The bit fields in fourth operand (the selector) specify for each position in destination what byte from which source is taken and what operation is applied to it before it is stored there. Refer to the AMD manuals for the detailed information about these bit fields. This instruction takes four operands, either second source or selector can be a 128-bit memory (or they can be SSE registers both), all the other operands have to be SSE registers. "vpshlb", "vpshlw", "vpshld" and "vpshlq" shift logically bytes, words, double words or quad words respectively. The amount of bits to shift by is specified for each element separately by the signed byte placed at the corresponding position in the third operand. The source containing elements to shift is provided as second operand. Either second or third operand can be 128-bit memory (or they can be SSE registers both) and the other operands have to be SSE registers. vpshld xmm3,xmm1,[ebx] ; shift bytes from xmm1 "vpshab", "vpshaw", "vpshad" and "vpshaq" arithmetically shift bytes, words, double words or quad words. These instructions follow the same rules as the logical shifts described above. "vprotb", "vprotw", "vprotd" and "vprotq" rotate bytes, word, double words or quad words. They follow the same rules as shifts, but additionally allow third operand to be immediate value, in which case the same amount of rotation is specified for all the elements in source. vprotb xmm0,[esi],3 ; rotate bytes to the left The MOVBE extension introduces just one new instruction, "movbe", which swaps bytes in value from source before storing it in destination, so can be used to load and store big endian values. It takes two operands, either the destination or source should be a 16-bit, 32-bit or 64-bit memory (the last one being only allowed in long mode), and the other operand should be a general register of the same size. The BMI extension, consisting of two subsets - BMI1 and BMI2, introduces new instructions operating on general registers, which use the same encoding as AVX instructions and so allow the extended syntax. All these instructions use 32-bit operands, and in long mode they also allow the forms with 64-bit operands. "andn" calculates the bitwise AND of second source with the inverted bits of first source and stores the result in destination. The destination and the first source have to be general registers, the second source can be general register or memory. andn edx,eax,[ebx] ; bit-multiply inverted eax with memory "bextr" extracts from the first source the sequence of bits using an index and length specified by bit fields in the second source operand and stores it into destination. The lowest 8 bits of second source specify the position of bit sequence to extract and the next 8 bits of second source specify the length of sequence. The first source can be a general register or memory, the other two operands have to be general registers. bextr eax,[esi],ecx ; extract bit field from memory "blsi" extracts the lowest set bit from the source, setting all the other bits in destination to zero. The destination must be a general register, the source can be general register or memory. blsi rax,r11 ; isolate the lowest set bit "blsmsk" sets all the bits in the destination up to the lowest set bit in the source, including this bit. "blsr" copies all the bits from the source to destination except for the lowest set bit, which is replaced by zero. These instructions follow the same rules for operands as "blsi". "tzcnt" counts the number of trailing zero bits, that is the zero bits up to the lowest set bit of source value. This instruction is analogous to "lzcnt" and follows the same rules for operands, so it also has a 16-bit version, unlike the other BMI instructions. "bzhi" is BMI2 instruction, which copies the bits from first source to destination, zeroing all the bits up from the position specified by second source. It follows the same rules for operands as "bextr". "pext" uses a mask in second source operand to select bits from first operands and puts the selected bits as a continuous sequence into destination. "pdep" performs the reverse operation - it takes sequence of bits from the first source and puts them consecutively at the positions where the bits in second source are set, setting all the other bits in destination to zero. These BMI2 instructions follow the same rules for operands as "andn". "mulx" is a BMI2 instruction which performs an unsigned multiplication of value from EDX or RDX register (depending on the size of specified operands) by the value from third operand, and stores the low half of result in the second operand, and the high half of result in the first operand, and it does it without affecting the flags. The third operand can be general register or memory, and both the destination operands have to be general registers. mulx edx,eax,ecx ; multiply edx by ecx into edx:eax "shlx", "shrx" and "sarx" are BMI2 instructions, which perform logical or arithmetical shifts of value from first source by the amount specified by second source, and store the result in destination without affecting the flags. The have the same rules for operands as "bzhi" instruction. "rorx" is a BMI2 instruction which rotates right the value from source operand by the constant amount specified in third operand and stores the result in destination without affecting the flags. The destination operand has to be general register, the source operand can be general register or memory, and the third operand has to be an immediate value. rorx eax,edx,7 ; rotate without affecting flags The TBM is an extension designed by AMD to supplement the BMI set. The "bextr" instruction is extended with a new form, in which second source is a 32-bit immediate value. "blsic" is a new instruction which performs the same operation as "blsi", but with the bits of result reversed. It uses the same rules for operands as "blsi". "blsfill" is a new instruction, which takes the value from source, sets all the bits below the lowest set bit and store the result in destination, it also uses the same rules for operands as "blsi". "blci", "blcic", "blcs", "blcmsk" and "blcfill" are instructions analogous to "blsi", "blsic", "blsr", "blsmsk" and "blsfill" respectively, but they perform the bit-inverted versions of the same operations. They follow the same rules for operands as the instructions they reflect. "tzmsk" finds the lowest set bit in value from source operand, sets all bits below it to 1 and all the rest of bits to zero, then writes the result to destination. "t1mskc" finds the least significant zero bit in the value from source operand, sets the bits below it to zero and all the other bits to 1, and writes the result to destination. These instructions have the same rules for operands as "blsi". 2.1.24 AVX-512 instructions The AVX-512 introduces 512-bit vector registers, which extend the 256-bit registers used by AVX and AVX2. It also extends the set of vector registers from 16 to 32, with the additional registers "zmm16" to "zmm31", their low 256-bit portions "ymm16" to "ymm31" and their low 128-bit portions "xmm16" to "xmm31". These additional registers can only be accessed in the long mode. Table 2.6 New registers available in long mode with AVX-512 /------------------------------------------------------------------\ | Size | Registers | |---------|--------------------------------------------------------| | 128-bit | xmm16 xmm17 xmm18 xmm19 xmm20 xmm21 xmm22 xmm23 | | | xmm24 xmm25 xmm26 xmm27 xmm28 xmm29 xmm30 xmm31 | |---------|--------------------------------------------------------| | 256-bit | ymm16 ymm17 ymm18 ymm19 ymm20 ymm21 ymm22 ymm23 | | | ymm24 ymm25 ymm26 ymm27 ymm28 ymm29 ymm30 ymm31 | |---------|--------------------------------------------------------| | 512-bit | zmm16 zmm17 zmm18 zmm19 zmm20 zmm21 zmm22 zmm23 | | | zmm24 zmm25 zmm26 zmm27 zmm28 zmm29 zmm30 zmm31 | \------------------------------------------------------------------/ In addition to new operand sizes and registers, the AVX-512 introduces a number of supplementary settings that can be included in the operands of AVX instructions. The destination operand of the most of AVX instructions can be followed by the name of an opmask register enclosed in braces, this modifier specifies a mask that decides which units of data in the destination operand are going to be updated. The "k0" register cannot be used as a destination mask. This setting can be further followed by "{z}" modifier to choose that the data units not selected by mask should be zeroed instead of leaving them unchanged. vaddpd zmm1{k1},zmm5,zword [rsi] ; update selected floats vaddps ymm6{k1}{z},ymm12,ymm24 ; update selected, zero other ones When an instruction that operates on packed data has a source operand loaded from a memory, the memory location may be just a single unit of data and the source used for the operation is created by broadcasting this value into all the units within the required size. To specify that such broadcasting method is used the memory operand should be followed by one of the "{1to2}", "{1to4}", "{1to8}", "{1to16}", "{1to32}" and "{1to64}" modifiers, selecting the appropriate multiply of a unit. vsubps zmm1,zmm2,dword [rsi] {1to16} ; subtract from all floats When an instruction does not use a memory operand often an additional operand may follow the source operands, containing the rounding mode specifier. When an instruction has variants that operate on different sizes of data, the rounding mode can be specified only when the register operands are 512-bit. vdivps zmm2,zmm3,zmm5,{ru-sae} ; round results up Table 2.7 AVX-512 rounding modes /----------------------------------------------------------\ | Operand | Description | |==========|===============================================| | {rn-sae} | round to nearest and suppress all exceptions | | {rd-sae} | round down and suppress all exceptions | | {ru-sae} | round up and suppress all exceptions | | {rz-sae} | round toward zero and suppress all exceptions | \----------------------------------------------------------/ Some of the instructions do not use a rounding mode but still allow to specify the exception suppression option with "{sae}" modifier in the additional operand. vmaxpd zmm0,zmm1,zmm2,{sae} ; suppress all exceptions The family of "gather" instructions in their AVX-512 variants use a new syntax with only two operands. The opmask register takes the role which was played by the third operand in the AVX2 syntax and it is mandatory in this case. vgatherdps xmm0{k1},[eax+xmm1] ; gather four floats vgatherdpd zmm0{k3},[ymm3*8] ; gather eight doubles The new family of "scatter" instructions perform an operation reverse to the one of "gather". They also take two operands, the destination is a memory with vector indexing and opmask modifier, and the source is a vector register. vscatterdps [eax+xmm1]{k1},xmm0 ; scatter four floats vscatterdpd [ymm3*8]{k3},zmm0 ; scatter eight doubles The AVX512_4VNNI extension introduces instructions with another unusual syntax variant. The first source operand of "vp4dpwssd" or "vp4dpwssds" instruction refers to an aligned block of four 512-bit registers, containing the base register specified by the operand. This can be indicated by attaching "+3" to the name of register, although it is optional. vp4dpwssd zmm1{k1}{z},zmm2+3,xword[rbx] 2.1.25 Other extensions of instruction set There is a number of additional instruction set extensions recognized by flat assembler, and examples of syntax of the instructions introduced by those extensions are provided here. For a detailed information on the operations performed by them, check out the manuals from Intel or AMD. The Virtual-Machine Extensions (VMX) provide a set of instructions for the management of virtual machines. The "vmxon" instruction, which enters the VMX operation, requires a single 64-bit memory operand, which should be a physical address of memory region, which the logical processor may use to support VMX operation. The "vmxoff" instruction, which leaves the VMX operation, has no operands. The "vmlaunch" and "vmresume", which launch or resume the virtual machines, and "vmcall", which allows guest software to call the VM monitor, use no operands either. The "vmptrld" loads the physical address of current Virtual Machine Control Structure (VMCS) from its memory operand, "vmptrst" stores the pointer to current VMCS into address specified by its memory operand, and "vmclear" sets the launch state of the VMCS referenced by its memory operand to clear. These three instruction all require single 64-bit memory operand. The "vmread" reads from VCMS a field specified by the source operand and stores it into the destination operand. The source operand should be a general purpose register, and the destination operand can be a register of memory. The "vmwrite" writes into a VMCS field specified by the destination operand the value provided by source operand. The source operand can be a general purpose register or memory, and the destination operand must be a register. The size of operands for those instructions should be 64-bit when in long mode, and 32-bit otherwise. The "invept" and "invvpid" invalidate the translation lookaside buffers (TLBs) and paging-structure caches, either derived from extended page tables (EPT), or based on the virtual processor identifier (VPID). These instructions require two operands, the first one being the general purpose register specifying the type of invalidation, and the second one being a 128-bit memory operand providing the invalidation descriptor. The first operand should be a 64-bit register when in long mode, and 32-bit register otherwise. The Safer Mode Extensions (SMX) provide the functionalities available throught the "getsec" instruction. This instruction takes no operands, and the function that is executed is determined by the contents of EAX register upon executing this instruction. The Secure Virtual Machine (SVM) is a variant of virtual machine extension used by AMD. The "skinit" instruction securely reinitializes the processor allowing the startup of trusted software, such as the virtual machine monitor (VMM). This instruction takes a single operand, which must be EAX, and provides a physical address of the secure loader block (SLB). The "vmrun" instruction is used to start a guest virtual machine, its only operand should be an accumulator register (AX, EAX or RAX, the last one available only in long mode) providing the physical address of the virtual machine control block (VMCB). The "vmsave" stores a subset of processor state into VMCB specified by its operand, and "vmload" loads the same subset of processor state from a specified VMCB. The same operand rules as for the "vmrun" apply to those two instructions. "vmmcall" allows the guest software to call the VMM. This instruction takes no operands. "stgi" set the global interrupt flag to 1, and "clgi" zeroes it. These instructions take no operands. "invlpga" invalidates the TLB mapping for a virtual page specified by the first operand (which has to be accumulator register) and address space identifier specified by the second operand (which must be ECX register). The XSAVE set of instructions allows to save and restore processor state components. "xsave" and "xsaveopt" store the components of processor state defined by bit mask in EDX and EAX registers into area defined by memory operand. "xrstor" restores from the area specified by memory operand the components of processor state defined by mask in EDX and EAX. The "xsave64", "xsaveopt64" and "xrstor64" are 64-bit versions of these instructions, allowed only in long mode. "xgetbv" read the contents of 64-bit XCR (extended control register) specified in ECX register into EDX and EAX registers. "xsetbv" writes the contents of EDX and EAX into the 64-bit XCR specified by ECX register. These instructions have no operands. The RDRAND extension introduces one new instruction, "rdrand", which loads the hardware-generated random value into general register. It takes one operand, which can be 16-bit, 32-bit or 64-bit register (with the last one being allowed only in long mode). The FSGSBASE extension adds long mode instructions that allow to read and write the segment base registers for FS and GS segments. "rdfsbase" and "rdgsbase" read the corresponding segment base registers into operand, while "wrfsbase" and "wrgsbase" write the value of operand into those register. All these instructions take one operand, which can be 32-bit or 64-bit general register. The INVPCID extension adds "invpcid" instruction, which invalidates mapping in the TLBs and paging caches based on the invalidation type specified in first operand and PCID invalidate descriptor specified in second operand. The first operands should be 32-bit general register when not in long mode, or 64-bit general register when in long mode. The second operand should be 128-bit memory location. The HLE and RTM extensions provide set of instructions for the transactional management. The "xacquire" and "xrelease" are new prefixes that can be used with some of the instructions to start or end lock elision on the memory address specified by prefixed instruction. The "xbegin" instruction starts the transactional execution, its operand is the address a fallback routine that gets executes in case of transaction abort, specified like the operand for near jump instruction. "xend" marks the end of transcational execution region, it takes no operands. "xabort" forces the transaction abort, it takes an 8-bit immediate value as its only operand, this value is passed in the highest bits of EAX to the fallback routine. "xtest" checks whether there is transactional execution in progress, this instruction takes no operands. The MPX extension adds instructions that operate on new bounds registers and aid in checking the memory references. For some of these instructions flat assemblers allows a special syntax that allows a fine control over their operation, where an address of a memory operand is separated into two parts with a comma. With "bndmk" instruction the first part of such address specifies the lower bound and the second one the upper bound. The lower bound can be either zero or a register, the upper bound can be any address that uses no more than one register (multiplied by 1, 2, 4, or 8). The addressing registers need to be 64-bit when in long mode, and 32-bit otherwise. bndmk bnd0,[rbx,100000h] ; lower bound in register, upper directly bndmk bnd1,[0,rbx] ; lower bound zero, upper in register In case of "bndldx" and "bndstx", the first part of memory operand specifies an address used to access a bound table entry, while the second part is either zero or a register that plays a role of an additional operand for such instruction. The address in the first part may use no more than one register and the register cannot be multiplied by a number other than 1. bndstx [rcx,rsi],bnd3 ; store bnd3 and rsi at rcx in the bound table bndldx bnd2,[rcx,rsi] ; load from bound table if entry matches rsi 2.2 Control directives This section describes the directives that control the assembly process, they are processed during the assembly and may cause some blocks of instructions to be assembled differently or not assembled at all. 2.2.1 Numerical constants The "=" directive allows to define the numerical constant. It should be preceded by the name for the constant and followed by the numerical expression providing the value. The value of such constants can be a number or an address, but - unlike labels - the numerical constants are not allowed to hold the register-based addresses. Besides this difference, in their basic variant numerical constants behave very much like labels and you can even forward-reference them (access their values before they actually get defined). There is, however, a second variant of numerical constants, which is recognized by assembler when you try to define the constant of name, under which there already was a numerical constant defined. In such case assembler treats that constant as an assembly-time variable and allows it to be assigned with new value, but forbids forward-referencing it (for obvious reasons). Let's see both the variant of numerical constants in one example: dd sum x = 1 x = x+2 sum = x Here the "x" is an assembly-time variable, and every time it is accessed, the value that was assigned to it the most recently is used. Thus if we tried to access the "x" before it gets defined the first time, like if we wrote "dd x" in place of the "dd sum" instruction, it would cause an error. And when it is re-defined with the "x = x+2" directive, the previous value of "x" is used to calculate the new one. So when the "sum" constant gets defined, the "x" has value of 3, and this value is assigned to the "sum". Since this one is defined only once in source, it is the standard numerical constant, and can be forward-referenced. So the "dd sum" is assembled as "dd 3". To read more about how the assembler is able to resolve this, see section 2.2.6. The value of numerical constant can be preceded by size operator, which can ensure that the value will fit in the range for the specified size, and can affect also how some of the calculations inside the numerical expression are performed. This example: c8 = byte -1 c32 = dword -1 defines two different constants, the first one fits in 8 bits, the second one fits in 32 bits. When you need to define constant with the value of address, which may be register-based (and thus you cannot employ numerical constant for this purpose), you can use the extended syntax of "label" directive (already described in section 1.2.3), like: label myaddr at ebp+4 which declares label placed at "ebp+4" address. However remember that labels, unlike numerical constants, cannot become assembly-time variables. 2.2.2 Conditional assembly "if" directive causes some block of instructions to be assembled only under certain condition. It should be followed by logical expression specifying the condition, instructions in next lines will be assembled only when this condition is met, otherwise they will be skipped. The optional "else if" directive followed with logical expression specifying additional condition begins the next block of instructions that will be assembled if previous conditions were not met, and the additional condition is met. The optional "else" directive begins the block of instructions that will be assembled if all the conditions were not met. The "end if" directive ends the last block of instructions. You should note that "if" directive is processed at assembly stage and therefore it doesn't affect any preprocessor directives, like the definitions of symbolic constants and macroinstructions - when the assembler recognizes the "if" directive, all the preprocessing has been already finished. The logical expression consist of logical values and logical operators. The logical operators are "~" for logical negation, "&" for logical and, "|" for logical or. The negation has the highest priority. Logical value can be a numerical expression, it will be false if it is equal to zero, otherwise it will be true. Two numerical expression can be compared using one of the following operators to make the logical value: "=" (equal), "<" (less), ">" (greater), "<=" (less or equal), ">=" (greater or equal), "<>" (not equal). The "used" operator followed by a symbol name, is the logical value that checks whether the given symbol is used somewhere (it returns correct result even if symbol is used only after this check). The "defined" operator can be followed by any expression, usually just by a single symbol name; it checks whether the given expression contains only symbols that are defined in the source and accessible from the current position. The "definite" operator does a similar check with restriction to symbols defined before current position in source. With "relativeto" operator it is possible to check whether values of two expressions differ only by constant amount. The valid syntax is a numerical expression followed by "relativeto" and then another expression (possibly register-based). Labels that have no simple numerical value can be tested this way to determine what kind of operations may be possible with them. The following simple example uses the "count" constant that should be defined somewhere in source: if count>0 mov cx,count rep movsb end if These two assembly instructions will be assembled only if the "count" constant is greater than 0. The next sample shows more complex conditional structure: if count & ~ count mod 4 mov cx,count/4 rep movsd else if count>4 mov cx,count/4 rep movsd mov cx,count mod 4 rep movsb else mov cx,count rep movsb end if The first block of instructions gets assembled when the "count" is non zero and divisible by four, if this condition is not met, the second logical expression, which follows the "else if", is evaluated and if it's true, the second block of instructions get assembled, otherwise the last block of instructions, which follows the line containing only "else", is assembled. There are also operators that allow comparison of values being any chains of symbols. The "eq" compares whether two such values are exactly the same. The "in" operator checks whether given value is a member of the list of values following this operator, the list should be enclosed between "<" and ">" characters, its members should be separated with commas. The symbols are considered the same when they have the same meaning for the assembler - for example "pword" and "fword" for assembler are the same and thus are not distinguished by the above operators. In the same way "16 eq 10h" is the true condition, however "16 eq 10+4" is not. The "eqtype" operator checks whether the two compared values have the same structure, and whether the structural elements are of the same type. The distinguished types include numerical expressions, individual quoted strings, floating point numbers, address expressions (the expressions enclosed in square brackets or preceded by "ptr" operator), instruction mnemonics, registers, size operators, jump type and code type operators. And each of the special characters that act as a separators, like comma or colon, is the separate type itself. For example, two values, each one consisting of register name followed by comma and numerical expression, will be regarded as of the same type, no matter what kind of register and how complicated numerical expression is used; with exception for the quoted strings and floating point values, which are the special kinds of numerical expressions and are treated as different types. Thus "eax,16 eqtype fs,3+7" condition is true, but "eax,16 eqtype eax,1.6" is false. 2.2.3 Repeating blocks of instructions "times" directive repeats one instruction specified number of times. It should be followed by numerical expression specifying number of repeats and the instruction to repeat (optionally colon can be used to separate number and instruction). When special symbol "%" is used inside the instruction, it is equal to the number of current repeat. For example "times 5 db %" will define five bytes with values 1, 2, 3, 4, 5. Recursive use of "times" directive is also allowed, so "times 3 times % db %" will define six bytes with values 1, 1, 2, 1, 2, 3. "repeat" directive repeats the whole block of instructions. It should be followed by numerical expression specifying number of repeats. Instructions to repeat are expected in next lines, ended with the "end repeat" directive, for example: repeat 8 mov byte [bx],% inc bx end repeat The generated code will store byte values from one to eight in the memory addressed by BX register. Number of repeats can be zero, in that case the instructions are not assembled at all. The "break" directive allows to stop repeating earlier and continue assembly from the first line after the "end repeat". Combined with the "if" directive it allows to stop repeating under some special condition, like: s = x/2 repeat 100 if x/s = s break end if s = (s+x/s)/2 end repeat The "while" directive repeats the block of instructions as long as the condition specified by the logical expression following it is true. The block of instructions to be repeated should end with the "end while" directive. Before each repetition the logical expression is evaluated and when its value is false, the assembly is continued starting from the first line after the "end while". Also in this case the "%" symbol holds the number of current repeat. The "break" directive can be used to stop this kind of loop in the same way as with "repeat" directive. The previous sample can be rewritten to use the "while" instead of "repeat" this way: s = x/2 while x/s <> s s = (s+x/s)/2 if % = 100 break end if end while The blocks defined with "if", "repeat" and "while" can be nested in any order, however they should be closed in the same order in which they were started. The "break" directive always stops processing the block that was started last with either the "repeat" or "while" directive. 2.2.4 Addressing spaces "org" directive sets address at which the following code is expected to appear in memory. It should be followed by numerical expression specifying the address. This directive begins the new addressing space, the following code itself is not moved in any way, but all the labels defined within it and the value of "$" symbol are affected as if it was put at the given address. However it's the responsibility of programmer to put the code at correct address at run-time. The "load" directive allows to define constant with a binary value loaded from the already assembled code. This directive should be followed by the name of the constant, then optionally size operator, then "from" operator and a numerical expression specifying a valid address in current addressing space. The size operator has unusual meaning in this case - it states how many bytes (up to 8) have to be loaded to form the binary value of constant. If no size operator is specified, one byte is loaded (thus value is in range from 0 to 255). The loaded data cannot exceed current offset. The "store" directive can modify the already generated code by replacing some of the previously generated data with the value defined by given numerical expression, which follows. The expression can be preceded by the optional size operator to specify how large value the expression defines, and therefore how much bytes will be stored, if there is no size operator, the size of one byte is assumed. Then the "at" operator and the numerical expression defining the valid address in current addressing code space, at which the given value have to be stored should follow. This is a directive for advanced appliances and should be used carefully. Both "load" and "store" directives in their basic variant (defined above) are limited to operate on places in current addressing space. The "$$" symbol is always equal to the base address of current addressing space, and the "$" symbol is the address of current position in that addressing space, therefore these two values define limits of the area, where "load" and "store" can operate. Combining the "load" and "store" directives allows to do things like encoding some of the already generated code. For example to encode the whole code generated in current addressing space you can use such block of directives: repeat $-$$ load a byte from $$+%-1 store byte a xor c at $$+%-1 end repeat and each byte of code will be xored with the value defined by "c" constant. "virtual" defines virtual data at specified address. This data will not be included in the output file, but labels defined there can be used in other parts of source. This directive can be followed by "at" operator and the numerical expression specifying the address for virtual data, otherwise is uses current address, the same as "virtual at $". Instructions defining data are expected in next lines, ended with "end virtual" directive. The block of virtual instructions itself is an independent addressing space, after it's ended, the context of previous addressing space is restored. The "virtual" directive can be used to create union of some variables, for example: GDTR dp ? virtual at GDTR GDT_limit dw ? GDT_address dd ? end virtual It defines two labels for parts of the 48-bit variable at "GDTR" address. It can be also used to define labels for some structures addressed by a register, for example: virtual at bx LDT_limit dw ? LDT_address dd ? end virtual With such definition instruction "mov ax,[LDT_limit]" will be assembled to the same instruction as "mov ax,[bx]". Declaring defined data values or instructions inside the virtual block could also be useful, because the "load" directive may be used to load the values from the virtually generated code into a constants. This directive in its basic version should be used after the code it loads but before the virtual block ends, because it can only load the values from the same addressing space. For example: virtual at 0 xor eax,eax and edx,eax load zeroq dword from 0 end virtual The above piece of code will define the "zeroq" constant containing four bytes of the machine code of the instructions defined inside the virtual block. This method can be also used to load some binary value from external file. For example this code: virtual at 0 file 'a.txt':10h,1 load char from 0 end virtual loads the single byte from offset 10h in file "a.txt" into the "char" constant. Instead of or in addition to an "at" argument, "virtual" can also be followed by an "as" keyword and a string defining an extension of additional file where the initialized content of the addressing space started by "virtual" is going to be stored at the end of a successful assembly. virtual at 0 as 'asc' times 256 db %-1 end virtual Any of the "section" directives described in 2.4 also begins a new addressing space. It is possible to declare a special kind of label that marks the current addressing space, by appending a double colon instead of a single one after a label name. This symbol cannot then be used in numerical expressions, the only place where it is allowed to use it is the extended syntax of "load" and "store" directives. It is possible to make these directives operate on a different addressing space than the current one, by specifying address with the two components: first the name of a special label that marks the addressing space, followed by the colon character and a numerical expression defining a valid address inside that addressing space. In the following example this extended syntax is used to load the value from a block after it has been closed: virtual at 0 hex_digits:: db '0123456789ABCDEF' end virtual load a byte from hex_digits:10 This way it is possible to operate on values inside any code block, including all the ones defined with "virtual". However it is not allowed to specify addressing space that has not been assembled yet, just as it is not allowed to specify an address in the current addressing space that exceeds the current offset. The addresses in any other addressing space are also limited by the boundaries of the block. The "virtual" directive can have a previously defined addressing space label as the only argument. This variant allows to extend a previously defined and closed block with additional data. Any definition of data within an extending block is going to have the same effect as if that definition was present in the original "virtual" block. virtual at 0 as 'log' Log:: end virtual virtual Log db 'Hello!',13,10 end virtual 2.2.5 Other directives "align" directive aligns code or data to the specified boundary. It should be followed by a numerical expression specifying the number of bytes, to the multiply of which the current address has to be aligned. The boundary value has to be the power of two. The "align" directive fills the bytes that had to be skipped to perform the alignment with the "nop" instructions and at the same time marks this area as uninitialized data, so if it is placed among other uninitialized data that wouldn't take space in the output file, the alignment bytes will act the same way. If you need to fill the alignment area with some other values, you can combine "align" with "virtual" to get the size of alignment needed and then create the alignment yourself, like: virtual align 16 a = $ - $$ end virtual db a dup 0 The "a" constant is defined to be the difference between address after alignment and address of the "virtual" block (see previous section), so it is equal to the size of needed alignment space. "display" directive displays the message at the assembly time. It should be followed by the quoted strings or byte values, separated with commas. It can be used to display values of some constants, for example: bits = 16 display 'Current offset is 0x' repeat bits/4 d = '0' + $ shr (bits-%*4) and 0Fh if d > '9' d = d + 'A'-'9'-1 end if display d end repeat display 13,10 This block of directives calculates the four hexadecimal digits of 16-bit value and converts them into characters for displaying. Note that this will not work if the adresses in current addressing space are relocatable (as it might happen with PE or object output formats), since only absolute values can be used this way. The absolute value may be obtained by calculating the relative address, like "$-$$", or "rva $" in case of PE format. The "err" directive immediately terminates the assembly process when it is encountered by assembler. The "assert" directive tests whether the logical expression that follows it is true, and if not, it signalizes the error. 2.2.6 Multiple passes Because the assembler allows to reference some of the labels or constants before they get actually defined, it has to predict the values of such labels and if there is even a suspicion that prediction failed in at least one case, it does one more pass, assembling the whole source, this time doing better prediction based on the values the labels got in the previous pass. The changing values of labels can cause some instructions to have encodings of different length, and this can cause the change in values of labels again. And since the labels and constants can also be used inside the expressions that affect the behavior of control directives, the whole block of source can be processed completely differently during the new pass. Thus the assembler does more and more passes, each time trying to do better predictions to approach the final solution, when all the values get predicted correctly. It uses various method for predicting the values, which has been chosen to allow finding in a few passes the solution of possibly smallest length for the most of the programs. Some of the errors, like the values not fitting in required boundaries, are not signaled during those intermediate passes, since it may happen that when some of the values are predicted better, these errors will disappear. However if assembler meets some illegal syntax construction or unknown instruction, it always stops immediately. Also defining some label more than once causes such error, because it makes the predictions groundless. Only the messages created with the "display" directive during the last performed pass get actually displayed. In case when the assembly has been stopped due to an error, these messages may reflect the predicted values that are not yet resolved correctly. The solution may sometimes not exist and in such cases the assembler will never manage to make correct predictions - for this reason there is a limit for a number of passes, and when assembler reaches this limit, it stops and displays the message that it is not able to generate the correct output. Consider the following example: if ~ defined alpha alpha: end if The "defined" operator gives the true value when the expression following it could be calculated in this place, what in this case means that the "alpha" label is defined somewhere. But the above block causes this label to be defined only when the value given by "defined" operator is false, what leads to an antynomy and makes it impossible to resolve such code. When processing the "if" directive assembler has to predict whether the "alpha" label will be defined somewhere (it wouldn't have to predict only if the label was already defined earlier in this pass), and whatever the prediction is, the opposite always happens. Thus the assembly will fail, unless the "alpha" label is defined somewhere in source preceding the above block of instructions - in such case, as it was already noted, the prediction is not needed and the block will just get skipped. The above sample might have been written as a try to define the label only when it was not yet defined. It fails, because the "defined" operator does check whether the label is defined anywhere, and this includes the definition inside this conditionally processed block. It could be easily corrected by using "definite" operator instead of "defined". But there is also another modification that could get it resolved: if ~ defined alpha | defined @f alpha: @@: end if The "@f" is always the same label as the nearest "@@" symbol in the source following it, so the above sample would mean the same if any unique name was used instead of the anonymous label. When "alpha" is not defined in any other place in source, the only possible solution is when this block gets defined, and this time this doesn't lead to the antynomy, because of the anonymous label which makes this block self-establishing. To better understand this, look at the blocks that has nothing more than this self-establishing: if defined @f @@: end if This is an example of source that may have more than one solution, as both cases when this block gets processed or not are equally correct. Which one of those two solutions we get depends on the algorithm on the assembler, in case of flat assembler - on the algorithm of predictions. Back to the previous sample, when "alpha" is not defined anywhere else, the condition for "if" block cannot be false, so we are left with only one possible solution, and we can hope the assembler will arrive at it. On the other hand, when "alpha" is defined in some other place, we've got two possible solutions again, but one of them causes "alpha" to be defined twice, and such an error causes assembler to abort the assembly immediately, as this is the kind of error that deeply disturbs the process of resolving. So we can get such source either correctly resolved or causing an error, and what we get may depend on the internal choices made by the assembler. However there are some facts about such choices that are certain. When assembler has to check whether the given symbol is defined and it was already defined in the current pass, no prediction is needed - it was already noted above. And when the given symbol has been defined never before, including all the already finished passes, the assembler predicts it to be not defined. Knowing this, we can expect that the simple self-establishing block shown above will not be assembled at all and that the previous sample will resolve correctly when "alpha" is defined somewhere before our conditional block, while it will itself define "alpha" when it's not already defined earlier, thus potentially causing the error because of double definition if the "alpha" is also defined somewhere later. The "used" operator may be expected to behave in a similar manner in analogous cases, however any other kinds of predictions may not be so simple and you should never rely on them this way. The "err" directive, usually used to stop the assembly when some condition is met, stops the assembly immediately, regardless of whether the current pass is final or intermediate. So even when the condition that caused this directive to be interpreted is mispredicted and temporary, and would eventually disappear in the later passes, the assembly is stopped anyway. The "assert" directive signalizes the error only if its expression is false after all the symbols have been resolved. You can use "assert 0" in place of "err" when you do not want to have assembly stopped during the intermediate passes. 2.3 Preprocessor directives All preprocessor directives are processed before the main assembly process, and therefore are not affected by the control directives. At this time also all comments are stripped out. 2.3.1 Including source files "include" directive includes the specified source file at the position where it is used. It should be followed by the quoted name of file that should be included, for example: include 'macros.inc' The whole included file is preprocessed before preprocessing the lines next to the line containing the "include" directive. There are no limits to the number of included files as long as they fit in memory. The quoted path can contain environment variables enclosed within "%" characters, they will be replaced with their values inside the path, both the "\" and "/" characters are allowed as a path separators. The file is first searched for in the directory containing file which included it and when it is not found there, the search is continued in the directories specified in the environment variable called INCLUDE (the multiple paths separated with semicolons can be defined there, they will be searched in the same order as specified). If file was not found in any of these places, preprocessor looks for it in the directory containing the main source file (the one specified in command line). These rules concern also paths given with the "file" directive. 2.3.2 Symbolic constants The symbolic constants are different from the numerical constants, before the assembly process they are replaced with their values everywhere in source lines after their definitions, and anything can become their values. The definition of symbolic constant consists of name of the constant followed by the "equ" directive. Everything that follows this directive will become the value of constant. If the value of symbolic constant contains other symbolic constants, they are replaced with their values before assigning this value to the new constant. For example: d equ dword NULL equ d 0 d equ edx After these three definitions the value of "NULL" constant is "dword 0" and the value of "d" is "edx". So, for example, "push NULL" will be assembled as "push dword 0" and "push d" will be assembled as "push edx". And if then the following line was put: d equ d,eax the "d" constant would get the new value of "edx,eax". This way the growing lists of symbols can be defined. "restore" directive allows to get back previous value of redefined symbolic constant. It should be followed by one more names of symbolic constants, separated with commas. So "restore d" after the above definitions will give "d" constant back the value "edx", the second one will restore it to value "dword", and one more will revert "d" to original meaning as if no such constant was defined. If there was no constant defined of given name, "restore" will not cause an error, it will be just ignored. Symbolic constant can be used to adjust the syntax of assembler to personal preferences. For example the following set of definitions provides the handy shortcuts for all the size operators: b equ byte w equ word d equ dword p equ pword f equ fword q equ qword t equ tword x equ dqword y equ qqword Because symbolic constant may also have an empty value, it can be used to allow the syntax with "offset" word before any address value: offset equ After this definition "mov ax,offset char" will be valid construction for copying the offset of "char" variable into "ax" register, because "offset" is replaced with an empty value, and therefore ignored. The "define" directive followed by the name of constant and then the value, is the alternative way of defining symbolic constant. The only difference between "define" and "equ" is that "define" assigns the value as it is, it does not replace the symbolic constants with their values inside it. Symbolic constants can also be defined with the "fix" directive, which has the same syntax as "equ", but defines constants of high priority - they are replaced with their symbolic values even before processing the preprocessor directives and macroinstructions, the only exception is "fix" directive itself, which has the highest possible priority, so it allows redefinition of constants defined this way. The "fix" directive can be used for syntax adjustments related to directives of preprocessor, what cannot be done with "equ" directive. For example: incl fix include defines a short name for "include" directive, while the similar definition done with "equ" directive wouldn't give such result, as standard symbolic constants are replaced with their values after searching the line for preprocessor directives. 2.3.3 Macroinstructions "macro" directive allows you to define your own complex instructions, called macroinstructions, using which can greatly simplify the process of programming. In its simplest form it's similar to symbolic constant definition. For example the following definition defines a shortcut for the "test al,0xFF" instruction: macro tst {test al,0xFF} After the "macro" directive there is a name of macroinstruction and then its contents enclosed between the "{" and "}" characters. You can use "tst" instruction anywhere after this definition and it will be assembled as "test al,0xFF". Defining symbolic constant "tst" of that value would give the similar result, but the difference is that the name of macroinstruction is recognized only as an instruction mnemonic. Also, macroinstructions are replaced with corresponding code even before the symbolic constants are replaced with their values. So if you define macroinstruction and symbolic constant of the same name, and use this name as an instruction mnemonic, it will be replaced with the contents of macroinstruction, but it will be replaced with value if symbolic constant if used somewhere inside the operands. The definition of macroinstruction can consist of many lines, because "{" and "}" characters don't have to be in the same line as "macro" directive. For example: macro stos0 { xor al,al stosb } The macroinstruction "stos0" will be replaced with these two assembly instructions anywhere it's used. Like instructions which needs some number of operands, the macroinstruction can be defined to need some number of arguments separated with commas. The names of needed argument should follow the name of macroinstruction in the line of "macro" directive and should be separated with commas if there is more than one. Anywhere one of these names occurs in the contents of macroinstruction, it will be replaced with corresponding value, provided when the macroinstruction is used. Here is an example of a macroinstruction that will do data alignment for binary output format: macro align value { rb (value-1)-($+value-1) mod value } When the "align 4" instruction is found after this macroinstruction is defined, it will be replaced with contents of this macroinstruction, and the "value" will there become 4, so the result will be "rb (4-1)-($+4-1) mod 4". If a macroinstruction is defined that uses an instruction with the same name inside its definition, the previous meaning of this name is used. Useful redefinition of macroinstructions can be done in that way, for example: macro mov op1,op2 { if op1 in & op2 in push op2 pop op1 else mov op1,op2 end if } This macroinstruction extends the syntax of "mov" instruction, allowing both operands to be segment registers. For example "mov ds,es" will be assembled as "push es" and "pop ds". In all other cases the standard "mov" instruction will be used. The syntax of this "mov" can be extended further by defining next macroinstruction of that name, which will use the previous macroinstruction: macro mov op1,op2,op3 { if op3 eq mov op1,op2 else mov op1,op2 mov op2,op3 end if } It allows "mov" instruction to have three operands, but it can still have two operands only, because when macroinstruction is given less arguments than it needs, the rest of arguments will have empty values. When three operands are given, this macroinstruction will become two macroinstructions of the previous definition, so "mov es,ds,dx" will be assembled as "push ds", "pop es" and "mov ds,dx". By placing the "*" after the name of argument you can mark the argument as required - preprocessor will not allow it to have an empty value. For example the above macroinstruction could be declared as "macro mov op1*,op2*,op3" to make sure that first two arguments will always have to be given some non empty values. Alternatively, you can provide the default value for argument, by placing the "=" followed by value after the name of argument. Then if the argument has an empty value provided, the default value will be used instead. When it's needed to provide macroinstruction with argument that contains some commas, such argument should be enclosed between "<" and ">" characters. If it contains more than one "<" character, the same number of ">" should be used to tell that the value of argument ends. When the name of the last argument of macroinstruction is followed by "&" character, this argument consumes everything up to the end of line, including commas. "purge" directive allows removing the last definition of specified macroinstruction. It should be followed by one or more names of macroinstructions, separated with commas. If such macroinstruction has not been defined, you will not get any error. For example after having the syntax of "mov" extended with the macroinstructions defined above, you can disable syntax with three operands back by using "purge mov" directive. Next "purge mov" will disable also syntax for two operands being segment registers, and all the next such directives will do nothing. If after the "macro" directive you enclose a group of argument declarations in square brackets, it will allow giving more values for this group of arguments when using that macroinstruction. Any additional argument following the last argument of such group will start the new group and will become the first argument of it. For this reason after the closing square bracket no more argument names can follow. The contents of macroinstruction will be processed for each such group of arguments separately. The simplest example is to enclose one argument name in square brackets: macro stoschar [char] { mov al,char stosb } This macroinstruction accepts unlimited number of arguments, and each one will be processed into these two instructions separately. For example "stoschar 1,2,3" will be assembled as the following instructions: mov al,1 stosb mov al,2 stosb mov al,3 stosb There are some special directives available only inside the definitions of macroinstructions. "local" directive defines local names, which will be replaced with unique values each time the macroinstruction is used. It should be followed by names separated with commas. If the name given as parameter to "local" directive begins with a dot or two dots, the unique labels generated by each evaluation of macroinstruction will have the same properties. This directive is usually needed for the constants or labels that macroinstruction defines and uses internally. For example: macro movstr { local move move: lodsb stosb test al,al jnz move } Each time this macroinstruction is used, "move" will become other unique name in its instructions, so you will not get an error you normally get when some label is defined more than once. "forward", "reverse" and "common" directives divide macroinstruction into blocks, each one processed after the processing of previous is finished. They differ in behavior only if macroinstruction allows multiple groups of arguments. Block of instructions that follows "forward" directive is processed for each group of arguments, from first to last - exactly like the default block (not preceded by any of these directives). Block that follows "reverse" directive is processed for each group of argument in reverse order - from last to first. Block that follows "common" directive is processed only once, commonly for all groups of arguments. Local name defined in one of the blocks is available in all the following blocks when processing the same group of arguments as when it was defined, and when it is defined in common block it is available in all the following blocks not depending on which group of arguments is processed. Here is an example of macroinstruction that will create the table of addresses to strings followed by these strings: macro strtbl name,[string] { common label name dword forward local label dd label forward label db string,0 } First argument given to this macroinstruction will become the label for table of addresses, next arguments should be the strings. First block is processed only once and defines the label, second block for each string declares its local name and defines the table entry holding the address to that string. Third block defines the data of each string with the corresponding label. The directive starting the block in macroinstruction can be followed by the first instruction of this block in the same line, like in the following example: macro stdcall proc,[arg] { reverse push arg common call proc } This macroinstruction can be used for calling the procedures using STDCALL convention, which has all the arguments pushed on stack in the reverse order. For example "stdcall foo,1,2,3" will be assembled as: push 3 push 2 push 1 call foo If some name inside macroinstruction has multiple values (it is either one of the arguments enclosed in square brackets or local name defined in the block following "forward" or "reverse" directive) and is used in block following the "common" directive, it will be replaced with all of its values, separated with commas. For example the following macroinstruction will pass all of the additional arguments to the previously defined "stdcall" macroinstruction: macro invoke proc,[arg] { common stdcall [proc],arg } It can be used to call indirectly (by the pointer stored in memory) the procedure using STDCALL convention. Inside macroinstruction also special operator "#" can be used. This operator causes two names to be concatenated into one name. It can be useful, because it's done after the arguments and local names are replaced with their values. The following macroinstruction will generate the conditional jump according to the "cond" argument: macro jif op1,cond,op2,label { cmp op1,op2 j#cond label } For example "jif ax,ae,10h,exit" will be assembled as "cmp ax,10h" and "jae exit" instructions. The "#" operator can be also used to concatenate two quoted strings into one. Also conversion of name into a quoted string is possible, with the "`" operator, which likewise can be used inside the macroinstruction. It converts the name that follows it into a quoted string - but note, that when it is followed by a macro argument which is being replaced with value containing more than one symbol, only the first of them will be converted, as the "`" operator converts only one symbol that immediately follows it. Here's an example of utilizing those two features: macro label name { label name if ~ used name display `name # " is defined but not used.",13,10 end if } When label defined with such macro is not used in the source, macro will warn you with the message, informing to which label it applies. To make macroinstruction behaving differently when some of the arguments are of some special type, for example a quoted strings, you can use "eqtype" comparison operator. Here's an example of utilizing it to distinguish a quoted string from an other argument: macro message arg { if arg eqtype "" local str jmp @f str db arg,0Dh,0Ah,24h @@: mov dx,str else mov dx,arg end if mov ah,9 int 21h } The above macro is designed for displaying messages in DOS programs. When the argument of this macro is some number, label, or variable, the string from that address is displayed, but when the argument is a quoted string, the created code will display that string followed by the carriage return and line feed. It is also possible to put a declaration of macroinstruction inside another macroinstruction, so one macro can define another, but there is a problem with such definitions caused by the fact, that "}" character cannot occur inside the macroinstruction, as it always means the end of definition. To overcome this problem, the escaping of symbols inside macroinstruction can be used. This is done by placing one or more backslashes in front of any other symbol (even the special character). Preprocessor sees such sequence as a single symbol, but each time it meets such symbol during the macroinstruction processing, it cuts the backslash character from the front of it. For example "\{" is treated as single symbol, but during processing of the macroinstruction it becomes the "{" symbol. This allows to put one definition of macroinstruction inside another: macro ext instr { macro instr op1,op2,op3 \{ if op3 eq instr op1,op2 else instr op1,op2 instr op2,op3 end if \} } ext add ext sub The macro "ext" is defined correctly, but when it is used, the "\{" and "\}" become the "{" and "}" symbols. So when the "ext add" is processed, the contents of macro becomes valid definition of a macroinstruction and this way the "add" macro becomes defined. In the same way "ext sub" defines the "sub" macro. The use of "\{" symbol wasn't really necessary here, but is done this way to make the definition more clear. If some directives specific to macroinstructions, like "local" or "common" are needed inside some macro embedded this way, they can be escaped in the same way. Escaping the symbol with more than one backslash is also allowed, which allows multiple levels of nesting the macroinstruction definitions. The another technique for defining one macroinstruction by another is to use the "fix" directive, which becomes useful when some macroinstruction only begins the definition of another one, without closing it. For example: macro tmacro [params] { common macro params { } MACRO fix tmacro ENDM fix } defines an alternative syntax for defining macroinstructions, which looks like: MACRO stoschar char mov al,char stosb ENDM Note that symbol that has such customized definition must be defined with "fix" directive, because only the prioritized symbolic constants are processed before the preprocessor looks for the "}" character while defining the macro. This might be a problem if one needed to perform some additional tasks one the end of such definition, but there is one more feature which helps in such cases. Namely it is possible to put any directive, instruction or macroinstruction just after the "}" character that ends the macroinstruction and it will be processed in the same way as if it was put in the next line. The "postpone" directive can be used to define a special type of macroinstruction that has no name or arguments and will get automatically called when the preprocessor reaches the end of source: postpone { code_size = $ } It is a very simplified kind of macroinstruction and it simply delegates a block of instructions to be put at the end. 2.3.4 Structures "struc" directive is a special variant of "macro" directive that is used to define data structures. Macroinstruction defined using the "struc" directive must be preceded by a label (like the data definition directive) when it's used. This label will be also attached at the beginning of every name starting with dot in the contents of macroinstruction. The macroinstruction defined using the "struc" directive can have the same name as some other macroinstruction defined using the "macro" directive, structure macroinstruction will not prevent the standard macroinstruction from being processed when there is no label before it and vice versa. All the rules and features concerning standard macroinstructions apply to structure macroinstructions. Here is the sample of structure macroinstruction: struc point x,y { .x dw x .y dw y } For example "my point 7,11" will define structure labeled "my", consisting of two variables: "my.x" with value 7 and "my.y" with value 11. If somewhere inside the definition of structure the name consisting of a single dot it found, it is replaced by the name of the label for the given instance of structure and this label will not be defined automatically in such case, allowing to completely customize the definition. The following example utilizes this feature to extend the data definition directive "db" with ability to calculate the size of defined data: struc db [data] { common . db data .size = $ - . } With such definition "msg db 'Hello!',13,10" will define also "msg.size" constant, equal to the size of defined data in bytes. Defining data structures addressed by registers or absolute values should be done using the "virtual" directive with structure macroinstruction (see 2.2.4). "restruc" directive removes the last definition of the structure, just like "purge" does with macroinstructions and "restore" with symbolic constants. It also has the same syntax - should be followed by one or more names of structure macroinstructions, separated with commas. 2.3.5 Repeating macroinstructions The "rept" directive is a special kind of macroinstruction, which makes given amount of duplicates of the block enclosed with braces. The basic syntax is "rept" directive followed by number and then block of source enclosed between the "{" and "}" characters. The simplest example: rept 5 { in al,dx } will make five duplicates of the "in al,dx" line. The block of instructions is defined in the same way as for the standard macroinstruction and any special operators and directives which can be used only inside macroinstructions are also allowed here. When the given count is zero, the block is simply skipped, as if you defined macroinstruction but never used it. The number of repetitions can be followed by the name of counter symbol, which will get replaced symbolically with the number of duplicate currently generated. So this: rept 3 counter { byte#counter db counter } will generate lines: byte1 db 1 byte2 db 2 byte3 db 3 The repetition mechanism applied to "rept" blocks is the same as the one used to process multiple groups of arguments for macroinstructions, so directives like "forward", "common" and "reverse" can be used in their usual meaning. Thus such macroinstruction: rept 7 num { reverse display `num } will display digits from 7 to 1 as text. The "local" directive behaves in the same way as inside macroinstruction with multiple groups of arguments, so: rept 21 { local label label: loop label } will generate unique label for each duplicate. The counter symbol by default counts from 1, but you can declare different base value by placing the number preceded by colon immediately after the name of counter. For example: rept 8 n:0 { pxor xmm#n,xmm#n } will generate code which will clear the contents of eight SSE registers. You can define multiple counters separated with commas, and each one can have different base. The number of repetitions and the base values for counters can be specified using the numerical expressions with operator rules identical as in the case of assembler. However each value used in such expression must either be a directly specified number, or a symbolic constant with value also being an expression that can be calculated by preprocessor (in such case the value of expression associated with symbolic constant is calculated first, and then substituted into the outer expression in place of that constant). If you need repetitions based on values that can only be calculated at assembly time, use one of the code repeating directives that are processed by assembler, see section 2.2.3. The "irp" directive iterates the single argument through the given list of parameters. The syntax is "irp" followed by the argument name, then the comma and then the list of parameters. The parameters are specified in the same way like in the invocation of standard macroinstruction, so they have to be separated with commas and each one can be enclosed with the "<" and ">" characters. Also the name of argument may be followed by "*" to mark that it cannot get an empty value. Such block: irp value, 2,3,5 { db value } will generate lines: db 2 db 3 db 5 The "irps" directive iterates through the given list of symbols, it should be followed by the argument name, then the comma and then the sequence of any symbols. Each symbol in this sequence, no matter whether it is the name symbol, symbol character or quoted string, becomes an argument value for one iteration. If there are no symbols following the comma, no iteration is done at all. This example: irps reg, al bx ecx { xor reg,reg } will generate lines: xor al,al xor bx,bx xor ecx,ecx The "irpv" directive iterates through all of the values that were assigned to the given symbolic variable. It should be followed by the argument name and the name of symbolic variable, separated with comma. When the symbolic variable is treated with "restore" directive to remove its latest value, that value is removed from the list of values accessed by "irpv". But any modifications made to that list during the iterations performed by "irpv" (by either defining a new value for symbolic variable, or destroying the value with "restore" directive) do not affect the operation performed by this directive - the list that gets iterated reflects the state of symbolic variable at the time when "irpv" directive was encountered. For example this snippet restores a symbolic variable called "d" to its initial state, before any values were assigned to it: irpv value, d { restore d } It simply generates as many copies of "restore" directive, as many values there are to remove. The blocks defined by the "irp", "irps" and "irpv" directives are also processed in the same way as any macroinstructions, so operators and directives specific to macroinstructions may be freely used also in this case. 2.3.6 Conditional preprocessing "match" directive causes some block of source to be preprocessed and passed to assembler only when the given sequence of symbols matches the specified pattern. The pattern comes first, ended with comma, then the symbols that have to be matched with the pattern, and finally the block of source, enclosed within braces as macroinstruction. There are the few rules for building the expression for matching, first is that any of symbol characters and any quoted string should be matched exactly as is. In this example: match +,+ { include 'first.inc' } match +,- { include 'second.inc' } the first file will get included, since "+" after comma matches the "+" in pattern, and the second file will not be included, since there is no match. To match any other symbol literally, it has to be preceded by "=" character in the pattern. Also to match the "=" character itself, or the comma, the "==" and "=," constructions have to be used. For example the "=a==" pattern will match the "a=" sequence. If some name symbol is placed in the pattern, it matches any sequence consisting of at least one symbol and then this name is replaced with the matched sequence everywhere inside the following block, analogously to the parameters of macroinstruction. For instance: match a-b, 0-7 { dw a,b-a } will generate the "dw 0,7-0" instruction. Each name is always matched with as few symbols as possible, leaving the rest for the following ones, so in this case: match a b, 1+2+3 { db a } the "a" name will match the "1" symbol, leaving the "+2+3" sequence to be matched with "b". But in this case: match a b, 1 { db a } there will be nothing left for "b" to match, so the block will not get processed at all. The block of source defined by match is processed in the same way as any macroinstruction, so any operators specific to macroinstructions can be used also in this case. What makes "match" directive more useful is the fact, that it replaces the symbolic constants with their values in the matched sequence of symbols (that is everywhere after comma up to the beginning of the source block) before performing the match. Thanks to this it can be used for example to process some block of source under the condition that some symbolic constant has the given value, like: match =TRUE, DEBUG { include 'debug.inc' } which will include the file only when the symbolic constant "DEBUG" was defined with value "TRUE". 2.3.7 Order of processing When combining various features of the preprocessor, it's important to know the order in which they are processed. As it was already noted, the highest priority has the "fix" directive and the replacements defined with it. This is done completely before doing any other preprocessing, therefore this piece of source: V fix { macro empty V V fix } V becomes a valid definition of an empty macroinstruction. It can be interpreted that the "fix" directive and prioritized symbolic constants are processed in a separate stage, and all other preprocessing is done after on the resulting source. The standard preprocessing that comes after, on each line begins with recognition of the first symbol. It starts with checking for the preprocessor directives, and when none of them is detected, preprocessor checks whether the first symbol is macroinstruction. If no macroinstruction is found, it moves to the second symbol of line, and again begins with checking for directives, which in this case is only the "equ" directive, as this is the only one that occurs as the second symbol in line. If there is no directive, the second symbol is checked for the case of structure macroinstruction and when none of those checks gives the positive result, the symbolic constants are replaced with their values and such line is passed to the assembler. To see it on the example, assume that there is defined the macroinstruction called "foo" and the structure macroinstruction called "bar". Those lines: foo equ foo bar would be then both interpreted as invocations of macroinstruction "foo", since the meaning of the first symbol overrides the meaning of second one. When the macroinstruction generates the new lines from its definition block, in every line it first scans for macroinstruction directives, and interpretes them accordingly. All the other content in the definition block is used to brew the new lines, replacing the macroinstruction parameters with their values and then processing the symbol escaping and "#" and "`" operators. The conversion operator has the higher priority than concatenation and if any of them operates on the escaped symbol, the escaping is cancelled before finishing the operation. After this is completed, the newly generated line goes through the standard preprocessing, as described above. Though the symbolic constants are usually only replaced in the lines, where no preprocessor directives nor macroinstructions has been found, there are some special cases where those replacements are performed in the parts of lines containing directives. First one is the definition of symbolic constant, where the replacements are done everywhere after the "equ" keyword and the resulting value is then assigned to the new constant (see 2.3.2). The second such case is the "match" directive, where the replacements are done in the symbols following comma before matching them with pattern. These features can be used for example to maintain the lists, like this set of definitions: list equ macro append item { match any, list \{ list equ list,item \} match , list \{ list equ item \} } The "list" constant is here initialized with empty value, and the "append" macroinstruction can be used to add the new items into this list, separating them with commas. The first match in this macroinstruction occurs only when the value of list is not empty (see 2.3.6), in such case the new value for the list is the previous one with the comma and the new item appended at the end. The second match happens only when the list is still empty, and in such case the list is defined to contain just the new item. So starting with the empty list, the "append 1" would define "list equ 1" and the "append 2" following it would define "list equ 1,2". One might then need to use this list as the parameters to some macroinstruction. But it cannot be done directly - if "foo" is the macroinstruction, then "foo list" would just pass the "list" symbol as a parameter to macro, since symbolic constants are not unrolled at this stage. For this purpose again "match" directive comes in handy: match params, list { foo params } The value of "list", if it's not empty, matches the "params" keyword, which is then replaced with matched value when generating the new lines defined by the block enclosed with braces. So if the "list" had value "1,2", the above line would generate the line containing "foo 1,2", which would then go through the standard preprocessing. The other special case is in the parameters of "rept" directive. The amount of repetitions and the base value for counter can be specified using numerical expressions, and if there is a symbolic constant with non-numerical name used in such an expression, preprocessor tries to evaluate its value as a numerical expression and if succeeds, it replaces the symbolic constant with the result of that calculation and continues to evaluate the primary expression. If the expression inside that symbolic constants also contains some symbolic constants, preprocessor will try to calculate all the needed values recursively. This allows to perform some calculations at the time of preprocessing, as long as all the values used are the numbers known at the preprocessing stage. A single repetition with "rept" can be used for the sole purpose of calculating some value, like in this example: define a b+4 define b 3 rept 1 result:a*b+2 { define c result } To compute the base value for "result" counter, preprocessor replaces the "b" with its value and recursively calculates the value of "a", obtaining 7 as the result, then it calculates the main expression with the result being 23. The "c" then gets defined with the first value of counter (because the block is processed just one time), which is the result of the computation, so the value of "c" is simple "23" symbol. Note that if "b" is later redefined with some other numerical value, the next time and expression containing "a" is calculated, the value of "a" will reflect the new value of "b", because the symbolic constant contains just the text of the expression. There is one more special case - when preprocessor goes to checking the second symbol in the line and it happens to be the colon character (what is then interpreted by assembler as definition of a label), it stops in this place and finishes the preprocessing of the first symbol (so if it's the symbolic constant it gets unrolled) and if it still appears to be the label, it performs the standard preprocessing starting from the place after the label. This allows to place preprocessor directives and macroinstructions after the labels, analogously to the instructions and directives processed by assembler, like: start: include 'start.inc' However if the label becomes broken during preprocessing (for example when it is the symbolic constant with empty value), only replacing of the symbolic constants is continued for the rest of line. It should be remembered, that the jobs performed by preprocessor are the preliminary operations on the texts symbols, that are done in a simple single pass before the main process of assembly. The text that is the result of preprocessing is passed to assembler, and it then does its multiple passes on it. Thus the control directives, which are recognized and processed only by the assembler - as they are dependent on the numerical values that may even vary between passes - are not recognized in any way by the preprocessor and have no effect on the preprocessing. Consider this example source: if 0 a = 1 b equ 2 end if dd b When it is preprocessed, they only directive that is recognized by the preprocessor is the "equ", which defines symbolic constant "b", so later in the source the "b" symbol is replaced with the value "2". Except for this replacement, the other lines are passes unchanged to the assembler. So after preprocessing the above source becomes: if 0 a = 1 end if dd 2 Now when assembler processes it, the condition for the "if" is false, and the "a" constant doesn't get defined. However symbolic constant "b" was processed normally, even though its definition was put just next to the one of "a". So because of the possible confusion you should be very careful every time when mixing the features of preprocessor and assembler - in such cases it is important to realize what the source will become after the preprocessing, and thus what the assembler will see and do its multiple passes on. 2.4 Formatter directives These directives are actually also a kind of control directives, with the purpose of controlling the format of generated code. "format" directive followed by the format identifier allows to select the output format. This directive should be put at the beginning of the source. It can always be followed in the same line by the "as" keyword and a quoted string specifying the default file extension for the output file. Unless the output file name was specified from the command line, assembler will use this extension when generating the output file. "use16" and "use32" directives force the assembler to generate 16-bit or 32-bit code, omitting the default setting for selected output format. "use64" enables generating the code for the long mode of x86-64 processors. Default output format is a flat binary file, it can also be selected by using "format binary" directive. When this format is chosen, special symbol "$%" can be used to get an offset within the output and "$%%" can be used to get the actual offset in the output file, omitting any undefined data that would be discarded if the output was ended at this point. Additionally, for this format "load" and "store" directives allow access to any data within the already generated output by following "from" or "at" keyword with ":" character and then an expression specifying the offset within the output. Below are described different output formats with the directives specific to these formats. 2.4.1 MZ executable To select the MZ output format, use "format MZ" directive. The default code setting for this format is 16-bit. "segment" directive defines a new segment, it should be followed by label, which value will be the number of defined segment, optionally "use16" or "use32" word can follow to specify whether code in this segment should be 16-bit or 32-bit. The origin of segment is aligned to paragraph (16 bytes). All the labels defined then will have values relative to the beginning of this segment. "entry" directive sets the entry point for MZ executable, it should be followed by the far address (name of segment, colon and the offset inside segment) of desired entry point. "stack" directive sets up the stack for MZ executable. It can be followed by numerical expression specifying the size of stack to be created automatically or by the far address of initial stack frame when you want to set up the stack manually. When no stack is defined, the stack of default size 4096 bytes will be created. "heap" directive should be followed by a 16-bit value defining maximum size of additional heap in paragraphs (this is heap in addition to stack and undefined data). Use "heap 0" to always allocate only memory program really needs. Default size of heap is 65535. 2.4.2 Portable Executable To select the Portable Executable output format, use "format PE" directive, it can be followed by additional format settings: first the target subsystem setting, which can be "console" or "GUI" for Windows applications, "native" for Windows drivers, "EFI", "EFIboot" or "EFIruntime" for the UEFI, it may be followed by the minimum version of system that the executable is targeted to (specified in form of floating-point value). Optional "DLL" and "WDM" keywords mark the output file as a dynamic link library and WDM driver respectively, the "large" keyword marks the executable as able to handle addresses larger than 2 GB and the "NX" keyword signalizes that the executable conforms to the restriction of not executing code residing in non-executable sections. After those settings can follow the "at" operator and a numerical expression specifying the base of PE image and then optionally "on" operator followed by the quoted string containing file name selects custom MZ stub for PE program (when specified file is not a MZ executable, it is treated as a flat binary executable file and converted into MZ format). The default code setting for this format is 32-bit. The example of fully featured PE format declaration: format PE GUI 4.0 DLL at 7000000h on 'stub.exe' To create PE file for the x86-64 architecture, use "PE64" keyword instead of "PE" in the format declaration, in such case the long mode code is generated by default. "section" directive defines a new section, it should be followed by quoted string defining the name of section, then one or more section flags can follow. Available flags are: "code", "data", "readable", "writeable", "executable", "shareable", "discardable", "notpageable". The origin of section is aligned to page (4096 bytes). Example declaration of PE section: section '.text' code readable executable Among with flags also one of the special PE data identifiers can be specified to mark the whole section as a special data, possible identifiers are "export", "import", "resource" and "fixups". If the section is marked to contain fixups, they are generated automatically and no more data needs to be defined in this section. Also resource data can be generated automatically from the resource file, it can be achieved by writing the "from" operator and quoted file name after the "resource" identifier. Below are the examples of sections containing some special PE data: section '.reloc' data readable discardable fixups section '.rsrc' data readable resource from 'my.res' "entry" directive sets the entry point for Portable Executable, the value of entry point should follow. "stack" directive sets up the size of stack for Portable Executable, value of stack reserve size should follow, optionally value of stack commit separated with comma can follow. When stack is not defined, it's set by default to size of 4096 bytes. "heap" directive chooses the size of heap for Portable Executable, value of heap reserve size should follow, optionally value of heap commit separated with comma can follow. When no heap is defined, it is set by default to size of 65536 bytes, when size of heap commit is unspecified, it is by default set to zero. "data" directive begins the definition of special PE data, it should be followed by one of the data identifiers ("export", "import", "resource" or "fixups") or by the number of data entry in PE header. The data should be defined in next lines, ended with "end data" directive. When fixups data definition is chosen, they are generated automatically and no more data needs to be defined there. The same applies to the resource data when the "resource" identifier is followed by "from" operator and quoted file name - in such case data is taken from the given resource file. The "rva" operator can be used inside the numerical expressions to obtain the RVA of the item addressed by the value it is applied to, that is the offset relative to the base of PE image. 2.4.3 Common Object File Format To select Common Object File Format, use "format COFF" or "format MS COFF" directive, depending whether you want to create classic (DJGPP) or Microsoft's variant of COFF file. The default code setting for this format is 32-bit. To create the file in Microsoft's COFF format for the x86-64 architecture, use "format MS64 COFF" setting, in such case long mode code is generated by default. "section" directive defines a new section, it should be followed by quoted string defining the name of section, then one or more section flags can follow. Section flags available for both COFF variants are "code" and "data", while flags "readable", "writeable", "executable", "shareable", "discardable", "notpageable", "linkremove" and "linkinfo" are available only with Microsoft's COFF variant. By default section is aligned to double word (four bytes), in case of Microsoft COFF variant other alignment can be specified by providing the "align" operator followed by alignment value (any power of two up to 8192) among the section flags. "extrn" directive defines the external symbol, it should be followed by the name of symbol and optionally the size operator specifying the size of data labeled by this symbol. The name of symbol can be also preceded by quoted string containing name of the external symbol and the "as" operator. Some example declarations of external symbols: extrn exit extrn '__imp__MessageBoxA@16' as MessageBox:dword "public" directive declares the existing symbol as public, it should be followed by the name of symbol, optionally it can be followed by the "as" operator and the quoted string containing name under which symbol should be available as public. Some examples of public symbols declarations: public main public start as '_start' Additionally, with COFF format it's possible to specify exported symbol as static, it's done by preceding the name of symbol with the "static" keyword. When using the Microsoft's COFF format, the "rva" operator can be used inside the numerical expressions to obtain the RVA of the item addressed by the value it is applied to. 2.4.4 Executable and Linkable Format To select ELF output format, use "format ELF" directive. The default code setting for this format is 32-bit. To create ELF file for the x86-64 architecture, use "format ELF64" directive, in such case the long mode code is generated by default. "section" directive defines a new section, it should be followed by quoted string defining the name of section, then can follow one or both of the "executable" and "writeable" flags, optionally also "align" operator followed by the number specifying the alignment of section (it has to be the power of two), if no alignment is specified, the default value is used, which is 4 or 8, depending on which format variant has been chosen. "extrn" and "public" directives have the same meaning and syntax as when the COFF output format is selected (described in previous section). The "rva" operator can be used also in the case of this format (however not when target architecture is x86-64), it converts the address into the offset relative to the GOT table, so it may be useful to create position-independent code. There's also a special "plt" operator, which allows to call the external functions through the Procedure Linkage Table. You can even create an alias for external function that will make it always be called through PLT, with the code like: extrn 'printf' as _printf printf = PLT _printf To create executable file, follow the format choice directive with the "executable" or "dynamic" keyword and optionally the number specifying the brand of the target operating system (for example value 3 would mark the executable for Linux system). With this format selected it is allowed to use "entry" directive followed by the value to set as entry point of program. On the other hand it makes "extrn" and "public" directives unavailable, and instead of "section" it expects the "segment" directive followed by one or more segment permission flags and optionally a marker of special ELF executable segment, which can be "interpreter", "dynamic", "note", "gnuehframe", "gnustack" or "gnurelro". Available permission flags are: "readable", "writeable" and "executable". The origin of a non-special segment is aligned to page (4096 bytes). EOF fasm/fasm.x640000755000175000017500000035161114533375770013613 0ustar privalovprivalovELF>@@@8@@@AAQ% @)H%H $H\HM6q @++ $ @`A1Ë؉% z1;|^}88 @b`A1;Ë0+s61һd t41һ Hd$$W.&$Hd$C @. @0T @CHsf`ZSfKdH HH8A*BH3<-t2= u=uDHƬu HtHH3 t@s܉)>u HtHH3 twfcHH/=CtNg)AÀ>uHqHH3A= ]=DM렀>uH=HH3{1¬< tt,0r< wk p rHÉBs0<=t< ttBsguì< tt BsH΁Bs0Ë=fu=XÉ%.1  2 uAL9u?g< AL9+E1IAb1 tAL9uAsQHǸ A"H t AL9uAsV @Hd$A @D$@g<0=2/<H8H3Ht'Hʬg"<=tt(t u [output] optional settings: -m set the limit in kilobytes for the available memory -p set the maximum allowed number of passes -d = define symbolic variable -s dump symbolic information for debugging ( kilobytes memory, x64) passes, seconds, bytes. failed to allocate memory within 32-bit addressing rangeHd$AAD$wHd$AAD$cHd$AAD$OHd$A*AD$;Hd$AAD$ Hd$AAD$Hd$AAD$=Hd$A7AD$\Hd$AFAD$HHd$AYAD$4Hd$AmAD$ Hd$AAD$ Hd$AAD$Hd$AAD$Hd$AAD$Hd$AAD$Hd$AAD$Hd$AAD$Hd$AAD$Hd$A/AD$lHd$AMAD$XHd$AhAD$DHd$AAD$0Hd$AAD$Hd$AAD$Hd$AAD$Hd$AAD$Hd$AAD$'A A=Hd$A'AD$=5gv gG gguð'gNgf'fÿ'AA=6t5.gv t gG gG %AHd$A'AD$Hd$A2AD$Hd$AHAD$Hd$AVAD$Hd$AcAD$Hd$AAD$Hd$AAD$Hd$AAD$Hd$AAD$uHd$AAD$dHd$AAD$SHd$A AD$BHd$A'AD$1Hd$A;uuKg>u>gVgTgf:u,'AgBggBggBg=fix  5*n5gg<Nr#Hd$<$wA<$Hd$rgB;07rgC;{ 5g<:1<g<u-'AgggFggFg=equ9Hd$T$4$5`5^-WgNrqgJ g+ /gwg{g=grgJ  _:gf;gfߋ4$Hd$gr $Hd$ gBHd$<$gw)g<$Hd$ǰ:ggB4$T$Hd$8 )gnsgtg>:B;gZgJ 9t&g;u gCg\9tg;:u g;:uIg)gz Hd$<$gHd$$9trggtg|ggJ |$)grg<$t$Hd$5#4$L$Hd$Hd$l$|$4$$<uIvDf__gf;u:gf;Du2Hd$,$wA&,$Hd$r 1 A g tc1guqŁ 1ʼng t21gug tgzv gt4$g u4$|$l$Hd$ Ë$|$l$Hd$ 1۸ŝg28rHd$|$4$1t-t#Hd$ $ɿwA/ $Hd$Ł 1 ͻ A g tk1Ńgug t!tt<J)gtgg0g5Ⱦ=¾ggg{Hd$4$1gB 4$Hd$gr$ g<{ t"kbYPh$ ^ m5='t@gt<{t<"t <uggΉ5g<{g<,t*<"t <t<=ug<t<"tgg0Hd$ $g<grt gB΋ $Hd$g<,t%vQHg<t&<"t <{t ug&tgNgƊ-5r=gJ gR$g<trg<"t7<{t@u)g;9sgsgfgggt $))g)g4*gƊ-fYgNgf\MHd$t$<$g30gً<$Hd$gD;4"ggg4$Hd$&gG;LgK<vt gCtg[0҉g<`t<#<t<;t <"t$0uމÉòggg>\t"ggOƃgpgFٻ'Ag׉YgFg0IƉg<ugfg_g*g>\u$<"<`tg_1t<#t)w"ggg9Hd$ $gug}gN)g$Hd$"gWggtt"tJ9g>uggg>\tg gmtgg'Auރg>"tBg>`ug<`t<"t/<ugg g>\ug gt<#tgg gggg<`<#Fg<t<;7<"t$0uòggg g>\9g븲"gggHd$DD$Hd$D3D$%Hd$DeD$Hd$gDBD$gBHd$$grgB ׸)1g<{<[u 9g<,t<]t<&g;,ug;,ʸgȋM1tg>*t"g>:tg>=uƉ5Z y: ƃ Cgr \g;&t ; gB )gJgzu tgB gB )g8wgFgtg=Jw4<:t<=t<*ug<,L@1 Fg>,2$<,&=tg<{1Hd$DD$Hd$DD$Hd$DD$==tDgHd$$g5dg;,uދ$Hd$g5;gnh gZ g;tg;"tgCgCgBg;tg;{ug<gHd$$gjg tgBvgNgt$Hd$Hd$DD$Hd$$5egȋD$, Ӌ$Hd$gJ gBgC gKg t g;ju $u$Hd$gNg>g>{-5g<t<,;56 ;dgZgrqr?grgCg\g;t;5g;tgZgCg\gr# 9]gZgCg\g;tgrrgr;5Bt#g<t<"tgFgF;5tg&g<,t<t <=tttg<t<"t8tg[gvgKgKguÉƉg;,1Hd$DVD$Hd$DvD$lHd$DD$THd$t$|$$;<$t(g7g1 gGgB gO)gJ Ӌ$|$t$Hd$ Hd$D+D$ Hd$D#D$Hd$DD$Hd$DD$Hd$DD$Hd$DD$Hd$DD$Hd$$Hd$D_D$g<{t*5Kgt<{t<;޹5(  1b9`tTg<} Ή=ޯgG;CD$ tgg$ggA$gx;t"gxuHd$$g$$Hd$ggxgg  Hd$\$ $tf;gfg;g<}/'<t"<;%bg<"ug}Hd$t$<$< t8gƿwAs"‹<$D$Hd$gNj $\$Hd$%gƋ,sE19tp<$D$Hd$gJgR  19tHd$t$$)Ӌ$t$Hd$r9wHd$$$Hd$+<$Hd$Hd$ $gJgR rgg;*tg,lj֋ $Hd$Hd$<$)닋 $D$Hd$L%t>11Hd$L$$"$L$Hd$; g,˃}ٰ-gfgfHd$<$ȹʚ;10Hd$$u tt0g1ҹ $Hd$ uʋ$Hd$)gCË<$t$Hd$gggg>.u"\$ t<t!gNgOggBƇgNgOgD$g8;"g8u g;\$Hd$t$<$g{gwgN)ggf;<$t$Hd$gg<t<;t<"tuggHd$$3$Hd$ $\$Hd$<}t5ҫD$DHd$H D$DHd$D$DHd$D$DHd$D$DȫHd$$Hd$$%g<gG;0gHd$ $gȋgz E=gl;-nİgfg?gHd$4$A g4$Hd$g+B gB0gAggg<:r3ugA*g<[r#ugag<{rg0ggg0 $Hd$g<}<,]g< tAE=tT!k%=ft4S D5 ;5ͩtP=tG|; t7=t 5 Hd$ $2r&g t $gzgtg $Hd$Ë $Hd$ȉŻAg t1g uHd$\$,$r5gѨ;$Sgggr,$\$Hd$Ë;!1ggBgBgB gg uă1g<"gg<oHd$4$Hd$<$Qg3gCtg[ggu;<$tg\t g/tt$a$Hd$st-g>t?Hd$,$Hd$<$at$t$a$Hd$,$Hd$s)빉4$Hd$<$\a$Hd$<$ggu4$Hd$gO)gNHd$DD$%$Hd$$%s 1SQOY5=ݦ5g;"Qg~g~;ggЧg>Hd$<$gNg<:tmg<=yg<u-Hd$t$ $gtgN $t$Hd$<$Hd$f1;<$Hd$n g~:tgg0g=gg-<$Hd$\gg0gf1 $T$Hd$<$Hd$Hd$D$\$4$gN gg4$\$D$Hd$ gHd$<$<$Hd$°gfgfgf f' f ffZ  f/q )gt#<:h;5=ߥt$Hd$D$DHd$0g=É+[=Hd$D|D$fHd$$xf f Ifg>,Hd$<$g( <$Hd$s°gfgfggf tf' t f t=f;\$ դ$T$Hd$f  Hd$<$0g4$4$Hd$<0tC<1tK $Hd$<$Q0g4$~4$Hd$<0t<1QgJ $ $2=f|$ g<Hd$<$g <$Hd$f $uG°gfgfg Hd$<$0g4$4$Hd$g $,$K$l $;5#c5/g>uXgg<:tHd$<$ <$Hd$s .gtf tCf' tuHd$<$gZ <$Hd$sxgDf tf' t f t=/ f;\$ $T$Hd$f gӠgg g=šf|$ gtn<Hd$<$g <$Hd$f l$u0$g>gN g,$$$ $"fB8fM/ff7fv%fefjfftf#t ft Рg;g<:[<,b<=<|R<&J<~B<><<<)(g<[:<]<{<}<#<`<;tb=1t<-<Hd$<$xALuggs.0g>?&<$Hd$g_<$Hd$gfg>+mf%f=`_gX<$Hd$<g<<<S<A<<gg>|Hd$<$gss<$Hd$N<$Hd$°gfgfg(g )gg>:ug딀 g>Hd$4$g$Hd$tgg0g_Xg>NHd$4$g$Hd$tgg0gg>Hd$4$gHd$t$ $Hd$<$ -!<$Hd$r <u H gf먋 $t$Hd$g,gfgf$Hd$Hd$\$t$<$xA <$T$\$Hd$ <kևgf(gfgg0gHg>"tvg>Hd$4$gNf(gfggfgf4$Hd$g>gưgng0gg>"g>:f(gfggg0gHd$t$<$xA)<$t$Hd$<gvHd$t$ $wA $t$Hd$uCla<$Hd$g>"uxgFg\Hd$\$ L$t$<$H$T$L$\$ Hd$9ljf(gfggsgsgfg0g(g)gg>(uq+`=Hd$t$<$ưggGg>=iư`gUg>>tg>=Eư<ưvG0mHd$$\$Hd$R0EHd$$4g>:ug''g<]t<,t ΰ)gf),gf뇰]g[ggf>u[Hd$4$g^g>:4$Hd$u>Hd$\$<$<$t$Hd$r<u0u0gHd$<$`xA<$Hd$^pgUg>(uưV Ng=j H=Qg>)u ՙ<$t$Hd$=t Hg>.t$r t ˉg~@tg>umHd$,$gHd$<$<$Hd$'Agglj9ugtr݉։,$Hd$0gt*,$Hd$gg<"tg?rwg:Gt gg|gGHd$4$ whrcg{xA{xAg}xA tGg}g<'Agw@g>.?g~.4={'Hd$<$=)Hd$L$4$5Pg);=~gfg4$L$Hd$fg<$Hd$Hd$\$4$gCI4$\$Hd$g;Xu gSjÃgF'Ag<@tO%tig>$tg>?uyutƸÃt9weƃvg~$tg~%tI1øøøøgf~%%u%Ãwƀtg'Ag(tKru tgGgugfugugGgGgGggGgfHd$DD$rD$DHd$g<)tΰ!ËHd$|$4$gf<u:r0<u,tct[ sVtQ<#tM<%tI<&tE<'tA4$Hd$xA8<$Hd$ug<g gGgø$|$Hd$gGgg<gϺt:Hd$4$grHd$DD$[D$DHd$4$Hd$=-(@|ggCg1g<"<;gȉ5Fg<$t ,0< Hd$4$ggGg;$Mgf;0xFg'tSg>_tM1ggggGr0r,gGr&r"rgGg,0r2< w.ggWr9wg<'t<_t,0r< w X$Hd$50;5 6g<'t7<_t3,0<w1҈΀@tÀ sg ɀ g Gt뱀t0;5g<'t`<_t\+tg>-ug>ugut4$Hd$g<t <+t5g1ҿ\AggWgW ]gg<.tn+tg>-urՃgg,0< sk \A t@ uHd$ $ v $Hd$Hd$ $ $Hd$\A:gG /gG gGt$ggWsgGg gGgfG<$Hd$ gG gG g؃ggG؃gG t0ggG gGggGgGggG1gGgggG gG g g _RgGu ggGgG ggG gOى1gG ggWs!gGggg_  gGgGg{t_gtVgCg;G}gGb[gS gg[gW gg_s!ggG gGg gGgGgggCgGgCgGgC gG Hd$ $g+KgSgg+gk ggCgS $Hd$ggog /g o t#gGugGgo ggg gOgG0Hd$<$w<gƀ|t&tGt$Hd$<1tw<0t]Hd$<$g/$Hd$<0tM<1ug0<0tY<1t.Hd$<$g$Hd$<1t<0ug0l<$_0V,r<$1Er <$04<$Hd$gg>~ug~ugg>u`ggHd$,$ZHd$$C$Hd$?,$Hd$uuggW)t4É1҉نgtC-s=u tg,tg>>t ;4$s`}=)9u5gu*g>>t ;4$s=Z=;4$u/4$|$Hd$g<,t;4$u4$|$Hd$4$|$Hd$%1fʄ2|t5=1><ڃڃ8>ăs;tg@ PP;Ƃg@t,f Ԃgf;Hug@tgf+Hfu g` g@t8f g`g@ ugf;Hug@tg@tgf;Ht ڃg@@t?g`g@u,f Vg@ugf;Hug@tg@tgf;Ht  4=uA tW+=@u} tg@uo-a@$fсfʁf; Ë#tgC ]g+CgC$gCgC$,9݁1g;gCgCgCgCg{gCgC ËՁ-9ͩg< < <G<t <t<g<g]g%N=ЀtK=7uBWgCgC9A6gg{ gCgCg>b1g2gω10ɋ-g+EgUgMz- gE u;gK ggSgk g+gS͉Ѐ΀-g gc g;gg;SgSċ-Bgm "gUgmg2C $g0C g:K gK g:k gk g;k gk t g;SgSf mgfKgSgcgCt?gf;K$gs r$fgf+KtgCtf "gf;Ku ~gKgƃêHd$$ 2=.$Hd$0Ɋ-8Zgc g;gg;SgSĊg2C $g0C g:K gK g:k gk 1g;S gS t?g;SgSf Y~gfKp~gSgCtpgf;KugCgKgc gs r;fgf+KgCgCf }gf;K BgKgKf }g@tgf;H|g@ u ~gfPffgfPgfH}gP}ggK %~%~ggF$~g<tGg<(g>.+ Z~|Hd$$S}g+CgCgC u3 'gK $Hd$gK ~g)gSgKz*b}gS=}F;=|:=/-B}"g<gӧ Ɖ}g<:t<ugf<ť%t}g>t g<(Hd$\$ $gKg>./,ņff݋ $\$Hd$gc-}7gc g;gg;SgSċ_| |@g<g'Hd$$g>ugg<|%{%{g<ɤGr"Hd$t$<$޿TAg<$t$Hd$U|{{$Hd$f1 g<:4<(k0{g+KgKg>urgf~):uigg>(;ƃR@g@@gfHf; hzg@ fNzgfCgK$gHd$$g>.դ j{q*,$Hd$-=t{u =c{1ʉg+EuJ ){g;Ew<Ã=\zuHd$DyD$D$D?zHd$8z*zc 'À=zZg<((g>."'=ztlyr zrygB u9w;ywg>tg<(ɢE&1Wz OzZ(=^zyyg<Hd$t$<$TAg<$t$Hd$;%yl;y` yUg<(+g>u=gHd$<$=x);<$=xgg1g<$Hd$1d%Hd$<$=x =xggg<$Hd$;=xg<,lx t<5Ex9t2gFg)΃t"uHd$4$赛4$Hd$;5AxugN gHd$4$=w5w1۬;=xt.%g>:uHd$DCwD$Hd$D7wD$-ww+v=9Hd$4$ wv9vtv4$Hd$뻋$Hd$D$DvHd$D$DvHd$n/sg<(.O&-v<΋-YvgE ?w10g+EgUgM +wgf]gfMgm߆fHd$L$$ vgC uv9t=ugK g>uGgf~(gNgKgK gK Hd$$'Agggׄ՞Ƌ$Hd$$Hd$ zvуggSgKD$gDCHd$gkg~)gƃ@g@@gfHf; t?@g@ fsgfCgKggC tlgc C@tHd$4$grgJgB )g;>t=)g)Bg)gZgZgg4$Hd$;=szHd$D}sD$D$DsHd$ssIDHd$$N$Hd$gC ~sg{Hd$t$<$+ sgsg~gss<$t$Hd$Ë. $gf' crgCPrgCgsqgC%sǝrr9rvgCrgCqn8gs/gb< f=' UrG`gf qgCgs,qgCHd$$A%u4g< `$Hd$gCIq$Hd${rgCp qgsw?f= qy$gS<pu g<u.gf~ u%0Rgf gC-pgC< Xqf +g{g<ugf~ uMsj<EKp_)$f=Z t f= f f= SHd$DoD$Eoo\(sg<uvg*og>ug>ugfFf=B8tσf=' tZf= t^f= tbf=Z t&f=ug>ugfFf=' t f= tf= uD$D*oHd$Ëon鎚9bXNrg>ugf~ ug<gff=%f=' lf= if= f=髗ngt<;mgff=' tMf= taf= tHd$DmD$gCm9D$DmHd$$nHd$$4$Hd$Hd$$;=mg>(&g;" g>uEHd$D$4$;=mDD$Ag<,t<$D$Hd$tq;=jmiHd$D$4$DD$AЋ$D$Hd$tu%=g>u%;=mD$Ag<,g<(tt]ggg;lgË-lgE t;|ltpl=nlÀ =m4myg<(ttgfgggO;l0ggf7g<(t:tFgÉg>.ѕHd$$g<(ܔilHd$$g>.gf$Hd$:tgfgfÉg>.?Hd$$g<(kHd$$g>.a<g$Hd$}k$Hd$gfg<(t.gf~gggFggfFf?%f=fSffff@f wggV f 1gFsgGgWf1tfg^ ff gf 1gggF fgf Hd$$g>:g<(jHd$$g>.Lpgg$Hd$i$Hd$gfgff( gFgt1dHd$$1g>:u8g>(֑g>.ΒHd$$$Hd$)$’g>,uAg>(g>.Hd$\$$$\$Hd$;$~$0Ί $Hd$:;=/h._ϐDg<, =Hd$4$Hd$<$gg0g@tg@u;<$tg\t g/tt$ $Hd$5spgHd$T$4$t$!!t$t$ $Hd$$Hd$s-g:u4$Hd$<$ $Hd$Ɉ؏4$Hd$g<(;g>.5t;gHd$<$=gt1sgsgfg$Hd$#g<(яg>.ː ;fHd$<$=Vgtg.mH@8;-f,Hd$<$=ft g<51g+g<(g>.Gٍэ;eōHd$<$=f5g.zrj;_e^Hd$<$="f7g.@;dHd$<$=elg.ގʅ -{dg+Mg}5g} tB=Wet.=Neu dug]g;g;Cv=!n.;#d"Hd$<$=dt/-=c-ccc]@sgsgfgg<C\=cc}cwc1@=|c7dg>g>. Oc 9Ig<<+<1<1<G<'<G<)<]g+aggCag bgOsa b kat agggCggOgC  gC gGgC g8up 0gfGgggCgG gC twagjaY:\aH`-q`gE u;`u``-T`gE tO`k`=1aM+_YP`10-`g+EgUgmz gggEggM gfgEgG_g@볋_g1g ȅgg { ttЃt߃t:]@ @@f=^w _` N`gfg 1gg =b_^P_N_@_0gc gG t#tu gOg;Kt: gOgKgc gggGgCgG gC z f Hd$4$gO gGgO gG 4$Hd$ftSg8FugN ԈuAgFg8F ugN u)gF g~u gFgN g~ ]gF gN 0gc gG t't8u 0gOg;KtO ؈gOgKgc gg)gGgCgG gC z=]u f Hd$4$gO gGgO gG 4$Hd$pYf tgf{u1g gg rHd$t$$0g~ t#ggV҃ggV 2g tEg~t g^ )g~ t g^ ggW҃ggW g~t gtgFg' ggg gg'ggVt҃ggV ug^ $Hd$f t\gfg~t!ggn f8gF ugFg~ t!?gn f8ggF ugF 4$Hd$$t$Hd$gfg;W'g;Hd$t$$f$Hd$f tRg~t"gF fg?gF g~ t"gF fg?}gF 4$Hd$Hd$4$ggVg~ 4$Hd$ggWgO g!g!Sg K ggWgO g g SgK ggWgO g1g1Sg0K gG ggWggWr?g gSggu&gK g@t w s4gggS;g{ uBgK 9u99u51ggC, ggCg#g;ugC g;2gG ggWggWsgOg 1gSgguNg@sFHd$4$gs sggS4$Hd$ ggs4$Hd$ygC ggChgfg tggWgW =gfwg t1guS gGuGg u@7gf7g tRg uԹ gGu1gt1ggWgW gt g_ g t g_ ׂg_ 110ggWgO g)gWgO zbgf~Y<<<~XuE%Xr0g8G tgG Wg@41g)gWg_ z!%Xr0g8G t;gG WgP4g@0TXu*HXg tgW 0gG ugf=XWWtgg Gug8w ugGg8u1g?ugu=9X!g~ t$ggV҃ggV \fg t#ggW҃ggW 1gu ggF1gFgg1Hd$$gF1gwgggfg'9wr"9s gg+gWs)щʉ؋$Hd$[Hd$D$$)1gwt3g)Hd$$gg)D$$Hd$g')D$$$D$Hd$닋$D$Hd$t҃ utggVggVgg Nug^ Ã=\Ut3=Vu*Ug@g@ 9}Uggfggfg rV<<pt11gf~gf^ggV҉  ss fffifOffff5Jf r f 1fst f u g^  ggW 1gf~twgf^gfFffsff s f%ffff~f/f ffff ~f1fsfftf%ff f o~g^ ff g1gG 1gf~trgf^gF ss %fff~f0 ffff}f1st%f }g^  g1gG g}1ggggfggfg +T TktfggWg t u=r Åu=s11҃=Su1Hd$DRD$D$DRHd$Rq@ SÃ=Ru*Hd$DcRD$D$DRHd$R?@uS [S<rggWg tZ=OÅF=;"S Sb<u'Sgg;W: RggWg t ÅR R<uggWg t ÁR eRggWdR JRgf{NRgG tg u ggW uÃ=NQuP@Q:Q]@1Qgal<(>{Q<<tw<tj<t\<tK{QggWqgfzgGQgG QgG QQ?11!1FQ>QQQC/Q'Q:Q,QQ#QQP Qg>.%zgGUPgG PgG P<tm<t<tw u@%PPt<8t8f=t f=Uy=}PutPgg;Wt=Oui11Ɋ RP-BPgfcgGgW gG gW ft t8< <<%Ot8y<<< t/x=O8F<x$8xxtx=OggWgg;Wjg:W `t uusxÈtMtH tCEu5=O@t,=Nu#=Ngfg;g;Wuɀ=NRN$<U<<2w=N@uGDt,t'=N@t%Eu =bNt둀Eu=RNu|Ettmsw Xbw0t)<t =!N@u(<u$%Nt83w$|tg>&t u8Hd$$$Hd$tHd$$z$Hd$ Hd$$u$Hd$L |LgJgugG g ugG gGKgG eLg_ ggWgO0g>~u4Hd$$g<<Lu<<<T<0<1<(DuQ=KHd$D$$Hd$DHKD$Hd$\$ $g<<<&<|ƈKg>(t:\$u$t J;\$u; $t&; $t=[Ku H$Hd$f$H $l$Hd$=%K=tX=K$=Kt>=J>tI=J(u0E<EnÀ=En$Hd$gfEg_<<[m?`Hd$T$\$ $g<,mg_<(t@<mg_4E $\$T$Hd$ <t aEgb|D<r?tB<ty<<xm=Dm`2=Dm2CDD $\$T$Hd$ DqgK`fCfD`D $\$T$Hd$ =WDu=IDuf=Crf=yCsDgDfz_ECCC $\$T$Hd$ =Cu=Cu= Cr=CsCfљ9t=CuCgB]qCg<,kg]<t8<(tb<[k^7C<tC_2C&Cg\CC<t _B_iB<t=<t{<<gk=Bk^!=Bk~ŠBBtBs_gwBgg8^fŠWBQB=XBu=JBu fr&fs t1$B _fלgfB^gpA|^]ŠAA=Au=Au rstA^[g A^=@u*Hd$DB@D$D$D@Hd$@ @KAHAg[<t3<[i\A<tr&]AgZÈ<t \@@gO[<<<[@i[Hd$T$\$ $g<,!ig[<(< ig<0r<@GZv@ $\$T$Hd$ t"X@[\N@,""uRDu-whx<= @ur \b?s\(aQ[b?=?@iF\gfi=?@uňu? ttð@h0[c?[`"uDDu)wh<C"=F?ur7[a?!![a>+ [>,1> $\$T$Hd$ %>t Ng>><rgsZ=>vg{7=V>L>Ƌ $\$T$Hd$ &a騿Zfr=>>Nj $\$T$Hd$ aoY:===Nj $\$T$Hd$ `7gĀ yxW=g<,fgX<[<(=<<egĀ u'.W]=W=<t SYC=A;=$1=e == =t==t=<eX XX<g<Me <<<=<@t/=<3e=<u=< u g<=m<epf<5WP<<t Q<VXI<'4<t"uDDu)wdl<C=<ur X^;W^;W;S"uDDu)wqd<C=;urWZ^r;W6^\;mWK;5;<tj<t}<<cWр=!;u=;s 9Hd$D$ $x$D$Hd$蝕ggH°Ng1CfV1f_gf vVm°=g%s:t \:AY:VɊN:G:=:%W번$/:b<b :g<,bgvT<[t*<sbgSt sb9T9t<Nb9gb"%9$99g<,a6SÀ=9@t+a=a9u=V9"u gK9Fta29gS<\<[aSHd$T$\$ $g<,zagjS<(t;<gagR8 $\$T$Hd$ <t T88<r4@\O\OP9Ê353t#t.tFk\t tt/CQ\O3A\=3@ \O$\=3@[<@[,1[<sd3=x3@[J,F3>31(3%53t t8[<<<tVt|[=2t|=2 t7=2@5[)€=2=^=2@ZolN=2="f+N=b2u-f|'f=}!:2jNgjfM2hNfΌgfD=2@fZZ=2@PZM1h\N臌gg</'%1e1g L<<[ZWLr1%1<t&<t2<tKYttt4CYM3Y=H1@YMY=+1@tY10SNgĀ Jt 0A$X0%0<tB<t!<t?Y6Y=0@Y+Y=0@X^LY=LLg<ϱDZ%?0405A0<2Àt#t.tFXt tt/CXK3X=0@KXKcX=/@.X<@8X,10X<sV/=/@X'=/Wt XtWWg,L/D/9/gI<tK<[tWI/<trK//p..gHð..<t1J=.@t.@..K...gH<t&<[V?I=Y.VZ.BgHV<.7=H.@V .cgH<t0<[VHg<,|VG-|VgGgVg<,GVG-=-@VdG-g<,VgH<[VWHr-<t<VvIe-bPgGtU<(U=Q-u=@-eWVHd$$-g<,UgvGtU<(jU=,uDV‹$Hd$gfgfg/=,@U =,@U|H dHH%,},gte<tagFt tT<(T=a,u=P,uVU=6,uf tfHfgf醭 ,Hv=,@pGfG\GR+E+g<,7T0+Hd$$gF<[T +bF$Hd$u+Gft<tg+_+V+M+ŀ=a+@SD8+g<,S+gE<[SE*<t <t< tSFFF*gCE<"<[B~(g<,P](Hd$$gB<(t6<Pg<P$L$\$T$ Hd$4D%((t<PS'$L$\$T$ Hd$CJUgA'g<,FPA''Hd$D$$g<,P'gB<(t.<Pg<O$D$Hd$tCe'bN't<O‹$D$Hd$?CDg靨 ''@'Hd$$g<,yO&gbA<tP<[_OA$Hd$%&t&8TOtFO&B<tg`@$Hd$8Ot tOvBjlB]&ZQ& @I&Ng<,N!&g@<t-<[N@=&t =%NAg?vNA%%%g.@<<['Nx@Hd$D$\$ $g<,Ng>(t4g>ug~(t'/?o% $\$T$Hd$ _A@0=%Hd$$g?<(M %t<Me$$Hd$t& A $\$T$Hd$ $GXWg>g<,FMg>(t$g>ug~(tm>$@0$Hd$D$$g><(Lj$t<L;#$D$Hd$W@G$.A#g骥/$'$r$@@=#g<,mLg]><t<[2L>g=È##r=#;L-L##g=<t3<[KD>_#<tri?Y#D:g=g>,tÈ<t :?*#("#g>(~g>u g~(mgp=<h<[iK=Hd$T$\$ $g>,t."> $\$T$Hd$ ""g=<(K"<t2<t~< K="xK^>=n"aKZ#>f!=N"u=@"u f|f=|p $\$T$Hd$ "iE{=F!=!u=!u |=|! $\$T$Hd$ !iD, $\$T$Hd$ !kD !)gR;g>,t=n!h!eg;<(I@!<t><<I=. Fg;:= E}<<t"<tvE==w@tX=n@D=\ugfrSƒq =9@gvgx=@Dcљ9esİgfC=tgf,7rҀ=Eʊggf-À=vt"w=dt=lu =r6s1À=DC=Pu =?dEs=sÃ=L:4!@h=cC=@BCTHd$$g<(1CHd$$Hd$DD$g>.Cz<t<t`C=uO366fugfD$DHd$$Hd$C$Hd$tgf铛56tg뱈%g4=^BP4<(QBg>.#C<<t"<t|=B==@t^=@BW=ugfrYƒq =t@9%Mgfsg魚=K@Aљ9sĊgft= tgf]hr΀= Cf%gfgf'=@A=t(g= tyg =@@mg#3=f@2<(@g>.A1<<t"<t@=8=+@ta="@@=ugf[ggf=tHd$$g$Hd$À=@2@ љ9l<=tgfg1<[?"2 @@=;w@Hd$$g<,?g1<[?1$Hd$ A@9@8?@@<t<t=@?9=@l?l912>Vg0<[>1 |?t?&t$Fta?=/@>8=@>812UgM0<[N>0  ??'t$Gt>=@i>u8=@S>S8=}>mg/<[=(0 >>BHd$D$$g<,=g/<[=/ R>J>$D$Hd$=1>8= >><t<t=@t=7=@^=^710g.<[<=/ =='t$Gt==Z@=7=D@<6=W=g<,,t Ԉgfً2g$<2ga$Ԉgf髋. ) g$<2gB$ g<,{2gk$<t<[h2$g $  g3$<42g# g<,2 g$<t<(t <[t1M^ 2^ $pO  F +&g駊* % "t=. @11 g<,k1g[#<\1g#=tjHd$\$L$$0Ɇ g<,1g#"1 <(1T$L$\$Hd$ Q+ӉE%ĉ<g<,0g"0<(0Èg"<0g+"g<,]0gM"<t,<[J0"==?0go!*04} nnhpg!</g!:%Q/Bg<,/g!<t<[/!VgA!~gj!<t$<[g/!i/gmf.djaMQ==8g<*g g<,*gx<t|<[u*=t8i*%,ug<h)gIY)Èfsg-<.)gEfDp$g&^JJDg< <[(%= t8(g<,q(ga<b(gCºfg%<vgg<,(gwrpg<'gQg<,'g<' fg<'g/8'g<,e'gU<V'gͻfPmt.'=@ '}g<,&g<&\f\Wg<&g=(g<,&g<t(<[&=t =&gx&g0<1&gg<,&g<t6<[&Q=kt=bt=Y%NDgt%/62f"g}<~%g)%q-%p8Pqk:eg<$g}1Eg<,$g<t<[$YgDJgg<h$gl$g<,H$g8<t<[5$}g*$~g|ypfflb8NC 8,f/: +`Dgr<tu<[o#=t =h#Hd$T$\$ $g<,3#g#<$#g $\$T$Hd$ gKHd$$cg<,"g<"gK$Hd$<<"=B@":fgi<j"gKg<,L"g<<t(<[9"=t =2"g0zqJg<<[!J:3t =*!<uHd$T$\$ $g<,!gs<t!gU $\$T$Hd$ g=wt=@ut>!uHd$$g<,!g< gË$Hd$f=`uJK. 4+" gw<x gYg<,Z gJ<t1<[G =:2 ggÀ=t(  q+h"_VMDwg<g g<,gz<t1<[w=ױ:gg/ų8f 0% g<[;%Vt :%]<벴무4,)g<[t  fgfLjfgfgEwfgf9wfg <[_g<,g<g:%k\DFL6<1)g<[:tg<,sg\<]g>齯8g&<['xg<,Rtwgtg>tPg>tJf=g<,f==9ug<, f=fgfg}u8gh<igJg<,RgB<[C髮fxg<g xg<,g <t.<(0ۆX="t;g /xg <gg g<,hgX <Yg: g>,t įid#t8I t=@g<,Og <t2<[ 1t<t 03虰g È<t  8gL <[tC<Ig g<,2g" <[t  逬Y Hd$T$\$ $g<,# c $\$T$Hd$ ?O 0938-r  << ~  À=@t@鬭2鞭yg <t?<[< W<t<tǮ; 5E &g È<&< fgb <[c t<`鲪xg) <t)<[&w g<,Q DgN Hd$$.g<,! a$Hd$JH=Y@t=*À=yg<,gr <t<[o gЫsg<,%g <[g <Hd$$ictt'=_@%=Pt=G@ =8 tgg $Hd$gyof=r^=@tJ<Hd$$[g<,;f=f`Lj\ÈU I=Z@++%!È gp<(h輘fgfgIng<(G<@t/< t$s-fg nfv-蹞˜9ufgfgmq =n@3fgfgm%**%g<,gr<[t<ogɦfbg<t2"<[#ug<,MpgGvg<,g<t<[,,kf="g<,Rf= 鉥yqc"ÈfZ J04Hd$$g<,g<[t<@Hd$<$V$D$Hd$ g;gu s 8`?i g0i%g<[ Zt deH ZHY%TP?g<g'=t=/@xfHf8gE<tL<[BHd$T$\$ $g<,#] $\$T$Hd$ apgGvg<,!Æ_3U ggg<g$tw<r t# @:%t=%ô و$ PLj t>$ 3$<r=@둈 t 0<u/gfĀ h:%at=X%L[<[u%:C<u gf6À%/%<+g~]O€=u]=wTf uL=@uF`VX-G;@tΐ fÀ%%g$<`ug,`ng$ À=AtfÀ=0ufÀ=@h H<t<t<tw t[<wS=@tN<tr9%t4%t/Et*Dt%À%t.%t)Et$Dtt<s &g_gÀ=r*5ctgYtgL@t=d@ 1 g3g<u(g<8t<:tÊgt %t D%t B t A%5 gÉ=%t %|t hD%l=}@u(1t=u Du fÀtVN&Ff f"ff#$<T<@E< $ =@ ">8vf&tEf'tBf#t?f%t,N3+> t =@'[<(<]g<,t =l@Rr#=9 (Z%b\cLgjZ0Ɇ gZ<[t6<W gG*u t8tH?Hd$ $rg>{g<g<zu*$u#acg$M$,;=%&(g$8 @g<}$Hd$t!=u:t :Ê=u<t< t<@tK.t:t5=uGHd$\$L$$g<,g<(H$L$\$Hd$ g>{7g<g$  g<}|g>{u4 ig<]gS g<}B t=u =@uxg>,urg~{uk w@lt3 gg<g$Jg<-g<g<0g<}ôf% <   f% f  0g<;u<[J e g<,&X@ A;f;6 ( &g딀  ;gk<kgb&g<,T;&ɑ % &g<,g<[G^j8f륀 SZQ >6f60~g<tw<[ g<,wgg<hg^%l=% 靎g Zg!Sg<,!ÀA950<[t :<[{ j J f . 0   fv lkp0 U J0ɀ C;f>8*& 0c 0 f:V0%0ɰD ǀ 0i  f f ff o ldf``: F  = 6 1fJ "   f-   f  f f8A  f@р f@Ā ff ff x tfw80YQCf ;f%f) !f fc $ 8b^0Z 1+  0> 0?%: 0ɀ u qf x-jg_g<t< ?=. &g" ff ff- g<tE  0  0f0Ɉ%8 t f ] \RfU:>Af8f 0 '!ff  Gug<,])g<,HÀ=Y鴇g<%g$È zg<tp<a<['g<,A%>'t8 r tfgWg<,jg<t<t-R<[+g"Ê%鸆guÊ8v:%<t<w&oft b=~@OTKg@g<,}녀  U~g<,N  !/g<,N5Dž8 %@I v7 j0c:! T O Dش80 *f- % À   0ɴ:,=s BSg<,ξg>,gF<ugF<(eb8]<r RN >695'vIeHS :0V  0Ɉ f  Cg<, 0Ɇ xg<[ c<gTg<,Hd$4$0Ɇ 4g<tQ4$Hd$<[ta 鮽Āp%, Ë$Hd$g: ʂHd$ $g&$Hd$< y |m鱼p_f_Ys KP:g<,g<[t<g鷼 A  fr &_~ .g<,0cȀ%hHd$$g<t4<[$Hd$):, g:%t$Hd$ 8g$<tw<[!r z~:i~"0aHd$$g<,RȀ%E$Hd$g:&< M   +'    @f8  :%d@u=kt=^Yt 0%>Hd$$g<,g<tJ<[$Hd$% 8|||og@t <`rP8"$Hd$%~GÊwt8t<r <u AyC 4$Hd$%!)$~       gW<tP<[T0t :Kbg<,(:%+̷g:% Hd$$\g<,:%XI$Hd$ܷ * %     _:%gg<,R9ĿɿHd$$g<,)g<t <[g$Hd$z龶gË$Hd$^ M O( 7g<tU<[%  g<,gu<vglzgÊԾ8Xt!J=̾@)<s g<, g<gm=eWņS@ 3/f2:"=/@x :f ֽA`˽g<,<# )   yf klg Y WQg<,1Ɇ ,3g<[t?<g:% tÈ %y3w ȼ ļ3     f u l lHd$$ g<,0?JKsË$Hd$f'y$Hd$wt<@8t}À [zϻ@À ̻ f5 ff 80m | qg<t:<[7 g<,%C F%Atg 0Ɇ g<,y  t8t*鋲 ׺ Ժ Ǻ     % |g<g:iTtAg<,I'um.w    % Q p۹g<,L3 g<,7g <[t<<gfÀtx|v=xunv:U`Ax<:t<2(t )j+ g<uEg  g<,za g<,egU<[Vs<[Dg<,5 g<,  {s}f}wP ig<g'Vt=Y@&g<, u  fgb<cgt=@^Ug<,* t   | ~$g<,0Ɇ YHd$ $g<[$Hd$/)t%-t8g>,t % Z:$:׶:ö<tN <u2t"t8nq:%k[qRq T=*q +l !  g<[gg<,{0Hd$$R$Hd$ƀ Ʊ  g <[[0%kt8X@t =Wu8/p828,' g<gg<,uge<t<[:ogq<t<B=Ĵ@! ~8y jg<g(Wg<,!7.%f%8 r%}8nh#pg<,TgD<ug8 薏rr/wnr-ypt h+s1 g4<(Hd$T$\$ $_` $\$T$Hd$ : ֲӎr  d $%~  g<g?ho X\ PEg<g1g<,0Ɇ g<t9<[_Hd$ $$Hd$t<t'gZ mg<,*gsÀ | lu \eYW <E2.i   ,аӰ%ǰŰG  z~ hg<,g<[<g2g<,Hd$4$0Ɇ g4$Hd$ <[t<u*eÆl ߯gUj0ۆɯ=ǯ?0O{g<,Hd$4$0Ɇ g4$Hd$ m<udTj=]P0N逦44.8)& w g<,v]g>+ug>()Vg=Į@[g<,6+@i 0g<g$`t`u@<Q=n@?9."=@<JuJ=tA=u8r0s+<t i=խr ǭ@%8ts:tx uygggŊ%y0 gGÀ=U u %Ofttt 5   ð%/ %%gggĊ% 0gG&4%~gGÀ=@tШH@;gGg%@t =@0gG4%rgGX=Q=Ru%88:gggb% 0%0gG$% %ث xgGū$u%v % t @t gGð%yO%lB͉ t71Ɋ Wu <t'1urs 2)É=_=Q5=g;=61guω;rg8\tg8/tg8.ugG ;=<tqr?<tQ<tT<u_f=9tf=/ s%sE.dllC.sys<.efi5.bin%ߩs&.com.obj.o%©s 1.exeggggg 1'Agt gg:tg/ g?u.g5֩gguωgN+ =glj==Y=VtO 2+ =ڨggO);=Ө=5 ;5|r g ==i#=\u%ɨa,+;=Gu=;=]+=ǧ=ŧ%Ƨ n=u |) o=ݨu=TËgeO M Og ";=-2-gE !=lg<tk<gK <J< <<'g>t)gf~(HgF5֧gtQ)gg<#g8x-=<<<%4-b{<i<-զ9R<< 7<<3r<D <t<'O<t<=%\/g<t<g$g<gf1gfPgHO؋gS;gCgC g<gff(gsggtg')<t<m%_gff(>ggtgB ;xggZg<g<gƉ0g<:t<u gf<%xgJ111nޤL(E(=JtA-RgE u4===0=#=A'Ê <<<'ËaHd$<$׹1g=k<$Hd$gfB gfBHd$D$$f"*+*gff gfCgf;u gfCgf+;$D$Hd$g<vgQƉÉ+)1g6Hd$$ $Hd$+=+°g>ugģе11&g<(P=tGgfBg<:g<(O=KpgfB$=Vu*Hd$DD$D$D9Hd$.I@g<(:t'f+=ۢOgfB*$=t1gfBg<:g<(O=gfB-#=pg込<(N=4YgfB #%r"gfBgJȉ=l)LJ=v)0g+=^gfMZgfz0gfBIȉ %ff ufgfBgfr&5)gfB gfB ؈gf B gfB É Hd$4$1 gf@gfMZgBgfBgBgB gfB gfJgfBMZgN g;=ZY1g@gfV0gNgV@h)gfV0gN gVufщ)t0r3Hd$ $g;՞1g $Hd$)ff%gfF gfV)gF<4$Hd$É1g1Hd$$01 $Gff%gfFg gfFgN<@)vgfF gfMZgFfgfF fgfFfgfFgfFgfFgF@)91g $Hd$4$Hd$1f#Lf @% ՝tfdg>g><g>ggtef r g>(Eg>.Hd$$g~ g~ gfVftEgFfff)gFdm%dsf1$Hd$ -h gf(g>.Hd$T$<$=N0u xIKJ><<$T$Hd$=}g>uggff(gƋ- t;t'+=֛= +ۚ=Ϛʼnt1ggfPEfgfBgB9gB=gB@~gBHfqgfB\fu gB8gB./\u@B%Or08t/u3Sg+B4gB(C%r08tE g+A0gQ4trAgA(g<(g>.uiBݓgB`g>,u4gg<(`g>.ZBgBdg;B`UXgBdgB`=AgBd8@B=ǔ ggA`gQdg>,uUgg<(g>.B= +gAhgQlg;Qdʽg;A`gAhgydgA`=gAhg<(hg>.buMAgBhg>,Ygg<(-g>.'fAgBlg;Bh"%-A=ٽ TgApgQtg>,gg<(ϻg>.ɼ@=t gAxgQ|g;Qtg;ApHd$D$$t ="t=tZ?g+CgC ;!gC=֒tgC gC$D$Hd$<<tËTgbgJ^@-r %N7+1w1=+lj'Hd$4$1ɇ ޑ5g)Ɖ5gQg9r-)t f1gfgЁg9sggggfgFggf⯉4$Hd$)g>ugff(ggt=t(f=0u%A=;;=,Hd$4$(Hd$$5gF ;z 褲(1g9fg9Fg9F  g9Ft)°蠲ggV =gNggVgNg ;߷ggV gFgNg4gfyt9ngf9tgf9t9Pgf9t0A;5+1g=ߏgG;QP1g,g1gg1ۋ51g>tbgf>tP t!1gfgf; wr<gfgf  u+ t!1gfgf; wrgfgf  ug~gF t*Ӌ@gf@ gG;g1gb5g>t%gf>ugF9~ 9g~gFՁt'Ӌӎgf@gG;@?g1g뛋5gNf Hd$ $Hd$<$+gVgG;1g˳g1gg1ۋ5C1g>Hd$4$g9nuy,gf>tj t81gfgf; w*rVgfgf  uEgf>uÃgf~u t!1gfgf; wrgfgf  u$gx4$Hd$gFgtY t'Ӌ$gf@ gG; g1g&5dg>tFHd$4$g9nu%Ngf>ugF9~ 9 ‹$gx4$Hd$gFgt봁t'Ӌ$gf@gG;g1gz$Hd$ $Hd$f8/5njgFgVg4Hd$<$;4$gNf Hd$ $Hd$<$+{gVgG;1gg1gg55g>tQHd$4$g9nu0gF9~9} ‹$4$Hd$gFgt멁t+Ӌ$gf@gG;IHgIgk$Hd$ $Hd$f5Hd$<$gFgNgHd$$ tQHd$ $+Mgf1gfgG;gff t gfgfۃ $Hd$⯋4$Hd$;4$r+tf1gf$Hd$$Hd$gCgKHd$ $+5gsgG;*)ggF g1gg $Hd$9r$Hd$Hd$,$Sg+HgH gg0YgN;=ĉñ+5t )0g,$Hd$9r4$Hd$诫+^gBPK׈gBgfBk(gJgDgJ<!g;BTt 1Ƀxatg tg|uggC ggCgDrgz(u"/)>5s9 0Hd$<$=9<$Hd$";$t _+߈)ى1gffЃчgCXËà ;=81ggCg{gC`%`s gCk1WgSgC  &gC @v`(gC ;1gg{gCgC1gZgB tgB gff(fgsggtKg>t9g>g%pr<+gCg C%Eg<(g>.Hd$$)5$Hd$ʅѰ ɰ= g SgC GLg{gC%gK0gS)gC 1(9u;ugKÀ=tbHd$\$$]u#=҆=ņ=tu=tj=YHd$$%sg[))؃xHd$$ԅu g{ r g{ cք ;]XgCg@gCqgC$\$Hd$=t dz+={=y=b  @g;ׄҬ1ggfLtgfdgfC%sgKHd$$w$Hd$gCۄgfC5Ȅ11;5ڃgts sJ މggfN ȉgggVgz tgRg:sg:r뙉gg 뇋Eg{ u^=?tU;Iu$ gt7t g>tigC%gg HgCigCgHg g gCgfC h)g+==%g $Hd$ qHHd$4$gv t#gw2Hd$<$g<$t$Hd$g.flagCt4$Hd$É)gCg4$Hd$ g;1ggELFgBgBgBgBgBgB(4gB.( gBgf>5 gBgf>$ gBi~kà ; p~1`NggCg{gCgCgZgB  lgB gC]g;~1ggELFgBgBgBgBgB>gB4@gB:@4@gBgf>s gBgf>b %{~N}gC ;~x}j~fW~W1gg{gCgCgZgB ~tgB gff(ægsggtg>t,g>usg,4gC0gCg<(yg>.sHd$$+$Hd$ʅR JgC ߨg{MgCV}5gC+<}Hd$$|=}t]=}tTHd$$=}t,|5=f}( !|t g{ b|g[))Hd$$=}%|m=|t q|{É+ {كK|u0gHd$<$56|=L{1g|tggt ȣg^gCtDfzgf;Cu6gS tIgCg8g@zufgfPRz隤KgfPfgFgzuCgC $g;CKg3Bgg1gC gg{ t  g<g{ t  ggC g3CgggCggC g0gggFgyu1ggFggg0gggFg1gg `x0ggRyt9tmmyu.g{ t gC .relg)g3 t0gg0gg{tgC.relgag)g3̸.flagftgfgz ,x+x1)xu-gC xfgfC2fؠgfC0+gC(xfgfC>fgfC<1(g~xtg1ɉgFggg~ tgFtggF$?1gFZx+XwgF 1gggF1 <$;5wgt$Hd$g1gBg$Hd$ ZgLwtg'9<$g'wtgwu g0+v$)vggvu ggg0gg0g;5u.$Hd$u)؉u yvt(g gg0ugB+fuSvg=vgvu ggg0gg0g gg0gB+u u|gB g+Bo1ggb1[tabgB.symgBgB .strgB uttf;t) toF Fug>(u2g>.Hd$$m!=uş$Hd$gB,ug>u>gf(g>.Hd$$*"=Tuyt$Hd$gB* f=st t1g%tggfCgC-tgcgkgk +sgB%t@{s10+mtktggSgK=3t tg>(u2g>.ӝHd$$C =vt$Hd$gBt@%sg>uDgf(g>.Hd$$!=#tHss$Hd$gB68f=rt |s1g%psggfC0gC-rs psgcgkgKgkgK+SrgBgJ;rgxugC rtgC g<(g>.ru qgB qgCgS%rpr7Hd$$[݋xrq4;^rrVr rggcgfCg>t>g>gfݚtϚtgc`gcg;Pgf qgq4;qsg8"; g#gfCPtg tdh$Hd$g;u =quM+pgC%gCgC 10уgEgUgMMq1ɇ `qt"gAgIgCgC gK)+9p1롋+q1܃=qu#;=pu q qÃ% qppo4+og+C;=Cpu g;u=1pgC)gC%"pgCg;t!=pug;tg;QtpgC gC%yHd$D$$ ݋=pk8Po@;#pr pggcgfC0g>t>g>gfttgc.gcg;gf ogn@;osg8" 8g#gfC0Ptg tdh$D$Hd$g;u =ou,+ sngKȃgCgSgCgS1ɇ Kot4gAgQgIgCgSgCgSgK+ nȃzoo1ȃ=nu);=nu nnnÃ%nnnk8m@+mg+C;=nu g;u=mgC()gC %mgCgSg;t$=rnug;t$g;Qt^ngC(gC(%nu3%mngB4gfB,Ѓ4;mt ZnlmgB @gfB8k8Ѓ@;mt 'nINCLUDE  +-/*=<>()[]{}:,|&~#`;\defineincludeMirpirpsirpvmacro matchpostpone+purgea reptrestorei restruce struc commonforwardlocal|reversefile line$ +-*/andmodorshlshrxor+-bsfbsrnotpltrvaalignasatdefineddefinitedupeqeqtypefrominonptr relativetousedbytedwordqwordword,/)WRrRPfzahalax bhblbp%bx#chclcs2cx!dhdi'dlds4dx"es1fs5gs6k0Pk1Qk2Rk3Sk4Tk5Uk6Vk7WmsAmz nxpe0r8r9rd!rn ru"rz#si&sp$ss3stbplcr0cr1cr2cr3cr4cr5cr6cr7cr8cr9 dildlldr0dr1dr2dr3dr4dr5dr6dr7dr8dr9eax@ebpEebxCecxAediGedxBefi eipelfPesiFespDfarguimm0mm1mm2mm3mm4mm5mm6mm7r10r11r12r13r14r15r8br8dHr8lr8w(r9br9dIr9lr9w)raxrbprbxrcxrdirdxriprsirspsae0silsplst0st1st2st3st4st5st6st7tr0@tr1Atr2Btr3Ctr4Dtr5Etr6Ftr7Gwdm1to21to41to8bnd0`bnd1abnd2bbnd3cbytecodecoff@cr10 cr11 cr12 cr13 cr14cr15datadr10dr11dr12dr13dr14dr15ms64Inearnotepe64zaEU\J LM NNbtXif inP^jawdjbrdjcrdjetdjgdjl|djopdjpzdjsxdjztdor 9aaa77aadշ8aamԷ8aas?7adc 9add 9and 9bndw8bsfeZbsreZbtcXbtrXbtsXcbw7cdq7clc7cld7cli7cmc7cmp8 9cqo8cwd7daa'7das/7decZOdivG=enderrfldpfstphlt7incZOinsljintͅ8jaesdjbevdjge}djle~djmp`jnavdjnbsdjncsdjneudjng~djnl}djnoqdjnp{djnsydjnzudjpezdjpo{dlarllds#SleaRles#Slfs#Slgs#Slslllss#Sltrkmov=mulG=negG=nopnnotG=org1out%_popLpordtrclSrcrSrepB8retRrolSrorSrsm.8salSsarSsbb 9shlSshrSstc7std7sti7strlsub( 9ud0Zud1Zud2 .8xor0 9adcxfYadoxYandnarplePblci&blcsblsiZblsrZbzhimcall`cdqe8clacʆmclgi݆mclts.8clwbcmps1icwde7datadppdAVdpps@VelseZ emmsw.8fabs!FpfaddMofbldqfchs FpfcomMofcos?FpfdivMofenisfildMqfistMqfld1(Fpfldz.FpfmulMofnopFpfsin>FpfstppfsubMoftst$Fpfxam%FpfxchrheapMidivG=imul[insbl7insdm7inswm7int17int3̝7intoΐ7invd.8iret7jcxzejnaerdjnbewdjnge|djnledkorbEjkordEskorqEzkorwElahf7lgdtWllidtWllldtklmswkloadlockB8lodsGhloop&fmovdwmovqxmovs7gmulxorpdVz{orpsVg{outsnjpanddtpdeppextpopaa7popdLpopf7popqLpopwLpushSIpxordtrepeB8repzB8retdQretfʙRretnRretqQretwRrorxsahf7salc֐7sarxTscashseta Psetb Psetc Psete Psetg Psetl Pseto Psetp Psets Psetz PsgdtWlshldUshlxfshrdUshrx]sidtWlsldtlsmswlstacˆmstgi܆mstoshtest`Everrkverwkvporwait7xaddmxchgrHxendՆmxlatEkaddpdXz{addpsXg{addsdX{addssX{alignandpdTz{andpsTg{bextrblcicblsicbndcl\bndcn`bndcu`bndmkxboundPbreakDbswap@ncmovaGeZcmovbBeZcmovcBeZcmoveDeZcmovgOeZcmovlLeZcmovo@eZcmovpJeZcmovsHeZcmovzDeZcmppd{cmpps{cmpsb7cmpsd{cmpsq8cmpss{cmpsw7cpuid.8crc32divpd^z{divps^g{divsd^{divss^{enter9Qentryextrnextrqފf2xm10FpfaddprfbstpqfclexsfcomitfcompMofdisisfdivprfdivrMofemms.8ffreerfiaddUpficomUpfidivUpfimulUpfinitsfistpMqfisubUpfldcwVsfldpi+Fpfmulprfnenisfprem8Fpfptan2Fpfsavesfsqrt:FpfstcwPsfstswsfsubprfsubrMofucomrfwait7fyl2x1Fpicebp7iretd7iretq8iretw7jecxzfjrcxzfkaddbJjkadddJskaddqJzkaddwJkandbAjkanddAskandqAzkandwAkmovbkmovdkmovqkmovwknotbDJknotdDSknotqDZknotwDakxorbGjkxordGskxorqGzkxorwGlabellddqugzleaveɝ7lodsb7lodsd7lodsq8lodsw7loopdfloope&floopqfloopweloopz&flzcntmaxpd_z{maxps_g{maxsd_{maxss_{minpd]z{minps]g{minsd]{minss]{movbemovsb7movsd$~movsq8movss~movsw7movsxrWmovzxrWmulpdYz{mulpsYg{mulsdY{mulssY{mwait"outsbn7outsdo7outswo7pabsbpabsdpabswpaddbdtpaddddtpaddqdtpaddwdtpandndtpauseʈpavgbdtpavgwdtpf2idpf2iwpfaccpfaddpfmaxpfminpfmulpfrcppfsubpi2fd pi2fw popada7popawa7popfd7popfq7popfw7pslldtpsllqtpsllwtpsradtpsrawtpsrldtpsrlqtpsrlwtpsubbdtpsubddtpsubqdtpsubwdtptest%pusha`7pushdSIpushf7pushqSIpushwSIrcppsSg{rcpssS{rdmsr2.8rdpidrdpmc3.8rdprumrdtsc1.8repneB8repnzB8retfdʰRretfqʦRretfwʺRretndQretnqQretnwRscasb7scasd7scasq8scasw7setae Psetbe Psetge Psetle Psetna Psetnb Psetnc Psetne Psetng Psetnl Psetno Psetnp Psetns Psetnz Psetpe Psetpo Pstack$storestosb7stosd7stosq8stosw7subpd\z{subps\g{subsd\{subss\{timesMtzcnttzmskvdppdAsvdpps@vmovdGvmovq7vmrun!vmxonvorpdV vorpsVyvpandvpord됣vporq+vpxorwhile wrmsr0.8wrssdwrssqxlatbם7xorpdWz{xorpsWg{xsavextestֆmaesdec%aesenc%aesimc%andnpdUz{andnpsUg{assert/blcmsk!blsmskZbndldx|bndmovbndstxclzerocmovaeCeZcmovbeFeZcmovgeMeZcmovleNeZcmovnaFeZcmovnbCeZcmovncCeZcmovneEeZcmovngNeZcmovnlMeZcmovnoAeZcmovnpKeZcmovnsIeZcmovnzEeZcmovpeJeZcmovpoKeZcomisd/|comiss/|fcmovbtfcmovetfcmovutfcomiptfcomppjrfdivrprffreeprficompUpfidivrUpfisttpMqfisubrUpfldenvrfldl2e*Fpfldl2t)Fpfldlg2,Fpfldln2-FpfnclexsfndisisfninitsfnsavesfnstcwVsfnstswsformat#fpatan3Fpfprem15Fpfrstorsfrstpmsfsavedrfsavew sfscale=Fpfsetpmsfstenvrfsubrprfucomitfucomprfxsavegetsec7.8haddpd|z{haddps|7|hsubpd}z{hsubps}7|invept̏invlpg;mkandnbBjkandndBskandnqBzkandnwBktestbJktestdSktestqZktestwakxnorbFjkxnordFskxnorqFzkxnorwFlfence踈llwpcbloopedfloopeqfloopeweloopne&floopnz&floopzdfloopzqfloopzwelwpins4lwpval4mfencemovapd(}movaps(}movdqafymovdquymovhpd~movhps~movlpd~movlps~movntiԉmovntqֈmovsxdcBXmovupd}movups}mwaitx"paddsbdtpaddswdtpextrb'pextrdpextrq pextrwpfnaccpfsubrphadddphaddwphsubdphsubwpinsrb mpinsrd"vpinsrq"pinsrw{vpmaxsb<%pmaxsd=%pmaxswdtpmaxubdtpmaxud?%pmaxuw>%pminsb8%pminsd9%pminswdtpminubdtpminud;%pminuw:%pmuldq(%pmulhwdtpmulld@%pmullwdtpopcntpsadbwdtpshufbpshufdfwpshufwwpsignbpsignd psignw pslldq}psmashqmpsrldq}psubsbdtpsubswdtpswapdpublicpushad`7pushaw`7pushfd7pushfq7pushfw7rdmsrq28rdpkrumrdrand,rdseed,rdsspd,rdsspq%rdtscpmrepeat' setalc֐7setnae Psetnbe Psetnge Psetnle Psfenceshufpds{shufps`{skinitslwpcbsqrtpdQz{sqrtpsQg{sqrtsdQ{sqrtssQ{swapgsymsysret.8t1mskctpausefumwaitvaddpdXvaddpsXkvaddsdXvaddssXvandpdT vandpsTyvcmppdHvcmpps\vcmpsdbvcmpssvvdivpd^vdivps^kvdivsd^vdivss^vlddquөvmaxpd_vmaxps_rvmaxsd_vmaxss_ĢvmcallmvmfuncԆmvminpd]vminps]rvminsd]vminss]Ģvmload!vmovsdvmovss­vmread׎vmsave!vmulpdYvmulpsYkvmulsdYvmulssYvmxoffĆmvpabsbvpabsdNvpabsqvpabswvpaddbɣvpadddvpaddq2vpaddwɣvpanddېvpandnvpandq+vpavgbɣvpavgwɣvpcmovvpcmpbvpcmpdױvpcmpqʱvpcmpwvpcombvpcomdvpcomqvpcomwvpermbݣvpermd6Svpermqvpermw֣vppermsvproldvprolqvprordvprorqvprotb vprotd vprotq vprotw vpshab vpshad vpshaq vpshaw vpshlb vpshld vpshlq vpshlw vpslldƷvpsllqvpsllwʷvpsradƷvpsraqⴷvpsrawʷvpsrldƷvpsrlqӻvpsrlwʷvpsubbɣvpsubdvpsubq2vpsubwɣvptest>vpxordvpxorq+vrcppsSRvrcpssS٢vsubpd\vsubps\kvsubsd\vsubss\vxorpdW vxorpsWywbinvd .8wrmsrq08wrpkrumwrussdwrussqxabortxbeginƑxgetbvІmxrstorxsavecxsavesxsetbvцmblcfillblendpd Vblendps VblsfillclflushMcmovnaeBeZcmovnbeGeZcmovngeLeZcmovnleOeZcmpeqpd{cmpeqps{cmpeqsd{cmpeqss{cmplepd{cmpleps{cmplesd{cmpless{cmpltpd{cmpltps{cmpltsd{cmpltss{cmpxchgmdisplayendbr32Gendbr64Gfcmovbetfcmovnbtfcmovnetfcmovnutfdecstp6Fpfincstp7Fpfldenvdrfldenvwrfnsavedsfnsavewsfnstenvrfrndintvpminsb8vpminsd9^vpminsq9vpminswɣvpminubɣvpminud;^vpminuq;vpminuw:vpmovdb1vpmovdw3vpmovqb2vpmovqd5vpmovqw4vpmovwb0vpmuldq(vpmulhwɣvpmulld@^vpmullq@vpmullwɣvprolvdWvprolvqvprorvdWvprorvqvpsadbwɣvpshlddqhvpshldqqvpshldwpvpshrddshvpshrdqsvpshrdwrvpshufbvpshufdpvpsignbGvpsignd Gvpsignw Gvpslldq&vpsllvdG^vpsllvqGvpsllvw֣vpsravdF^vpsravqFvpsravw֣vpsrldq&vpsrlvdE^vpsrlvqEvpsrlvw֣vpsubsbɣvpsubswɣvshufpdvshufpsbvsqrtpdQڡvsqrtpsQIvsqrtsdQvsqrtssQvtestpd>vtestps>xrstorsxsave64addsubpdz{addsubps7|blendvpdblendvpscldemoteSclrssbsycmpneqpd{cmpneqps{cmpneqsd{cmpneqss{cmpnlepd{cmpnleps{cmpnlesd{cmpnless{cmpnltpd{cmpnltps{cmpnltsd{cmpnltss{cmpordpd{cmpordps{cmpordsd{cmpordss{cvtdq2pd'|cvtdq2ps[g{cvtpd2dq7|cvtpd2pi-ocvtpd2psZz{cvtpi2pd*/cvtpi2ps*6cvtps2dq[z{cvtps2pdZ.|cvtps2pi-fcvtsd2si-Łcvtsd2ssZ{cvtsi2sd*Àcvtsi2ss*cvtss2sdZ{cvtss2si-fcmovnbetfnstenvdrfnstenvwrfxsave64insertps!kortestbJkortestdSkortestqZkortestwakshiftlb2+kshiftld3+kshiftlq3$kshiftlw2$kshiftrb0+kshiftrd1+kshiftrq1$kshiftrw0$kunpckbwKjkunpckdqKzkunpckwdKmaskmovqimonitorx"movmskpdmovmskpsmovntdqa*movshdupG|movsldupG|packssdwkdtpacksswbcdtpackusdw+%packuswbgdtpblendvbpfrcpit1pfrcpit2pfrsqit1pmovmskbhupmovsxbd!0pmovsxbq"9pmovsxbw 'pmovsxdq%Tpmovsxwd#Bpmovsxwq$Kpmovzxbd10pmovzxbq29pmovzxbw0'pmovzxdq5Tpmovzxwd3Bpmovzxwq4Kpmulhrsw prefetchrdfsbaseSrdgsbaseSrstorsspߖsetssbsyЖsha1msg1,sha1msg2,sysenter4.8sysexitq58umonitorunpckhpdz{unpckhpsg{unpcklpdz{unpcklpsg{vblendpd vblendps vcmpeqpdHvcmpeqps\vcmpeqsdbvcmpeqssvvcmpgepd Hvcmpgeps \vcmpgesd bvcmpgess vvcmpgtpdHvcmpgtps\vcmpgtsdbvcmpgtssvvcmplepdHvcmpleps\vcmplesdbvcmplessvvcmpltpdHvcmpltps\vcmpltsdbvcmpltssvvfmaddpdi+vfmaddpsh+vfmaddsdk/vfmaddssj3vfmsubpdm+vfmsubpsl+vfmsubsdo/vfmsubssn3vldmxcsrvmlaunch†mvmovddup"vmovdqu8ovmovhlpsbvmovlhpsbvmovntdqPvmovntpd+Ivmovntps+WvmpsadbwBvmresumeÆmvpaddusbɣvpadduswɣvpalignrvpblenddvpblendwvpcmpeqbtvpcmpeqdvvpcmpeqq)vpcmpeqwuvpcmpgtbdvpcmpgtdfvpcmpgtq7vpcmpgtwevpcmplebvpcmpledױvpcmpleqʱvpcmplewvpcmpltbvpcmpltdױvpcmpltqʱvpcmpltwvpcomeqbvpcomeqdvpcomeqqvpcomeqwvpcomgebvpcomgedvpcomgeqvpcomgewvpcomgtbvpcomgtdvpcomgtqvpcomgtwvpcomlebvpcomledvpcomleqvpcomlewvpcomltbvpcomltdvpcomltqvpcomltwvpdpbusdPWvpdpwssdRWvpermi2buݣvpermi2dvWvpermi2qvvpermi2wu֣vpermt2b}ݣvpermt2d~Wvpermt2q~vpermt2w}֣vphaddbdLvphaddbqLvphaddbwLvphadddqLvphaddswGvphaddwdLvphaddwqLvphsubbwLvphsubdqLvphsubswGvphsubwdLvplzcntdDGvplzcntqDvpmacsdd\vpmacswd\vpmacsww\vpmaddwdɣvpmovb2m)vpmovd2m9vpmovm2b(tvpmovm2d8tvpmovm2q8mvpmovm2w(mvpmovq2m9vpmovsdb!vpmovsdw#vpmovsqb"vpmovsqd%vpmovsqw$vpmovswb vpmovw2m)vpmulhuwɣvpmuludq2vpopcntbTGvpopcntdUvvpopcntqURvpopcntwT@vpshldvdqWvpshldvqqvpshldvwp֣vpshrdvdsWvpshrdvqsvpshrdvwH֣vpshufhwvpshuflwvpsubusbɣvpsubuswɣvptestmb&vptestmd'vptestmq'vptestmw&vrangepdPvrangepsPvrangesdQvrangessQvrcp14pdLRvrcp14psLvvrcp14sdMvrcp14ssMvrcp28pd˰vrcp28ps߰vrcp28sdˊvrcp28ss˥vroundpd vroundpsvroundsd hvroundss dvrsqrtpsRRvrsqrtssR٢vstmxcsrvucomisd.vucomiss.vzeroallwwbnoinvd :8wrfsbaseSwrgsbaseSxacquireB8xreleaseB8xrstor64xsavec64xsaveoptxsaves64cmpxchg8bncvttpd2dqz{cvttpd2pi,ocvttps2dq[G|cvttps2pi,fcvttsd2si,Łcvttss2si,extractpsfxrstor64gf2p8mulb%movdir64bBpclmulqdqpcmpestriaVpcmpestrm`VpcmpistricVpcmpistrmbVpmaddubswprefetchwpunpckhbwhdtpunpckhdqjdtpunpckhwdidtpunpcklbw`dtpunpckldqbdtpunpcklwdadtpvalidateimrmpadjustqmrmpupdateimsha1nexte,sha1rnds4yuseavx256useavx512vaddsubpdvaddsubpsvblendmpde!vblendmpsevblendvpdKwvblendvpsJwvcmpneqpdHvcmpneqps\vcmpneqsdbvcmpneqssvvcmpngepd Hvcmpngeps \vcmpngesd bvcmpngess vvcmpngtpd Hvcmpngtps \vcmpngtsd bvcmpngtss vvcmpnlepdHvcmpnleps\vcmpnlesdbvcmpnlessvvcmpnltpdHvcmpnltps\vcmpnltsdbvcmpnltssvvcmpordpdHvcmpordps\vcmpordsdbvcmpordssvvcvtdq2pdvcvtdq2ps[Ivcvtpd2dqvcvtpd2psZvcvtpd2qq{ӡvcvtph2psvcvtps2dq[2vcvtps2pdZvcvtps2ph vcvtps2qq{vcvtqq2pdvcvtqq2ps[vcvtsd2si-vcvtsd2ssZvcvtsi2sd*uvcvtsi2ss*vcvtss2sdZĢvcvtss2si-vdbpsadbwBvexpandpdvexpandpsGvfnmaddpdy+vfnmaddpsx+vfnmaddsd{/vfnmaddssz3vfnmsubpd}+vfnmsubps|+vfnmsubsd/vfnmsubss~3vgetexppdBKvgetexppsBovgetexpsdCvgetexpssCvinsertps!Nvmovdqa32ovmovdqa64ovmovdqu16ovmovdqu32ovmovdqu64ovmovmskpdvmovmskpsvmovntdqa*+vmovshdupܮvmovsldupܮvp4dpwssdRWvpackssdwkvpacksswbcɣvpackusdw+^vpackuswbgɣvpblendmbfݣvpblendmddWvpblendmqdvpblendmwf֣vpblendvbLwvpcmpleubvpcmpleudıvpcmpleuqvpcmpleuwݱvpcmpltubvpcmpltudıvpcmpltuqvpcmpltuwݱvpcmpneqbvpcmpneqdױvpcmpneqqʱvpcmpneqwvpcmpnlebvpcmpnledױvpcmpnleqʱvpcmpnlewvpcmpnltbvpcmpnltdױvpcmpnltqʱvpcmpnltwvpcomequbvpcomequdvpcomequqvpcomequwvpcomgeubvpcomgeudvpcomgeuqvpcomgeuwvpcomgtubvpcomgtudvpcomgtuqvpcomgtuwvpcomleubvpcomleudvpcomleuqvpcomleuwvpcomltubvpcomltudvpcomltuqvpcomltuwvpcomneqbvpcomneqdvpcomneqqvpcomneqwvpdpbusdsQWvpdpwssdsSWvpermi2pdwvpermi2pswWvpermilpdvpermilpsvpermt2pdvpermt2psWvpexpandbbGvpexpanddGvpexpandqvpexpandwbvphaddubdLvphaddubqLvphaddubwLvphaddudqLvphadduwdLvphadduwqLvpmacsdqh\vpmacsdql\vpmacssdd\vpmacsswd\vpmacssww\vpmadcswd\vpmovmskb׊vpmovsxbd!vpmovsxbq"vpmovsxbw vpmovsxdq%vpmovsxwd#vpmovsxwq$vpmovusdbvpmovusdwvpmovusqbvpmovusqdvpmovusqwvpmovuswbvpmovzxbd1vpmovzxbq2vpmovzxbw0vpmovzxdq5vpmovzxwd3vpmovzxwq4vpmulhrsw vptestnmb&vptestnmd'Ҳvptestnmq'ֲvptestnmw&vreducepdVvreducepsVvreducesdWvreducessWvscalefpd,Bvscalefps,fvscalefsd-vscalefss-vunpckhpd vunpckhpsyvunpcklpd vunpcklpsyxrstors64aesdeclast%aesenclast%clflushoptcmpunordpd{cmpunordps{cmpunordsd{cmpunordss{cmpxchg16bnloadall286.8loadall386.8maskmovdqumphminposuwA%prefetcht0_prefetcht1_prefetcht2_punpckhqdqmz{punpcklqdqlz{sha256msg1,sha256msg2,vcmptruepdHvcmptrueps\vcmptruesdbvcmptruessvvcvtpd2udqyvcvtpd2uqqyӡvcvtps2udqyBvcvtps2uqqyvcvtsd2usiyvcvtss2usiyvcvttpd2dqvcvttpd2qqzvcvttps2dq[vcvttps2qqzvcvttsd2si,vcvttss2si,vcvtudq2pdzvcvtudq2psz;vcvtuqq2pdzvcvtuqq2pszvcvtusi2sd{nvcvtusi2ss{{vextractpsHvfpclasspdfvfpclasspsfvfpclasssdgvfpclassssgvgatherdpdvgatherdpsvgatherqpdvgatherqpsvgetmantpd&vgetmantps&vgetmantsd'vgetmantss'vgf2p8mulbvmaskmovpd-hvmaskmovps,hvp4dpwssdsSWvpclmulqdqvpcmpestrialvpcmpestrm`lvpcmpistriclvpcmpistrmblvpcmpnequbvpcmpnequdıvpcmpnequqvpcmpnequwݱvpcmpnleubvpcmpnleudıvpcmpnleuqvpcmpnleuwݱvpcmpnltubvpcmpnltudıvpcmpnltuqvpcmpnltuwݱvpcomnequbvpcomnequdvpcomnequqvpcomnequwvpcomtruebvpcomtruedvpcomtrueqvpcomtruewvperm2f128"vperm2i128F"vpermil2pdIvpermil2psHvpgatherddvpgatherdqvpgatherqdvpgatherqqvpmacssdqh\vpmacssdql\vpmadcsswd\vpmaddubswvpmaskmovdhvpmaskmovqavpternlogd%hvpternlogq%vpunpckhbwhɣvpunpckhdqjvpunpckhwdiɣvpunpcklbw`ɣvpunpckldqbvpunpcklwdaɣvrsqrt14pdNRvrsqrt14psNvvrsqrt14sdOvrsqrt14ssOvrsqrt28pd˰vrsqrt28ps߰vrsqrt28sd͊vrsqrt28ssͥvshuff32x4#Hvshuff64x2#6vshufi32x4CHvshufi64x2C6vzeroupperwxsaveopt64pclmulhqhdqpclmullqhdqprefetchnta_prefetchwt1saveprevsspЖsha256rnds2vaesdeclastٯvaesenclastٯvcmpeq_ospdHvcmpeq_osps\vcmpeq_ossdbvcmpeq_osssvvcmpeq_uqpdHvcmpeq_uqps\vcmpeq_uqsdbvcmpeq_uqssvvcmpeq_uspdHvcmpeq_usps\vcmpeq_ussdbvcmpeq_usssvvcmpfalsepd Hvcmpfalseps \vcmpfalsesd bvcmpfalsess vvcmpge_oqpdHvcmpge_oqps\vcmpge_oqsdbvcmpge_oqssvvcmpgt_oqpdHvcmpgt_oqps\vcmpgt_oqsdbvcmpgt_oqssvvcmple_oqpdHvcmple_oqps\vcmple_oqsdbvcmple_oqssvvcmplt_oqpdHvcmplt_oqps\vcmplt_oqsdbvcmplt_oqssvvcmpord_spdHvcmpord_sps\vcmpord_ssdbvcmpord_sssvvcmpunordpdHvcmpunordps\vcmpunordsdbvcmpunordssvvcompresspdvcompresspsvcvttpd2udqxvcvttpd2uqqxvcvttps2udqxvcvttps2uqqxvcvttsd2usixvcvttss2usixvfixupimmpdTvfixupimmpsTvfixupimmsdUvfixupimmssUvfmadd132pdvfmadd132psvfmadd132sdvfmadd132ss vfmadd213pdvfmadd213psvfmadd213sdvfmadd213ss vfmadd231pdvfmadd231psvfmadd231sdvfmadd231ss vfmaddsubpd]+vfmaddsubps\+vfmsub132pdvfmsub132psvfmsub132sdvfmsub132ss vfmsub213pdvfmsub213psvfmsub213sdvfmsub213ss vfmsub231pdvfmsub231psvfmsub231sdvfmsub231ss vfmsubaddpd_+vfmsubaddps^+vinsertf128vinserti1288vmaskmovdqu~vpcomfalsebvpcomfalsedvpcomfalseqvpcomfalsewvpcompressbcvpcompressdvpcompressqvpcompresswcvpcomtrueubvpcomtrueudvpcomtrueuqvpcomtrueuwvpconflictdGvpconflictqvphminposuwA>vpmadd52huqvpmadd52luqvpscatterddfvpscatterdq_vpscatterqdfvpscatterqq_vpunpckhqdqm2vpunpcklqdql2vrndscalepd vrndscalepsvrndscalesd vrndscaless vscatterdpd_vscatterdpsfvscatterqpd_vscatterqpsfpclmulhqhqdqpclmulhqlqdqpclmullqhqdqpclmullqlqdqvbroadcastsdûvbroadcastssvcmpneq_oqpd Hvcmpneq_oqps \vcmpneq_oqsd bvcmpneq_oqss vvcmpneq_ospdHvcmpneq_osps\vcmpneq_ossdbvcmpneq_osssvvcmpneq_uspdHvcmpneq_usps\vcmpneq_ussdbvcmpneq_usssvvcmpnge_uqpdHvcmpnge_uqps\vcmpnge_uqsdbvcmpnge_uqssvvcmpngt_uqpdHvcmpngt_uqps\vcmpngt_uqsdbvcmpngt_uqssvvcmpnle_uqpdHvcmpnle_uqps\vcmpnle_uqsdbvcmpnle_uqssvvcmpnlt_uqpdHvcmpnlt_uqps\vcmpnlt_uqsdbvcmpnlt_uqssvvextractf128vextracti1289vfnmadd132pdvfnmadd132psvfnmadd132sdvfnmadd132ss vfnmadd213pdvfnmadd213psvfnmadd213sdvfnmadd213ss vfnmadd231pdvfnmadd231psvfnmadd231sdvfnmadd231ss vfnmsub132pdvfnmsub132psvfnmsub132sdvfnmsub132ss vfnmsub213pdvfnmsub213psvfnmsub213sdvfnmsub213ss vfnmsub231pdvfnmsub231psvfnmsub231sdvfnmsub231ss vinsertf32x4yvinsertf32x8gvinsertf64x2rvinsertf64x4`vinserti32x48yvinserti32x8:gvinserti64x28rvinserti64x4:`vpbroadcastbxλvpbroadcastdXֻvpbroadcastqYڻvpbroadcastwyһvpclmulhqhdqvpclmullqhdqvpcomfalseubvpcomfalseudvpcomfalseuqvpcomfalseuwvpermilmo2pdgvpermilmo2psxvpermilmz2pdgvpermilmz2psxvpermiltd2pdgvpermiltd2psxvpshufbitqmbgf2p8affineqbVvcmptrue_uspdHvcmptrue_usps\vcmptrue_ussdbvcmptrue_usssvvcmpunord_spdHvcmpunord_sps\vcmpunord_ssdbvcmpunord_sssvvextractf32x4vextractf32x8vextractf64x2vextractf64x4xvextracti32x49vextracti32x8;vextracti64x29vextracti64x4;xvgatherpf0dpdvgatherpf0dpsvgatherpf0qpdvgatherpf0qpsvgatherpf1dpdvgatherpf1dpsvgatherpf1qpdvgatherpf1qpsvpclmulhqlqdqvpclmullqlqdqvbroadcastf128vbroadcasti128Zvcmpfalse_ospdHvcmpfalse_osps\vcmpfalse_ossdbvcmpfalse_osssvvfmaddsub132pdvfmaddsub132psvfmaddsub213pdvfmaddsub213psvfmaddsub231pdvfmaddsub231psvfmsubadd132pdvfmsubadd132psvfmsubadd213pdvfmsubadd213psvfmsubadd231pdvfmsubadd231psvgf2p8affineqb vpmultishiftqbvscatterpf0dpdvscatterpf0dpsvscatterpf0qpdvscatterpf0qpsvscatterpf1dpdvscatterpf1dpsvscatterpf1qpdvscatterpf1qpsaeskeygenassistVvbroadcastf32x2vbroadcastf32x4vbroadcastf32x8vbroadcastf64x2vbroadcastf64x4vbroadcasti32x2Yvbroadcasti32x4Zvbroadcasti32x8[vbroadcasti64x2Zvbroadcasti64x4[vpbroadcastmb2q*mvpbroadcastmw2d:tgf2p8affineinvqbVvaeskeygenassistlvgf2p8affineinvqb WWdbdddfdpdq>dt {duUdw^rbrdrrfrprq8rt rwfileout of memoryout of stack spacesource file not foundcode cannot be generatedformat limitations exceededinvalid definition providedwrite failedfile not founderror reading fileinvalid file formatinvalid macro argumentsincomplete macrounexpected charactersinvalid argumentillegal instructioninvalid operandinvalid size of operandoperand size not specifiedoperand sizes do not matchinvalid size of address valueaddress sizes do not agreedisallowed combination of registersnot encodable with long immediaterelative jump out of rangeinvalid expressioninvalid addressinvalid valuevalue out of rangeundefined symbolsymbolout of scopeinvalid use of symbolname too longinvalid namereserved word used as symbolsymbol already definedmissing end quotemissing end directiveunexpected instructionextra characters on linesection is not aligned enoughsetting already specifieddata already definedtoo many repeatserror directive encountered in source fileassertion failedfasm/license.txt0000644000175000017500000000336714533376740014502 0ustar privalovprivalov flat assembler version 1.73 Copyright (c) 1999-2023, Tomasz Grysztar. All rights reserved. This program is free for commercial and non-commercial use as long as the following conditions are adhered to. Copyright remains Tomasz Grysztar, and as such any Copyright notices in the code are not to be removed. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The licence and distribution terms for any publically available version or derivative of this code cannot be changed. i.e. this code cannot simply be copied and put under another distribution licence (including the GNU Public Licence). fasm/source/0000755000175000017500000000000014533376755013614 5ustar privalovprivalovfasm/source/DOS/0000755000175000017500000000000014533376740014233 5ustar privalovprivalovfasm/source/DOS/dpmi.inc0000644000175000017500000000371514533376740015665 0ustar privalovprivalov ; flat assembler interface for DOS ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. init_dpmi_memory: mov ax,500h ; get free memory information mov edi,[buffer_address] int 31h mov ebx,[edi] allocate_dpmi_memory: mov edx,[memory_setting] shl edx,10 jz dpmi_memory_size_ok cmp ebx,edx jbe dpmi_memory_size_ok mov ebx,edx dpmi_memory_size_ok: mov [memory_end],ebx mov ecx,ebx shr ebx,16 mov ax,501h int 31h jnc dpmi_memory_ok mov ebx,[memory_end] shr ebx,1 cmp ebx,4000h jb out_of_memory jmp allocate_dpmi_memory dpmi_memory_ok: shl ebx,16 mov bx,cx sub ebx,[program_base] jc out_of_memory mov [memory_start],ebx add [memory_end],ebx mov ax,100h ; get free conventional memory size mov bx,-1 int 31h movzx ecx,bx shl ecx,4 jecxz no_conventional_memory mov ax,100h ; allocate all conventional memory int 31h movzx edi,ax shl edi,4 sub edi,[program_base] jc no_conventional_memory mov [additional_memory],edi mov [additional_memory_end],edi add [additional_memory_end],ecx mov eax,[memory_end] sub eax,[memory_start] shr eax,2 cmp eax,ecx ja no_conventional_memory ret no_conventional_memory: mov eax,[memory_end] mov ebx,[memory_start] sub eax,ebx shr eax,2 mov [additional_memory],ebx add ebx,eax mov [additional_memory_end],ebx mov [memory_start],ebx ret dpmi_dos_int: mov [real_mode_segment],main simulate_real_mode: push 0 ; SS:SP (DPMI will allocate stack) push 0 ; CS:IP (ignored) push 0 push [real_mode_segment] ; DS push [real_mode_segment] ; ES stc pushfw push eax push ecx push edx push ebx push 0 push ebp push esi push edi mov ax,300h mov bx,21h xor cx,cx mov edi,esp push es ss pop es int 31h pop es mov edi,[esp] mov esi,[esp+4] mov ebp,[esp+8] mov ebx,[esp+10h] mov edx,[esp+14h] mov ecx,[esp+18h] mov ah,[esp+20h] sahf mov eax,[esp+1Ch] lea esp,[esp+32h] ret dpmi_dos_int_with_buffer: mov [real_mode_segment],buffer jmp simulate_real_mode fasm/source/DOS/fasm.asm0000644000175000017500000001623214533376740015667 0ustar privalovprivalov ; flat assembler interface for DOS ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. format MZ heap 0 stack 8000h entry main:start include 'modes.inc' segment main use16 start: mov ax,ds mov dx,[2Ch] push cs cs pop ds es mov [psp_segment],ax mov [environment_segment],dx mov dx,_logo mov ah,9 int 21h cld call go32 use32 call get_params jc information call init_memory mov esi,_memory_prefix call display_string mov eax,[memory_end] sub eax,[memory_start] add eax,[additional_memory_end] sub eax,[additional_memory] shr eax,10 call display_number mov esi,_memory_suffix call display_string xor ah,ah int 1Ah mov ax,cx shl eax,16 mov ax,dx mov [start_time],eax cmp [mode],dpmi je compile jmp main+(first_segment shr 4):first_gate-first_segment compile: and [preprocessing_done],0 call preprocessor or [preprocessing_done],-1 call parser call assembler call formatter finish: call display_user_messages movzx eax,[current_pass] inc eax call display_number mov esi,_passes_suffix call display_string xor ah,ah int 1Ah mov ax,cx shl eax,16 mov ax,dx sub eax,[start_time] mov ebx,100 mul ebx mov ebx,182 div ebx or eax,eax jz display_bytes_count xor edx,edx mov ebx,10 div ebx push edx call display_number mov ah,2 mov dl,'.' int 21h pop eax call display_number mov esi,_seconds_suffix call display_string display_bytes_count: mov eax,[written_size] call display_number mov esi,_bytes_suffix call display_string xor al,al jmp exit_program information: mov esi,_usage call display_string mov al,1 jmp exit_program get_params: mov [input_file],0 mov [output_file],0 mov [symbols_file],0 mov [memory_setting],0 mov [passes_limit],100 mov [definitions_pointer],predefinitions push ds mov ds,[psp_segment] mov esi,81h mov edi,params find_param: lodsb cmp al,20h je find_param cmp al,'-' je option_param cmp al,0Dh je all_params or al,al jz all_params cmp [es:input_file],0 jne get_output_file mov [es:input_file],edi jmp process_param get_output_file: cmp [es:output_file],0 jne bad_params mov [es:output_file],edi process_param: cmp al,22h je string_param copy_param: stosb lodsb cmp al,20h je param_end cmp al,0Dh je param_end or al,al jz param_end jmp copy_param string_param: lodsb cmp al,22h je string_param_end cmp al,0Dh je param_end or al,al jz param_end stosb jmp string_param option_param: lodsb cmp al,'m' je memory_option cmp al,'M' je memory_option cmp al,'p' je passes_option cmp al,'P' je passes_option cmp al,'d' je definition_option cmp al,'D' je definition_option cmp al,'s' je symbols_option cmp al,'S' je symbols_option invalid_option: pop ds stc ret get_option_value: xor eax,eax mov edx,eax get_option_digit: lodsb cmp al,20h je option_value_ok cmp al,0Dh je option_value_ok or al,al jz option_value_ok sub al,30h jc bad_params_value cmp al,9 ja bad_params_value imul edx,10 jo bad_params_value add edx,eax jc bad_params_value jmp get_option_digit option_value_ok: dec esi clc ret bad_params_value: stc ret memory_option: lodsb cmp al,20h je memory_option cmp al,0Dh je invalid_option or al,al jz invalid_option dec esi call get_option_value jc invalid_option or edx,edx jz invalid_option cmp edx,1 shl (32-10) jae invalid_option mov [es:memory_setting],edx jmp find_param passes_option: lodsb cmp al,20h je passes_option cmp al,0Dh je invalid_option or al,al jz invalid_option dec esi call get_option_value jc bad_params or edx,edx jz invalid_option cmp edx,10000h ja invalid_option mov [es:passes_limit],dx jmp find_param definition_option: lodsb cmp al,20h je definition_option cmp al,0Dh je bad_params or al,al jz bad_params dec esi push edi mov edi,[es:definitions_pointer] call convert_definition_option mov [es:definitions_pointer],edi pop edi jc invalid_option jmp find_param symbols_option: mov [es:symbols_file],edi find_symbols_file_name: lodsb cmp al,20h jne process_param jmp find_symbols_file_name param_end: dec esi string_param_end: xor al,al stosb jmp find_param all_params: xor al,al stosb pop ds cmp [input_file],0 je no_input_file mov eax,[definitions_pointer] mov byte [eax],0 mov [initial_definitions],predefinitions clc ret bad_params: pop ds no_input_file: stc ret convert_definition_option: mov ecx,edi xor al,al stosb copy_definition_name: lodsb cmp al,'=' je copy_definition_value cmp al,20h je bad_definition_option cmp al,0Dh je bad_definition_option or al,al jz bad_definition_option stosb inc byte [es:ecx] jnz copy_definition_name bad_definition_option: stc ret copy_definition_value: lodsb cmp al,20h je definition_value_end cmp al,0Dh je definition_value_end or al,al jz definition_value_end cmp al,'\' jne definition_value_character cmp byte [esi],20h jne definition_value_character lodsb definition_value_character: stosb jmp copy_definition_value definition_value_end: dec esi xor al,al stosb clc ret include '..\version.inc' _logo db 'flat assembler version ',VERSION_STRING,24h _copyright db 'Copyright (c) 1999-2022, Tomasz Grysztar',0Dh,0Ah,0 _usage db 0Dh,0Ah db 'usage: fasm [output]',0Dh,0Ah db 'optional settings:',0Dh,0Ah db ' -m set the limit in kilobytes for the available memory',0Dh,0Ah db ' -p set the maximum allowed number of passes',0Dh,0Ah db ' -d = define symbolic variable',0Dh,0Ah db ' -s dump symbolic information for debugging',0Dh,0Ah db 0 _memory_prefix db ' (',0 _memory_suffix db ' kilobytes memory)',0Dh,0Ah,0 _passes_suffix db ' passes, ',0 _seconds_suffix db ' seconds, ',0 _bytes_suffix db ' bytes.',0Dh,0Ah,0 error_prefix db 'error: ',0 error_suffix db '.' cr_lf db 0Dh,0Ah,0 line_number_start db ' [',0 line_data_start db ':',0Dh,0Ah,0 preprocessed_instruction_prefix db 'processed: ',0 include 'dpmi.inc' align 16 first_segment: include '..\preproce.inc' include '..\parser.inc' include '..\exprpars.inc' align 16 second_segment: include '..\exprcalc.inc' include '..\errors.inc' include '..\symbdump.inc' include 'system.inc' first_gate: and [preprocessing_done],0 call preprocessor or [preprocessing_done],-1 call parser jmp main+(second_segment shr 4):second_gate-second_segment first_segment_top = $ - first_segment include '..\assemble.inc' include '..\formats.inc' include '..\x86_64.inc' include '..\avx.inc' second_gate: call assembler call formatter jmp main:finish second_segment_top = $ - second_segment if first_segment_top>=10000h | second_segment_top>=10000h if UNREAL_ENABLED>0 UNREAL_ENABLED = -1 else UNREAL_ENABLED = 0 end if else if UNREAL_ENABLED<0 UNREAL_ENABLED = -1 else UNREAL_ENABLED = 1 end if end if include '..\tables.inc' include '..\messages.inc' align 4 include '..\variable.inc' memory_setting dd ? start_time dd ? definitions_pointer dd ? params rb 100h predefinitions rb 100h mode dw ? real_mode_segment dw ? displayed_count dd ? last_displayed rb 2 preprocessing_done db ? segment buffer rb 1000h fasm/source/DOS/modes.inc0000644000175000017500000002426314533376740016044 0ustar privalovprivalov ; flat assembler interface for DOS ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. segment modes use16 real32: mov ax,7202h push ax popf pushf pop bx cmp ax,bx je processor_ok call init_error db 'required 80386 or better',24h processor_ok: mov eax,ds shl eax,4 mov [program_base],eax mov eax,buffer shl eax,4 sub eax,[program_base] mov [buffer_address],eax if UNREAL_ENABLED>0 smsw ax test al,1 jnz dpmi mov eax,cs ; calculate linear address of GDT shl eax,4 or dword [cs:real32_GDT+10],eax or dword [cs:real16_GDT+10],eax add [cs:real32_GDT_address],eax add [cs:real16_GDT_address],eax cli lgdt [cs:real32_GDTR] mov eax,cr0 or al,1 mov cr0,eax jmp 1 shl 3:test_pm32 no_rm32: sti jmp dpmi test_pm32: use32 mov eax,cr0 and al,not 1 mov cr0,eax mov ebx,0FFFFh jmp modes:test_rm32 test_rm32: inc ebx jz short no_rm32 lgdt [cs:real16_GDTR] mov eax,cr0 or al,1 mov cr0,eax jmp 1 shl 3:test_pm16 test_pm16: use16 mov eax,cr0 and al,not 1 mov cr0,eax jmp modes:test_rm16 test_rm16: sti mov bx,(400h+(100h*interrupt.size)) shr 4 mov ah,48h int 21h jc not_enough_memory push ds es mov es,ax push cs pop ds movzx eax,ax shl eax,4 mov [real32_IDT_base],eax mov dx,100h xor bx,bx mov di,400h init_interrupts: mov si,interrupt mov [si+interrupt.vector],bx mov word [es:bx],di mov word [es:bx+2],es mov cx,interrupt.size rep movsb add bx,4 dec dx jnz init_interrupts pop es ds call modes:switch_real32 use32 mov [mode],real32 retfw use16 switch_real32: pushfw push eax push word ds push word es push word fs push word gs cli mov eax,ss mov cr3,eax lgdt [cs:real32_GDTR] mov eax,cr0 ; switch to protected mode or al,1 mov cr0,eax jmp 1 shl 3:pm32_start pm32_start: use32 mov ax,2 shl 3 ; load 32-bit data descriptor mov ds,ax ; to all data segment registers mov es,ax mov fs,ax mov gs,ax mov ss,ax mov eax,cr0 ; switch back to real mode and al,not 1 mov cr0,eax jmp modes:pm32_end pm32_end: mov eax,cr3 mov ss,ax lidt [cs:real32_IDTR] pop word gs pop word fs pop word es pop word ds pop eax popfw retfw switch_real16: pushfw push eax cli lgdt [cs:real16_GDTR] mov eax,cr0 ; switch to protected mode or al,1 mov cr0,eax jmp 1 shl 3:pm16_start pm16_start: use16 mov eax,cr0 ; switch back to real mode and al,not 1 mov cr0,eax jmp modes:pm16_end pm16_end: lidt [cs:real16_IDTR] pop eax popfw retfd use32 interrupt: call modes:switch_real16 use16 movzx esp,sp push word [esp+4] push cs call .real16 pushfw pop word [esp+4] call modes:switch_real32 use32 iretw .real16: use16 push eax push ds xor ax,ax mov ds,ax mov eax,[word 0] label .vector word at $-2-interrupt pop ds xchg eax,[esp] retfw .size = $-interrupt label real32_GDTR pword real32_GDT_limit dw 3*8-1 ; limit of GDT real32_GDT_address dd real32_GDT ; linear address of GDT real32_GDT rw 4 ; null descriptor dw 0FFFFh,0,9A00h,0CFh ; 32-bit code descriptor dw 0FFFFh,0,9200h,08Fh ; 4 GB data descriptor label real16_GDTR pword real16_GDT_limit dw 2*8-1 ; limit of GDT real16_GDT_address dd real16_GDT ; linear address of GDT real16_GDT rw 4 ; null descriptor dw 0FFFFh,0,9A00h,0 ; 16-bit code descriptor label real32_IDTR pword real32_IDT_limit dw 3FFh real32_IDT_base dd ? label real16_IDTR pword real16_IDT_limit dw 3FFh real16_IDT_base dd 0 end if dpmi: mov ax,1687h int 2Fh or ax,ax ; DPMI installed? jnz no_dpmi test bl,1 ; 32-bit programs supported? jz no_dpmi mov word [cs:mode_switch],di mov word [cs:mode_switch+2],es mov bx,si ; allocate memory for DPMI data mov ah,48h int 21h jc not_enough_memory mov ds,[environment_segment] mov es,ax mov ax,1 call far [cs:mode_switch] ; switch to protected mode jc no_dpmi mov cx,1 xor ax,ax int 31h ; allocate descriptor for code mov si,ax xor ax,ax int 31h ; allocate descriptor for data mov di,ax mov dx,cs lar cx,dx shr cx,8 or cx,0C000h mov bx,si mov ax,9 int 31h ; set code descriptor access rights mov dx,ds lar cx,dx shr cx,8 or cx,0C000h mov bx,di int 31h ; set data descriptor access rights mov ecx,main shl ecx,4 mov dx,cx shr ecx,16 mov ax,7 int 31h ; set data descriptor base address movzx ecx,word [esp+2] shl ecx,4 mov dx,cx shr ecx,16 mov bx,si int 31h ; set code descriptor base address mov cx,0FFFFh mov dx,0FFFFh mov ax,8 ; set segment limit to 4 GB int 31h mov bx,di int 31h mov ax,ds mov ds,di mov [psp_segment],es mov [environment_segment],ax mov es,di mov [mode],dpmi pop ebx movzx ebx,bx push esi push ebx retfd init_error: push cs pop ds mov dx,init_error_prefix mov ah,9 int 21h pop dx int 21h mov dx,init_error_suffix int 21h mov ax,04CFFh int 21h init_error_prefix db 0Dh,0Ah,'error: ',24h init_error_suffix db '.',0Dh,0Ah,24h mode_switch dd ? not_enough_memory: call init_error db 'not enough conventional memory',24h if UNREAL_ENABLED>0 no_dpmi: smsw ax test al,1 jz no_real32 call init_error db 'system is in protected mode without 32-bit DPMI services',24h no_real32: call init_error db 'processor is not able to enter 32-bit real mode',24h else no_dpmi: call init_error db 'no 32-bit DPMI services are available',24h end if use32 if UNREAL_ENABLED>0 init_real32_memory: mov ax,4300h ; check for XMS int 2Fh cmp al,80h ; XMS present? je xms_init mov ax,0E801h ; check for large free extended memory int 15h jnc large_raw_memory mov ah,88h ; how much extended memory free? int 15h or ax,ax jz no_extended_memory movzx eax,ax ; convert AX kilobytes to pointer shl eax,10 jmp use_raw_memory large_raw_memory: movzx ecx,cx shl ecx,10 movzx edx,dx shl edx,16 mov eax,ecx add eax,edx use_raw_memory: add eax,100000h sub eax,[program_base] mov [memory_end],eax push ds push 0 ; DS := 0 pop ds call enable_a20 ; enable A20 call test_a20 ; is A20 enabled? jz a20_ok pop ds jmp no_extended_memory a20_ok: lds bx,dword [4*19h] mov eax,100000h ; initial free extended memory base cmp dword [bx+12h],'VDIS' ; VDISK memory allocation? jne short no_vdisk ; if present, get base of free memory mov eax,dword [bx+2Ch] ; get first free extended memory byte add eax,0Fh ; align on paragraph and eax,0FFFFF0h ; address is only 24bit no_vdisk: push 0FFFFh ; DS := FFFFh for ext mem addressing pop ds cmp dword [13h],'VDIS' ; VDISK memory allocation? jne short vdisk_ok ; if present, get base of free memory movzx ebx,word [2Eh] ; get first free kilobyte shl ebx,10 cmp eax,ebx ; pick larger of 2 addresses ja short vdisk_ok mov eax,ebx vdisk_ok: pop ds sub eax,[program_base] mov [memory_start],eax mov edx,[memory_setting] shl edx,10 jz extended_memory_ok mov eax,[memory_end] sub eax,[memory_start] sub eax,edx jbe extended_memory_ok sub [memory_end],eax jmp extended_memory_ok enable_a20: call test_a20 ; is A20 already enabled? jz a20_enabled ; if yes, done in al,92h ; PS/2 A20 enable or al,2 out 92h,al call test_a20 ; is A20 enabled? jz a20_enabled ; if yes, done call kb_wait ; AT A20 enable jnz a20_enabled mov al,0D1h out 64h,al call kb_wait jnz a20_enabled mov al,0DFh out 60h,al call kb_wait a20_enabled: retn kb_wait: ; wait for safe to write to 8042 xor cx,cx .loop: in al,64h ; read 8042 status test al,2 ; buffer full? loopnz .loop ; if yes, loop retn test_a20: ; test for enabled A20 mov al,[0] ; get byte from 0:0 mov ah,al ; preserve old byte not al ; modify byte xchg al,[100000h] ; put modified byte to 0FFFFh:10h cmp ah,[0] ; set zero if byte at 0:0 not modified mov [100000h],al ; restore byte at 0FFFFh:10h retn ; return, zero if A20 enabled xms_init: push es mov ax,4310h ; get XMS driver address int 2Fh mov word [cs:xms_proc],bx ; store XMS driver address mov word [cs:xms_proc+2],es pop es mov ah,3 ; enable A20 call call_xms cmp ax,1 ; error enabling A20? jne no_extended_memory mov ah,88h ; get free extended memory size (XMS 3.0) xor bl,bl call call_xms or bl,bl jz xms_large_init mov ah,8 ; get free extended memory size xor bl,bl call call_xms or bl,bl jnz no_extended_memory mov dx,ax movzx eax,ax shl eax,10 mov [memory_end],eax mov ah,9 ; allocate largest memory block xms_allocate: mov ecx,[memory_setting] shl ecx,10 jz xms_size_ok cmp ecx,[memory_end] jae xms_size_ok mov [memory_end],ecx mov edx,[memory_setting] xms_size_ok: call call_xms mov [cs:xms_handle],dx cmp ax,1 jne no_extended_memory mov ah,0Ch ; lock extended memory block call call_xms cmp ax,1 jne no_extended_memory shl edx,16 mov dx,bx sub edx,[program_base] mov [memory_start],edx ; store memory block address add [memory_end],edx jmp extended_memory_ok xms_large_init: mov edx,eax shl eax,10 mov [memory_end],eax mov ah,89h ; allocate largest memory block (XMS 3.0) jmp xms_allocate call_xms: call modes:switch_real16 use16 call far dword [cs:xms_proc] call modes:switch_real32 use32 retn no_extended_memory: xor eax,eax mov [memory_start],eax extended_memory_ok: mov ah,48h ; get free conventional memory size mov bx,-1 int 21h movzx ecx,bx shl ecx,4 mov ah,48h ; allocate all conventional memory int 21h movzx edi,ax shl edi,4 sub edi,[program_base] mov [additional_memory],edi mov [additional_memory_end],edi add [additional_memory_end],ecx cmp [memory_start],0 je only_conventional_memory mov eax,[memory_end] sub eax,[memory_start] shr eax,2 cmp eax,ecx jbe real32_memory_ok mov eax,[memory_end] mov ebx,[memory_start] sub eax,ebx shr eax,2 mov [additional_memory],ebx add ebx,eax mov [additional_memory_end],ebx mov [memory_start],ebx real32_memory_ok: retf only_conventional_memory: shr ecx,2 ; use part of conventional memory add edi,ecx ; as a substitute for extended memory mov [memory_start],edi xchg [additional_memory_end],edi mov [memory_end],edi retf free_real32_memory: cmp [cs:xms_handle],0 je no_xms mov ah,0Dh ; unlock extended memory block mov dx,[cs:xms_handle] call call_xms mov ah,0Ah ; free extended memory block call call_xms no_xms: retf xms_proc dd ? ; XMS driver pointer xms_handle dw ? ; handle of XMS memory block end if fasm/source/DOS/system.inc0000644000175000017500000002123714533376740016257 0ustar privalovprivalov ; flat assembler interface for DOS ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. go32: use16 call modes:real32 use32 retw program_base dd ? buffer_address dd ? psp_segment dw ? environment_segment dw ? if UNREAL_ENABLED>0 init_memory: mov [stack_limit],0 cmp [mode],dpmi je init_dpmi_memory call modes:init_real32_memory ret dos_int: cmp [mode],dpmi je dpmi_dos_int stc int 21h ret dos_int_with_buffer: cmp [mode],dpmi je dpmi_dos_int_with_buffer push ds buffer pop ds stc int 21h pop ds ret exit_program: cmp [mode],dpmi je exit_state_ok push eax call modes:free_real32_memory pop eax exit_state_ok: mov ah,4Ch int 21h else init_memory: mov [stack_limit],0 jmp init_dpmi_memory dos_int: jmp dpmi_dos_int dos_int_with_buffer: jmp dpmi_dos_int_with_buffer exit_program: mov ah,4Ch int 21h end if get_environment_variable: mov ebx,esi push ds mov ds,[environment_segment] xor esi,esi compare_variable_names: mov edx,ebx compare_character: lodsb mov ah,[es:edx] inc edx cmp al,'=' je end_of_variable_name or ah,ah jz next_variable sub ah,al jz compare_character cmp ah,20h jne next_variable cmp al,41h jb next_variable cmp al,5Ah jna compare_character next_variable: lodsb or al,al jnz next_variable cmp byte [esi],0 jne compare_variable_names pop ds ret end_of_variable_name: or ah,ah jnz next_variable copy_variable_value: lodsb cmp edi,[es:memory_end] jae out_of_memory stosb or al,al jnz copy_variable_value dec edi pop ds ret open: push esi edi call adapt_path mov ax,716Ch mov bx,100000b mov dx,1 xor cx,cx xor si,si call dos_int_with_buffer jnc open_done cmp ax,7100h je old_open stc jmp open_done old_open: mov ax,3D00h xor dx,dx call dos_int_with_buffer open_done: mov bx,ax pop edi esi ret adapt_path: mov esi,edx mov edi,[buffer_address] copy_path: lodsb cmp al,'/' jne path_char_ok mov al,'\' path_char_ok: stosb or al,al jnz copy_path ret create: push esi edi call adapt_path mov ax,716Ch mov bx,100001b mov dx,10010b xor cx,cx xor si,si xor di,di call dos_int_with_buffer jnc create_done cmp ax,7100h je old_create stc jmp create_done old_create: mov ah,3Ch xor cx,cx xor dx,dx call dos_int_with_buffer create_done: mov bx,ax pop edi esi ret write: push edx esi edi ebp mov ebp,ecx mov esi,edx .loop: mov ecx,1000h sub ebp,1000h jnc .write add ebp,1000h mov ecx,ebp xor ebp,ebp .write: push ecx mov edi,[buffer_address] shr ecx,2 rep movsd mov ecx,[esp] and ecx,11b rep movsb pop ecx mov ah,40h xor dx,dx call dos_int_with_buffer or ebp,ebp jnz .loop pop ebp edi esi edx ret read: push edx esi edi ebp mov ebp,ecx mov edi,edx .loop: mov ecx,1000h sub ebp,1000h jnc .read add ebp,1000h mov ecx,ebp xor ebp,ebp .read: push ecx mov ah,3Fh xor dx,dx call dos_int_with_buffer cmp ax,cx jne .eof mov esi,[buffer_address] mov ecx,[esp] shr ecx,2 rep movsd pop ecx and ecx,11b rep movsb or ebp,ebp jnz .loop .exit: pop ebp edi esi edx ret .eof: pop ecx stc jmp .exit close: mov ah,3Eh int 21h ret lseek: mov ah,42h mov ecx,edx shr ecx,16 int 21h pushf shl edx,16 popf mov dx,ax mov eax,edx ret display_string: lods byte [esi] or al,al jz string_end mov dl,al mov ah,2 int 21h jmp display_string string_end: ret display_number: push ebx mov ecx,1000000000 xor edx,edx xor bl,bl display_loop: div ecx push edx cmp ecx,1 je display_digit or bl,bl jnz display_digit or al,al jz digit_ok not bl display_digit: mov dl,al add dl,30h mov ah,2 int 21h digit_ok: mov eax,ecx xor edx,edx mov ecx,10 div ecx mov ecx,eax pop eax or ecx,ecx jnz display_loop pop ebx ret display_user_messages: mov [displayed_count],0 call show_display_buffer cmp [displayed_count],1 jb line_break_ok je make_line_break mov ax,word [last_displayed] cmp ax,0A0Dh je line_break_ok cmp ax,0D0Ah je line_break_ok make_line_break: mov ah,2 mov dl,0Dh int 21h mov dl,0Ah int 21h line_break_ok: ret display_block: add [displayed_count],ecx cmp ecx,1 ja take_last_two_characters jb display_character mov al,[last_displayed+1] mov ah,[esi] mov word [last_displayed],ax jmp display_character take_last_two_characters: mov ax,[esi+ecx-2] mov word [last_displayed],ax display_character: lods byte [esi] mov dl,al mov ah,2 int 21h loopd display_character ret fatal_error: mov esi,error_prefix call display_string pop esi call display_string mov esi,error_suffix call display_string mov al,0FFh jmp exit_program assembler_error: call display_user_messages mov ebx,[current_line] test ebx,ebx jz display_error_message pushd 0 get_error_lines: mov eax,[ebx] cmp byte [eax],0 je get_next_error_line push ebx test byte [ebx+7],80h jz display_error_line mov edx,ebx find_definition_origin: mov edx,[edx+12] test byte [edx+7],80h jnz find_definition_origin push edx get_next_error_line: mov ebx,[ebx+8] jmp get_error_lines display_error_line: mov esi,[ebx] call display_string mov esi,line_number_start call display_string mov eax,[ebx+4] and eax,7FFFFFFFh call display_number mov dl,']' mov ah,2 int 21h pop esi cmp ebx,esi je line_number_ok mov dl,20h mov ah,2 int 21h push esi mov esi,[esi] movzx ecx,byte [esi] inc esi call display_block mov esi,line_number_start call display_string pop esi mov eax,[esi+4] and eax,7FFFFFFFh call display_number mov dl,']' mov ah,2 int 21h line_number_ok: mov esi,line_data_start call display_string mov esi,ebx mov edx,[esi] call open mov al,2 xor edx,edx call lseek mov edx,[esi+8] sub eax,edx jz line_data_displayed mov [counter],eax xor al,al call lseek mov esi,[additional_memory] read_line_data: mov ecx,100h cmp ecx,[counter] jbe bytes_count_ok mov ecx,[counter] bytes_count_ok: sub [counter],ecx lea eax,[esi+ecx] cmp eax,[additional_memory_end] ja out_of_memory push ecx mov edx,esi call read pop ecx get_line_data: mov al,[esi] cmp al,0Ah je display_line_data cmp al,0Dh je display_line_data cmp al,1Ah je display_line_data or al,al jz display_line_data inc esi loop get_line_data cmp [counter],0 ja read_line_data display_line_data: call close mov ecx,esi mov esi,[additional_memory] sub ecx,esi call display_block line_data_displayed: mov esi,cr_lf call display_string pop ebx or ebx,ebx jnz display_error_line cmp [preprocessing_done],0 je display_error_message mov esi,preprocessed_instruction_prefix call display_string mov esi,[current_line] add esi,16 mov edi,[additional_memory] xor dl,dl convert_instruction: lodsb cmp al,1Ah je copy_symbol cmp al,22h je copy_symbol cmp al,3Bh je instruction_converted stosb or al,al jz instruction_converted xor dl,dl jmp convert_instruction copy_symbol: or dl,dl jz space_ok mov byte [edi],20h inc edi space_ok: cmp al,22h je quoted lodsb movzx ecx,al rep movsb or dl,-1 jmp convert_instruction quoted: mov al,27h stosb lodsd mov ecx,eax jecxz quoted_copied copy_quoted: lodsb stosb cmp al,27h jne quote_ok stosb quote_ok: loop copy_quoted quoted_copied: mov al,27h stosb or dl,-1 jmp convert_instruction instruction_converted: xor al,al stosb mov esi,[additional_memory] call display_string mov esi,cr_lf call display_string display_error_message: mov esi,error_prefix call display_string pop esi call display_string mov esi,error_suffix call display_string mov al,2 jmp exit_program make_timestamp: mov ah,2Ah int 21h push dx cx movzx ecx,cx mov eax,ecx sub eax,1970 mov ebx,365 mul ebx mov ebp,eax mov eax,ecx sub eax,1969 shr eax,2 add ebp,eax mov eax,ecx sub eax,1901 mov ebx,100 div ebx sub ebp,eax mov eax,ecx xor edx,edx sub eax,1601 mov ebx,400 div ebx add ebp,eax movzx ecx,byte [esp+3] mov eax,ecx dec eax mov ebx,30 mul ebx add ebp,eax cmp ecx,8 jbe months_correction mov eax,ecx sub eax,7 shr eax,1 add ebp,eax mov ecx,8 months_correction: mov eax,ecx shr eax,1 add ebp,eax cmp ecx,2 pop cx jbe day_correction_ok sub ebp,2 test ecx,11b jnz day_correction_ok xor edx,edx mov eax,ecx mov ebx,100 div ebx or edx,edx jnz day_correction mov eax,ecx mov ebx,400 div ebx or edx,edx jnz day_correction_ok day_correction: inc ebp day_correction_ok: pop dx movzx eax,dl dec eax add eax,ebp mov ebx,24 mul ebx push eax mov ah,2Ch int 21h pop eax push dx movzx ebx,ch add eax,ebx mov ebx,60 mul ebx movzx ebx,cl add eax,ebx mov ebx,60 mul ebx pop bx movzx ebx,bh add eax,ebx adc edx,0 ret fasm/source/Linux/0000755000175000017500000000000014533376740014705 5ustar privalovprivalovfasm/source/Linux/fasm.asm0000644000175000017500000001406414533376740016342 0ustar privalovprivalov ; flat assembler interface for Linux ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. format ELF executable 3 entry start segment readable executable start: mov [con_handle],1 mov esi,_logo call display_string mov [command_line],esp mov ecx,[esp] lea ebx,[esp+4+ecx*4+4] mov [environment],ebx call get_params jc information call init_memory mov esi,_memory_prefix call display_string mov eax,[memory_end] sub eax,[memory_start] add eax,[additional_memory_end] sub eax,[additional_memory] shr eax,10 call display_number mov esi,_memory_suffix call display_string mov eax,78 mov ebx,buffer xor ecx,ecx int 0x80 mov eax,dword [buffer] mov ecx,1000 mul ecx mov ebx,eax mov eax,dword [buffer+4] div ecx add eax,ebx mov [start_time],eax and [preprocessing_done],0 call preprocessor or [preprocessing_done],-1 call parser call assembler call formatter call display_user_messages movzx eax,[current_pass] inc eax call display_number mov esi,_passes_suffix call display_string mov eax,78 mov ebx,buffer xor ecx,ecx int 0x80 mov eax,dword [buffer] mov ecx,1000 mul ecx mov ebx,eax mov eax,dword [buffer+4] div ecx add eax,ebx sub eax,[start_time] jnc time_ok add eax,3600000 time_ok: xor edx,edx mov ebx,100 div ebx or eax,eax jz display_bytes_count xor edx,edx mov ebx,10 div ebx push edx call display_number mov dl,'.' call display_character pop eax call display_number mov esi,_seconds_suffix call display_string display_bytes_count: mov eax,[written_size] call display_number mov esi,_bytes_suffix call display_string xor al,al jmp exit_program information: mov esi,_usage call display_string mov al,1 jmp exit_program get_params: mov ebx,[command_line] mov [input_file],0 mov [output_file],0 mov [symbols_file],0 mov [memory_setting],0 mov [passes_limit],100 mov ecx,[ebx] add ebx,8 dec ecx jz bad_params mov [definitions_pointer],predefinitions get_param: mov esi,[ebx] mov al,[esi] cmp al,'-' je option_param cmp [input_file],0 jne get_output_file mov [input_file],esi jmp next_param get_output_file: cmp [output_file],0 jne bad_params mov [output_file],esi jmp next_param option_param: inc esi lodsb cmp al,'m' je memory_option cmp al,'M' je memory_option cmp al,'p' je passes_option cmp al,'P' je passes_option cmp al,'d' je definition_option cmp al,'D' je definition_option cmp al,'s' je symbols_option cmp al,'S' je symbols_option bad_params: stc ret memory_option: cmp byte [esi],0 jne get_memory_setting dec ecx jz bad_params add ebx,4 mov esi,[ebx] get_memory_setting: call get_option_value or edx,edx jz bad_params cmp edx,1 shl (32-10) jae bad_params mov [memory_setting],edx jmp next_param passes_option: cmp byte [esi],0 jne get_passes_setting dec ecx jz bad_params add ebx,4 mov esi,[ebx] get_passes_setting: call get_option_value or edx,edx jz bad_params cmp edx,10000h ja bad_params mov [passes_limit],dx next_param: add ebx,4 dec ecx jnz get_param cmp [input_file],0 je bad_params mov eax,[definitions_pointer] mov byte [eax],0 mov [initial_definitions],predefinitions clc ret definition_option: cmp byte [esi],0 jne get_definition dec ecx jz bad_params add ebx,4 mov esi,[ebx] get_definition: push edi mov edi,[definitions_pointer] call convert_definition_option mov [definitions_pointer],edi pop edi jc bad_params jmp next_param symbols_option: cmp byte [esi],0 jne get_symbols_setting dec ecx jz bad_params add ebx,4 mov esi,[ebx] get_symbols_setting: mov [symbols_file],esi jmp next_param get_option_value: xor eax,eax mov edx,eax get_option_digit: lodsb cmp al,20h je option_value_ok or al,al jz option_value_ok sub al,30h jc invalid_option_value cmp al,9 ja invalid_option_value imul edx,10 jo invalid_option_value add edx,eax jc invalid_option_value jmp get_option_digit option_value_ok: dec esi clc ret invalid_option_value: stc ret convert_definition_option: mov edx,edi cmp edi,predefinitions+1000h jae bad_definition_option xor al,al stosb copy_definition_name: lodsb cmp al,'=' je copy_definition_value cmp al,20h je bad_definition_option or al,al jz bad_definition_option cmp edi,predefinitions+1000h jae bad_definition_option stosb inc byte [edx] jnz copy_definition_name bad_definition_option: stc ret copy_definition_value: lodsb cmp al,20h je definition_value_end or al,al jz definition_value_end cmp edi,predefinitions+1000h jae bad_definition_option stosb jmp copy_definition_value definition_value_end: dec esi cmp edi,predefinitions+1000h jae bad_definition_option xor al,al stosb clc ret include 'system.inc' include '..\version.inc' _copyright db 'Copyright (c) 1999-2022, Tomasz Grysztar',0xA,0 _logo db 'flat assembler version ',VERSION_STRING,0 _usage db 0xA db 'usage: fasm [output]',0xA db 'optional settings:',0xA db ' -m set the limit in kilobytes for the available memory',0xA db ' -p set the maximum allowed number of passes',0xA db ' -d = define symbolic variable',0xA db ' -s dump symbolic information for debugging',0xA db 0 _memory_prefix db ' (',0 _memory_suffix db ' kilobytes memory)',0xA,0 _passes_suffix db ' passes, ',0 _seconds_suffix db ' seconds, ',0 _bytes_suffix db ' bytes.',0xA,0 include '..\errors.inc' include '..\symbdump.inc' include '..\preproce.inc' include '..\parser.inc' include '..\exprpars.inc' include '..\assemble.inc' include '..\exprcalc.inc' include '..\formats.inc' include '..\x86_64.inc' include '..\avx.inc' include '..\tables.inc' include '..\messages.inc' segment readable writeable align 4 include '..\variable.inc' command_line dd ? memory_setting dd ? definitions_pointer dd ? environment dd ? timestamp dq ? start_time dd ? con_handle dd ? displayed_count dd ? last_displayed db ? character db ? preprocessing_done db ? predefinitions rb 1000h buffer rb 1000h fasm/source/Linux/system.inc0000644000175000017500000001656514533376740016741 0ustar privalovprivalov ; flat assembler interface for Linux ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. O_ACCMODE = 0003o O_RDONLY = 0000o O_WRONLY = 0001o O_RDWR = 0002o O_CREAT = 0100o O_EXCL = 0200o O_NOCTTY = 0400o O_TRUNC = 1000o O_APPEND = 2000o O_NONBLOCK = 4000o S_ISUID = 4000o S_ISGID = 2000o S_ISVTX = 1000o S_IRUSR = 0400o S_IWUSR = 0200o S_IXUSR = 0100o S_IRGRP = 0040o S_IWGRP = 0020o S_IXGRP = 0010o S_IROTH = 0004o S_IWOTH = 0002o S_IXOTH = 0001o init_memory: mov eax,esp and eax,not 0FFFh add eax,1000h-10000h mov [stack_limit],eax xor ebx,ebx mov eax,45 int 0x80 mov [additional_memory],eax mov ecx,[memory_setting] shl ecx,10 jnz allocate_memory mov ecx,1000000h allocate_memory: mov ebx,[additional_memory] add ebx,ecx mov eax,45 int 0x80 mov [memory_end],eax sub eax,[additional_memory] shr eax,2 add eax,[additional_memory] mov [additional_memory_end],eax mov [memory_start],eax ret exit_program: movzx ebx,al mov eax,1 int 0x80 get_environment_variable: mov ecx,esi mov ebx,[environment] next_variable: mov esi,[ebx] test esi,esi jz no_environment_variable add ebx,4 compare_variable_names: mov edx,ecx compare_character: lodsb mov ah,[edx] inc edx cmp al,'=' je end_of_variable_name or ah,ah jz next_variable sub ah,al jz compare_character cmp ah,20h jne next_variable cmp al,41h jb next_variable cmp al,5Ah jna compare_character jmp next_variable no_environment_variable: ret end_of_variable_name: or ah,ah jnz next_variable copy_variable_value: lodsb cmp edi,[memory_end] jae out_of_memory stosb or al,al jnz copy_variable_value dec edi ret open: push esi edi ebp call adapt_path mov eax,5 mov ebx,buffer mov ecx,O_RDONLY xor edx,edx int 0x80 pop ebp edi esi test eax,eax js file_error mov ebx,eax clc ret adapt_path: mov esi,edx mov edi,buffer copy_path: lods byte [esi] cmp al,'\' jne path_char_ok mov al,'/' path_char_ok: stos byte [edi] or al,al jnz copy_path cmp edi,buffer+1000h ja out_of_memory ret create: push esi edi ebp edx call adapt_path mov ebx,buffer mov ecx,O_CREAT+O_TRUNC+O_WRONLY mov edx,S_IRUSR+S_IWUSR+S_IRGRP+S_IROTH pop eax cmp eax,[output_file] jne do_create cmp [output_format],5 jne do_create bt [format_flags],0 jnc do_create or edx,S_IXUSR+S_IXGRP+S_IXOTH do_create: mov eax,5 int 0x80 pop ebp edi esi test eax,eax js file_error mov ebx,eax clc ret close: mov eax,6 int 0x80 ret read: push ecx edx esi edi ebp mov eax,3 xchg ecx,edx int 0x80 pop ebp edi esi edx ecx test eax,eax js file_error cmp eax,ecx jne file_error clc ret file_error: stc ret write: push edx esi edi ebp mov eax,4 xchg ecx,edx int 0x80 pop ebp edi esi edx test eax,eax js file_error clc ret lseek: mov ecx,edx xor edx,edx mov dl,al mov eax,19 int 0x80 cmp eax,-1 je file_error clc ret display_string: push ebx mov edi,esi mov edx,esi or ecx,-1 xor al,al repne scasb neg ecx sub ecx,2 mov eax,4 mov ebx,[con_handle] xchg ecx,edx int 0x80 pop ebx ret display_character: push ebx mov [character],dl mov eax,4 mov ebx,[con_handle] mov ecx,character mov edx,1 int 0x80 pop ebx ret display_number: push ebx mov ecx,1000000000 xor edx,edx xor bl,bl display_loop: div ecx push edx cmp ecx,1 je display_digit or bl,bl jnz display_digit or al,al jz digit_ok not bl display_digit: mov dl,al add dl,30h push ebx ecx call display_character pop ecx ebx digit_ok: mov eax,ecx xor edx,edx mov ecx,10 div ecx mov ecx,eax pop eax or ecx,ecx jnz display_loop pop ebx ret display_user_messages: mov [displayed_count],0 call show_display_buffer cmp [displayed_count],0 je line_break_ok cmp [last_displayed],0Ah je line_break_ok mov dl,0Ah call display_character line_break_ok: ret display_block: jecxz block_displayed add [displayed_count],ecx mov al,[esi+ecx-1] mov [last_displayed],al push ebx mov eax,4 mov ebx,[con_handle] mov edx,ecx mov ecx,esi int 0x80 pop ebx block_displayed: ret fatal_error: mov [con_handle],2 mov esi,error_prefix call display_string pop esi call display_string mov esi,error_suffix call display_string mov al,0FFh jmp exit_program assembler_error: mov [con_handle],2 call display_user_messages mov ebx,[current_line] test ebx,ebx jz display_error_message pushd 0 get_error_lines: mov eax,[ebx] cmp byte [eax],0 je get_next_error_line push ebx test byte [ebx+7],80h jz display_error_line mov edx,ebx find_definition_origin: mov edx,[edx+12] test byte [edx+7],80h jnz find_definition_origin push edx get_next_error_line: mov ebx,[ebx+8] jmp get_error_lines display_error_line: mov esi,[ebx] call display_string mov esi,line_number_start call display_string mov eax,[ebx+4] and eax,7FFFFFFFh call display_number mov dl,']' call display_character pop esi cmp ebx,esi je line_number_ok mov dl,20h call display_character push esi mov esi,[esi] movzx ecx,byte [esi] inc esi call display_block mov esi,line_number_start call display_string pop esi mov eax,[esi+4] and eax,7FFFFFFFh call display_number mov dl,']' call display_character line_number_ok: mov esi,line_data_start call display_string mov esi,ebx mov edx,[esi] call open mov al,2 xor edx,edx call lseek mov edx,[esi+8] sub eax,edx jz line_data_displayed push eax xor al,al call lseek mov ecx,[esp] mov edx,[additional_memory] lea eax,[edx+ecx] cmp eax,[additional_memory_end] ja out_of_memory call read call close pop ecx mov esi,[additional_memory] get_line_data: mov al,[esi] cmp al,0Ah je display_line_data cmp al,0Dh je display_line_data cmp al,1Ah je display_line_data or al,al jz display_line_data inc esi loop get_line_data display_line_data: mov ecx,esi mov esi,[additional_memory] sub ecx,esi call display_block line_data_displayed: mov esi,lf call display_string pop ebx or ebx,ebx jnz display_error_line cmp [preprocessing_done],0 je display_error_message mov esi,preprocessed_instruction_prefix call display_string mov esi,[current_line] add esi,16 mov edi,[additional_memory] xor dl,dl convert_instruction: lodsb cmp al,1Ah je copy_symbol cmp al,22h je copy_symbol cmp al,3Bh je instruction_converted stosb or al,al jz instruction_converted xor dl,dl jmp convert_instruction copy_symbol: or dl,dl jz space_ok mov byte [edi],20h inc edi space_ok: cmp al,22h je quoted lodsb movzx ecx,al rep movsb or dl,-1 jmp convert_instruction quoted: mov al,27h stosb lodsd mov ecx,eax jecxz quoted_copied copy_quoted: lodsb stosb cmp al,27h jne quote_ok stosb quote_ok: loop copy_quoted quoted_copied: mov al,27h stosb or dl,-1 jmp convert_instruction instruction_converted: xor al,al stosb mov esi,[additional_memory] call display_string mov esi,lf call display_string display_error_message: mov esi,error_prefix call display_string pop esi call display_string mov esi,error_suffix call display_string mov al,2 jmp exit_program make_timestamp: mov eax,13 mov ebx,timestamp int 0x80 mov eax,dword [timestamp] mov edx,dword [timestamp+4] ret error_prefix db 'error: ',0 error_suffix db '.' lf db 0xA,0 line_number_start db ' [',0 line_data_start db ':',0xA,0 preprocessed_instruction_prefix db 'processed: ',0 fasm/source/Linux/x64/0000755000175000017500000000000014533376740015326 5ustar privalovprivalovfasm/source/Linux/x64/fasm.asm0000644000175000017500000001477514533376740016774 0ustar privalovprivalov ; flat assembler interface for Linux x64 ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. format ELF64 executable 3 at 400000h entry start include 'modes.inc' segment readable executable start: mov [con_handle],1 mov esi,_logo call display_string mov [command_line],rsp mov rcx,[rsp] lea rbx,[rsp+8+rcx*8+8] mov [environment],rbx call get_params jc information call init_memory mov esi,_memory_prefix call display_string mov eax,[memory_end] sub eax,[memory_start] add eax,[additional_memory_end] sub eax,[additional_memory] shr eax,10 call display_number mov esi,_memory_suffix call display_string mov eax,96 mov edi,buffer xor esi,esi syscall mov eax,dword [buffer] mov ecx,1000 mul ecx mov ebx,eax mov eax,dword [buffer+4] div ecx add eax,ebx mov [start_time],eax and [preprocessing_done],0 call preprocessor or [preprocessing_done],-1 call parser call assembler call formatter call display_user_messages movzx eax,[current_pass] inc eax call display_number mov esi,_passes_suffix call display_string mov eax,96 mov edi,buffer xor esi,esi syscall mov eax,dword [buffer] mov ecx,1000 mul ecx mov ebx,eax mov eax,dword [buffer+4] div ecx add eax,ebx sub eax,[start_time] jnc time_ok add eax,3600000 time_ok: xor edx,edx mov ebx,100 div ebx or eax,eax jz display_bytes_count xor edx,edx mov ebx,10 div ebx push edx call display_number mov dl,'.' call display_character pop eax call display_number mov esi,_seconds_suffix call display_string display_bytes_count: mov eax,[written_size] call display_number mov esi,_bytes_suffix call display_string xor al,al jmp exit_program information: mov esi,_usage call display_string mov al,1 jmp exit_program get_params: mov rbx,[command_line] mov [input_file],0 mov [output_file],0 mov [symbols_file],0 mov [memory_setting],0 mov [passes_limit],100 mov rcx,[rbx] add rbx,8*2 dec rcx jz bad_params mov [definitions_pointer],predefinitions mov [path_pointer],paths get_param: mov rsi,[rbx] mov al,[rsi] cmp al,'-' je option_param cmp [input_file],0 jne get_output_file call collect_path mov [input_file],edx jmp next_param get_output_file: cmp [output_file],0 jne bad_params call collect_path mov [output_file],edx jmp next_param option_param: inc rsi lodsb cmp al,'m' je memory_option cmp al,'M' je memory_option cmp al,'p' je passes_option cmp al,'P' je passes_option cmp al,'d' je definition_option cmp al,'D' je definition_option cmp al,'s' je symbols_option cmp al,'S' je symbols_option bad_params: stc ret memory_option: cmp byte [rsi],0 jne get_memory_setting dec rcx jz bad_params add rbx,8 mov rsi,[rbx] get_memory_setting: call get_option_value or edx,edx jz bad_params cmp edx,1 shl (32-10) jae bad_params mov [memory_setting],edx jmp next_param passes_option: cmp byte [rsi],0 jne get_passes_setting dec rcx jz bad_params add rbx,8 mov rsi,[rbx] get_passes_setting: call get_option_value or edx,edx jz bad_params cmp edx,10000h ja bad_params mov [passes_limit],dx next_param: add rbx,8 dec rcx jnz get_param cmp [input_file],0 je bad_params mov eax,[definitions_pointer] mov byte [eax],0 mov [initial_definitions],predefinitions clc ret definition_option: cmp byte [rsi],0 jne get_definition dec rcx jz bad_params add rbx,8 mov rsi,[rbx] get_definition: mov r12d,edi mov edi,[definitions_pointer] call convert_definition_option mov [definitions_pointer],edi mov edi,r12d jc bad_params jmp next_param symbols_option: cmp byte [rsi],0 jne get_symbols_setting dec rcx jz bad_params add rbx,8 mov rsi,[rbx] get_symbols_setting: call collect_path mov [symbols_file],edx jmp next_param get_option_value: xor eax,eax mov edx,eax get_option_digit: lodsb cmp al,20h je option_value_ok or al,al jz option_value_ok sub al,30h jc invalid_option_value cmp al,9 ja invalid_option_value imul edx,10 jo invalid_option_value add edx,eax jc invalid_option_value jmp get_option_digit option_value_ok: dec rsi clc ret invalid_option_value: stc ret convert_definition_option: mov edx,edi cmp edi,predefinitions+1000h jae bad_definition_option xor al,al stosb copy_definition_name: lodsb cmp al,'=' je copy_definition_value cmp al,20h je bad_definition_option or al,al jz bad_definition_option cmp edi,predefinitions+1000h jae bad_definition_option stosb inc byte [edx] jnz copy_definition_name bad_definition_option: stc ret copy_definition_value: lodsb cmp al,20h je definition_value_end or al,al jz definition_value_end cmp edi,predefinitions+1000h jae bad_definition_option stosb jmp copy_definition_value definition_value_end: dec rsi cmp edi,predefinitions+1000h jae bad_definition_option xor al,al stosb clc ret collect_path: mov edi,[path_pointer] mov edx,edi copy_path_to_low_memory: lodsb stosb test al,al jnz copy_path_to_low_memory mov [path_pointer],edi retn include 'system.inc' include '..\..\version.inc' _copyright db 'Copyright (c) 1999-2022, Tomasz Grysztar',0xA,0 _logo db 'flat assembler version ',VERSION_STRING,0 _usage db 0xA db 'usage: fasm [output]',0xA db 'optional settings:',0xA db ' -m set the limit in kilobytes for the available memory',0xA db ' -p set the maximum allowed number of passes',0xA db ' -d = define symbolic variable',0xA db ' -s dump symbolic information for debugging',0xA db 0 _memory_prefix db ' (',0 _memory_suffix db ' kilobytes memory, x64)',0xA,0 _passes_suffix db ' passes, ',0 _seconds_suffix db ' seconds, ',0 _bytes_suffix db ' bytes.',0xA,0 _no_low_memory db 'failed to allocate memory within 32-bit addressing range',0 include '..\..\errors.inc' include '..\..\symbdump.inc' include '..\..\preproce.inc' include '..\..\parser.inc' include '..\..\exprpars.inc' include '..\..\assemble.inc' include '..\..\exprcalc.inc' include '..\..\x86_64.inc' include '..\..\avx.inc' include '..\..\formats.inc' include '..\..\tables.inc' include '..\..\messages.inc' segment readable writeable align 4 include '..\..\variable.inc' command_line dq ? memory_setting dd ? path_pointer dd ? definitions_pointer dd ? environment dq ? timestamp dq ? start_time dd ? con_handle dd ? displayed_count dd ? last_displayed db ? character db ? preprocessing_done db ? buffer rb 1000h predefinitions rb 1000h paths rb 10000h fasm/source/Linux/x64/modes.inc0000644000175000017500000000543414533376740017136 0ustar privalovprivalov ; flat assembler interface for Linux x64 ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. esp equ +rsp macro pushD [arg] { common local offset,total offset = 0 lea rsp,[rsp-total] forward offset = offset + 4 if arg eqtype eax mov dword [rsp+total-offset],arg else mov r8d,dword arg mov [rsp+total-offset],r8d end if common total = offset } macro popD [arg] { common local offset offset = 0 forward if arg eqtype [mem] mov r8d,[rsp+offset] mov dword arg,r8d else mov arg,dword [rsp+offset] end if offset = offset + 4 common lea rsp,[rsp+offset] } macro add dest,src { if dest eq esp add rsp,src else add dest,src end if } macro mov dest,src { if src eq esp mov dest,ESP else mov dest,src end if } macro cmp dest,src { if dest eq esp cmp ESP,src else cmp dest,src end if } macro use32 { macro push args \{ local list,arg,status define list define arg irps sym, args \\{ define status match =dword, sym \\\{ define status : \\\} match [any, status arg sym \\\{ define arg [any match [mem], arg \\\\{ match previous, list \\\\\{ define list previous,[mem] \\\\\} match , list \\\\\{ define list [mem] \\\\\} define arg \\\\} define status : \\\} match [, status arg sym \\\{ define arg [ define status : \\\} match , status \\\{ match previous, list \\\\{ define list previous,sym \\\\} match , list \\\\{ define list sym \\\\} \\\} \\} match arg, list \\{ pushD arg \\} \} macro pop args \{ local list,arg,status define list define arg irps sym, args \\{ define status match =dword, sym \\\{ define status : \\\} match [any, status arg sym \\\{ define arg [any match [mem], arg \\\\{ match previous, list \\\\\{ define list previous,[mem] \\\\\} match , list \\\\\{ define list [mem] \\\\\} define arg \\\\} define status : \\\} match [, status arg sym \\\{ define arg [ define status : \\\} match , status \\\{ match previous, list \\\\{ define list previous,sym \\\\} match , list \\\\{ define list sym \\\\} \\\} \\} match arg, list \\{ popD arg \\} \} macro jmp arg \{ if arg eq near eax jmp near rax else if arg eq near edx jmp near rdx else if arg eqtype [mem] mov r8d,arg jmp near r8 else jmp arg end if \} macro call arg \{ if 1 match =near =dword [mem], arg \\{ mov r8d,[mem] call near r8 else \\} call arg end if \} macro salc ; for fasm's core it does not need to preserve flags \{ setc al neg al \} macro jcxz target ; for fasm's core it does not need to preserve flags \{ test cx,cx jz target \} use64 } macro use16 { purge push,pop,jmp,call,salc,jcxz use16 } use32 fasm/source/Linux/x64/system.inc0000644000175000017500000002117314533376740017351 0ustar privalovprivalov ; flat assembler interface for Linux x64 ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. O_ACCMODE = 0003o O_RDONLY = 0000o O_WRONLY = 0001o O_RDWR = 0002o O_CREAT = 0100o O_EXCL = 0200o O_NOCTTY = 0400o O_TRUNC = 1000o O_APPEND = 2000o O_NONBLOCK = 4000o S_ISUID = 4000o S_ISGID = 2000o S_ISVTX = 1000o S_IRUSR = 0400o S_IWUSR = 0200o S_IXUSR = 0100o S_IRGRP = 0040o S_IWGRP = 0020o S_IXGRP = 0010o S_IROTH = 0004o S_IWOTH = 0002o S_IXOTH = 0001o init_memory: mov eax,esp and eax,not 0FFFh add eax,1000h-10000h mov [stack_limit],eax xor edi,edi mov eax,12 syscall mov ecx,[memory_setting] shl ecx,10 jnz allocate_memory mov ecx,1000000h allocate_memory: mov r9d,eax cmp rax,r9 jne high_brk mov [additional_memory],eax lea edi,[eax+ecx] mov eax,12 syscall mov r9d,eax cmp rax,r9 jne no_low_memory mov [memory_end],eax sub eax,[additional_memory] shr eax,2 add eax,[additional_memory] mov [additional_memory_end],eax mov [memory_start],eax ret high_brk: xor r9d,r9d or r8,-1 mov r10d,62h ; MAP_PRIVATE + MAP_ANONYMOUS + MAP_32BIT mov edx,3 ; PROT_READ + PROT_WRITE mov esi,ecx xor edi,edi mov eax,9 ; sys_mmap syscall cmp eax,-1 je mmap_with_hint mov r9d,eax cmp rax,r9 jne mmap_unusable add r9d,esi jnc mmap_ok mmap_unusable: mov rdi,rax mov eax,11 ; sys_munmap syscall mmap_with_hint: mov r10d,22h ; MAP_PRIVATE + MAP_ANONYMOUS mov edx,3 ; PROT_READ + PROT_WRITE mov edi,480000h mov eax,9 ; sys_mmap syscall cmp eax,-1 je no_low_memory mov r9d,eax cmp rax,r9 jne no_low_memory add r9d,esi jnc mmap_ok no_low_memory: mov esi,lf call display_string push _no_low_memory jmp fatal_error mmap_ok: mov [additional_memory],eax lea edi,[eax+esi] mov [memory_end],edi shr esi,2 add eax,esi mov [additional_memory_end],eax mov [memory_start],eax ret exit_program: movzx edi,al mov eax,60 syscall get_environment_variable: mov ecx,esi mov rbx,[environment] next_variable: mov rsi,[rbx] test rsi,rsi jz no_environment_variable add rbx,8 compare_variable_names: mov edx,ecx compare_character: lodsb mov ah,[edx] inc edx cmp al,'=' je end_of_variable_name or ah,ah jz next_variable sub ah,al jz compare_character cmp ah,20h jne next_variable cmp al,41h jb next_variable cmp al,5Ah jna compare_character jmp next_variable no_environment_variable: ret end_of_variable_name: or ah,ah jnz next_variable copy_variable_value: lodsb cmp edi,[memory_end] jae out_of_memory stosb or al,al jnz copy_variable_value dec edi ret open: mov r12d,esi mov r13d,edi call adapt_path mov eax,2 mov edi,buffer mov esi,O_RDONLY xor edx,edx syscall mov esi,r12d mov edi,r13d test eax,eax js file_error mov ebx,eax clc ret adapt_path: mov esi,edx mov edi,buffer copy_path: lods byte [esi] cmp al,'\' jne path_char_ok mov al,'/' path_char_ok: stos byte [edi] or al,al jnz copy_path cmp edi,buffer+1000h ja out_of_memory ret create: mov r12d,esi mov r13d,edi mov r15d,edx call adapt_path mov edi,buffer mov esi,O_CREAT+O_TRUNC+O_WRONLY mov edx,S_IRUSR+S_IWUSR+S_IRGRP+S_IROTH cmp r15d,[output_file] jne do_create cmp [output_format],5 jne do_create bt [format_flags],0 jnc do_create or edx,S_IXUSR+S_IXGRP+S_IXOTH do_create: mov eax,2 syscall mov esi,r12d mov edi,r13d test eax,eax js file_error mov ebx,eax clc ret close: mov r13d,edi mov edi,ebx mov eax,3 syscall mov edi,r13d ret read: mov r12d,esi mov r13d,edi mov eax,0 mov edi,ebx mov esi,edx mov edx,ecx syscall mov ecx,edx mov edx,esi mov esi,r12d mov edi,r13d test eax,eax js file_error cmp eax,ecx jne file_error clc ret file_error: stc ret write: mov r12d,esi mov r13d,edi mov eax,1 mov edi,ebx mov esi,edx mov edx,ecx syscall mov ecx,edx mov edx,esi mov esi,r12d mov edi,r13d test eax,eax js file_error clc ret lseek: mov r12d,esi mov r13d,edi mov edi,ebx mov esi,edx xor edx,edx mov dl,al mov eax,8 syscall mov esi,r12d mov edi,r13d cmp eax,-1 je file_error clc ret display_string: mov edi,esi mov edx,esi or ecx,-1 xor al,al repne scasb neg ecx sub ecx,2 mov eax,1 mov edi,[con_handle] mov esi,edx mov edx,ecx syscall ret display_character: mov r12d,esi mov r13d,edi mov [character],dl mov eax,1 mov edi,[con_handle] mov esi,character mov edx,1 syscall mov esi,r12d mov edi,r13d ret display_number: mov r14d,ebx mov ecx,1000000000 xor edx,edx xor bl,bl display_loop: div ecx mov r15d,edx cmp ecx,1 je display_digit or bl,bl jnz display_digit or al,al jz digit_ok not bl display_digit: mov dl,al add dl,30h mov r10d,ecx call display_character mov ecx,r10d digit_ok: mov eax,ecx xor edx,edx mov ecx,10 div ecx mov ecx,eax mov eax,r15d or ecx,ecx jnz display_loop mov ebx,r14d ret display_user_messages: mov [displayed_count],0 call show_display_buffer cmp [displayed_count],0 je line_break_ok cmp [last_displayed],0Ah je line_break_ok mov dl,0Ah call display_character line_break_ok: ret display_block: jecxz block_displayed add [displayed_count],ecx mov al,[esi+ecx-1] mov [last_displayed],al mov r13d,edi mov eax,1 mov edi,[con_handle] mov edx,ecx syscall mov edi,r13d block_displayed: ret fatal_error: mov [con_handle],2 mov esi,error_prefix call display_string pop esi call display_string mov esi,error_suffix call display_string mov al,0FFh jmp exit_program assembler_error: mov [con_handle],2 call display_user_messages mov ebx,[current_line] test ebx,ebx jz display_error_message push dword 0 get_error_lines: mov eax,[ebx] cmp byte [eax],0 je get_next_error_line push ebx test byte [ebx+7],80h jz display_error_line mov edx,ebx find_definition_origin: mov edx,[edx+12] test byte [edx+7],80h jnz find_definition_origin push edx get_next_error_line: mov ebx,[ebx+8] jmp get_error_lines display_error_line: mov esi,[ebx] call display_string mov esi,line_number_start call display_string mov eax,[ebx+4] and eax,7FFFFFFFh call display_number mov dl,']' call display_character pop esi cmp ebx,esi je line_number_ok mov dl,20h call display_character push esi mov esi,[esi] movzx ecx,byte [esi] inc esi call display_block mov esi,line_number_start call display_string pop esi mov eax,[esi+4] and eax,7FFFFFFFh call display_number mov dl,']' call display_character line_number_ok: mov esi,line_data_start call display_string mov esi,ebx mov edx,[esi] call open mov al,2 xor edx,edx call lseek mov edx,[esi+8] sub eax,edx jz line_data_displayed push eax xor al,al call lseek mov ecx,[esp] mov edx,[additional_memory] lea eax,[edx+ecx] cmp eax,[additional_memory_end] ja out_of_memory call read call close pop ecx mov esi,[additional_memory] get_line_data: mov al,[esi] cmp al,0Ah je display_line_data cmp al,0Dh je display_line_data cmp al,1Ah je display_line_data or al,al jz display_line_data inc esi loop get_line_data display_line_data: mov ecx,esi mov esi,[additional_memory] sub ecx,esi call display_block line_data_displayed: mov esi,lf call display_string pop ebx or ebx,ebx jnz display_error_line cmp [preprocessing_done],0 je display_error_message mov esi,preprocessed_instruction_prefix call display_string mov esi,[current_line] add esi,16 mov edi,[additional_memory] xor dl,dl convert_instruction: lodsb cmp al,1Ah je copy_symbol cmp al,22h je copy_symbol cmp al,3Bh je instruction_converted stosb or al,al jz instruction_converted xor dl,dl jmp convert_instruction copy_symbol: or dl,dl jz space_ok mov byte [edi],20h inc edi space_ok: cmp al,22h je quoted lodsb movzx ecx,al rep movsb or dl,-1 jmp convert_instruction quoted: mov al,27h stosb lodsd mov ecx,eax jecxz quoted_copied copy_quoted: lodsb stosb cmp al,27h jne quote_ok stosb quote_ok: loop copy_quoted quoted_copied: mov al,27h stosb or dl,-1 jmp convert_instruction instruction_converted: xor al,al stosb mov esi,[additional_memory] call display_string mov esi,lf call display_string display_error_message: mov esi,error_prefix call display_string pop esi call display_string mov esi,error_suffix call display_string mov al,2 jmp exit_program make_timestamp: mov r13d,edi mov eax,201 mov edi,timestamp syscall mov eax,dword [timestamp] mov edx,dword [timestamp+4] mov edi,r13d ret error_prefix db 'error: ',0 error_suffix db '.' lf db 0xA,0 line_number_start db ' [',0 line_data_start db ':',0xA,0 preprocessed_instruction_prefix db 'processed: ',0 fasm/source/Win32/0000755000175000017500000000000014533376740014510 5ustar privalovprivalovfasm/source/Win32/fasm.asm0000644000175000017500000002001514533376740016136 0ustar privalovprivalov ; flat assembler interface for Win32 ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. format PE console section '.text' code readable executable start: mov [con_handle],STD_OUTPUT_HANDLE mov esi,_logo call display_string call get_params jc information call init_memory mov esi,_memory_prefix call display_string mov eax,[memory_end] sub eax,[memory_start] add eax,[additional_memory_end] sub eax,[additional_memory] shr eax,10 call display_number mov esi,_memory_suffix call display_string call [GetTickCount] mov [start_time],eax and [preprocessing_done],0 call preprocessor or [preprocessing_done],-1 call parser call assembler call formatter call display_user_messages movzx eax,[current_pass] inc eax call display_number mov esi,_passes_suffix call display_string call [GetTickCount] sub eax,[start_time] xor edx,edx mov ebx,100 div ebx or eax,eax jz display_bytes_count xor edx,edx mov ebx,10 div ebx push edx call display_number mov dl,'.' call display_character pop eax call display_number mov esi,_seconds_suffix call display_string display_bytes_count: mov eax,[written_size] call display_number mov esi,_bytes_suffix call display_string xor al,al jmp exit_program information: mov esi,_usage call display_string mov al,1 jmp exit_program get_params: mov [input_file],0 mov [output_file],0 mov [symbols_file],0 mov [memory_setting],0 mov [passes_limit],100 call [GetCommandLine] mov [definitions_pointer],predefinitions mov esi,eax mov edi,params find_command_start: lodsb cmp al,20h je find_command_start cmp al,22h je skip_quoted_name skip_name: lodsb cmp al,20h je find_param or al,al jz all_params jmp skip_name skip_quoted_name: lodsb cmp al,22h je find_param or al,al jz all_params jmp skip_quoted_name find_param: lodsb cmp al,20h je find_param cmp al,'-' je option_param cmp al,0Dh je all_params or al,al jz all_params cmp [input_file],0 jne get_output_file mov [input_file],edi jmp process_param get_output_file: cmp [output_file],0 jne bad_params mov [output_file],edi process_param: cmp al,22h je string_param copy_param: cmp edi,params+1000h jae bad_params stosb lodsb cmp al,20h je param_end cmp al,0Dh je param_end or al,al jz param_end jmp copy_param string_param: lodsb cmp al,22h je string_param_end cmp al,0Dh je param_end or al,al jz param_end cmp edi,params+1000h jae bad_params stosb jmp string_param option_param: lodsb cmp al,'m' je memory_option cmp al,'M' je memory_option cmp al,'p' je passes_option cmp al,'P' je passes_option cmp al,'d' je definition_option cmp al,'D' je definition_option cmp al,'s' je symbols_option cmp al,'S' je symbols_option bad_params: stc ret get_option_value: xor eax,eax mov edx,eax get_option_digit: lodsb cmp al,20h je option_value_ok cmp al,0Dh je option_value_ok or al,al jz option_value_ok sub al,30h jc invalid_option_value cmp al,9 ja invalid_option_value imul edx,10 jo invalid_option_value add edx,eax jc invalid_option_value jmp get_option_digit option_value_ok: dec esi clc ret invalid_option_value: stc ret memory_option: lodsb cmp al,20h je memory_option cmp al,0Dh je bad_params or al,al jz bad_params dec esi call get_option_value or edx,edx jz bad_params cmp edx,1 shl (32-10) jae bad_params mov [memory_setting],edx jmp find_param passes_option: lodsb cmp al,20h je passes_option cmp al,0Dh je bad_params or al,al jz bad_params dec esi call get_option_value or edx,edx jz bad_params cmp edx,10000h ja bad_params mov [passes_limit],dx jmp find_param definition_option: lodsb cmp al,20h je definition_option cmp al,0Dh je bad_params or al,al jz bad_params dec esi push edi mov edi,[definitions_pointer] call convert_definition_option mov [definitions_pointer],edi pop edi jc bad_params jmp find_param symbols_option: mov [symbols_file],edi find_symbols_file_name: lodsb cmp al,20h jne process_param jmp find_symbols_file_name param_end: dec esi string_param_end: cmp edi,params+1000h jae bad_params xor al,al stosb jmp find_param all_params: cmp [input_file],0 je bad_params mov eax,[definitions_pointer] mov byte [eax],0 mov [initial_definitions],predefinitions clc ret convert_definition_option: mov ecx,edi cmp edi,predefinitions+1000h jae bad_definition_option xor al,al stosb copy_definition_name: lodsb cmp al,'=' je copy_definition_value cmp al,20h je bad_definition_option cmp al,0Dh je bad_definition_option or al,al jz bad_definition_option cmp edi,predefinitions+1000h jae bad_definition_option stosb inc byte [ecx] jnz copy_definition_name bad_definition_option: stc ret copy_definition_value: lodsb cmp al,20h je definition_value_end cmp al,0Dh je definition_value_end or al,al jz definition_value_end cmp al,'\' jne definition_value_character cmp byte [esi],20h jne definition_value_character lodsb definition_value_character: cmp edi,predefinitions+1000h jae bad_definition_option stosb jmp copy_definition_value definition_value_end: dec esi cmp edi,predefinitions+1000h jae bad_definition_option xor al,al stosb clc ret include 'system.inc' include '..\errors.inc' include '..\symbdump.inc' include '..\preproce.inc' include '..\parser.inc' include '..\exprpars.inc' include '..\assemble.inc' include '..\exprcalc.inc' include '..\formats.inc' include '..\x86_64.inc' include '..\avx.inc' include '..\tables.inc' include '..\messages.inc' section '.data' data readable writeable include '..\version.inc' _copyright db 'Copyright (c) 1999-2022, Tomasz Grysztar',0Dh,0Ah,0 _logo db 'flat assembler version ',VERSION_STRING,0 _usage db 0Dh,0Ah db 'usage: fasm [output]',0Dh,0Ah db 'optional settings:',0Dh,0Ah db ' -m set the limit in kilobytes for the available memory',0Dh,0Ah db ' -p set the maximum allowed number of passes',0Dh,0Ah db ' -d = define symbolic variable',0Dh,0Ah db ' -s dump symbolic information for debugging',0Dh,0Ah db 0 _memory_prefix db ' (',0 _memory_suffix db ' kilobytes memory)',0Dh,0Ah,0 _passes_suffix db ' passes, ',0 _seconds_suffix db ' seconds, ',0 _bytes_suffix db ' bytes.',0Dh,0Ah,0 align 4 include '..\variable.inc' con_handle dd ? memory_setting dd ? start_time dd ? definitions_pointer dd ? bytes_count dd ? displayed_count dd ? character db ? last_displayed rb 2 preprocessing_done db ? params rb 1000h options rb 1000h predefinitions rb 1000h buffer rb 4000h stack 10000h section '.idata' import data readable writeable dd 0,0,0,rva kernel_name,rva kernel_table dd 0,0,0,0,0 kernel_table: ExitProcess dd rva _ExitProcess CreateFile dd rva _CreateFileA ReadFile dd rva _ReadFile WriteFile dd rva _WriteFile CloseHandle dd rva _CloseHandle SetFilePointer dd rva _SetFilePointer GetCommandLine dd rva _GetCommandLineA GetEnvironmentVariable dd rva _GetEnvironmentVariable GetStdHandle dd rva _GetStdHandle VirtualAlloc dd rva _VirtualAlloc VirtualFree dd rva _VirtualFree GetTickCount dd rva _GetTickCount GetSystemTime dd rva _GetSystemTime GlobalMemoryStatus dd rva _GlobalMemoryStatus dd 0 kernel_name db 'KERNEL32.DLL',0 _ExitProcess dw 0 db 'ExitProcess',0 _CreateFileA dw 0 db 'CreateFileA',0 _ReadFile dw 0 db 'ReadFile',0 _WriteFile dw 0 db 'WriteFile',0 _CloseHandle dw 0 db 'CloseHandle',0 _SetFilePointer dw 0 db 'SetFilePointer',0 _GetCommandLineA dw 0 db 'GetCommandLineA',0 _GetEnvironmentVariable dw 0 db 'GetEnvironmentVariableA',0 _GetStdHandle dw 0 db 'GetStdHandle',0 _VirtualAlloc dw 0 db 'VirtualAlloc',0 _VirtualFree dw 0 db 'VirtualFree',0 _GetTickCount dw 0 db 'GetTickCount',0 _GetSystemTime dw 0 db 'GetSystemTime',0 _GlobalMemoryStatus dw 0 db 'GlobalMemoryStatus',0 section '.reloc' fixups data readable discardable fasm/source/Win32/system.inc0000644000175000017500000002212114533376740016525 0ustar privalovprivalov ; flat assembler interface for Win32 ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. CREATE_NEW = 1 CREATE_ALWAYS = 2 OPEN_EXISTING = 3 OPEN_ALWAYS = 4 TRUNCATE_EXISTING = 5 FILE_SHARE_READ = 1 FILE_SHARE_WRITE = 2 FILE_SHARE_DELETE = 4 GENERIC_READ = 80000000h GENERIC_WRITE = 40000000h STD_INPUT_HANDLE = 0FFFFFFF6h STD_OUTPUT_HANDLE = 0FFFFFFF5h STD_ERROR_HANDLE = 0FFFFFFF4h MEM_COMMIT = 1000h MEM_RESERVE = 2000h MEM_DECOMMIT = 4000h MEM_RELEASE = 8000h MEM_FREE = 10000h MEM_PRIVATE = 20000h MEM_MAPPED = 40000h MEM_RESET = 80000h MEM_TOP_DOWN = 100000h PAGE_NOACCESS = 1 PAGE_READONLY = 2 PAGE_READWRITE = 4 PAGE_WRITECOPY = 8 PAGE_EXECUTE = 10h PAGE_EXECUTE_READ = 20h PAGE_EXECUTE_READWRITE = 40h PAGE_EXECUTE_WRITECOPY = 80h PAGE_GUARD = 100h PAGE_NOCACHE = 200h init_memory: xor eax,eax mov [memory_start],eax mov eax,esp and eax,not 0FFFh add eax,1000h-10000h mov [stack_limit],eax mov eax,[memory_setting] shl eax,10 jnz allocate_memory push buffer call [GlobalMemoryStatus] mov eax,dword [buffer+20] mov edx,dword [buffer+12] cmp eax,0 jl large_memory cmp edx,0 jl large_memory shr eax,2 add eax,edx jmp allocate_memory large_memory: mov eax,80000000h allocate_memory: mov edx,eax shr edx,2 mov ecx,eax sub ecx,edx mov [memory_end],ecx mov [additional_memory_end],edx push PAGE_READWRITE push MEM_COMMIT push eax push 0 call [VirtualAlloc] or eax,eax jz not_enough_memory mov [memory_start],eax add eax,[memory_end] mov [memory_end],eax mov [additional_memory],eax add [additional_memory_end],eax ret not_enough_memory: mov eax,[additional_memory_end] shl eax,1 cmp eax,4000h jb out_of_memory jmp allocate_memory exit_program: movzx eax,al push eax mov eax,[memory_start] test eax,eax jz do_exit push MEM_RELEASE push 0 push eax call [VirtualFree] do_exit: call [ExitProcess] get_environment_variable: mov ecx,[memory_end] sub ecx,edi cmp ecx,4000h jbe buffer_for_variable_ok mov ecx,4000h buffer_for_variable_ok: push ecx push edi push esi call [GetEnvironmentVariable] add edi,eax cmp edi,[memory_end] jae out_of_memory ret open: push 0 push 0 push OPEN_EXISTING push 0 push FILE_SHARE_READ push GENERIC_READ push edx call [CreateFile] cmp eax,-1 je file_error mov ebx,eax clc ret file_error: stc ret create: push 0 push 0 push CREATE_ALWAYS push 0 push FILE_SHARE_READ push GENERIC_WRITE push edx call [CreateFile] cmp eax,-1 je file_error mov ebx,eax clc ret write: push 0 push bytes_count push ecx push edx push ebx call [WriteFile] or eax,eax jz file_error clc ret read: mov ebp,ecx push 0 push bytes_count push ecx push edx push ebx call [ReadFile] or eax,eax jz file_error cmp ebp,[bytes_count] jne file_error clc ret close: push ebx call [CloseHandle] ret lseek: movzx eax,al push eax push 0 push edx push ebx call [SetFilePointer] cmp eax,-1 je file_error clc ret display_string: push [con_handle] call [GetStdHandle] mov ebp,eax mov edi,esi or ecx,-1 xor al,al repne scasb neg ecx sub ecx,2 push 0 push bytes_count push ecx push esi push ebp call [WriteFile] ret display_character: push ebx mov [character],dl push [con_handle] call [GetStdHandle] mov ebx,eax push 0 push bytes_count push 1 push character push ebx call [WriteFile] pop ebx ret display_number: push ebx mov ecx,1000000000 xor edx,edx xor bl,bl display_loop: div ecx push edx cmp ecx,1 je display_digit or bl,bl jnz display_digit or al,al jz digit_ok not bl display_digit: mov dl,al add dl,30h push ecx call display_character pop ecx digit_ok: mov eax,ecx xor edx,edx mov ecx,10 div ecx mov ecx,eax pop eax or ecx,ecx jnz display_loop pop ebx ret display_user_messages: mov [displayed_count],0 call show_display_buffer cmp [displayed_count],1 jb line_break_ok je make_line_break mov ax,word [last_displayed] cmp ax,0A0Dh je line_break_ok cmp ax,0D0Ah je line_break_ok make_line_break: mov word [buffer],0A0Dh push [con_handle] call [GetStdHandle] push 0 push bytes_count push 2 push buffer push eax call [WriteFile] line_break_ok: ret display_block: add [displayed_count],ecx cmp ecx,1 ja take_last_two_characters jb block_displayed mov al,[last_displayed+1] mov ah,[esi] mov word [last_displayed],ax jmp block_ok take_last_two_characters: mov ax,[esi+ecx-2] mov word [last_displayed],ax block_ok: push ecx push [con_handle] call [GetStdHandle] pop ecx push 0 push bytes_count push ecx push esi push eax call [WriteFile] block_displayed: ret fatal_error: mov [con_handle],STD_ERROR_HANDLE mov esi,error_prefix call display_string pop esi call display_string mov esi,error_suffix call display_string mov al,0FFh jmp exit_program assembler_error: mov [con_handle],STD_ERROR_HANDLE call display_user_messages mov ebx,[current_line] test ebx,ebx jz display_error_message push dword 0 get_error_lines: mov eax,[ebx] cmp byte [eax],0 je get_next_error_line push ebx test byte [ebx+7],80h jz display_error_line mov edx,ebx find_definition_origin: mov edx,[edx+12] test byte [edx+7],80h jnz find_definition_origin push edx get_next_error_line: mov ebx,[ebx+8] jmp get_error_lines display_error_line: mov esi,[ebx] call display_string mov esi,line_number_start call display_string mov eax,[ebx+4] and eax,7FFFFFFFh call display_number mov dl,']' call display_character pop esi cmp ebx,esi je line_number_ok mov dl,20h call display_character push esi mov esi,[esi] movzx ecx,byte [esi] inc esi call display_block mov esi,line_number_start call display_string pop esi mov eax,[esi+4] and eax,7FFFFFFFh call display_number mov dl,']' call display_character line_number_ok: mov esi,line_data_start call display_string mov esi,ebx mov edx,[esi] call open mov al,2 xor edx,edx call lseek mov edx,[esi+8] sub eax,edx jz line_data_displayed push eax xor al,al call lseek mov ecx,[esp] mov edx,[additional_memory] lea eax,[edx+ecx] cmp eax,[additional_memory_end] ja out_of_memory call read call close pop ecx mov esi,[additional_memory] get_line_data: mov al,[esi] cmp al,0Ah je display_line_data cmp al,0Dh je display_line_data cmp al,1Ah je display_line_data or al,al jz display_line_data inc esi loop get_line_data display_line_data: mov ecx,esi mov esi,[additional_memory] sub ecx,esi call display_block line_data_displayed: mov esi,cr_lf call display_string pop ebx or ebx,ebx jnz display_error_line cmp [preprocessing_done],0 je display_error_message mov esi,preprocessed_instruction_prefix call display_string mov esi,[current_line] add esi,16 mov edi,[additional_memory] xor dl,dl convert_instruction: lodsb cmp al,1Ah je copy_symbol cmp al,22h je copy_symbol cmp al,3Bh je instruction_converted stosb or al,al jz instruction_converted xor dl,dl jmp convert_instruction copy_symbol: or dl,dl jz space_ok mov byte [edi],20h inc edi space_ok: cmp al,22h je quoted lodsb movzx ecx,al rep movsb or dl,-1 jmp convert_instruction quoted: mov al,27h stosb lodsd mov ecx,eax jecxz quoted_copied copy_quoted: lodsb stosb cmp al,27h jne quote_ok stosb quote_ok: loop copy_quoted quoted_copied: mov al,27h stosb or dl,-1 jmp convert_instruction instruction_converted: xor al,al stosb mov esi,[additional_memory] call display_string mov esi,cr_lf call display_string display_error_message: mov esi,error_prefix call display_string pop esi call display_string mov esi,error_suffix call display_string mov al,2 jmp exit_program make_timestamp: push buffer call [GetSystemTime] movzx ecx,word [buffer] mov eax,ecx sub eax,1970 mov ebx,365 mul ebx mov ebp,eax mov eax,ecx sub eax,1969 shr eax,2 add ebp,eax mov eax,ecx sub eax,1901 mov ebx,100 div ebx sub ebp,eax mov eax,ecx xor edx,edx sub eax,1601 mov ebx,400 div ebx add ebp,eax movzx ecx,word [buffer+2] mov eax,ecx dec eax mov ebx,30 mul ebx add ebp,eax cmp ecx,8 jbe months_correction mov eax,ecx sub eax,7 shr eax,1 add ebp,eax mov ecx,8 months_correction: mov eax,ecx shr eax,1 add ebp,eax cmp ecx,2 jbe day_correction_ok sub ebp,2 movzx ecx,word [buffer] test ecx,11b jnz day_correction_ok xor edx,edx mov eax,ecx mov ebx,100 div ebx or edx,edx jnz day_correction mov eax,ecx mov ebx,400 div ebx or edx,edx jnz day_correction_ok day_correction: inc ebp day_correction_ok: movzx eax,word [buffer+6] dec eax add eax,ebp mov ebx,24 mul ebx movzx ecx,word [buffer+8] add eax,ecx mov ebx,60 mul ebx movzx ecx,word [buffer+10] add eax,ecx mov ebx,60 mul ebx movzx ecx,word [buffer+12] add eax,ecx adc edx,0 ret error_prefix db 'error: ',0 error_suffix db '.' cr_lf db 0Dh,0Ah,0 line_number_start db ' [',0 line_data_start db ':',0Dh,0Ah,0 preprocessed_instruction_prefix db 'processed: ',0 fasm/source/assemble.inc0000644000175000017500000012222614533376740016101 0ustar privalovprivalov ; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. assembler: xor eax,eax mov [stub_size],eax mov [current_pass],ax mov [resolver_flags],eax mov [number_of_sections],eax mov [actual_fixups_size],eax assembler_loop: mov eax,[labels_list] mov [tagged_blocks],eax mov eax,[additional_memory] mov [free_additional_memory],eax mov eax,[additional_memory_end] mov [structures_buffer],eax mov esi,[source_start] mov edi,[code_start] xor eax,eax mov dword [adjustment],eax mov dword [adjustment+4],eax mov [addressing_space],eax mov [error_line],eax mov [counter],eax mov [format_flags],eax mov [number_of_relocations],eax mov [undefined_data_end],eax mov [file_extension],eax mov [next_pass_needed],al mov [output_format],al mov [adjustment_sign],al mov [evex_mode],al mov [code_type],16 call init_addressing_space pass_loop: call assemble_line jnc pass_loop mov eax,[additional_memory_end] cmp eax,[structures_buffer] je pass_done sub eax,18h mov eax,[eax+4] mov [current_line],eax jmp missing_end_directive pass_done: call close_pass mov eax,[labels_list] check_symbols: cmp eax,[memory_end] jae symbols_checked test byte [eax+8],8 jz symbol_defined_ok mov cx,[current_pass] cmp cx,[eax+18] jne symbol_defined_ok test byte [eax+8],1 jz symbol_defined_ok sub cx,[eax+16] cmp cx,1 jne symbol_defined_ok and byte [eax+8],not 1 or [next_pass_needed],-1 symbol_defined_ok: test byte [eax+8],10h jz use_prediction_ok mov cx,[current_pass] and byte [eax+8],not 10h test byte [eax+8],20h jnz check_use_prediction cmp cx,[eax+18] jne use_prediction_ok test byte [eax+8],8 jz use_prediction_ok jmp use_misprediction check_use_prediction: test byte [eax+8],8 jz use_misprediction cmp cx,[eax+18] je use_prediction_ok use_misprediction: or [next_pass_needed],-1 use_prediction_ok: test byte [eax+8],40h jz check_next_symbol and byte [eax+8],not 40h test byte [eax+8],4 jnz define_misprediction mov cx,[current_pass] test byte [eax+8],80h jnz check_define_prediction cmp cx,[eax+16] jne check_next_symbol test byte [eax+8],1 jz check_next_symbol jmp define_misprediction check_define_prediction: test byte [eax+8],1 jz define_misprediction cmp cx,[eax+16] je check_next_symbol define_misprediction: or [next_pass_needed],-1 check_next_symbol: add eax,LABEL_STRUCTURE_SIZE jmp check_symbols symbols_checked: cmp [next_pass_needed],0 jne next_pass mov eax,[error_line] or eax,eax jz assemble_ok mov [current_line],eax cmp [error],undefined_symbol jne error_confirmed mov eax,[error_info] or eax,eax jz error_confirmed test byte [eax+8],1 jnz next_pass error_confirmed: call error_handler error_handler: mov eax,[error] sub eax,error_handler add [esp],eax ret next_pass: inc [current_pass] mov ax,[current_pass] cmp ax,[passes_limit] je code_cannot_be_generated jmp assembler_loop assemble_ok: ret create_addressing_space: mov ebx,[addressing_space] test ebx,ebx jz init_addressing_space test byte [ebx+0Ah],1 jnz illegal_instruction mov eax,edi sub eax,[ebx+18h] mov [ebx+1Ch],eax init_addressing_space: mov ebx,[tagged_blocks] mov dword [ebx-4],10h mov dword [ebx-8],24h sub ebx,8+24h cmp ebx,edi jbe out_of_memory mov [tagged_blocks],ebx mov [addressing_space],ebx xor eax,eax mov [ebx],edi mov [ebx+4],eax mov [ebx+8],eax mov [ebx+10h],eax mov [ebx+14h],eax mov [ebx+18h],edi mov [ebx+1Ch],eax mov [ebx+20h],eax ret assemble_line: mov eax,[tagged_blocks] sub eax,100h cmp edi,eax ja out_of_memory lods byte [esi] cmp al,1 je assemble_instruction jb source_end cmp al,3 jb define_label je define_constant cmp al,4 je label_addressing_space cmp al,0Fh je new_line cmp al,13h je code_type_setting cmp al,10h jne illegal_instruction lods byte [esi] jmp segment_prefix code_type_setting: lods byte [esi] mov [code_type],al jmp instruction_assembled new_line: lods dword [esi] mov [current_line],eax and [prefix_flags],0 cmp [symbols_file],0 je continue_line cmp [next_pass_needed],0 jne continue_line mov ebx,[tagged_blocks] mov dword [ebx-4],1 mov dword [ebx-8],14h sub ebx,8+14h cmp ebx,edi jbe out_of_memory mov [tagged_blocks],ebx mov [ebx],eax mov [ebx+4],edi mov eax,[addressing_space] mov [ebx+8],eax mov al,[code_type] mov [ebx+10h],al continue_line: cmp byte [esi],0Fh je line_assembled jmp assemble_line define_label: lods dword [esi] cmp eax,0Fh jb invalid_use_of_symbol je reserved_word_used_as_symbol mov ebx,eax lods byte [esi] mov [label_size],al call make_label jmp continue_line make_label: mov eax,edi xor edx,edx xor cl,cl mov ebp,[addressing_space] sub eax,[ds:ebp] sbb edx,[ds:ebp+4] sbb cl,[ds:ebp+8] jp label_value_ok call recoverable_overflow label_value_ok: mov [address_sign],cl test byte [ds:ebp+0Ah],1 jnz make_virtual_label or byte [ebx+9],1 xchg eax,[ebx] xchg edx,[ebx+4] mov ch,[ebx+9] shr ch,1 and ch,1 neg ch sub eax,[ebx] sbb edx,[ebx+4] sbb ch,cl mov dword [adjustment],eax mov dword [adjustment+4],edx mov [adjustment_sign],ch or al,ch or eax,edx setnz ah jmp finish_label make_virtual_label: and byte [ebx+9],not 1 cmp eax,[ebx] mov [ebx],eax setne ah cmp edx,[ebx+4] mov [ebx+4],edx setne al or ah,al finish_label: mov ebp,[addressing_space] mov ch,[ds:ebp+9] mov cl,[label_size] mov edx,[ds:ebp+14h] mov ebp,[ds:ebp+10h] finish_label_symbol: mov al,[address_sign] xor al,[ebx+9] and al,10b or ah,al xor [ebx+9],al cmp cl,[ebx+10] mov [ebx+10],cl setne al or ah,al cmp ch,[ebx+11] mov [ebx+11],ch setne al or ah,al cmp ebp,[ebx+12] mov [ebx+12],ebp setne al or ah,al or ch,ch jz label_symbol_ok cmp edx,[ebx+20] mov [ebx+20],edx setne al or ah,al label_symbol_ok: mov cx,[current_pass] xchg [ebx+16],cx mov edx,[current_line] mov [ebx+28],edx and byte [ebx+8],not 2 test byte [ebx+8],1 jz new_label cmp cx,[ebx+16] je symbol_already_defined btr dword [ebx+8],10 jc requalified_label inc cx sub cx,[ebx+16] setnz al or ah,al jz label_made test byte [ebx+8],8 jz label_made mov cx,[current_pass] cmp cx,[ebx+18] jne label_made requalified_label: or [next_pass_needed],-1 label_made: ret new_label: or byte [ebx+8],1 ret define_constant: lods dword [esi] inc esi cmp eax,0Fh jb invalid_use_of_symbol je reserved_word_used_as_symbol push eax or [operand_flags],1 call get_value pop ebx xor cl,cl mov ch,[value_type] cmp ch,3 je invalid_use_of_symbol make_constant: and byte [ebx+9],not 1 cmp eax,[ebx] mov [ebx],eax setne ah cmp edx,[ebx+4] mov [ebx+4],edx setne al or ah,al mov al,[value_sign] xor al,[ebx+9] and al,10b or ah,al xor [ebx+9],al cmp cl,[ebx+10] mov [ebx+10],cl setne al or ah,al cmp ch,[ebx+11] mov [ebx+11],ch setne al or ah,al xor edx,edx cmp edx,[ebx+12] mov [ebx+12],edx setne al or ah,al or ch,ch jz constant_symbol_ok mov edx,[symbol_identifier] cmp edx,[ebx+20] mov [ebx+20],edx setne al or ah,al constant_symbol_ok: mov cx,[current_pass] xchg [ebx+16],cx mov edx,[current_line] mov [ebx+28],edx test byte [ebx+8],1 jz new_constant cmp cx,[ebx+16] jne redeclare_constant test byte [ebx+8],2 jz symbol_already_defined or byte [ebx+8],4 and byte [ebx+9],not 4 jmp instruction_assembled redeclare_constant: btr dword [ebx+8],10 jc requalified_constant inc cx sub cx,[ebx+16] setnz al or ah,al jz instruction_assembled test byte [ebx+8],4 jnz instruction_assembled test byte [ebx+8],8 jz instruction_assembled mov cx,[current_pass] cmp cx,[ebx+18] jne instruction_assembled requalified_constant: or [next_pass_needed],-1 jmp instruction_assembled new_constant: or byte [ebx+8],1+2 jmp instruction_assembled label_addressing_space: lods dword [esi] cmp eax,0Fh jb invalid_use_of_symbol je reserved_word_used_as_symbol mov cx,[current_pass] test byte [eax+8],1 jz make_addressing_space_label cmp cx,[eax+16] je symbol_already_defined test byte [eax+9],4 jnz make_addressing_space_label or [next_pass_needed],-1 make_addressing_space_label: mov dx,[eax+8] and dx,not (2 or 100h) or dx,1 or 4 or 400h mov [eax+8],dx mov [eax+16],cx mov edx,[current_line] mov [eax+28],edx mov ebx,[addressing_space] mov [eax],ebx or byte [ebx+0Ah],2 jmp continue_line assemble_instruction: ; mov [operand_size],0 ; mov [operand_flags],0 ; mov [operand_prefix],0 ; mov [rex_prefix],0 and dword [operand_size],0 ; mov [opcode_prefix],0 ; mov [vex_required],0 ; mov [vex_register],0 ; mov [immediate_size],0 and dword [opcode_prefix],0 call instruction_handler instruction_handler: movzx ebx,word [esi] mov al,[esi+2] add esi,3 add [esp],ebx ret instruction_assembled: test [prefix_flags],not 1 jnz illegal_instruction mov al,[esi] cmp al,0Fh je line_assembled or al,al jnz extra_characters_on_line line_assembled: clc ret source_end: dec esi stc ret org_directive: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_qword_value mov cl,[value_type] test cl,1 jnz invalid_use_of_symbol push eax mov ebx,[addressing_space] mov eax,edi sub eax,[ebx+18h] mov [ebx+1Ch],eax test byte [ebx+0Ah],1 jnz in_virtual call init_addressing_space jmp org_space_ok in_virtual: call close_virtual_addressing_space call init_addressing_space or byte [ebx+0Ah],1 org_space_ok: pop eax mov [ebx+9],cl mov cl,[value_sign] sub [ebx],eax sbb [ebx+4],edx sbb byte [ebx+8],cl jp org_value_ok call recoverable_overflow org_value_ok: mov edx,[symbol_identifier] mov [ebx+14h],edx cmp [output_format],1 ja instruction_assembled cmp edi,[code_start] jne instruction_assembled cmp eax,100h jne instruction_assembled bts [format_flags],0 jmp instruction_assembled label_directive: lods byte [esi] cmp al,2 jne invalid_argument lods dword [esi] cmp eax,0Fh jb invalid_use_of_symbol je reserved_word_used_as_symbol inc esi mov ebx,eax mov [label_size],0 lods byte [esi] cmp al,':' je get_label_size dec esi cmp al,11h jne label_size_ok get_label_size: lods word [esi] cmp al,11h jne invalid_argument mov [label_size],ah label_size_ok: cmp byte [esi],80h je get_free_label_value call make_label jmp instruction_assembled get_free_label_value: inc esi lods byte [esi] cmp al,'(' jne invalid_argument push ebx ecx or byte [ebx+8],4 cmp byte [esi],'.' je invalid_value call get_address_value or bh,bh setnz ch xchg ch,cl mov bp,cx shl ebp,16 xchg bl,bh mov bp,bx pop ecx ebx and byte [ebx+8],not 4 mov ch,[value_type] test ch,1 jnz invalid_use_of_symbol make_free_label: and byte [ebx+9],not 1 cmp eax,[ebx] mov [ebx],eax setne ah cmp edx,[ebx+4] mov [ebx+4],edx setne al or ah,al mov edx,[address_symbol] mov cl,[label_size] call finish_label_symbol jmp instruction_assembled load_directive: lods byte [esi] cmp al,2 jne invalid_argument lods dword [esi] cmp eax,0Fh jb invalid_use_of_symbol je reserved_word_used_as_symbol inc esi push eax mov al,1 cmp byte [esi],11h jne load_size_ok lods byte [esi] lods byte [esi] load_size_ok: cmp al,8 ja invalid_value mov [operand_size],al and dword [value],0 and dword [value+4],0 lods byte [esi] cmp al,82h jne invalid_argument call get_data_point jc value_loaded push esi edi mov esi,ebx mov edi,value rep movs byte [edi],[esi] pop edi esi value_loaded: mov [value_sign],0 mov eax,dword [value] mov edx,dword [value+4] pop ebx xor cx,cx jmp make_constant get_data_point: lods byte [esi] cmp al,':' je get_data_offset cmp al,'(' jne invalid_argument mov ebx,[addressing_space] mov ecx,edi sub ecx,[ebx+18h] mov [ebx+1Ch],ecx cmp byte [esi],11h jne get_data_address cmp word [esi+1+4],'):' jne get_data_address inc esi lods dword [esi] add esi,2 cmp byte [esi],'(' jne invalid_argument inc esi cmp eax,0Fh jbe reserved_word_used_as_symbol mov edx,undefined_symbol test byte [eax+8],1 jz addressing_space_unavailable mov edx,symbol_out_of_scope mov cx,[eax+16] cmp cx,[current_pass] jne addressing_space_unavailable test byte [eax+9],4 jz invalid_use_of_symbol mov ebx,eax mov ax,[current_pass] mov [ebx+18],ax or byte [ebx+8],8 call store_label_reference get_addressing_space: mov ebx,[ebx] get_data_address: push ebx cmp byte [esi],'.' je invalid_value or [operand_flags],1 call get_address_value pop ebp call calculate_relative_offset cmp [next_pass_needed],0 jne data_address_type_ok cmp [value_type],0 jne invalid_use_of_symbol data_address_type_ok: mov ebx,edi xor ecx,ecx add ebx,eax adc edx,ecx mov eax,ebx sub eax,[ds:ebp+18h] sbb edx,ecx jnz bad_data_address mov cl,[operand_size] add eax,ecx cmp eax,[ds:ebp+1Ch] ja bad_data_address clc ret addressing_space_unavailable: cmp [error_line],0 jne get_data_address push [current_line] pop [error_line] mov [error],edx mov [error_info],eax jmp get_data_address bad_data_address: call recoverable_overflow stc ret get_data_offset: cmp [output_format],2 jae invalid_operand lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_dword_value cmp [value_type],0 je data_offset_ok call recoverable_invalid_address data_offset_ok: add eax,[code_start] jc bad_data_address mov ebx,eax movzx ecx,[operand_size] add eax,ecx jc bad_data_address mov edx,[addressing_space] test byte [edx+0Ah],1 jnz data_offset_from_virtual cmp eax,edi ja bad_data_address clc ret data_offset_from_virtual: cmp eax,[undefined_data_end] ja bad_data_address clc ret store_directive: cmp byte [esi],11h je sized_store lods byte [esi] cmp al,'(' jne invalid_argument call get_byte_value xor edx,edx movzx eax,al mov [operand_size],1 jmp store_value_ok sized_store: or [operand_flags],1 call get_value store_value_ok: cmp [value_type],0 jne invalid_use_of_symbol mov dword [value],eax mov dword [value+4],edx lods byte [esi] cmp al,80h jne invalid_argument call get_data_point jc instruction_assembled push esi edi mov esi,value mov edi,ebx rep movs byte [edi],[esi] mov eax,edi pop edi esi cmp ebx,[undefined_data_end] jae instruction_assembled cmp eax,[undefined_data_start] jbe instruction_assembled mov [undefined_data_start],eax jmp instruction_assembled display_directive: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],0 jne display_byte inc esi lods dword [esi] mov ecx,eax push edi mov edi,[tagged_blocks] sub edi,8 sub edi,eax cmp edi,[esp] jbe out_of_memory mov [tagged_blocks],edi rep movs byte [edi],[esi] stos dword [edi] xor eax,eax stos dword [edi] pop edi inc esi jmp display_next display_byte: call get_byte_value push edi mov edi,[tagged_blocks] sub edi,8+1 mov [tagged_blocks],edi stos byte [edi] mov eax,1 stos dword [edi] dec eax stos dword [edi] pop edi display_next: cmp edi,[tagged_blocks] ja out_of_memory lods byte [esi] cmp al,',' je display_directive dec esi jmp instruction_assembled show_display_buffer: mov eax,[tagged_blocks] or eax,eax jz display_done mov esi,[labels_list] cmp esi,eax je display_done display_messages: sub esi,8 mov eax,[esi+4] mov ecx,[esi] sub esi,ecx cmp eax,10h je write_addressing_space test eax,eax jnz skip_block push esi call display_block pop esi skip_block: cmp esi,[tagged_blocks] jne display_messages display_done: ret write_addressing_space: mov ecx,[esi+20h] jecxz skip_block push esi mov edi,[free_additional_memory] mov esi,[output_file] test esi,esi jz addressing_space_written xor ebx,ebx copy_output_path: lodsb cmp edi,[structures_buffer] jae out_of_memory stosb test al,al jz output_path_copied cmp al,'/' je new_path_segment cmp al,'\' je new_path_segment cmp al,'.' jne copy_output_path mov ebx,edi jmp copy_output_path new_path_segment: xor ebx,ebx jmp copy_output_path output_path_copied: test ebx,ebx jnz append_extension mov byte [edi-1],'.' mov ebx,edi append_extension: mov edi,ebx add ebx,ecx inc ebx cmp ebx,[structures_buffer] jae out_of_memory mov esi,[esp] mov esi,[esi+18h] sub esi,ecx rep movs byte [edi],[esi] xor al,al stos byte [edi] mov edx,[free_additional_memory] call create jc write_failed mov esi,[esp] mov edx,[esi+18h] mov ecx,[esi+1Ch] call write jc write_failed call close addressing_space_written: pop esi jmp skip_block times_directive: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value cmp eax,0 je zero_times cmp byte [esi],':' jne times_argument_ok inc esi times_argument_ok: push [counter] push [counter_limit] mov [counter_limit],eax mov [counter],1 times_loop: mov eax,esp sub eax,[stack_limit] cmp eax,100h jb stack_overflow push esi or [prefix_flags],1 call continue_line mov eax,[counter_limit] cmp [counter],eax je times_done inc [counter] pop esi jmp times_loop times_done: pop eax pop [counter_limit] pop [counter] jmp instruction_assembled zero_times: call skip_symbol jnc zero_times jmp instruction_assembled virtual_directive: lods byte [esi] cmp al,'(' je continue_virtual_area cmp al,80h jne virtual_at_current lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_address_value mov ebp,[address_symbol] or bh,bh setnz ch jmp set_virtual virtual_at_current: dec esi virtual_fallback: mov ebp,[addressing_space] mov al,[ds:ebp+9] mov [value_type],al mov eax,edi xor edx,edx xor cl,cl sub eax,[ds:ebp] sbb edx,[ds:ebp+4] sbb cl,[ds:ebp+8] mov [address_sign],cl mov bx,[ds:ebp+10h] mov cx,[ds:ebp+10h+2] xchg bh,bl xchg ch,cl mov ebp,[ds:ebp+14h] set_virtual: xchg bl,bh xchg cl,ch shl ecx,16 mov cx,bx push ecx eax mov ebx,[addressing_space] test byte [ebx+0Ah],1 jnz non_virtual_end_ok mov eax,edi xchg eax,[undefined_data_end] cmp eax,edi je non_virtual_end_ok mov [undefined_data_start],edi non_virtual_end_ok: call allocate_virtual_structure_data call init_addressing_space or byte [ebx+0Ah],1 cmp byte [esi],86h jne addressing_space_extension_ok cmp word [esi+1],'(' jne invalid_argument mov ecx,[esi+3] add esi,3+4 add [ebx+18h],ecx mov [ebx+20h],ecx or byte [ebx+0Ah],2 push ebx mov ebx,characters get_extension: lods byte [esi] stos byte [edi] xlat byte [ebx] test al,al jz invalid_argument loop get_extension inc esi pop ebx addressing_space_extension_ok: pop eax mov cl,[address_sign] not eax not edx not cl add eax,1 adc edx,0 adc cl,0 add eax,edi adc edx,0 adc cl,0 mov [ebx],eax mov [ebx+4],edx mov [ebx+8],cl pop dword [ebx+10h] mov [ebx+14h],ebp mov al,[value_type] test al,1 jnz invalid_use_of_symbol mov [ebx+9],al jmp instruction_assembled allocate_structure_data: mov ebx,[structures_buffer] sub ebx,18h cmp ebx,[free_additional_memory] jb out_of_memory mov [structures_buffer],ebx ret find_structure_data: mov ebx,[structures_buffer] scan_structures: cmp ebx,[additional_memory_end] je no_such_structure cmp ax,[ebx] je structure_data_found add ebx,18h jmp scan_structures structure_data_found: ret no_such_structure: stc ret allocate_virtual_structure_data: call allocate_structure_data mov word [ebx],virtual_directive-instruction_handler mov ecx,[addressing_space] mov [ebx+12],ecx mov [ebx+8],edi mov ecx,[current_line] mov [ebx+4],ecx mov ebx,[addressing_space] mov eax,edi sub eax,[ebx+18h] mov [ebx+1Ch],eax ret continue_virtual_area: cmp byte [esi],11h jne invalid_argument cmp byte [esi+1+4],')' jne invalid_argument inc esi lods dword [esi] inc esi cmp eax,0Fh jbe reserved_word_used_as_symbol mov edx,undefined_symbol test byte [eax+8],1 jz virtual_area_unavailable mov edx,symbol_out_of_scope mov cx,[eax+16] cmp cx,[current_pass] jne virtual_area_unavailable mov edx,invalid_use_of_symbol test byte [eax+9],4 jz virtual_area_unavailable mov ebx,eax mov ax,[current_pass] mov [ebx+18],ax or byte [ebx+8],8 call store_label_reference mov ebx,[ebx] test byte [ebx+0Ah],4 jz virtual_area_unavailable and byte [ebx+0Ah],not 4 mov edx,ebx call allocate_virtual_structure_data mov [addressing_space],edx push esi mov esi,[edx+18h] mov ecx,[edx+1Ch] mov eax,[edx+20h] sub esi,eax add ecx,eax lea eax,[edi+ecx] cmp eax,[tagged_blocks] jae out_of_memory mov eax,esi sub eax,edi sub [edx+18h],eax sub [edx],eax sbb dword [edx+4],0 sbb byte [edx+8],0 mov al,cl shr ecx,2 rep movs dword [edi],[esi] mov cl,al and cl,11b rep movs byte [edi],[esi] pop esi jmp instruction_assembled virtual_area_unavailable: cmp [error_line],0 jne virtual_fallback push [current_line] pop [error_line] mov [error],edx mov [error_info],eax jmp virtual_fallback end_virtual: call find_structure_data jc unexpected_instruction push ebx call close_virtual_addressing_space pop ebx mov eax,[ebx+12] mov [addressing_space],eax mov edi,[ebx+8] remove_structure_data: push esi edi mov ecx,ebx sub ecx,[structures_buffer] shr ecx,2 lea esi,[ebx-4] lea edi,[esi+18h] std rep movs dword [edi],[esi] cld add [structures_buffer],18h pop edi esi ret close_virtual_addressing_space: mov ebx,[addressing_space] mov eax,edi sub eax,[ebx+18h] mov [ebx+1Ch],eax add eax,[ebx+20h] test byte [ebx+0Ah],2 jz addressing_space_closed or byte [ebx+0Ah],4 push esi edi ecx edx mov ecx,eax mov eax,[tagged_blocks] mov dword [eax-4],11h mov dword [eax-8],ecx sub eax,8 sub eax,ecx mov [tagged_blocks],eax lea edi,[eax+ecx-1] add eax,[ebx+20h] xchg eax,[ebx+18h] sub eax,[ebx+20h] lea esi,[eax+ecx-1] mov eax,edi sub eax,esi std shr ecx,1 jnc virtual_byte_ok movs byte [edi],[esi] virtual_byte_ok: dec esi dec edi shr ecx,1 jnc virtual_word_ok movs word [edi],[esi] virtual_word_ok: sub esi,2 sub edi,2 rep movs dword [edi],[esi] cld xor edx,edx add [ebx],eax adc dword [ebx+4],edx adc byte [ebx+8],dl pop edx ecx edi esi addressing_space_closed: ret repeat_directive: test [prefix_flags],1 jnz unexpected_instruction lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value cmp eax,0 je zero_repeat call allocate_structure_data mov word [ebx],repeat_directive-instruction_handler xchg eax,[counter_limit] mov [ebx+10h],eax mov eax,1 xchg eax,[counter] mov [ebx+14h],eax mov [ebx+8],esi mov eax,[current_line] mov [ebx+4],eax jmp instruction_assembled end_repeat: test [prefix_flags],1 jnz unexpected_instruction call find_structure_data jc unexpected_instruction mov eax,[counter_limit] inc [counter] cmp [counter],eax jbe continue_repeating stop_repeat: mov eax,[ebx+10h] mov [counter_limit],eax mov eax,[ebx+14h] mov [counter],eax call remove_structure_data jmp instruction_assembled continue_repeating: mov esi,[ebx+8] jmp instruction_assembled zero_repeat: mov al,[esi] or al,al jz missing_end_directive cmp al,0Fh jne extra_characters_on_line call find_end_repeat jmp instruction_assembled find_end_repeat: call find_structure_end cmp ax,repeat_directive-instruction_handler jne unexpected_instruction ret while_directive: test [prefix_flags],1 jnz unexpected_instruction call allocate_structure_data mov word [ebx],while_directive-instruction_handler mov eax,1 xchg eax,[counter] mov [ebx+10h],eax mov [ebx+8],esi mov eax,[current_line] mov [ebx+4],eax do_while: push ebx call calculate_logical_expression or al,al jnz while_true mov al,[esi] or al,al jz missing_end_directive cmp al,0Fh jne extra_characters_on_line stop_while: call find_end_while pop ebx mov eax,[ebx+10h] mov [counter],eax call remove_structure_data jmp instruction_assembled while_true: pop ebx jmp instruction_assembled end_while: test [prefix_flags],1 jnz unexpected_instruction call find_structure_data jc unexpected_instruction mov eax,[ebx+4] mov [current_line],eax inc [counter] jz too_many_repeats mov esi,[ebx+8] jmp do_while find_end_while: call find_structure_end cmp ax,while_directive-instruction_handler jne unexpected_instruction ret if_directive: test [prefix_flags],1 jnz unexpected_instruction call calculate_logical_expression mov dl,al mov al,[esi] or al,al jz missing_end_directive cmp al,0Fh jne extra_characters_on_line or dl,dl jnz if_true call find_else jc instruction_assembled mov al,[esi] cmp al,1 jne else_true cmp word [esi+1],if_directive-instruction_handler jne else_true add esi,4 jmp if_directive if_true: xor al,al make_if_structure: call allocate_structure_data mov word [ebx],if_directive-instruction_handler mov byte [ebx+2],al mov eax,[current_line] mov [ebx+4],eax jmp instruction_assembled else_true: or al,al jz missing_end_directive cmp al,0Fh jne extra_characters_on_line or al,-1 jmp make_if_structure else_directive: test [prefix_flags],1 jnz unexpected_instruction mov ax,if_directive-instruction_handler call find_structure_data jc unexpected_instruction cmp byte [ebx+2],0 jne unexpected_instruction found_else: mov al,[esi] cmp al,1 jne skip_else cmp word [esi+1],if_directive-instruction_handler jne skip_else add esi,4 call find_else jnc found_else call remove_structure_data jmp instruction_assembled skip_else: or al,al jz missing_end_directive cmp al,0Fh jne extra_characters_on_line call find_end_if call remove_structure_data jmp instruction_assembled end_if: test [prefix_flags],1 jnz unexpected_instruction call find_structure_data jc unexpected_instruction call remove_structure_data jmp instruction_assembled find_else: call find_structure_end cmp ax,else_directive-instruction_handler je else_found cmp ax,if_directive-instruction_handler jne unexpected_instruction stc ret else_found: clc ret find_end_if: call find_structure_end cmp ax,if_directive-instruction_handler jne unexpected_instruction ret find_structure_end: push [error_line] mov eax,[current_line] mov [error_line],eax find_end_directive: call skip_symbol jnc find_end_directive lods byte [esi] cmp al,0Fh jne no_end_directive lods dword [esi] mov [current_line],eax skip_labels: cmp byte [esi],2 jne labels_ok add esi,6 jmp skip_labels labels_ok: cmp byte [esi],1 jne find_end_directive mov ax,[esi+1] cmp ax,prefix_instruction-instruction_handler je find_end_directive add esi,4 cmp ax,repeat_directive-instruction_handler je skip_repeat cmp ax,while_directive-instruction_handler je skip_while cmp ax,if_directive-instruction_handler je skip_if cmp ax,else_directive-instruction_handler je structure_end cmp ax,end_directive-instruction_handler jne find_end_directive cmp byte [esi],1 jne find_end_directive mov ax,[esi+1] add esi,4 cmp ax,repeat_directive-instruction_handler je structure_end cmp ax,while_directive-instruction_handler je structure_end cmp ax,if_directive-instruction_handler jne find_end_directive structure_end: pop [error_line] ret no_end_directive: mov eax,[error_line] mov [current_line],eax jmp missing_end_directive skip_repeat: call find_end_repeat jmp find_end_directive skip_while: call find_end_while jmp find_end_directive skip_if: call skip_if_block jmp find_end_directive skip_if_block: call find_else jc if_block_skipped cmp byte [esi],1 jne skip_after_else cmp word [esi+1],if_directive-instruction_handler jne skip_after_else add esi,4 jmp skip_if_block skip_after_else: call find_end_if if_block_skipped: ret end_directive: lods byte [esi] cmp al,1 jne invalid_argument lods word [esi] inc esi cmp ax,virtual_directive-instruction_handler je end_virtual cmp ax,repeat_directive-instruction_handler je end_repeat cmp ax,while_directive-instruction_handler je end_while cmp ax,if_directive-instruction_handler je end_if cmp ax,data_directive-instruction_handler je end_data jmp invalid_argument break_directive: mov ebx,[structures_buffer] mov al,[esi] or al,al jz find_breakable_structure cmp al,0Fh jne extra_characters_on_line find_breakable_structure: cmp ebx,[additional_memory_end] je unexpected_instruction mov ax,[ebx] cmp ax,repeat_directive-instruction_handler je break_repeat cmp ax,while_directive-instruction_handler je break_while cmp ax,if_directive-instruction_handler je break_if add ebx,18h jmp find_breakable_structure break_if: push [current_line] mov eax,[ebx+4] mov [current_line],eax call remove_structure_data call skip_if_block pop [current_line] mov ebx,[structures_buffer] jmp find_breakable_structure break_repeat: push ebx call find_end_repeat pop ebx jmp stop_repeat break_while: push ebx jmp stop_while define_data: cmp edi,[tagged_blocks] jae out_of_memory cmp byte [esi],'(' jne simple_data_value mov ebx,esi inc esi call skip_expression xchg esi,ebx cmp byte [ebx],81h jne simple_data_value inc esi call get_count_value inc esi or eax,eax jz duplicate_zero_times cmp byte [esi],91h jne duplicate_single_data_value inc esi duplicate_data: push eax esi duplicated_values: cmp edi,[tagged_blocks] jae out_of_memory clc call near dword [esp+8] lods byte [esi] cmp al,',' je duplicated_values cmp al,92h jne invalid_argument pop ebx eax dec eax jz data_defined mov esi,ebx jmp duplicate_data duplicate_single_data_value: cmp edi,[tagged_blocks] jae out_of_memory push eax esi clc call near dword [esp+8] pop ebx eax dec eax jz data_defined mov esi,ebx jmp duplicate_single_data_value duplicate_zero_times: cmp byte [esi],91h jne skip_single_data_value inc esi skip_data_value: call skip_symbol jc invalid_argument cmp byte [esi],92h jne skip_data_value inc esi jmp data_defined skip_single_data_value: call skip_symbol jmp data_defined simple_data_value: cmp edi,[tagged_blocks] jae out_of_memory clc call near dword [esp] data_defined: lods byte [esi] cmp al,',' je define_data dec esi stc ret data_bytes: call define_data jc instruction_assembled lods byte [esi] cmp al,'(' je get_byte cmp al,'?' jne invalid_argument mov eax,edi mov byte [edi],0 inc edi jmp undefined_data get_byte: cmp byte [esi],0 je get_string call get_byte_value stos byte [edi] ret get_string: inc esi lods dword [esi] mov ecx,eax lea eax,[edi+ecx] cmp eax,[tagged_blocks] ja out_of_memory rep movs byte [edi],[esi] inc esi ret undefined_data: mov ebp,[addressing_space] test byte [ds:ebp+0Ah],1 jz mark_undefined_data ret mark_undefined_data: cmp eax,[undefined_data_end] je undefined_data_ok mov [undefined_data_start],eax undefined_data_ok: mov [undefined_data_end],edi ret data_unicode: or [base_code],-1 jmp define_words data_words: mov [base_code],0 define_words: call define_data jc instruction_assembled lods byte [esi] cmp al,'(' je get_word cmp al,'?' jne invalid_argument mov eax,edi and word [edi],0 scas word [edi] jmp undefined_data ret get_word: cmp [base_code],0 je word_data_value cmp byte [esi],0 je word_string word_data_value: call get_word_value call mark_relocation stos word [edi] ret word_string: inc esi lods dword [esi] mov ecx,eax jecxz word_string_ok lea eax,[edi+ecx*2] cmp eax,[tagged_blocks] ja out_of_memory xor ah,ah copy_word_string: lods byte [esi] stos word [edi] loop copy_word_string word_string_ok: inc esi ret data_dwords: call define_data jc instruction_assembled lods byte [esi] cmp al,'(' je get_dword cmp al,'?' jne invalid_argument mov eax,edi and dword [edi],0 scas dword [edi] jmp undefined_data get_dword: push esi call get_dword_value pop ebx cmp byte [esi],':' je complex_dword call mark_relocation stos dword [edi] ret complex_dword: mov esi,ebx cmp byte [esi],'.' je invalid_value call get_word_value push eax inc esi lods byte [esi] cmp al,'(' jne invalid_operand mov al,[value_type] push eax cmp byte [esi],'.' je invalid_value call get_word_value call mark_relocation stos word [edi] pop eax mov [value_type],al pop eax call mark_relocation stos word [edi] ret data_pwords: call define_data jc instruction_assembled lods byte [esi] cmp al,'(' je get_pword cmp al,'?' jne invalid_argument mov eax,edi and dword [edi],0 scas dword [edi] and word [edi],0 scas word [edi] jmp undefined_data get_pword: push esi call get_pword_value pop ebx cmp byte [esi],':' je complex_pword call mark_relocation stos dword [edi] mov ax,dx stos word [edi] ret complex_pword: mov esi,ebx cmp byte [esi],'.' je invalid_value call get_word_value push eax inc esi lods byte [esi] cmp al,'(' jne invalid_operand mov al,[value_type] push eax cmp byte [esi],'.' je invalid_value call get_dword_value call mark_relocation stos dword [edi] pop eax mov [value_type],al pop eax call mark_relocation stos word [edi] ret data_qwords: call define_data jc instruction_assembled lods byte [esi] cmp al,'(' je get_qword cmp al,'?' jne invalid_argument mov eax,edi and dword [edi],0 scas dword [edi] and dword [edi],0 scas dword [edi] jmp undefined_data get_qword: call get_qword_value call mark_relocation stos dword [edi] mov eax,edx stos dword [edi] ret data_twords: call define_data jc instruction_assembled lods byte [esi] cmp al,'(' je get_tword cmp al,'?' jne invalid_argument mov eax,edi and dword [edi],0 scas dword [edi] and dword [edi],0 scas dword [edi] and word [edi],0 scas word [edi] jmp undefined_data get_tword: cmp byte [esi],'.' jne complex_tword inc esi cmp word [esi+8],8000h je fp_zero_tword mov eax,[esi] stos dword [edi] mov eax,[esi+4] stos dword [edi] mov ax,[esi+8] add ax,3FFFh jo value_out_of_range cmp ax,7FFFh jge value_out_of_range cmp ax,0 jg tword_exp_ok mov cx,ax neg cx inc cx cmp cx,64 jae value_out_of_range cmp cx,32 ja large_shift mov eax,[esi] mov edx,[esi+4] mov ebx,edx shr edx,cl shrd eax,ebx,cl jmp tword_mantissa_shift_done large_shift: sub cx,32 xor edx,edx mov eax,[esi+4] shr eax,cl tword_mantissa_shift_done: jnc store_shifted_mantissa add eax,1 adc edx,0 store_shifted_mantissa: mov [edi-8],eax mov [edi-4],edx xor ax,ax test edx,1 shl 31 jz tword_exp_ok inc ax tword_exp_ok: mov bl,[esi+11] shl bx,15 or ax,bx stos word [edi] add esi,13 ret fp_zero_tword: xor eax,eax stos dword [edi] stos dword [edi] mov al,[esi+11] shl ax,15 stos word [edi] add esi,13 ret complex_tword: call get_word_value push eax cmp byte [esi],':' jne invalid_operand inc esi lods byte [esi] cmp al,'(' jne invalid_operand mov al,[value_type] push eax cmp byte [esi],'.' je invalid_value call get_qword_value call mark_relocation stos dword [edi] mov eax,edx stos dword [edi] pop eax mov [value_type],al pop eax call mark_relocation stos word [edi] ret data_file: lods word [esi] cmp ax,'(' jne invalid_argument add esi,4 call open_binary_file mov eax,[esi-4] lea esi,[esi+eax+1] mov al,2 xor edx,edx call lseek push eax xor edx,edx cmp byte [esi],':' jne position_ok inc esi cmp byte [esi],'(' jne invalid_argument inc esi cmp byte [esi],'.' je invalid_value push ebx call get_count_value pop ebx mov edx,eax sub [esp],edx jc value_out_of_range position_ok: cmp byte [esi],',' jne size_ok inc esi cmp byte [esi],'(' jne invalid_argument inc esi cmp byte [esi],'.' je invalid_value push ebx edx call get_count_value pop edx ebx cmp eax,[esp] ja value_out_of_range mov [esp],eax size_ok: xor al,al call lseek pop ecx mov edx,edi add edi,ecx jc out_of_memory cmp edi,[tagged_blocks] ja out_of_memory call read jc error_reading_file call close lods byte [esi] cmp al,',' je data_file dec esi jmp instruction_assembled open_binary_file: push esi push edi mov eax,[current_line] find_current_source_path: mov esi,[eax] test byte [eax+7],80h jz get_current_path mov eax,[eax+8] jmp find_current_source_path get_current_path: lodsb stosb or al,al jnz get_current_path cut_current_path: cmp edi,[esp] je current_path_ok cmp byte [edi-1],'\' je current_path_ok cmp byte [edi-1],'/' je current_path_ok dec edi jmp cut_current_path current_path_ok: mov esi,[esp+4] call expand_path pop edx mov esi,edx call open jnc file_opened mov edx,[include_paths] search_in_include_paths: push edx esi mov edi,esi mov esi,[esp+4] call get_include_directory mov [esp+4],esi mov esi,[esp+8] call expand_path pop edx mov esi,edx call open pop edx jnc file_opened cmp byte [edx],0 jne search_in_include_paths mov edi,esi mov esi,[esp] push edi call expand_path pop edx mov esi,edx call open jc file_not_found file_opened: mov edi,esi pop esi ret reserve_bytes: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov ecx,eax mov edx,ecx add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je zero_bytes add edi,ecx jmp reserved_data zero_bytes: xor eax,eax shr ecx,1 jnc bytes_stosb_ok stos byte [edi] bytes_stosb_ok: shr ecx,1 jnc bytes_stosw_ok stos word [edi] bytes_stosw_ok: rep stos dword [edi] reserved_data: pop eax call undefined_data jmp instruction_assembled reserve_words: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov ecx,eax mov edx,ecx shl edx,1 jc out_of_memory add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je zero_words lea edi,[edi+ecx*2] jmp reserved_data zero_words: xor eax,eax shr ecx,1 jnc words_stosw_ok stos word [edi] words_stosw_ok: rep stos dword [edi] jmp reserved_data reserve_dwords: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov ecx,eax mov edx,ecx shl edx,1 jc out_of_memory shl edx,1 jc out_of_memory add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je zero_dwords lea edi,[edi+ecx*4] jmp reserved_data zero_dwords: xor eax,eax rep stos dword [edi] jmp reserved_data reserve_pwords: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov ecx,eax shl ecx,1 jc out_of_memory add ecx,eax mov edx,ecx shl edx,1 jc out_of_memory add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je zero_words lea edi,[edi+ecx*2] jmp reserved_data reserve_qwords: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov ecx,eax shl ecx,1 jc out_of_memory mov edx,ecx shl edx,1 jc out_of_memory shl edx,1 jc out_of_memory add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je zero_dwords lea edi,[edi+ecx*4] jmp reserved_data reserve_twords: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov ecx,eax shl ecx,2 jc out_of_memory add ecx,eax mov edx,ecx shl edx,1 jc out_of_memory add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je zero_words lea edi,[edi+ecx*2] jmp reserved_data align_directive: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov edx,eax dec edx test eax,edx jnz invalid_align_value or eax,eax jz invalid_align_value cmp eax,1 je instruction_assembled mov ecx,edi mov ebp,[addressing_space] sub ecx,[ds:ebp] cmp dword [ds:ebp+10h],0 jne section_not_aligned_enough cmp byte [ds:ebp+9],0 je make_alignment cmp [output_format],3 je pe_alignment cmp [output_format],5 jne object_alignment test [format_flags],1 jnz pe_alignment object_alignment: mov ebx,[ds:ebp+14h] cmp byte [ebx],0 jne section_not_aligned_enough cmp eax,[ebx+10h] jbe make_alignment jmp section_not_aligned_enough pe_alignment: cmp eax,1000h ja section_not_aligned_enough make_alignment: dec eax and ecx,eax jz instruction_assembled neg ecx add ecx,eax inc ecx mov edx,ecx add edx,edi jc out_of_memory cmp edx,[tagged_blocks] ja out_of_memory push edi cmp [next_pass_needed],0 je nops add edi,ecx jmp reserved_data invalid_align_value: cmp [error_line],0 jne instruction_assembled mov eax,[current_line] mov [error_line],eax mov [error],invalid_value jmp instruction_assembled nops: mov eax,90909090h shr ecx,1 jnc nops_stosb_ok stos byte [edi] nops_stosb_ok: shr ecx,1 jnc nops_stosw_ok stos word [edi] nops_stosw_ok: rep stos dword [edi] jmp reserved_data err_directive: mov al,[esi] cmp al,0Fh je invoked_error or al,al jz invoked_error jmp extra_characters_on_line assert_directive: call calculate_logical_expression or al,al jnz instruction_assembled cmp [error_line],0 jne instruction_assembled mov eax,[current_line] mov [error_line],eax mov [error],assertion_failed jmp instruction_assembled fasm/source/avx.inc0000644000175000017500000021237314533376740015107 0ustar privalovprivalov ; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. avx_single_source_pd_instruction_er_evex: or [vex_required],8 avx_single_source_pd_instruction_er: or [operand_flags],2+4+8 jmp avx_pd_instruction avx_single_source_pd_instruction_sae_evex: or [vex_required],8 or [operand_flags],2+4 jmp avx_pd_instruction avx_pd_instruction_imm8: mov [immediate_size],1 jmp avx_pd_instruction avx_pd_instruction_er: or [operand_flags],8 avx_pd_instruction_sae: or [operand_flags],4 avx_pd_instruction: mov [opcode_prefix],66h or [rex_prefix],80h mov cx,0800h jmp avx_instruction_with_broadcast avx_pd_instruction_38_evex: or [vex_required],8 mov [supplemental_code],al mov al,38h jmp avx_pd_instruction avx_cvtps2dq_instruction: mov [opcode_prefix],66h jmp avx_single_source_ps_instruction_er avx_cvtudq2ps_instruction: mov [opcode_prefix],0F2h avx_single_source_ps_instruction_er_evex: or [vex_required],8 avx_single_source_ps_instruction_er: or [operand_flags],2+4+8 jmp avx_ps_instruction avx_single_source_ps_instruction_noevex: or [operand_flags],2 or [vex_required],2 jmp avx_ps_instruction avx_ps_instruction_imm8: mov [immediate_size],1 jmp avx_ps_instruction avx_ps_instruction_er: or [operand_flags],8 avx_ps_instruction_sae: or [operand_flags],4 avx_ps_instruction: mov cx,0400h jmp avx_instruction_with_broadcast avx_ps_instruction_66_38_evex: or [vex_required],8 mov [opcode_prefix],66h mov [supplemental_code],al mov al,38h jmp avx_ps_instruction avx_sd_instruction_er: or [operand_flags],8 avx_sd_instruction_sae: or [operand_flags],4 avx_sd_instruction: mov [opcode_prefix],0F2h or [rex_prefix],80h mov cl,8 jmp avx_instruction avx_ss_instruction_er: or [operand_flags],8 avx_ss_instruction_sae: or [operand_flags],4 avx_ss_instruction: mov [opcode_prefix],0F3h mov cl,4 jmp avx_instruction avx_ss_instruction_noevex: or [vex_required],2 jmp avx_ss_instruction avx_single_source_q_instruction_38_evex: or [operand_flags],2 avx_q_instruction_38_evex: or [vex_required],8 avx_q_instruction_38: mov [supplemental_code],al mov al,38h jmp avx_q_instruction avx_q_instruction_38_w1_evex: or [vex_required],8 avx_q_instruction_38_w1: or [rex_prefix],8 jmp avx_q_instruction_38 avx_q_instruction_3a_imm8_w1: or [rex_prefix],8 jmp avx_q_instruction_3a_imm8 avx_q_instruction_3a_imm8_evex: or [vex_required],8 avx_q_instruction_3a_imm8: mov [immediate_size],1 mov [supplemental_code],al mov al,3Ah jmp avx_q_instruction avx_q_instruction_evex: or [vex_required],8 avx_q_instruction: or [rex_prefix],80h mov ch,8 jmp avx_pi_instruction avx_single_source_d_instruction_38_evex_w1: or [rex_prefix],8 avx_single_source_d_instruction_38_evex: or [vex_required],8 avx_single_source_d_instruction_38: or [operand_flags],2 jmp avx_d_instruction_38 avx_d_instruction_38_evex: or [vex_required],8 avx_d_instruction_38: mov [supplemental_code],al mov al,38h jmp avx_d_instruction avx_d_instruction_3a_imm8_evex: mov [immediate_size],1 or [vex_required],8 mov [supplemental_code],al mov al,3Ah jmp avx_d_instruction avx_single_source_d_instruction_imm8: or [operand_flags],2 mov [immediate_size],1 jmp avx_d_instruction avx_d_instruction_evex: or [vex_required],8 avx_d_instruction: mov ch,4 jmp avx_pi_instruction avx_bw_instruction_3a_imm8_w1_evex: or [rex_prefix],8 avx_bw_instruction_3a_imm8_evex: mov [immediate_size],1 or [vex_required],8 mov [supplemental_code],al mov al,3Ah jmp avx_bw_instruction avx_single_source_bw_instruction_38: or [operand_flags],2 avx_bw_instruction_38: mov [supplemental_code],al mov al,38h avx_bw_instruction: xor ch,ch avx_pi_instruction: mov [opcode_prefix],66h xor cl,cl jmp avx_instruction_with_broadcast avx_bw_instruction_38_w1_evex: or [rex_prefix],8 avx_bw_instruction_38_evex: or [vex_required],8 jmp avx_bw_instruction_38 avx_pd_instruction_noevex: xor cl,cl or [vex_required],2 mov [opcode_prefix],66h jmp avx_instruction avx_ps_instruction_noevex: or [vex_required],2 mov [opcode_prefix],0F2h xor cl,cl jmp avx_instruction avx_instruction: xor ch,ch avx_instruction_with_broadcast: mov [mmx_size],cl mov [broadcast_size],ch mov [base_code],0Fh mov [extended_code],al avx_xop_common: or [vex_required],1 lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand avx_reg: lods byte [esi] call convert_avx_register mov [postbyte_register],al call take_avx512_mask avx_vex_reg: test [operand_flags],2 jnz avx_vex_reg_ok lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [vex_register],al avx_vex_reg_ok: mov al,[mmx_size] or al,al jz avx_regs_size_ok mov ah,[operand_size] or ah,ah jz avx_regs_size_ok cmp al,ah je avx_regs_size_ok ja invalid_operand_size cmp ah,16 jne invalid_operand_size avx_regs_size_ok: lods byte [esi] cmp al,',' jne invalid_operand avx_regs_rm: call take_avx_rm jc avx_regs_reg mov al,[immediate_size] cmp al,1 je mmx_imm8 jb instruction_ready cmp al,-4 je sse_cmp_mem_ok cmp byte [esi],',' jne invalid_operand inc esi call take_avx_register shl al,4 jc invalid_operand or byte [value],al test al,80h jz avx_regs_mem_reg_store cmp [code_type],64 jne invalid_operand avx_regs_mem_reg_store: call take_imm4_if_needed call store_instruction_with_imm8 jmp instruction_assembled avx_regs_reg: mov bl,al call take_avx512_rounding mov al,[immediate_size] cmp al,1 je mmx_nomem_imm8 jb nomem_instruction_ready cmp al,-4 je sse_cmp_nomem_ok lods byte [esi] cmp al,',' jne invalid_operand mov al,bl shl al,4 jc invalid_operand or byte [value],al test al,80h jz avx_regs_reg_ cmp [code_type],64 jne invalid_operand avx_regs_reg_: call take_avx_rm jc avx_regs_reg_reg cmp [immediate_size],-2 jg invalid_operand or [rex_prefix],8 call take_imm4_if_needed call store_instruction_with_imm8 jmp instruction_assembled avx_regs_reg_reg: shl al,4 jc invalid_operand and byte [value],1111b or byte [value],al call take_imm4_if_needed call store_nomem_instruction mov al,byte [value] stos byte [edi] jmp instruction_assembled take_avx_rm: xor cl,cl xchg cl,[operand_size] lods byte [esi] call get_size_operator cmp al,'[' je take_avx_mem cmp al,10h jne invalid_operand mov [operand_size],cl lods byte [esi] call convert_avx_register or cl,cl jnz avx_reg_ok or cl,[mmx_size] jz avx_reg_ok cmp ah,cl je avx_reg_ok jb invalid_operand_size cmp ah,16 jne invalid_operand_size avx_reg_ok: stc ret take_avx_mem: push ecx call get_address cmp byte [esi],'{' jne avx_mem_ok inc esi lods byte [esi] cmp al,1Fh jne invalid_operand mov al,[esi] shr al,4 cmp al,1 jne invalid_operand mov al,[mmx_size] or al,al jnz avx_mem_broadcast_check mov eax,[esp] or al,al jnz avx_mem_broadcast_check mov al,[broadcast_size] mov [mmx_size],al mov ah,cl lods byte [esi] and al,1111b mov cl,al mov al,[broadcast_size] shl al,cl mov [esp],al mov cl,ah jmp avx_mem_broadcast_ok avx_mem_broadcast_check: bsf eax,eax xchg al,[broadcast_size] mov [mmx_size],al bsf eax,eax jz invalid_operand mov ah,[broadcast_size] sub ah,al lods byte [esi] and al,1111b cmp al,ah jne invalid_operand_size avx_mem_broadcast_ok: or [vex_required],40h lods byte [esi] cmp al,'}' jne invalid_operand avx_mem_ok: pop eax or al,al jz avx_mem_size_deciding xchg al,[operand_size] cmp [mmx_size],0 jne avx_mem_size_enforced or al,al jz avx_mem_size_ok cmp al,[operand_size] jne operand_sizes_do_not_match avx_mem_size_ok: clc ret avx_mem_size_deciding: mov al,[operand_size] cmp [mmx_size],0 jne avx_mem_size_enforced cmp al,16 je avx_mem_size_ok cmp al,32 je avx_mem_size_ok cmp al,64 je avx_mem_size_ok or al,al jnz invalid_operand_size call recoverable_unknown_size avx_mem_size_enforced: or al,al jz avx_mem_size_ok cmp al,[mmx_size] je avx_mem_size_ok jmp invalid_operand_size take_imm4_if_needed: cmp [immediate_size],-3 jne imm4_ok push ebx ecx edx lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] cmp al,'(' jne invalid_operand call get_byte_value test al,11110000b jnz value_out_of_range or byte [value],al pop edx ecx ebx imm4_ok: ret take_avx512_mask: cmp byte [esi],'{' jne avx512_masking_ok test [operand_flags],10h jnz invalid_operand inc esi lods byte [esi] cmp al,14h jne invalid_operand lods byte [esi] mov ah,al shr ah,4 cmp ah,5 jne invalid_operand and al,111b or al,al jz invalid_operand mov [mask_register],al or [vex_required],20h lods byte [esi] cmp al,'}' jne invalid_operand cmp byte [esi],'{' jne avx512_masking_ok test [operand_flags],20h jnz invalid_operand inc esi lods byte [esi] cmp al,1Fh jne invalid_operand lods byte [esi] or al,al jnz invalid_operand or [mask_register],80h lods byte [esi] cmp al,'}' jne invalid_operand avx512_masking_ok: retn take_avx512_rounding: test [operand_flags],4+8 jz avx512_rounding_done test [operand_flags],8 jz avx512_rounding_allowed cmp [mmx_size],0 jne avx512_rounding_allowed cmp [operand_size],64 jne avx512_rounding_done avx512_rounding_allowed: cmp byte [esi],',' jne avx512_rounding_done cmp byte [esi+1],'{' jne avx512_rounding_done add esi,2 mov [rounding_mode],0 or [vex_required],40h test [operand_flags],8 jz take_sae or [vex_required],80h lods byte [esi] cmp al,1Fh jne invalid_operand lods byte [esi] mov ah,al shr ah,4 cmp ah,2 jne invalid_operand and al,11b mov [rounding_mode],al lods byte [esi] cmp al,'-' jne invalid_operand take_sae: lods byte [esi] cmp al,1Fh jne invalid_operand lods byte [esi] cmp al,30h jne invalid_operand lods byte [esi] cmp al,'}' jne invalid_operand avx512_rounding_done: retn avx_movdqu_instruction: mov ah,0F3h jmp avx_movdq_instruction avx_movdqa_instruction: mov ah,66h avx_movdq_instruction: mov [opcode_prefix],ah or [vex_required],2 jmp avx_movps_instruction avx512_movdqu16_instruction: or [rex_prefix],8 avx512_movdqu8_instruction: mov ah,0F2h jmp avx_movdq_instruction_evex avx512_movdqu64_instruction: or [rex_prefix],8 avx512_movdqu32_instruction: mov ah,0F3h jmp avx_movdq_instruction_evex avx512_movdqa64_instruction: or [rex_prefix],8 avx512_movdqa32_instruction: mov ah,66h avx_movdq_instruction_evex: mov [opcode_prefix],ah or [vex_required],8 jmp avx_movps_instruction avx_movpd_instruction: mov [opcode_prefix],66h or [rex_prefix],80h avx_movps_instruction: or [operand_flags],2 mov [base_code],0Fh mov [extended_code],al or [vex_required],1 xor al,al mov [mmx_size],al mov [broadcast_size],al lods byte [esi] call get_size_operator cmp al,10h je avx_reg inc [extended_code] test [extended_code],1 jnz avx_mem add [extended_code],-1+10h avx_mem: cmp al,'[' jne invalid_operand call get_address or [operand_flags],20h call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [postbyte_register],al jmp instruction_ready avx_movntpd_instruction: or [rex_prefix],80h avx_movntdq_instruction: mov [opcode_prefix],66h avx_movntps_instruction: mov [base_code],0Fh mov [extended_code],al or [vex_required],1 or [operand_flags],10h mov [mmx_size],0 lods byte [esi] call get_size_operator jmp avx_mem avx_compress_q_instruction: or [rex_prefix],8 avx_compress_d_instruction: or [vex_required],8 mov [mmx_size],0 call setup_66_0f_38 lods byte [esi] call get_size_operator cmp al,10h jne avx_mem lods byte [esi] call convert_avx_register mov bl,al call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [postbyte_register],al jmp nomem_instruction_ready avx_lddqu_instruction: mov ah,0F2h or [vex_required],2 avx_load_instruction: mov [opcode_prefix],ah mov [base_code],0Fh mov [extended_code],al mov [mmx_size],0 or [vex_required],1 call take_avx_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address jmp instruction_ready avx_movntdqa_instruction: mov [supplemental_code],al mov al,38h mov ah,66h jmp avx_load_instruction avx_movq_instruction: or [rex_prefix],8 mov [mmx_size],8 jmp avx_mov_instruction avx_movd_instruction: mov [mmx_size],4 avx_mov_instruction: or [vex_required],1 mov [opcode_prefix],66h mov [base_code],0Fh mov [extended_code],7Eh lods byte [esi] call get_size_operator cmp al,10h je avx_movd_reg cmp al,'[' jne invalid_operand call get_address mov al,[mmx_size] not al and [operand_size],al jnz invalid_operand_size lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_avx_register cmp ah,16 jne invalid_operand_size mov [postbyte_register],al cmp [mmx_size],8 jne instruction_ready and [rex_prefix],not 8 or [rex_prefix],80h mov [extended_code],0D6h jmp instruction_ready avx_movd_reg: lods byte [esi] cmp al,0C0h jae avx_movd_xmmreg call convert_register cmp ah,[mmx_size] jne invalid_operand_size mov [operand_size],0 mov bl,al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_avx_register cmp ah,16 jne invalid_operand_size mov [postbyte_register],al avx_movd_reg_ready: test [rex_prefix],8 jz nomem_instruction_ready cmp [code_type],64 jne illegal_instruction jmp nomem_instruction_ready avx_movd_xmmreg: sub [extended_code],10h call convert_avx_register cmp ah,16 jne invalid_operand_size mov [postbyte_register],al mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je avx_movd_xmmreg_reg cmp al,'[' jne invalid_operand call get_address mov al,[mmx_size] cmp al,8 jne avx_movd_xmmreg_mem_ready call avx_movq_xmmreg_xmmreg_opcode avx_movd_xmmreg_mem_ready: not al test [operand_size],al jnz invalid_operand_size jmp instruction_ready avx_movd_xmmreg_reg: lods byte [esi] cmp al,0C0h jae avx_movq_xmmreg_xmmreg call convert_register cmp ah,[mmx_size] jne invalid_operand_size mov bl,al jmp avx_movd_reg_ready avx_movq_xmmreg_xmmreg: cmp [mmx_size],8 jne invalid_operand call avx_movq_xmmreg_xmmreg_opcode call convert_avx_register cmp ah,16 jne invalid_operand_size mov bl,al jmp nomem_instruction_ready avx_movq_xmmreg_xmmreg_opcode: and [rex_prefix],not 8 or [rex_prefix],80h add [extended_code],10h mov [opcode_prefix],0F3h ret avx_movddup_instruction: or [vex_required],1 mov [opcode_prefix],0F2h mov [base_code],0Fh mov [extended_code],al or [rex_prefix],80h xor al,al mov [mmx_size],al mov [broadcast_size],al lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_avx_register mov [postbyte_register],al cmp ah,16 ja avx_movddup_size_ok mov [mmx_size],8 avx_movddup_size_ok: call take_avx512_mask jmp avx_vex_reg_ok avx_movlpd_instruction: mov [opcode_prefix],66h or [rex_prefix],80h avx_movlps_instruction: mov [base_code],0Fh mov [extended_code],al mov [mmx_size],8 mov [broadcast_size],0 or [vex_required],1 lods byte [esi] call get_size_operator cmp al,10h jne avx_movlps_mem lods byte [esi] call convert_avx_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [vex_register],al cmp [operand_size],16 jne invalid_operand mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand call take_avx_rm jc invalid_operand jmp instruction_ready avx_movlps_mem: cmp al,'[' jne invalid_operand call get_address avx_movlps_mem_: mov al,[operand_size] or al,al jz avx_movlps_mem_size_ok cmp al,[mmx_size] jne invalid_operand_size mov [operand_size],0 avx_movlps_mem_size_ok: lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register cmp ah,16 jne invalid_operand mov [postbyte_register],al inc [extended_code] jmp instruction_ready avx_movhlps_instruction: mov [base_code],0Fh mov [extended_code],al or [vex_required],1 call take_avx_register cmp ah,16 jne invalid_operand mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [vex_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov bl,al jmp nomem_instruction_ready avx_movsd_instruction: mov al,0F2h mov cl,8 or [rex_prefix],80h jmp avx_movs_instruction avx_movss_instruction: mov al,0F3h mov cl,4 avx_movs_instruction: mov [opcode_prefix],al mov [mmx_size],cl or [vex_required],1 mov [base_code],0Fh mov [extended_code],10h lods byte [esi] call get_size_operator cmp al,10h jne avx_movs_mem lods byte [esi] call convert_avx_register cmp ah,16 jne invalid_operand mov [postbyte_register],al call take_avx512_mask xor cl,cl xchg cl,[operand_size] lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne avx_movs_reg_mem mov [operand_size],cl lods byte [esi] call convert_avx_register mov [vex_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov bl,al cmp bl,8 jb nomem_instruction_ready inc [extended_code] xchg bl,[postbyte_register] jmp nomem_instruction_ready avx_movs_reg_mem: cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] or al,al jz avx_movs_reg_mem_ok cmp al,[mmx_size] jne invalid_operand_size avx_movs_reg_mem_ok: jmp instruction_ready avx_movs_mem: cmp al,'[' jne invalid_operand call get_address or [operand_flags],20h call take_avx512_mask jmp avx_movlps_mem_ avx_comiss_instruction: or [operand_flags],2+4+10h mov cl,4 jmp avx_instruction avx_comisd_instruction: or [operand_flags],2+4+10h mov [opcode_prefix],66h or [rex_prefix],80h mov cl,8 jmp avx_instruction avx_movshdup_instruction: or [operand_flags],2 mov [opcode_prefix],0F3h xor cl,cl jmp avx_instruction avx_cvtqq2pd_instruction: mov [opcode_prefix],0F3h or [vex_required],8 or [operand_flags],2+4+8 or [rex_prefix],8 mov cx,0800h jmp avx_instruction_with_broadcast avx_pshuf_w_instruction: mov [opcode_prefix],al or [operand_flags],2 mov [immediate_size],1 mov al,70h xor cl,cl jmp avx_instruction avx_single_source_128bit_instruction_38_noevex: or [operand_flags],2 avx_128bit_instruction_38_noevex: mov cl,16 jmp avx_instruction_38_noevex avx_single_source_instruction_38_noevex: or [operand_flags],2 jmp avx_pi_instruction_38_noevex avx_pi_instruction_38_noevex: xor cl,cl avx_instruction_38_noevex: or [vex_required],2 avx_instruction_38: mov [opcode_prefix],66h mov [supplemental_code],al mov al,38h jmp avx_instruction avx_ss_instruction_3a_imm8_noevex: mov cl,4 jmp avx_instruction_3a_imm8_noevex avx_sd_instruction_3a_imm8_noevex: mov cl,8 jmp avx_instruction_3a_imm8_noevex avx_single_source_128bit_instruction_3a_imm8_noevex: or [operand_flags],2 avx_128bit_instruction_3a_imm8_noevex: mov cl,16 jmp avx_instruction_3a_imm8_noevex avx_triple_source_instruction_3a_noevex: xor cl,cl mov [immediate_size],-1 mov byte [value],0 jmp avx_instruction_3a_noevex avx_single_source_instruction_3a_imm8_noevex: or [operand_flags],2 avx_pi_instruction_3a_imm8_noevex: xor cl,cl avx_instruction_3a_imm8_noevex: mov [immediate_size],1 avx_instruction_3a_noevex: or [vex_required],2 avx_instruction_3a: mov [opcode_prefix],66h mov [supplemental_code],al mov al,3Ah jmp avx_instruction avx_pi_instruction_3a_imm8: xor cl,cl mov [immediate_size],1 jmp avx_instruction_3a avx_pclmulqdq_instruction: mov byte [value],al mov [immediate_size],-4 xor cl,cl mov al,44h or [operand_flags],10h jmp avx_instruction_3a avx_instruction_38_nomask: or [operand_flags],10h xor cl,cl jmp avx_instruction_38 avx512_single_source_pd_instruction_sae_imm8: or [operand_flags],2 avx512_pd_instruction_sae_imm8: or [rex_prefix],8 mov cx,0800h jmp avx512_instruction_sae_imm8 avx512_single_source_ps_instruction_sae_imm8: or [operand_flags],2 avx512_ps_instruction_sae_imm8: mov cx,0400h jmp avx512_instruction_sae_imm8 avx512_sd_instruction_sae_imm8: or [rex_prefix],8 mov cx,0008h jmp avx512_instruction_sae_imm8 avx512_ss_instruction_sae_imm8: mov cx,0004h avx512_instruction_sae_imm8: or [operand_flags],4 avx512_instruction_imm8: or [vex_required],8 mov [opcode_prefix],66h mov [immediate_size],1 mov [supplemental_code],al mov al,3Ah jmp avx_instruction_with_broadcast avx512_pd_instruction_er: or [operand_flags],4+8 jmp avx512_pd_instruction avx512_single_source_pd_instruction_sae: or [operand_flags],4 avx512_single_source_pd_instruction: or [operand_flags],2 avx512_pd_instruction: or [rex_prefix],8 mov cx,0800h jmp avx512_instruction avx512_ps_instruction_er: or [operand_flags],4+8 jmp avx512_ps_instruction avx512_single_source_ps_instruction_sae: or [operand_flags],4 avx512_single_source_ps_instruction: or [operand_flags],2 avx512_ps_instruction: mov cx,0400h jmp avx512_instruction avx512_sd_instruction_er: or [operand_flags],8 avx512_sd_instruction_sae: or [operand_flags],4 avx512_sd_instruction: or [rex_prefix],8 mov cx,0008h jmp avx512_instruction avx512_ss_instruction_er: or [operand_flags],8 avx512_ss_instruction_sae: or [operand_flags],4 avx512_ss_instruction: mov cx,0004h avx512_instruction: or [vex_required],8 mov [opcode_prefix],66h mov [supplemental_code],al mov al,38h jmp avx_instruction_with_broadcast avx512_exp2pd_instruction: or [rex_prefix],8 or [operand_flags],2+4 mov cx,0840h jmp avx512_instruction avx512_exp2ps_instruction: or [operand_flags],2+4 mov cx,0440h jmp avx512_instruction fma_instruction_pd: or [rex_prefix],8 mov cx,0800h jmp fma_instruction fma_instruction_ps: mov cx,0400h jmp fma_instruction fma_instruction_sd: or [rex_prefix],8 mov cx,0008h jmp fma_instruction fma_instruction_ss: mov cx,0004h fma_instruction: or [operand_flags],4+8 mov [opcode_prefix],66h mov [supplemental_code],al mov al,38h jmp avx_instruction_with_broadcast fma4_instruction_p: xor cl,cl jmp fma4_instruction fma4_instruction_sd: mov cl,8 jmp fma4_instruction fma4_instruction_ss: mov cl,4 fma4_instruction: mov [immediate_size],-2 mov byte [value],0 jmp avx_instruction_3a_noevex avx_cmp_pd_instruction: mov [opcode_prefix],66h or [rex_prefix],80h mov cx,0800h jmp avx_cmp_instruction avx_cmp_ps_instruction: mov cx,0400h jmp avx_cmp_instruction avx_cmp_sd_instruction: mov [opcode_prefix],0F2h or [rex_prefix],80h mov cx,0008h jmp avx_cmp_instruction avx_cmp_ss_instruction: mov [opcode_prefix],0F3h mov cx,0004h avx_cmp_instruction: mov byte [value],al mov [immediate_size],-4 or [operand_flags],4+20h mov al,0C2h jmp avx_cmp_common avx_cmpeqq_instruction: or [rex_prefix],80h mov ch,8 mov [supplemental_code],al mov al,38h jmp avx_cmp_pi_instruction avx_cmpeqd_instruction: mov ch,4 jmp avx_cmp_pi_instruction avx_cmpeqb_instruction: xor ch,ch jmp avx_cmp_pi_instruction avx512_cmp_uq_instruction: or [rex_prefix],8 mov ch,8 mov ah,1Eh jmp avx_cmp_pi_instruction_evex avx512_cmp_ud_instruction: mov ch,4 mov ah,1Eh jmp avx_cmp_pi_instruction_evex avx512_cmp_q_instruction: or [rex_prefix],8 mov ch,8 mov ah,1Fh jmp avx_cmp_pi_instruction_evex avx512_cmp_d_instruction: mov ch,4 mov ah,1Fh jmp avx_cmp_pi_instruction_evex avx512_cmp_uw_instruction: or [rex_prefix],8 avx512_cmp_ub_instruction: xor ch,ch mov ah,3Eh jmp avx_cmp_pi_instruction_evex avx512_cmp_w_instruction: or [rex_prefix],8 avx512_cmp_b_instruction: xor ch,ch mov ah,3Fh avx_cmp_pi_instruction_evex: mov byte [value],al mov [immediate_size],-4 mov [supplemental_code],ah mov al,3Ah or [vex_required],8 avx_cmp_pi_instruction: xor cl,cl or [operand_flags],20h mov [opcode_prefix],66h avx_cmp_common: mov [mmx_size],cl mov [broadcast_size],ch mov [extended_code],al mov [base_code],0Fh lods byte [esi] call get_size_operator cmp al,14h je avx_maskreg cmp al,10h jne invalid_operand or [vex_required],2 jmp avx_reg avx_maskreg: cmp [operand_size],0 jne invalid_operand_size or [vex_required],8 lods byte [esi] call convert_mask_register mov [postbyte_register],al call take_avx512_mask jmp avx_vex_reg avx512_fpclasspd_instruction: or [rex_prefix],8 mov cx,0800h jmp avx_fpclass_instruction avx512_fpclassps_instruction: mov cx,0400h jmp avx_fpclass_instruction avx512_fpclasssd_instruction: or [rex_prefix],8 mov cx,0008h jmp avx_fpclass_instruction avx512_fpclassss_instruction: mov cx,0004h avx_fpclass_instruction: mov [broadcast_size],ch mov [mmx_size],cl or [operand_flags],2 call setup_66_0f_3a mov [immediate_size],1 lods byte [esi] cmp al,14h je avx_maskreg jmp invalid_operand avx512_ptestnmd_instruction: mov ch,4 jmp avx512_ptestnm_instruction avx512_ptestnmq_instruction: or [rex_prefix],8 mov ch,8 jmp avx512_ptestnm_instruction avx512_ptestnmw_instruction: or [rex_prefix],8 avx512_ptestnmb_instruction: xor ch,ch avx512_ptestnm_instruction: mov ah,0F3h jmp avx512_ptest_instruction avx512_ptestmd_instruction: mov ch,4 jmp avx512_ptestm_instruction avx512_ptestmq_instruction: or [rex_prefix],8 mov ch,8 jmp avx512_ptestm_instruction avx512_ptestmw_instruction: or [rex_prefix],8 avx512_ptestmb_instruction: xor ch,ch avx512_ptestm_instruction: mov ah,66h avx512_ptest_instruction: xor cl,cl mov [opcode_prefix],ah mov [supplemental_code],al mov al,38h or [vex_required],8 jmp avx_cmp_common mask_shift_instruction_q: or [rex_prefix],8 mask_shift_instruction_d: or [operand_flags],2 or [immediate_size],1 mov [opcode_prefix],66h mov [supplemental_code],al mov al,3Ah jmp mask_instruction mask_instruction_single_source_b: mov [opcode_prefix],66h jmp mask_instruction_single_source_w mask_instruction_single_source_d: mov [opcode_prefix],66h mask_instruction_single_source_q: or [rex_prefix],8 mask_instruction_single_source_w: or [operand_flags],2 jmp mask_instruction mask_instruction_b: mov [opcode_prefix],66h jmp mask_instruction_w mask_instruction_d: mov [opcode_prefix],66h mask_instruction_q: or [rex_prefix],8 mask_instruction_w: mov [operand_size],32 mask_instruction: or [vex_required],1 mov [base_code],0Fh mov [extended_code],al call take_mask_register mov [postbyte_register],al test [operand_flags],2 jnz mask_instruction_nds_ok lods byte [esi] cmp al,',' jne invalid_operand call take_mask_register mov [vex_register],al mask_instruction_nds_ok: lods byte [esi] cmp al,',' jne invalid_operand call take_mask_register mov bl,al cmp [immediate_size],0 jne mmx_nomem_imm8 jmp nomem_instruction_ready take_mask_register: lods byte [esi] cmp al,14h jne invalid_operand lods byte [esi] convert_mask_register: mov ah,al shr ah,4 cmp ah,5 jne invalid_operand and al,1111b ret kmov_instruction: mov [mmx_size],al or [vex_required],1 mov [base_code],0Fh mov [extended_code],90h lods byte [esi] cmp al,14h je kmov_maskreg cmp al,10h je kmov_reg call get_size_operator inc [extended_code] cmp al,'[' jne invalid_argument call get_address lods byte [esi] cmp al,',' jne invalid_operand call take_mask_register mov [postbyte_register],al kmov_with_mem: mov ah,[mmx_size] mov al,[operand_size] or al,al jz kmov_mem_size_ok cmp al,ah jne invalid_operand_size kmov_mem_size_ok: call setup_kmov_prefix jmp instruction_ready setup_kmov_prefix: cmp ah,4 jb kmov_w_ok or [rex_prefix],8 kmov_w_ok: test ah,1 or 4 jz kmov_prefix_ok mov [opcode_prefix],66h kmov_prefix_ok: ret kmov_maskreg: lods byte [esi] call convert_mask_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] cmp al,14h je kmov_maskreg_maskreg cmp al,10h je kmov_maskreg_reg call get_size_operator cmp al,'[' jne invalid_argument call get_address jmp kmov_with_mem kmov_maskreg_maskreg: lods byte [esi] call convert_mask_register mov bl,al mov ah,[mmx_size] call setup_kmov_prefix jmp nomem_instruction_ready kmov_maskreg_reg: add [extended_code],2 lods byte [esi] call convert_register kmov_with_reg: mov bl,al mov al,[mmx_size] mov ah,4 cmp al,ah jbe kmov_reg_size_check mov ah,al kmov_reg_size_check: cmp ah,[operand_size] jne invalid_operand_size cmp al,8 je kmov_f2_w1 cmp al,2 ja kmov_f2 je nomem_instruction_ready mov [opcode_prefix],66h jmp nomem_instruction_ready kmov_f2_w1: or [rex_prefix],8 cmp [code_type],64 jne illegal_instruction kmov_f2: mov [opcode_prefix],0F2h jmp nomem_instruction_ready kmov_reg: add [extended_code],3 lods byte [esi] call convert_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_mask_register jmp kmov_with_reg avx512_pmov_m2_instruction_w1: or [rex_prefix],8 avx512_pmov_m2_instruction: or [vex_required],8 call setup_f3_0f_38 call take_avx_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_mask_register mov bl,al jmp nomem_instruction_ready avx512_pmov_2m_instruction_w1: or [rex_prefix],8 avx512_pmov_2m_instruction: or [vex_required],8 call setup_f3_0f_38 call take_mask_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov bl,al jmp nomem_instruction_ready setup_f3_0f_38: mov [extended_code],38h mov [supplemental_code],al mov [base_code],0Fh mov [opcode_prefix],0F3h ret vzeroall_instruction: mov [operand_size],32 vzeroupper_instruction: mov [base_code],0Fh mov [extended_code],al and [displacement_compression],0 call store_vex_instruction_code jmp instruction_assembled vstmxcsr_instruction: or [vex_required],2 jmp stmxcsr_instruction avx_perm2f128_instruction: or [vex_required],2 xor ch,ch avx_instruction_imm8_without_128bit: mov [immediate_size],1 mov ah,3Ah jmp avx_instruction_without_128bit avx512_shuf_q_instruction: or [rex_prefix],8 or [vex_required],8 mov ch,8 jmp avx_instruction_imm8_without_128bit avx512_shuf_d_instruction: or [vex_required],8 mov ch,4 jmp avx_instruction_imm8_without_128bit avx_permd_instruction: mov ah,38h mov ch,4 avx_instruction_without_128bit: xor cl,cl call setup_avx_66_supplemental call take_avx_register cmp ah,32 jb invalid_operand_size mov [postbyte_register],al call take_avx512_mask jmp avx_vex_reg setup_avx_66_supplemental: mov [opcode_prefix],66h mov [broadcast_size],ch mov [mmx_size],cl mov [base_code],0Fh mov [extended_code],ah mov [supplemental_code],al or [vex_required],1 ret avx_permq_instruction: or [rex_prefix],8 mov ch,8 jmp avx_permil_instruction avx_permilpd_instruction: or [rex_prefix],80h mov ch,8 jmp avx_permil_instruction avx_permilps_instruction: mov ch,4 avx_permil_instruction: or [operand_flags],2 xor cl,cl mov ah,3Ah call setup_avx_66_supplemental call take_avx_register cmp [supplemental_code],4 jae avx_permil_size_ok cmp ah,32 jb invalid_operand_size avx_permil_size_ok: mov [postbyte_register],al call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand call take_avx_rm jnc mmx_imm8 mov bl,al cmp byte [esi],',' jne invalid_operand mov al,[esi+1] cmp al,11h jne avx_permil_rm_or_imm8 mov al,[esi+3] avx_permil_rm_or_imm8: cmp al,'(' je mmx_nomem_imm8 mov [vex_register],bl inc esi mov [extended_code],38h mov al,[supplemental_code] cmp al,4 jb avx_permq_rm add [supplemental_code],8 jmp avx_regs_rm avx_permq_rm: or [vex_required],8 shl al,5 neg al add al,36h mov [supplemental_code],al jmp avx_regs_rm vpermil_2pd_instruction: mov [immediate_size],-2 mov byte [value],al mov al,49h jmp vpermil2_instruction_setup vpermil_2ps_instruction: mov [immediate_size],-2 mov byte [value],al mov al,48h jmp vpermil2_instruction_setup vpermil2_instruction: mov [immediate_size],-3 mov byte [value],0 vpermil2_instruction_setup: or [vex_required],2 mov [base_code],0Fh mov [supplemental_code],al mov al,3Ah xor cl,cl jmp avx_instruction avx_shift_q_instruction_evex: or [vex_required],8 avx_shift_q_instruction: or [rex_prefix],80h mov cl,8 jmp avx_shift_instruction avx_shift_d_instruction: mov cl,4 jmp avx_shift_instruction avx_shift_bw_instruction: xor cl,cl avx_shift_instruction: mov [broadcast_size],cl mov [mmx_size],0 mov [opcode_prefix],66h mov [base_code],0Fh mov [extended_code],al or [vex_required],1 call take_avx_register mov [postbyte_register],al call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand xor cl,cl xchg cl,[operand_size] lods byte [esi] call get_size_operator cmp al,'[' je avx_shift_reg_mem mov [operand_size],cl cmp al,10h jne invalid_operand lods byte [esi] call convert_avx_register mov [vex_register],al lods byte [esi] cmp al,',' jne invalid_operand push esi xor cl,cl xchg cl,[operand_size] lods byte [esi] call get_size_operator cmp al,10h je avx_shift_reg_reg_reg pop esi cmp al,'[' je avx_shift_reg_reg_mem xchg cl,[operand_size] test cl,not 1 jnz invalid_operand_size dec esi call convert_avx_shift_opcode mov bl,al jmp mmx_nomem_imm8 convert_avx_shift_opcode: mov al,[extended_code] mov ah,al and ah,1111b add ah,70h mov [extended_code],ah shr al,4 sub al,0Ch shl al,1 xchg al,[postbyte_register] xchg al,[vex_register] ret avx_shift_reg_reg_reg: pop eax lods byte [esi] call convert_xmm_register xchg cl,[operand_size] mov bl,al jmp nomem_instruction_ready avx_shift_reg_reg_mem: mov [mmx_size],16 push ecx lods byte [esi] call get_size_operator call get_address pop eax xchg al,[operand_size] test al,al jz instruction_ready cmp al,16 jne invalid_operand_size jmp instruction_ready avx_shift_reg_mem: or [vex_required],8 call take_avx_mem call convert_avx_shift_opcode jmp mmx_imm8 avx_shift_dq_instruction: mov [postbyte_register],al mov [opcode_prefix],66h mov [base_code],0Fh mov [extended_code],73h or [vex_required],1 mov [mmx_size],0 call take_avx_register mov [vex_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' je avx_shift_dq_reg_mem cmp al,10h jne invalid_operand lods byte [esi] call convert_avx_register mov bl,al jmp mmx_nomem_imm8 avx_shift_dq_reg_mem: or [vex_required],8 call get_address jmp mmx_imm8 avx512_rotate_q_instruction: mov cl,8 or [rex_prefix],cl jmp avx512_rotate_instruction avx512_rotate_d_instruction: mov cl,4 avx512_rotate_instruction: mov [broadcast_size],cl mov [postbyte_register],al mov [opcode_prefix],66h mov [base_code],0Fh mov [extended_code],72h or [vex_required],8 mov [mmx_size],0 mov [immediate_size],1 call take_avx_register mov [vex_register],al call take_avx512_mask jmp avx_vex_reg_ok avx_pmovsxbq_instruction: mov cl,2 jmp avx_pmovsx_instruction avx_pmovsxbd_instruction: mov cl,4 jmp avx_pmovsx_instruction avx_pmovsxbw_instruction: mov cl,8 avx_pmovsx_instruction: mov [mmx_size],cl or [vex_required],1 call setup_66_0f_38 call take_avx_register mov [postbyte_register],al call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand xor al,al xchg al,[operand_size] bsf ecx,eax sub cl,4 shl [mmx_size],cl push eax lods byte [esi] call get_size_operator cmp al,10h je avx_pmovsx_reg_reg cmp al,'[' jne invalid_operand call get_address pop eax xchg al,[operand_size] or al,al jz instruction_ready cmp al,[mmx_size] jne invalid_operand_size jmp instruction_ready avx_pmovsx_reg_reg: lods byte [esi] call convert_avx_register mov bl,al cmp ah,[mmx_size] je avx_pmovsx_xmmreg_reg_size_ok jb invalid_operand_size cmp ah,16 jne invalid_operand_size avx_pmovsx_xmmreg_reg_size_ok: pop eax mov [operand_size],al jmp nomem_instruction_ready avx512_pmovqb_instruction: mov cl,2 jmp avx512_pmov_instruction avx512_pmovdb_instruction: mov cl,4 jmp avx512_pmov_instruction avx512_pmovwb_instruction: mov cl,8 avx512_pmov_instruction: mov [mmx_size],cl or [vex_required],8 mov [extended_code],38h mov [supplemental_code],al mov [base_code],0Fh mov [opcode_prefix],0F3h lods byte [esi] call get_size_operator cmp al,10h je avx512_pmov_reg cmp al,'[' jne invalid_operand call get_address or [operand_flags],20h call avx512_pmov_common or al,al jz instruction_ready cmp al,[mmx_size] jne invalid_operand_size jmp instruction_ready avx512_pmov_common: call take_avx512_mask xor al,al xchg al,[operand_size] push eax lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [postbyte_register],al mov al,ah mov ah,cl bsf ecx,eax sub cl,4 shl [mmx_size],cl mov cl,ah pop eax ret avx512_pmov_reg: lods byte [esi] call convert_avx_register mov bl,al call avx512_pmov_common cmp al,[mmx_size] je nomem_instruction_ready jb invalid_operand_size cmp al,16 jne invalid_operand_size jmp nomem_instruction_ready avx_broadcast_128_instruction_noevex: or [vex_required],2 mov cl,10h jmp avx_broadcast_instruction avx512_broadcast_32x2_instruction: mov cl,08h jmp avx_broadcast_instruction_evex avx512_broadcast_32x4_instruction: mov cl,10h jmp avx_broadcast_instruction_evex avx512_broadcast_32x8_instruction: mov cl,20h jmp avx_broadcast_instruction_evex avx512_broadcast_64x2_instruction: mov cl,10h jmp avx_broadcast_instruction_w1_evex avx512_broadcast_64x4_instruction: mov cl,20h avx_broadcast_instruction_w1_evex: or [rex_prefix],8 avx_broadcast_instruction_evex: or [vex_required],8 jmp avx_broadcast_instruction avx_broadcastss_instruction: mov cl,4 jmp avx_broadcast_instruction avx_broadcastsd_instruction: or [rex_prefix],80h mov cl,8 jmp avx_broadcast_instruction avx_pbroadcastb_instruction: mov cl,1 jmp avx_broadcast_pi_instruction avx_pbroadcastw_instruction: mov cl,2 jmp avx_broadcast_pi_instruction avx_pbroadcastd_instruction: mov cl,4 jmp avx_broadcast_pi_instruction avx_pbroadcastq_instruction: mov cl,8 or [rex_prefix],80h avx_broadcast_pi_instruction: or [operand_flags],40h avx_broadcast_instruction: mov [opcode_prefix],66h mov [supplemental_code],al mov al,38h mov [mmx_size],cl mov [base_code],0Fh mov [extended_code],al or [vex_required],1 call take_avx_register cmp ah,[mmx_size] je invalid_operand_size test [operand_flags],40h jnz avx_broadcast_destination_size_ok cmp [mmx_size],4 je avx_broadcast_destination_size_ok cmp [supplemental_code],59h je avx_broadcast_destination_size_ok cmp ah,16 je invalid_operand_size avx_broadcast_destination_size_ok: xor ah,ah xchg ah,[operand_size] push eax call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je avx_broadcast_reg_reg cmp al,'[' jne invalid_operand call get_address pop eax xchg ah,[operand_size] mov [postbyte_register],al mov al,[broadcast_size] mov al,[mmx_size] cmp al,ah je instruction_ready or al,al jz instruction_ready or ah,ah jz instruction_ready jmp invalid_operand_size avx_broadcast_reg_reg: lods byte [esi] test [operand_flags],40h jz avx_broadcast_reg_avx_reg cmp al,60h jb avx_broadcast_reg_general_reg cmp al,80h jb avx_broadcast_reg_avx_reg cmp al,0C0h jb avx_broadcast_reg_general_reg avx_broadcast_reg_avx_reg: call convert_avx_register mov bl,al mov al,[mmx_size] or al,al jz avx_broadcast_reg_avx_reg_size_ok cmp ah,16 jne invalid_operand_size cmp al,ah jae invalid_operand avx_broadcast_reg_avx_reg_size_ok: pop eax xchg ah,[operand_size] mov [postbyte_register],al test [vex_required],2 jnz invalid_operand jmp nomem_instruction_ready avx_broadcast_reg_general_reg: call convert_register mov bl,al mov al,[mmx_size] or al,al jz avx_broadcast_reg_general_reg_size_ok cmp al,ah je avx_broadcast_reg_general_reg_size_ok ja invalid_operand_size cmp ah,4 jne invalid_operand_size avx_broadcast_reg_general_reg_size_ok: cmp al,4 jb avx_broadcast_reg_general_reg_ready cmp al,8 mov al,3 jne avx_broadcast_reg_general_reg_ready or [rex_prefix],8 avx_broadcast_reg_general_reg_ready: add al,7Ah-1 mov [supplemental_code],al or [vex_required],8 pop eax xchg ah,[operand_size] mov [postbyte_register],al jmp nomem_instruction_ready avx512_extract_64x4_instruction: or [rex_prefix],8 avx512_extract_32x8_instruction: or [vex_required],8 mov cl,32 jmp avx_extractf_instruction avx512_extract_64x2_instruction: or [rex_prefix],8 avx512_extract_32x4_instruction: or [vex_required],8 mov cl,16 jmp avx_extractf_instruction avx_extractf128_instruction: or [vex_required],2 mov cl,16 avx_extractf_instruction: mov [mmx_size],cl call setup_66_0f_3a lods byte [esi] call get_size_operator cmp al,10h je avx_extractf_reg cmp al,'[' jne invalid_operand call get_address xor al,al xchg al,[operand_size] or al,al jz avx_extractf_mem_size_ok cmp al,[mmx_size] jne invalid_operand_size avx_extractf_mem_size_ok: call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register cmp ah,[mmx_size] jbe invalid_operand_size mov [postbyte_register],al jmp mmx_imm8 avx_extractf_reg: lods byte [esi] call convert_avx_register cmp ah,[mmx_size] jne invalid_operand_size push eax call take_avx512_mask mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register cmp ah,[mmx_size] jbe invalid_operand_size mov [postbyte_register],al pop ebx jmp mmx_nomem_imm8 avx512_insert_64x4_instruction: or [rex_prefix],8 avx512_insert_32x8_instruction: or [vex_required],8 mov cl,32 jmp avx_insertf_instruction avx512_insert_64x2_instruction: or [rex_prefix],8 avx512_insert_32x4_instruction: or [vex_required],8 mov cl,16 jmp avx_insertf_instruction avx_insertf128_instruction: or [vex_required],2 mov cl,16 avx_insertf_instruction: mov [mmx_size],cl mov [broadcast_size],0 call setup_66_0f_3a call take_avx_register cmp ah,[mmx_size] jbe invalid_operand mov [postbyte_register],al call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [vex_register],al mov al,[mmx_size] xchg al,[operand_size] push eax lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je avx_insertf_reg_reg_reg cmp al,'[' jne invalid_operand call get_address pop eax mov [operand_size],al jmp mmx_imm8 avx_insertf_reg_reg_reg: lods byte [esi] call convert_avx_register mov bl,al pop eax mov [operand_size],al jmp mmx_nomem_imm8 avx_extract_b_instruction: mov cl,1 jmp avx_extract_instruction avx_extract_w_instruction: mov cl,2 jmp avx_extract_instruction avx_extract_q_instruction: or [rex_prefix],8 mov cl,8 jmp avx_extract_instruction avx_extract_d_instruction: mov cl,4 avx_extract_instruction: mov [mmx_size],cl call setup_66_0f_3a or [vex_required],1 lods byte [esi] call get_size_operator cmp al,10h je avx_extractps_reg cmp al,'[' jne invalid_operand call get_address mov al,[mmx_size] not al and [operand_size],al jnz invalid_operand_size lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_avx_register cmp ah,16 jne invalid_operand_size mov [postbyte_register],al jmp mmx_imm8 avx_extractps_reg: lods byte [esi] call convert_register mov bl,al mov al,[mmx_size] cmp ah,al jb invalid_operand_size cmp ah,4 je avx_extractps_reg_size_ok cmp ah,8 jne invalid_operand_size cmp [code_type],64 jne invalid_operand cmp al,4 jae avx_extractps_reg_size_ok or [rex_prefix],8 avx_extractps_reg_size_ok: mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_avx_register cmp ah,16 jne invalid_operand_size mov [postbyte_register],al cmp [supplemental_code],15h jne mmx_nomem_imm8 mov [extended_code],0C5h xchg bl,[postbyte_register] jmp mmx_nomem_imm8 avx_insertps_instruction: mov [immediate_size],1 or [operand_flags],10h mov [opcode_prefix],66h mov [supplemental_code],al mov al,3Ah mov cl,4 jmp avx_instruction avx_pinsrb_instruction: mov cl,1 jmp avx_pinsr_instruction_3a avx_pinsrw_instruction: mov cl,2 jmp avx_pinsr_instruction avx_pinsrd_instruction: mov cl,4 jmp avx_pinsr_instruction_3a avx_pinsrq_instruction: cmp [code_type],64 jne illegal_instruction mov cl,8 or [rex_prefix],8 avx_pinsr_instruction_3a: mov [supplemental_code],al mov al,3Ah avx_pinsr_instruction: mov [opcode_prefix],66h mov [base_code],0Fh mov [extended_code],al mov [mmx_size],cl or [vex_required],1 call take_avx_register cmp ah,16 jne invalid_operand_size mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [vex_register],al jmp pinsr_xmmreg avx_cvtudq2pd_instruction: or [vex_required],8 avx_cvtdq2pd_instruction: mov [opcode_prefix],0F3h mov cl,4 jmp avx_cvt_d_instruction avx_cvtps2qq_instruction: or [operand_flags],8 avx_cvttps2qq_instruction: or [operand_flags],4 or [vex_required],8 mov [opcode_prefix],66h mov cl,4 jmp avx_cvt_d_instruction avx_cvtps2pd_instruction: or [operand_flags],4 mov cl,4 avx_cvt_d_instruction: mov [base_code],0Fh mov [extended_code],al or [vex_required],1 mov [broadcast_size],cl call take_avx_register mov [postbyte_register],al call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand xor ecx,ecx xchg cl,[operand_size] mov al,cl shr al,1 mov [mmx_size],al lods byte [esi] call get_size_operator cmp al,'[' je avx_cvt_d_reg_mem cmp al,10h jne invalid_operand mov [operand_size],0 lods byte [esi] call convert_avx_register cmp ah,[mmx_size] je avx_cvt_d_reg_reg_size_ok jb invalid_operand_size cmp ah,16 jne invalid_operand_size avx_cvt_d_reg_reg_size_ok: mov bl,al mov [operand_size],cl call take_avx512_rounding jmp nomem_instruction_ready avx_cvt_d_reg_mem: call take_avx_mem jmp instruction_ready avx_cvtpd2dq_instruction: or [operand_flags],4+8 mov [opcode_prefix],0F2h jmp avx_cvt_q_instruction avx_cvtuqq2ps_instruction: mov [opcode_prefix],0F2h avx_cvtpd2udq_instruction: or [operand_flags],8 avx_cvttpd2udq_instruction: or [operand_flags],4 or [vex_required],8 jmp avx_cvt_q_instruction avx_cvtpd2ps_instruction: or [operand_flags],8 avx_cvttpd2dq_instruction: or [operand_flags],4 mov [opcode_prefix],66h avx_cvt_q_instruction: mov [broadcast_size],8 mov [base_code],0Fh mov [extended_code],al or [vex_required],1 or [rex_prefix],80h call take_avx_register mov [postbyte_register],al push eax call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand xor al,al mov [operand_size],al mov [mmx_size],al call take_avx_rm jnc avx_cvt_q_reg_mem mov bl,al pop eax call avx_cvt_q_check_size call take_avx512_rounding jmp nomem_instruction_ready avx_cvt_q_reg_mem: pop eax call avx_cvt_q_check_size jmp instruction_ready avx_cvt_q_check_size: mov al,[operand_size] or al,al jz avx_cvt_q_size_not_specified cmp al,64 ja invalid_operand_size shr al,1 cmp al,ah je avx_cvt_q_size_ok ja invalid_operand_size cmp ah,16 jne invalid_operand_size avx_cvt_q_size_ok: ret avx_cvt_q_size_not_specified: cmp ah,64 shr 1 jne recoverable_unknown_size mov [operand_size],64 ret avx_cvttps2udq_instruction: or [vex_required],8 or [operand_flags],2+4 mov cx,0400h jmp avx_instruction_with_broadcast avx_cvttps2dq_instruction: mov [opcode_prefix],0F3h or [operand_flags],2+4 mov cx,0400h jmp avx_instruction_with_broadcast avx_cvtph2ps_instruction: mov [opcode_prefix],66h mov [supplemental_code],al or [operand_flags],4 mov al,38h xor cl,cl jmp avx_cvt_d_instruction avx_cvtps2ph_instruction: call setup_66_0f_3a or [vex_required],1 or [operand_flags],4 lods byte [esi] call get_size_operator cmp al,10h je vcvtps2ph_reg cmp al,'[' jne invalid_operand call get_address call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand shl [operand_size],1 call take_avx_register mov [postbyte_register],al shr ah,1 mov [mmx_size],ah jmp mmx_imm8 vcvtps2ph_reg: lods byte [esi] call convert_avx_register mov bl,al call take_avx512_mask xor cl,cl xchg cl,[operand_size] shl cl,1 lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [postbyte_register],al or cl,cl jz vcvtps2ph_reg_size_ok cmp cl,ah je vcvtps2ph_reg_size_ok jb invalid_operand_size cmp ah,16 jne invalid_operand_size vcvtps2ph_reg_size_ok: call take_avx512_rounding jmp mmx_nomem_imm8 avx_cvtsd2usi_instruction: or [operand_flags],8 avx_cvttsd2usi_instruction: or [vex_required],8 jmp avx_cvttsd2si_instruction avx_cvtsd2si_instruction: or [operand_flags],8 avx_cvttsd2si_instruction: mov ah,0F2h mov cl,8 jmp avx_cvt_2si_instruction avx_cvtss2usi_instruction: or [operand_flags],8 avx_cvttss2usi_instruction: or [vex_required],8 jmp avx_cvttss2si_instruction avx_cvtss2si_instruction: or [operand_flags],8 avx_cvttss2si_instruction: mov ah,0F3h mov cl,4 avx_cvt_2si_instruction: or [operand_flags],2+4 mov [mmx_size],cl mov [broadcast_size],0 mov [opcode_prefix],ah mov [base_code],0Fh mov [extended_code],al or [vex_required],1 lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_register mov [postbyte_register],al mov [operand_size],0 cmp ah,4 je avx_cvt_2si_reg cmp ah,8 jne invalid_operand_size call operand_64bit avx_cvt_2si_reg: lods byte [esi] cmp al,',' jne invalid_operand call take_avx_rm jnc instruction_ready mov bl,al call take_avx512_rounding jmp nomem_instruction_ready avx_cvtusi2sd_instruction: or [vex_required],8 avx_cvtsi2sd_instruction: mov ah,0F2h mov cl,8 jmp avx_cvtsi_instruction avx_cvtusi2ss_instruction: or [vex_required],8 avx_cvtsi2ss_instruction: mov ah,0F3h mov cl,4 avx_cvtsi_instruction: or [operand_flags],2+4+8 mov [mmx_size],cl mov [opcode_prefix],ah mov [base_code],0Fh mov [extended_code],al or [vex_required],1 call take_avx_register cmp ah,16 jne invalid_operand_size mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [vex_register],al lods byte [esi] cmp al,',' jne invalid_operand mov [operand_size],0 lods byte [esi] call get_size_operator cmp al,'[' je avx_cvtsi_reg_reg_mem cmp al,10h jne invalid_operand lods byte [esi] call convert_register mov bl,al cmp ah,4 je avx_cvtsi_reg_reg_reg32 cmp ah,8 jne invalid_operand_size call operand_64bit avx_cvtsi_rounding: call take_avx512_rounding jmp nomem_instruction_ready avx_cvtsi_reg_reg_reg32: cmp [mmx_size],8 jne avx_cvtsi_rounding jmp nomem_instruction_ready avx_cvtsi_reg_reg_mem: call get_address mov al,[operand_size] mov [mmx_size],al or al,al jz single_mem_nosize cmp al,4 je instruction_ready cmp al,8 jne invalid_operand_size call operand_64bit jmp instruction_ready avx_maskmov_w1_instruction: or [rex_prefix],8 avx_maskmov_instruction: call setup_66_0f_38 mov [mmx_size],0 or [vex_required],2 lods byte [esi] call get_size_operator cmp al,10h jne avx_maskmov_mem lods byte [esi] call convert_avx_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [vex_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address jmp instruction_ready avx_maskmov_mem: cmp al,'[' jne invalid_operand call get_address lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [vex_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [postbyte_register],al add [supplemental_code],2 jmp instruction_ready avx_movmskpd_instruction: mov [opcode_prefix],66h avx_movmskps_instruction: mov [base_code],0Fh mov [extended_code],50h or [vex_required],2 lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_register mov [postbyte_register],al cmp ah,4 je avx_movmskps_reg_ok cmp ah,8 jne invalid_operand_size cmp [code_type],64 jne invalid_operand avx_movmskps_reg_ok: mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov bl,al jmp nomem_instruction_ready avx_maskmovdqu_instruction: or [vex_required],2 jmp maskmovdqu_instruction avx_pmovmskb_instruction: or [vex_required],2 mov [opcode_prefix],66h mov [base_code],0Fh mov [extended_code],al lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_register cmp ah,4 je avx_pmovmskb_reg_size_ok cmp [code_type],64 jne invalid_operand_size cmp ah,8 jnz invalid_operand_size avx_pmovmskb_reg_size_ok: mov [postbyte_register],al mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov bl,al jmp nomem_instruction_ready gather_pd_instruction: or [rex_prefix],8 gather_ps_instruction: call setup_66_0f_38 or [vex_required],4 or [operand_flags],20h call take_avx_register mov [postbyte_register],al call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand xor cl,cl xchg cl,[operand_size] push ecx lods byte [esi] call get_size_operator cmp al,'[' jne invalid_argument call get_address pop eax xchg al,[operand_size] gather_mem_size_check: mov ah,4 test [rex_prefix],8 jz gather_elements_size_ok add ah,ah gather_elements_size_ok: mov [mmx_size],ah test al,al jz gather_mem_size_ok cmp al,ah jne invalid_operand_size gather_mem_size_ok: cmp byte [esi],',' je gather_reg_mem_reg test [vex_required],20h jz invalid_operand mov ah,[operand_size] mov al,80h jmp gather_arguments_ok gather_reg_mem_reg: or [vex_required],2 inc esi call take_avx_register gather_arguments_ok: mov [vex_register],al cmp al,[postbyte_register] je disallowed_combination_of_registers mov al,bl and al,11111b cmp al,[postbyte_register] je disallowed_combination_of_registers cmp al,[vex_register] je disallowed_combination_of_registers mov al,bl shr al,5 cmp al,0Ch shr 1 je gather_vr128 mov ah,32 cmp al,6 shr 1 jne gather_regular add ah,ah gather_regular: mov al,[rex_prefix] shr al,3 xor al,[supplemental_code] test al,1 jz gather_uniform test [supplemental_code],1 jz gather_double mov al,ah xchg al,[operand_size] add al,al cmp al,ah jne invalid_operand_size jmp instruction_ready gather_double: add ah,ah gather_uniform: cmp ah,[operand_size] jne invalid_operand_size jmp instruction_ready gather_vr128: cmp ah,16 je instruction_ready cmp ah,32 jne invalid_operand_size test [supplemental_code],1 jnz invalid_operand_size test [rex_prefix],8 jz invalid_operand_size jmp instruction_ready scatter_pd_instruction: or [rex_prefix],8 scatter_ps_instruction: call setup_66_0f_38 or [vex_required],4+8 or [operand_flags],20h lods byte [esi] call get_size_operator cmp al,'[' jne invalid_argument call get_address call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand xor al,al xchg al,[operand_size] push eax call take_avx_register mov [postbyte_register],al pop eax jmp gather_mem_size_check gatherpf_qpd_instruction: mov ah,0C7h jmp gatherpf_pd_instruction gatherpf_dpd_instruction: mov ah,0C6h gatherpf_pd_instruction: or [rex_prefix],8 mov cl,8 jmp gatherpf_instruction gatherpf_qps_instruction: mov ah,0C7h jmp gatherpf_ps_instruction gatherpf_dps_instruction: mov ah,0C6h gatherpf_ps_instruction: mov cl,4 gatherpf_instruction: mov [mmx_size],cl mov [postbyte_register],al mov al,ah call setup_66_0f_38 or [vex_required],4+8 or [operand_flags],20h lods byte [esi] call get_size_operator cmp al,'[' jne invalid_argument call get_address call take_avx512_mask mov ah,[mmx_size] mov al,[operand_size] or al,al jz gatherpf_mem_size_ok cmp al,ah jne invalid_operand_size gatherpf_mem_size_ok: mov [operand_size],64 mov al,6 shr 1 cmp ah,4 je gatherpf_check_vsib cmp [supplemental_code],0C6h jne gatherpf_check_vsib mov al,0Eh shr 1 gatherpf_check_vsib: mov ah,bl shr ah,5 cmp al,ah jne invalid_operand jmp instruction_ready bmi_instruction: mov [base_code],0Fh mov [extended_code],38h mov [supplemental_code],0F3h mov [postbyte_register],al bmi_reg: or [vex_required],2 lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_register mov [vex_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je bmi_reg_reg cmp al,'[' jne invalid_argument call get_address call operand_32or64 jmp instruction_ready bmi_reg_reg: lods byte [esi] call convert_register mov bl,al call operand_32or64 jmp nomem_instruction_ready operand_32or64: mov al,[operand_size] cmp al,4 je operand_32or64_ok cmp al,8 jne invalid_operand_size cmp [code_type],64 jne invalid_operand or [rex_prefix],8 operand_32or64_ok: ret pdep_instruction: mov [opcode_prefix],0F2h jmp andn_instruction pext_instruction: mov [opcode_prefix],0F3h andn_instruction: mov [base_code],0Fh mov [extended_code],38h mov [supplemental_code],al or [vex_required],2 lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand jmp bmi_reg sarx_instruction: mov [opcode_prefix],0F3h jmp bzhi_instruction shrx_instruction: mov [opcode_prefix],0F2h jmp bzhi_instruction shlx_instruction: mov [opcode_prefix],66h bzhi_instruction: mov [base_code],0Fh mov [extended_code],38h mov [supplemental_code],al or [vex_required],2 call get_reg_mem jc bzhi_reg_reg call get_vex_source_register jc invalid_operand call operand_32or64 jmp instruction_ready bzhi_reg_reg: call get_vex_source_register jc invalid_operand call operand_32or64 jmp nomem_instruction_ready get_vex_source_register: lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne no_vex_source_register lods byte [esi] call convert_register mov [vex_register],al clc ret no_vex_source_register: stc ret bextr_instruction: mov [base_code],0Fh mov [extended_code],38h mov [supplemental_code],al or [vex_required],2 call get_reg_mem jc bextr_reg_reg call get_vex_source_register jc bextr_reg_mem_imm32 call operand_32or64 jmp instruction_ready bextr_reg_reg: call get_vex_source_register jc bextr_reg_reg_imm32 call operand_32or64 jmp nomem_instruction_ready setup_bextr_imm_opcode: mov [xop_opcode_map],0Ah mov [base_code],10h call operand_32or64 ret bextr_reg_mem_imm32: call get_imm32 call setup_bextr_imm_opcode jmp store_instruction_with_imm32 bextr_reg_reg_imm32: call get_imm32 call setup_bextr_imm_opcode store_nomem_instruction_with_imm32: call store_nomem_instruction mov eax,dword [value] call mark_relocation stos dword [edi] jmp instruction_assembled get_imm32: cmp al,'(' jne invalid_operand push edx ebx ecx call get_dword_value mov dword [value],eax pop ecx ebx edx ret rorx_instruction: mov [opcode_prefix],0F2h mov [base_code],0Fh mov [extended_code],3Ah mov [supplemental_code],al or [vex_required],2 call get_reg_mem jc rorx_reg_reg call operand_32or64 jmp mmx_imm8 rorx_reg_reg: call operand_32or64 jmp mmx_nomem_imm8 tbm_instruction: mov [xop_opcode_map],9 mov ah,al shr ah,4 and al,111b mov [base_code],ah mov [postbyte_register],al jmp bmi_reg llwpcb_instruction: or [vex_required],2 mov [xop_opcode_map],9 mov [base_code],12h mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_register mov bl,al call operand_32or64 jmp nomem_instruction_ready lwpins_instruction: or [vex_required],2 mov [xop_opcode_map],0Ah mov [base_code],12h mov [vex_register],al lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand xor cl,cl xchg cl,[operand_size] lods byte [esi] call get_size_operator cmp al,10h je lwpins_reg_reg cmp al,'[' jne invalid_argument push ecx call get_address pop eax xchg al,[operand_size] test al,al jz lwpins_reg_mem_size_ok cmp al,4 jne invalid_operand_size lwpins_reg_mem_size_ok: call prepare_lwpins jmp store_instruction_with_imm32 lwpins_reg_reg: lods byte [esi] call convert_register cmp ah,4 jne invalid_operand_size mov [operand_size],cl mov bl,al call prepare_lwpins jmp store_nomem_instruction_with_imm32 prepare_lwpins: lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_imm32 call operand_32or64 mov al,[vex_register] xchg al,[postbyte_register] mov [vex_register],al ret xop_single_source_sd_instruction: or [operand_flags],2 mov [mmx_size],8 jmp xop_instruction_9 xop_single_source_ss_instruction: or [operand_flags],2 mov [mmx_size],4 jmp xop_instruction_9 xop_single_source_instruction: or [operand_flags],2 mov [mmx_size],0 xop_instruction_9: mov [base_code],al mov [xop_opcode_map],9 jmp avx_xop_common xop_single_source_128bit_instruction: or [operand_flags],2 mov [mmx_size],16 jmp xop_instruction_9 xop_triple_source_128bit_instruction: mov [immediate_size],-1 mov byte [value],0 mov [mmx_size],16 jmp xop_instruction_8 xop_128bit_instruction: mov [immediate_size],-2 mov byte [value],0 mov [mmx_size],16 xop_instruction_8: mov [base_code],al mov [xop_opcode_map],8 jmp avx_xop_common xop_pcom_b_instruction: mov ah,0CCh jmp xop_pcom_instruction xop_pcom_d_instruction: mov ah,0CEh jmp xop_pcom_instruction xop_pcom_q_instruction: mov ah,0CFh jmp xop_pcom_instruction xop_pcom_w_instruction: mov ah,0CDh jmp xop_pcom_instruction xop_pcom_ub_instruction: mov ah,0ECh jmp xop_pcom_instruction xop_pcom_ud_instruction: mov ah,0EEh jmp xop_pcom_instruction xop_pcom_uq_instruction: mov ah,0EFh jmp xop_pcom_instruction xop_pcom_uw_instruction: mov ah,0EDh xop_pcom_instruction: mov byte [value],al mov [immediate_size],-4 mov [mmx_size],16 mov [base_code],ah mov [xop_opcode_map],8 jmp avx_xop_common vpcmov_instruction: or [vex_required],2 mov [immediate_size],-2 mov byte [value],0 mov [mmx_size],0 mov [base_code],al mov [xop_opcode_map],8 jmp avx_xop_common xop_shift_instruction: mov [base_code],al or [vex_required],2 mov [xop_opcode_map],9 call take_avx_register cmp ah,16 jne invalid_operand mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' je xop_shift_reg_mem cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [vex_register],al lods byte [esi] cmp al,',' jne invalid_operand push esi xor cl,cl xchg cl,[operand_size] lods byte [esi] call get_size_operator pop esi xchg cl,[operand_size] cmp al,'[' je xop_shift_reg_reg_mem cmp al,10h jne xop_shift_reg_reg_imm call take_avx_register mov bl,al xchg bl,[vex_register] jmp nomem_instruction_ready xop_shift_reg_reg_mem: or [rex_prefix],8 lods byte [esi] call get_size_operator call get_address jmp instruction_ready xop_shift_reg_reg_imm: xor bl,bl xchg bl,[vex_register] cmp [base_code],94h jae invalid_operand add [base_code],30h mov [xop_opcode_map],8 dec esi jmp mmx_nomem_imm8 xop_shift_reg_mem: call get_address lods byte [esi] cmp al,',' jne invalid_operand push esi xor cl,cl xchg cl,[operand_size] lods byte [esi] call get_size_operator pop esi xchg cl,[operand_size] cmp al,10h jne xop_shift_reg_mem_imm call take_avx_register mov [vex_register],al jmp instruction_ready xop_shift_reg_mem_imm: cmp [base_code],94h jae invalid_operand add [base_code],30h mov [xop_opcode_map],8 dec esi jmp mmx_imm8 avx512_4vnniw_instruction: mov [opcode_prefix],0F2h mov [base_code],0Fh mov [extended_code],38h mov [supplemental_code],al mov [mmx_size],16 mov [broadcast_size],0 or [vex_required],8 call take_avx_register mov [postbyte_register],al call take_avx512_mask lods byte [esi] cmp al,',' jne invalid_operand call take_avx_register mov [vex_register],al cmp byte [esi],'+' jne reg4_ok inc esi cmp dword [esi],29030128h jne invalid_operand lods dword [esi] reg4_ok: cmp [operand_size],64 jne invalid_operand_size mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand call take_avx_rm jc invalid_operand mov [operand_size],64 jmp instruction_ready set_evex_mode: mov [evex_mode],al jmp instruction_assembled take_avx_register: lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] convert_avx_register: mov ah,al and al,1Fh and ah,0E0h sub ah,60h jb invalid_operand jz avx512_register_size sub ah,60h jb invalid_operand jnz avx_register_size_ok mov ah,16 jmp avx_register_size_ok avx512_register_size: mov ah,64 avx_register_size_ok: cmp al,8 jb match_register_size cmp [code_type],64 jne invalid_operand jmp match_register_size store_vex_instruction_code: test [rex_prefix],10h jnz invalid_operand test [vex_required],0F8h jnz store_evex_instruction_code test [vex_register],10000b jnz store_evex_instruction_code cmp [operand_size],64 je store_evex_instruction_code mov al,[base_code] cmp al,0Fh jne store_xop_instruction_code test [vex_required],2 jnz prepare_vex cmp [evex_mode],0 je prepare_vex cmp [displacement_compression],1 jne prepare_vex cmp edx,80h jb prepare_vex cmp edx,-80h jae prepare_vex mov al,bl or al,bh shr al,4 cmp al,2 je prepare_vex call compress_displacement cmp [displacement_compression],2 ja prepare_evex jb prepare_vex dec [displacement_compression] mov edx,[uncompressed_displacement] prepare_vex: mov ah,[extended_code] cmp ah,38h je store_vex_0f38_instruction_code cmp ah,3Ah je store_vex_0f3a_instruction_code test [rex_prefix],1011b jnz store_vex_0f_instruction_code mov [edi+2],ah mov byte [edi],0C5h mov al,[vex_register] not al shl al,3 mov ah,[rex_prefix] shl ah,5 and ah,80h xor al,ah call get_vex_lpp_bits mov [edi+1],al call check_vex add edi,3 ret get_vex_lpp_bits: cmp [operand_size],32 jne get_vex_pp_bits or al,100b get_vex_pp_bits: mov ah,[opcode_prefix] cmp ah,66h je vex_66 cmp ah,0F3h je vex_f3 cmp ah,0F2h je vex_f2 test ah,ah jnz disallowed_combination_of_registers ret vex_f2: or al,11b ret vex_f3: or al,10b ret vex_66: or al,1 ret store_vex_0f38_instruction_code: mov al,11100010b mov ah,[supplemental_code] jmp make_c4_vex store_vex_0f3a_instruction_code: mov al,11100011b mov ah,[supplemental_code] jmp make_c4_vex store_vex_0f_instruction_code: mov al,11100001b make_c4_vex: mov [edi+3],ah mov byte [edi],0C4h mov ah,[rex_prefix] shl ah,5 xor al,ah mov [edi+1],al call check_vex mov al,[vex_register] xor al,1111b shl al,3 mov ah,[rex_prefix] shl ah,4 and ah,80h or al,ah call get_vex_lpp_bits mov [edi+2],al add edi,4 ret check_vex: cmp [code_type],64 je vex_ok not al test al,11000000b jnz invalid_operand test [rex_prefix],40h jnz invalid_operand vex_ok: ret store_xop_instruction_code: mov [edi+3],al mov byte [edi],8Fh mov al,[xop_opcode_map] mov ah,[rex_prefix] test ah,40h jz xop_ok cmp [code_type],64 jne invalid_operand xop_ok: not ah shl ah,5 xor al,ah mov [edi+1],al mov al,[vex_register] xor al,1111b shl al,3 mov ah,[rex_prefix] shl ah,4 and ah,80h or al,ah call get_vex_lpp_bits mov [edi+2],al add edi,4 ret store_evex_instruction_code: test [vex_required],2 jnz invalid_operand cmp [base_code],0Fh jne invalid_operand cmp [displacement_compression],1 jne prepare_evex call compress_displacement prepare_evex: mov ah,[extended_code] cmp ah,38h je store_evex_0f38_instruction_code cmp ah,3Ah je store_evex_0f3a_instruction_code mov al,11110001b make_evex: mov [edi+4],ah mov byte [edi],62h mov ah,[rex_prefix] shl ah,5 xor al,ah mov ah,[vex_required] and ah,10h xor al,ah mov [edi+1],al call check_vex mov al,[vex_register] not al and al,1111b shl al,3 mov ah,[rex_prefix] shl ah,4 or ah,[rex_prefix] and ah,80h or al,ah or al,100b call get_vex_pp_bits mov [edi+2],al mov al,[vex_register] not al shr al,1 and al,1000b test [vex_required],80h jne evex_rounding mov ah,[operand_size] cmp ah,16 jbe evex_l_ok or al,ah jmp evex_l_ok evex_rounding: mov ah,[rounding_mode] shl ah,5 or al,ah evex_l_ok: test [vex_required],20h jz evex_zaaa_ok or al,[mask_register] evex_zaaa_ok: test [vex_required],40h jz evex_b_ok or al,10h evex_b_ok: mov [edi+3],al add edi,5 ret store_evex_0f38_instruction_code: mov al,11110010b mov ah,[supplemental_code] jmp make_evex store_evex_0f3a_instruction_code: mov al,11110011b mov ah,[supplemental_code] jmp make_evex compress_displacement: mov ebp,ecx mov [uncompressed_displacement],edx or edx,edx jz displacement_compressed xor ecx,ecx mov cl,[mmx_size] test cl,cl jnz calculate_displacement_scale mov cl,[operand_size] calculate_displacement_scale: bsf ecx,ecx jz displacement_compression_ok xor eax,eax shrd eax,edx,cl jnz displacement_not_compressed sar edx,cl cmp edx,80h jb displacement_compressed cmp edx,-80h jnb displacement_compressed shl edx,cl displacement_not_compressed: inc [displacement_compression] jmp displacement_compression_ok displacement_compressed: add [displacement_compression],2 displacement_compression_ok: mov ecx,ebp ret fasm/source/errors.inc0000644000175000017500000001035714533376740015623 0ustar privalovprivalov ; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. out_of_memory: push _out_of_memory jmp fatal_error stack_overflow: push _stack_overflow jmp fatal_error main_file_not_found: push _main_file_not_found jmp fatal_error write_failed: push _write_failed jmp fatal_error code_cannot_be_generated: push _code_cannot_be_generated jmp general_error format_limitations_exceeded: push _format_limitations_exceeded jmp general_error invalid_definition: push _invalid_definition general_error: cmp [symbols_file],0 je fatal_error call dump_preprocessed_source jmp fatal_error file_not_found: push _file_not_found jmp error_with_source error_reading_file: push _error_reading_file jmp error_with_source invalid_file_format: push _invalid_file_format jmp error_with_source invalid_macro_arguments: push _invalid_macro_arguments jmp error_with_source incomplete_macro: push _incomplete_macro jmp error_with_source unexpected_characters: push _unexpected_characters jmp error_with_source invalid_argument: push _invalid_argument jmp error_with_source illegal_instruction: push _illegal_instruction jmp error_with_source invalid_operand: push _invalid_operand jmp error_with_source invalid_operand_size: push _invalid_operand_size jmp error_with_source operand_size_not_specified: push _operand_size_not_specified jmp error_with_source operand_sizes_do_not_match: push _operand_sizes_do_not_match jmp error_with_source invalid_address_size: push _invalid_address_size jmp error_with_source address_sizes_do_not_agree: push _address_sizes_do_not_agree jmp error_with_source disallowed_combination_of_registers: push _disallowed_combination_of_registers jmp error_with_source long_immediate_not_encodable: push _long_immediate_not_encodable jmp error_with_source relative_jump_out_of_range: push _relative_jump_out_of_range jmp error_with_source invalid_expression: push _invalid_expression jmp error_with_source invalid_address: push _invalid_address jmp error_with_source invalid_value: push _invalid_value jmp error_with_source value_out_of_range: push _value_out_of_range jmp error_with_source undefined_symbol: mov edi,message mov esi,_undefined_symbol call copy_asciiz push message cmp [error_info],0 je error_with_source mov esi,[error_info] mov esi,[esi+24] or esi,esi jz error_with_source mov byte [edi-1],20h call write_quoted_symbol_name jmp error_with_source copy_asciiz: lods byte [esi] stos byte [edi] test al,al jnz copy_asciiz ret write_quoted_symbol_name: mov al,27h stosb movzx ecx,byte [esi-1] rep movs byte [edi],[esi] mov ax,27h stosw ret symbol_out_of_scope: mov edi,message mov esi,_symbol_out_of_scope_1 call copy_asciiz cmp [error_info],0 je finish_symbol_out_of_scope_message mov esi,[error_info] mov esi,[esi+24] or esi,esi jz finish_symbol_out_of_scope_message mov byte [edi-1],20h call write_quoted_symbol_name finish_symbol_out_of_scope_message: mov byte [edi-1],20h mov esi,_symbol_out_of_scope_2 call copy_asciiz push message jmp error_with_source invalid_use_of_symbol: push _invalid_use_of_symbol jmp error_with_source name_too_long: push _name_too_long jmp error_with_source invalid_name: push _invalid_name jmp error_with_source reserved_word_used_as_symbol: push _reserved_word_used_as_symbol jmp error_with_source symbol_already_defined: push _symbol_already_defined jmp error_with_source missing_end_quote: push _missing_end_quote jmp error_with_source missing_end_directive: push _missing_end_directive jmp error_with_source unexpected_instruction: push _unexpected_instruction jmp error_with_source extra_characters_on_line: push _extra_characters_on_line jmp error_with_source section_not_aligned_enough: push _section_not_aligned_enough jmp error_with_source setting_already_specified: push _setting_already_specified jmp error_with_source data_already_defined: push _data_already_defined jmp error_with_source too_many_repeats: push _too_many_repeats jmp error_with_source assertion_failed: push _assertion_failed jmp error_with_source invoked_error: push _invoked_error error_with_source: cmp [symbols_file],0 je assembler_error call dump_preprocessed_source call restore_preprocessed_source jmp assembler_error fasm/source/exprcalc.inc0000644000175000017500000011744014533376740016111 0ustar privalovprivalov ; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. calculate_expression: mov [current_offset],edi mov [value_undefined],0 cmp byte [esi],0 je get_string_value cmp byte [esi],'.' je convert_fp calculation_loop: mov eax,[tagged_blocks] sub eax,0Ch cmp eax,edi jbe out_of_memory lods byte [esi] cmp al,1 je get_byte_number cmp al,2 je get_word_number cmp al,4 je get_dword_number cmp al,8 je get_qword_number cmp al,0Fh je value_out_of_range cmp al,10h je get_register cmp al,11h je get_label cmp al,')' je expression_calculated cmp al,']' je expression_calculated cmp al,'!' je invalid_expression sub edi,14h mov ebx,edi sub ebx,14h cmp al,0F0h je calculate_rva cmp al,0F1h je calculate_plt cmp al,0D0h je calculate_not cmp al,0E0h je calculate_bsf cmp al,0E1h je calculate_bsr cmp al,083h je calculate_neg mov dx,[ebx+8] or dx,[edi+8] cmp al,80h je calculate_add cmp al,81h je calculate_sub mov ah,[ebx+12] or ah,[edi+12] jz absolute_values_calculation call recoverable_misuse absolute_values_calculation: cmp al,90h je calculate_mul cmp al,91h je calculate_div or dx,dx jnz invalid_expression cmp al,0A0h je calculate_mod cmp al,0B0h je calculate_and cmp al,0B1h je calculate_or cmp al,0B2h je calculate_xor cmp al,0C0h je calculate_shl cmp al,0C1h je calculate_shr jmp invalid_expression expression_calculated: sub edi,14h cmp [value_undefined],0 je expression_value_ok xor eax,eax mov [edi],eax mov [edi+4],eax mov [edi+12],eax expression_value_ok: ret get_byte_number: xor eax,eax lods byte [esi] stos dword [edi] xor al,al stos dword [edi] got_number: and word [edi-8+8],0 and word [edi-8+12],0 and dword [edi-8+16],0 add edi,0Ch jmp calculation_loop get_word_number: xor eax,eax lods word [esi] stos dword [edi] xor ax,ax stos dword [edi] jmp got_number get_dword_number: movs dword [edi],[esi] xor eax,eax stos dword [edi] jmp got_number get_qword_number: movs dword [edi],[esi] movs dword [edi],[esi] jmp got_number get_register: mov byte [edi+9],0 and word [edi+12],0 lods byte [esi] mov [edi+8],al mov byte [edi+10],1 xor eax,eax mov [edi+16],eax stos dword [edi] stos dword [edi] add edi,0Ch jmp calculation_loop get_label: xor eax,eax mov [edi+8],eax mov [edi+12],eax mov [edi+20],eax lods dword [esi] cmp eax,0Fh jb predefined_label je reserved_word_used_as_symbol mov ebx,eax mov ax,[current_pass] mov [ebx+18],ax mov cl,[ebx+9] shr cl,1 and cl,1 neg cl or byte [ebx+8],8 test byte [ebx+8],1 jz label_undefined cmp ax,[ebx+16] je unadjusted_label test byte [ebx+8],4 jnz label_out_of_scope test byte [ebx+9],1 jz unadjusted_label mov eax,[ebx] sub eax,dword [adjustment] stos dword [edi] mov eax,[ebx+4] sbb eax,dword [adjustment+4] stos dword [edi] sbb cl,[adjustment_sign] mov [edi-8+13],cl mov eax,dword [adjustment] or al,[adjustment_sign] or eax,dword [adjustment+4] jz got_label or [next_pass_needed],-1 jmp got_label unadjusted_label: mov eax,[ebx] stos dword [edi] mov eax,[ebx+4] stos dword [edi] mov [edi-8+13],cl got_label: test byte [ebx+9],4 jnz invalid_use_of_symbol call store_label_reference mov al,[ebx+11] mov [edi-8+12],al mov eax,[ebx+12] mov [edi-8+8],eax cmp al,ah jne labeled_registers_ok shr eax,16 add al,ah jo labeled_registers_ok xor ah,ah mov [edi-8+10],ax mov [edi-8+9],ah labeled_registers_ok: mov eax,[ebx+20] mov [edi-8+16],eax add edi,0Ch mov al,[ebx+10] or al,al jz calculation_loop test [operand_flags],1 jnz calculation_loop check_size: xchg [operand_size],al or al,al jz calculation_loop cmp al,[operand_size] jne operand_sizes_do_not_match jmp calculation_loop actual_file_offset_label: mov eax,[undefined_data_end] mov ebp,[addressing_space] test byte [ds:ebp+0Ah],1 jnz use_undefined_data_offset cmp eax,[current_offset] jne use_current_offset use_undefined_data_offset: mov eax,[undefined_data_start] jmp make_file_offset_label current_file_offset_label: mov ebp,[addressing_space] test byte [ds:ebp+0Ah],1 jz use_current_offset mov eax,[undefined_data_end] jmp make_file_offset_label use_current_offset: mov eax,[current_offset] make_file_offset_label: cmp [output_format],2 jae invalid_use_of_symbol sub eax,[code_start] jmp make_dword_label_value current_offset_label: mov eax,[current_offset] make_current_offset_label: xor edx,edx xor ch,ch mov ebp,[addressing_space] sub eax,[ds:ebp] sbb edx,[ds:ebp+4] sbb ch,[ds:ebp+8] jp current_offset_label_ok call recoverable_overflow current_offset_label_ok: stos dword [edi] mov eax,edx stos dword [edi] mov eax,[ds:ebp+10h] stos dword [edi] mov cl,[ds:ebp+9] mov [edi-12+12],cx mov eax,[ds:ebp+14h] mov [edi-12+16],eax add edi,8 jmp calculation_loop org_origin_label: mov eax,[addressing_space] mov eax,[eax+18h] jmp make_current_offset_label counter_label: mov eax,[counter] make_dword_label_value: stos dword [edi] xor eax,eax stos dword [edi] add edi,0Ch jmp calculation_loop timestamp_label: call make_timestamp make_qword_label_value: stos dword [edi] mov eax,edx stos dword [edi] add edi,0Ch jmp calculation_loop predefined_label: or eax,eax jz current_offset_label cmp eax,1 je counter_label cmp eax,2 je timestamp_label cmp eax,3 je org_origin_label cmp eax,4 je current_file_offset_label cmp eax,5 je actual_file_offset_label mov edx,invalid_value jmp error_undefined label_out_of_scope: mov edx,symbol_out_of_scope jmp error_undefined label_undefined: mov edx,undefined_symbol error_undefined: cmp [current_pass],1 ja undefined_value force_next_pass: or [next_pass_needed],-1 undefined_value: or [value_undefined],-1 and word [edi+12],0 xor eax,eax stos dword [edi] stos dword [edi] add edi,0Ch cmp [error_line],0 jne calculation_loop mov eax,[current_line] mov [error_line],eax mov [error],edx mov [error_info],ebx jmp calculation_loop calculate_add: xor ah,ah mov ah,[ebx+12] mov al,[edi+12] or al,al jz add_values or ah,ah jz add_relocatable add ah,al jnz invalid_add mov ecx,[edi+16] cmp ecx,[ebx+16] je add_values invalid_add: call recoverable_misuse jmp add_values add_relocatable: mov ah,al mov ecx,[edi+16] mov [ebx+16],ecx add_values: mov [ebx+12],ah mov eax,[edi] add [ebx],eax mov eax,[edi+4] adc [ebx+4],eax mov al,[edi+13] adc [ebx+13],al jp add_sign_ok call recoverable_overflow add_sign_ok: or dx,dx jz calculation_loop push esi mov esi,ebx mov cl,[edi+10] mov al,[edi+8] call add_register mov cl,[edi+11] mov al,[edi+9] call add_register pop esi jmp calculation_loop add_register: or al,al jz add_register_done add_register_start: cmp [esi+8],al jne add_in_second_slot add [esi+10],cl jo value_out_of_range jnz add_register_done mov byte [esi+8],0 ret add_in_second_slot: cmp [esi+9],al jne create_in_first_slot add [esi+11],cl jo value_out_of_range jnz add_register_done mov byte [esi+9],0 ret create_in_first_slot: cmp byte [esi+8],0 jne create_in_second_slot mov [esi+8],al mov [esi+10],cl ret create_in_second_slot: cmp byte [esi+9],0 jne invalid_expression mov [esi+9],al mov [esi+11],cl add_register_done: ret out_of_range: jmp calculation_loop calculate_sub: xor ah,ah mov ah,[ebx+12] mov al,[edi+12] or al,al jz sub_values or ah,ah jz negate_relocatable cmp al,ah jne invalid_sub xor ah,ah mov ecx,[edi+16] cmp ecx,[ebx+16] je sub_values invalid_sub: call recoverable_misuse jmp sub_values negate_relocatable: neg al mov ah,al mov ecx,[edi+16] mov [ebx+16],ecx sub_values: mov [ebx+12],ah mov eax,[edi] sub [ebx],eax mov eax,[edi+4] sbb [ebx+4],eax mov al,[edi+13] sbb [ebx+13],al jp sub_sign_ok cmp [error_line],0 jne sub_sign_ok call recoverable_overflow sub_sign_ok: or dx,dx jz calculation_loop push esi mov esi,ebx mov cl,[edi+10] mov al,[edi+8] call sub_register mov cl,[edi+11] mov al,[edi+9] call sub_register pop esi jmp calculation_loop sub_register: or al,al jz add_register_done neg cl jo value_out_of_range jmp add_register_start calculate_mul: or dx,dx jz mul_start cmp word [ebx+8],0 jne mul_start xor ecx,ecx swap_values: mov eax,[ebx+ecx] xchg eax,[edi+ecx] mov [ebx+ecx],eax add ecx,4 cmp ecx,16 jb swap_values mul_start: push esi edx mov esi,ebx xor bl,bl cmp byte [esi+13],0 je mul_first_sign_ok xor bl,-1 mov eax,[esi] mov edx,[esi+4] not eax not edx add eax,1 adc edx,0 mov [esi],eax mov [esi+4],edx or eax,edx jz mul_overflow mul_first_sign_ok: cmp byte [edi+13],0 je mul_second_sign_ok xor bl,-1 cmp byte [esi+8],0 je mul_first_register_sign_ok neg byte [esi+10] jo invalid_expression mul_first_register_sign_ok: cmp byte [esi+9],0 je mul_second_register_sign_ok neg byte [esi+11] jo invalid_expression mul_second_register_sign_ok: mov eax,[edi] mov edx,[edi+4] not eax not edx add eax,1 adc edx,0 mov [edi],eax mov [edi+4],edx or eax,edx jz mul_overflow mul_second_sign_ok: cmp dword [esi+4],0 jz mul_numbers cmp dword [edi+4],0 jz mul_numbers jnz mul_overflow mul_numbers: mov eax,[esi+4] mul dword [edi] or edx,edx jnz mul_overflow mov ecx,eax mov eax,[esi] mul dword [edi+4] or edx,edx jnz mul_overflow add ecx,eax jc mul_overflow mov eax,[esi] mul dword [edi] add edx,ecx jc mul_overflow mov [esi],eax mov [esi+4],edx or bl,bl jz mul_ok not eax not edx add eax,1 adc edx,0 mov [esi],eax mov [esi+4],edx or eax,edx jnz mul_ok not bl mul_ok: mov [esi+13],bl pop edx or dx,dx jz mul_calculated cmp word [edi+8],0 jne invalid_value cmp byte [esi+8],0 je mul_first_register_ok call get_byte_scale imul byte [esi+10] mov dl,ah cbw cmp ah,dl jne value_out_of_range mov [esi+10],al or al,al jnz mul_first_register_ok mov [esi+8],al mul_first_register_ok: cmp byte [esi+9],0 je mul_calculated call get_byte_scale imul byte [esi+11] mov dl,ah cbw cmp ah,dl jne value_out_of_range mov [esi+11],al or al,al jnz mul_calculated mov [esi+9],al mul_calculated: pop esi jmp calculation_loop mul_overflow: pop edx esi call recoverable_overflow jmp calculation_loop get_byte_scale: mov al,[edi] cbw cwde cdq cmp edx,[edi+4] jne value_out_of_range cmp eax,[edi] jne value_out_of_range ret calculate_div: push esi edx mov esi,ebx call div_64 pop edx or dx,dx jz div_calculated cmp byte [esi+8],0 je div_first_register_ok call get_byte_scale or al,al jz value_out_of_range mov al,[esi+10] cbw idiv byte [edi] or ah,ah jnz invalid_use_of_symbol mov [esi+10],al div_first_register_ok: cmp byte [esi+9],0 je div_calculated call get_byte_scale or al,al jz value_out_of_range mov al,[esi+11] cbw idiv byte [edi] or ah,ah jnz invalid_use_of_symbol mov [esi+11],al div_calculated: pop esi jmp calculation_loop calculate_mod: push esi mov esi,ebx call div_64 mov [esi],eax mov [esi+4],edx mov [esi+13],bh pop esi jmp calculation_loop calculate_and: mov eax,[edi] mov edx,[edi+4] mov cl,[edi+13] and [ebx],eax and [ebx+4],edx and [ebx+13],cl jmp calculation_loop calculate_or: mov eax,[edi] mov edx,[edi+4] mov cl,[edi+13] or [ebx],eax or [ebx+4],edx or [ebx+13],cl jmp calculation_loop calculate_xor: mov eax,[edi] mov edx,[edi+4] mov cl,[edi+13] xor [ebx],eax xor [ebx+4],edx xor [ebx+13],cl jmp calculation_loop shr_negative: mov byte [edi+13],0 not dword [edi] not dword [edi+4] add dword [edi],1 adc dword [edi+4],0 jc shl_over calculate_shl: cmp byte [edi+13],0 jne shl_negative mov edx,[ebx+4] mov eax,[ebx] cmp dword [edi+4],0 jne shl_over movsx ecx,byte [ebx+13] xchg ecx,[edi] cmp ecx,64 je shl_max ja shl_over cmp ecx,32 jae shl_high shld [edi],edx,cl shld edx,eax,cl shl eax,cl mov [ebx],eax mov [ebx+4],edx jmp shl_done shl_over: cmp byte [ebx+13],0 jne shl_overflow shl_max: movsx ecx,byte [ebx+13] cmp eax,ecx jne shl_overflow cmp edx,ecx jne shl_overflow xor eax,eax mov [ebx],eax mov [ebx+4],eax jmp calculation_loop shl_high: sub cl,32 shld [edi],edx,cl shld edx,eax,cl shl eax,cl mov [ebx+4],eax and dword [ebx],0 cmp edx,[edi] jne shl_overflow shl_done: movsx eax,byte [ebx+13] cmp eax,[edi] je calculation_loop shl_overflow: call recoverable_overflow jmp calculation_loop shl_negative: mov byte [edi+13],0 not dword [edi] not dword [edi+4] add dword [edi],1 adc dword [edi+4],0 jnc calculate_shr dec dword [edi+4] calculate_shr: cmp byte [edi+13],0 jne shr_negative mov edx,[ebx+4] mov eax,[ebx] cmp dword [edi+4],0 jne shr_over mov ecx,[edi] cmp ecx,64 jae shr_over push esi movsx esi,byte [ebx+13] cmp ecx,32 jae shr_high shrd eax,edx,cl shrd edx,esi,cl mov [ebx],eax mov [ebx+4],edx pop esi jmp calculation_loop shr_high: sub cl,32 shrd edx,esi,cl mov [ebx],edx mov [ebx+4],esi pop esi jmp calculation_loop shr_over: movsx eax,byte [ebx+13] mov dword [ebx],eax mov dword [ebx+4],eax jmp calculation_loop calculate_not: cmp word [edi+8],0 jne invalid_expression cmp byte [edi+12],0 je not_ok call recoverable_misuse not_ok: not dword [edi] not dword [edi+4] not byte [edi+13] add edi,14h jmp calculation_loop calculate_bsf: cmp word [edi+8],0 jne invalid_expression cmp byte [edi+12],0 je bsf_ok call recoverable_misuse bsf_ok: xor ecx,ecx bsf eax,[edi] jnz finish_bs mov ecx,32 bsf eax,[edi+4] jnz finish_bs cmp byte [edi+13],0 jne finish_bs bs_overflow: call recoverable_overflow add edi,14h jmp calculation_loop calculate_bsr: cmp word [edi+8],0 jne invalid_expression cmp byte [edi+12],0 je bsr_ok call recoverable_misuse bsr_ok: cmp byte [edi+13],0 jne bs_overflow mov ecx,32 bsr eax,[edi+4] jnz finish_bs xor ecx,ecx bsr eax,[edi] jz bs_overflow finish_bs: add eax,ecx xor edx,edx mov [edi],eax mov [edi+4],edx mov [edi+13],dl add edi,14h jmp calculation_loop calculate_neg: cmp byte [edi+8],0 je neg_first_register_ok neg byte [edi+10] jo invalid_expression neg_first_register_ok: cmp byte [edi+9],0 je neg_second_register_ok neg byte [edi+11] jo invalid_expression neg_second_register_ok: neg byte [edi+12] xor eax,eax xor edx,edx xor cl,cl xchg eax,[edi] xchg edx,[edi+4] xchg cl,[edi+13] sub [edi],eax sbb [edi+4],edx sbb [edi+13],cl jp neg_sign_ok call recoverable_overflow neg_sign_ok: add edi,14h jmp calculation_loop calculate_rva: cmp word [edi+8],0 jne invalid_expression mov al,[output_format] cmp al,5 je calculate_gotoff cmp al,4 je calculate_coff_rva cmp al,3 jne invalid_expression test [format_flags],8 jnz pe64_rva mov al,2 bt [resolver_flags],0 jc rva_type_ok xor al,al rva_type_ok: cmp byte [edi+12],al je rva_ok call recoverable_misuse rva_ok: mov byte [edi+12],0 mov eax,[code_start] mov eax,[eax+34h] xor edx,edx finish_rva: sub [edi],eax sbb [edi+4],edx sbb byte [edi+13],0 jp rva_finished call recoverable_overflow rva_finished: add edi,14h jmp calculation_loop pe64_rva: mov al,4 bt [resolver_flags],0 jc pe64_rva_type_ok xor al,al pe64_rva_type_ok: cmp byte [edi+12],al je pe64_rva_ok call recoverable_misuse pe64_rva_ok: mov byte [edi+12],0 mov eax,[code_start] mov edx,[eax+34h] mov eax,[eax+30h] jmp finish_rva calculate_gotoff: test [format_flags],1 jnz calculate_elf_dyn_rva test [format_flags],8 jnz invalid_expression calculate_coff_rva: mov dl,5 cmp byte [edi+12],2 je change_value_type incorrect_change_of_value_type: call recoverable_misuse change_value_type: mov byte [edi+12],dl add edi,14h jmp calculation_loop calculate_elf_dyn_rva: xor dl,dl test byte [edi+12],1 jnz incorrect_change_of_value_type jmp change_value_type calculate_plt: cmp word [edi+8],0 jne invalid_expression cmp [output_format],5 jne invalid_expression test [format_flags],1 jnz invalid_expression mov dl,6 mov dh,2 test [format_flags],8 jz check_value_for_plt mov dh,4 check_value_for_plt: mov eax,[edi] or eax,[edi+4] jnz incorrect_change_of_value_type cmp byte [edi+12],dh jne incorrect_change_of_value_type mov eax,[edi+16] cmp byte [eax],80h jne incorrect_change_of_value_type jmp change_value_type div_64: xor ebx,ebx cmp dword [edi],0 jne divider_ok cmp dword [edi+4],0 jne divider_ok cmp [next_pass_needed],0 je value_out_of_range jmp div_done divider_ok: cmp byte [esi+13],0 je div_first_sign_ok mov eax,[esi] mov edx,[esi+4] not eax not edx add eax,1 adc edx,0 mov [esi],eax mov [esi+4],edx or eax,edx jz value_out_of_range xor bx,-1 div_first_sign_ok: cmp byte [edi+13],0 je div_second_sign_ok mov eax,[edi] mov edx,[edi+4] not eax not edx add eax,1 adc edx,0 mov [edi],eax mov [edi+4],edx or eax,edx jz value_out_of_range xor bl,-1 div_second_sign_ok: cmp dword [edi+4],0 jne div_high mov ecx,[edi] mov eax,[esi+4] xor edx,edx div ecx mov [esi+4],eax mov eax,[esi] div ecx mov [esi],eax mov eax,edx xor edx,edx jmp div_done div_high: push ebx mov eax,[esi+4] xor edx,edx div dword [edi+4] mov ebx,[esi] mov [esi],eax and dword [esi+4],0 mov ecx,edx mul dword [edi] div_high_loop: cmp ecx,edx ja div_high_done jb div_high_large_correction cmp ebx,eax jae div_high_done div_high_correction: dec dword [esi] sub eax,[edi] sbb edx,[edi+4] jnc div_high_loop div_high_done: sub ebx,eax sbb ecx,edx mov edx,ecx mov eax,ebx pop ebx jmp div_done div_high_large_correction: push eax edx mov eax,edx sub eax,ecx xor edx,edx div dword [edi+4] shr eax,1 jz div_high_small_correction sub [esi],eax push eax mul dword [edi+4] sub dword [esp+4],eax pop eax mul dword [edi] sub dword [esp+4],eax sbb dword [esp],edx pop edx eax jmp div_high_loop div_high_small_correction: pop edx eax jmp div_high_correction div_done: or bh,bh jz remainder_ok not eax not edx add eax,1 adc edx,0 mov ecx,eax or ecx,edx jnz remainder_ok not bh remainder_ok: or bl,bl jz div_ok not dword [esi] not dword [esi+4] add dword [esi],1 adc dword [esi+4],0 mov ecx,[esi] or ecx,[esi+4] jnz div_ok not bl div_ok: mov [esi+13],bl ret store_label_reference: cmp [symbols_file],0 je label_reference_ok cmp [next_pass_needed],0 jne label_reference_ok mov eax,[tagged_blocks] mov dword [eax-4],2 mov dword [eax-8],4 sub eax,8+4 cmp eax,edi jbe out_of_memory mov [tagged_blocks],eax mov [eax],ebx label_reference_ok: ret convert_fp: inc esi and word [edi+8],0 and word [edi+12],0 mov al,[value_size] cmp al,2 je convert_fp_word cmp al,4 je convert_fp_dword test al,not 8 jz convert_fp_qword call recoverable_misuse convert_fp_qword: xor eax,eax xor edx,edx cmp word [esi+8],8000h je fp_qword_store mov bx,[esi+8] mov eax,[esi] mov edx,[esi+4] add eax,eax adc edx,edx mov ecx,edx shr edx,12 shrd eax,ecx,12 jnc fp_qword_ok add eax,1 adc edx,0 bt edx,20 jnc fp_qword_ok and edx,1 shl 20 - 1 inc bx shr edx,1 rcr eax,1 fp_qword_ok: add bx,3FFh cmp bx,7FFh jge value_out_of_range cmp bx,0 jg fp_qword_exp_ok or edx,1 shl 20 mov cx,bx neg cx inc cx cmp cx,52+1 ja value_out_of_range cmp cx,32 jb fp_qword_small_shift sub cx,32 mov eax,edx xor edx,edx shr eax,cl jmp fp_qword_shift_done fp_qword_small_shift: mov ebx,edx shr edx,cl shrd eax,ebx,cl fp_qword_shift_done: mov bx,0 jnc fp_qword_exp_ok add eax,1 adc edx,0 test edx,1 shl 20 jz fp_qword_exp_ok and edx,1 shl 20 - 1 inc bx fp_qword_exp_ok: shl ebx,20 or edx,ebx jnz fp_qword_store or eax,eax jz value_out_of_range fp_qword_store: mov bl,[esi+11] shl ebx,31 or edx,ebx mov [edi],eax mov [edi+4],edx add esi,13 ret convert_fp_word: xor eax,eax cmp word [esi+8],8000h je fp_word_store mov bx,[esi+8] mov ax,[esi+6] shl ax,1 shr ax,6 jnc fp_word_ok inc ax bt ax,10 jnc fp_word_ok and ax,1 shl 10 - 1 inc bx shr ax,1 fp_word_ok: add bx,0Fh cmp bx,01Fh jge value_out_of_range cmp bx,0 jg fp_word_exp_ok or ax,1 shl 10 mov cx,bx neg cx inc cx cmp cx,10+1 ja value_out_of_range xor bx,bx shr ax,cl jnc fp_word_exp_ok inc ax test ax,1 shl 10 jz fp_word_exp_ok and ax,1 shl 10 - 1 inc bx fp_word_exp_ok: shl bx,10 or ax,bx jz value_out_of_range fp_word_store: mov bl,[esi+11] shl bx,15 or ax,bx mov [edi],eax xor eax,eax mov [edi+4],eax add esi,13 ret convert_fp_dword: xor eax,eax cmp word [esi+8],8000h je fp_dword_store mov bx,[esi+8] mov eax,[esi+4] shl eax,1 shr eax,9 jnc fp_dword_ok inc eax bt eax,23 jnc fp_dword_ok and eax,1 shl 23 - 1 inc bx shr eax,1 fp_dword_ok: add bx,7Fh cmp bx,0FFh jge value_out_of_range cmp bx,0 jg fp_dword_exp_ok or eax,1 shl 23 mov cx,bx neg cx inc cx cmp cx,23+1 ja value_out_of_range xor bx,bx shr eax,cl jnc fp_dword_exp_ok inc eax test eax,1 shl 23 jz fp_dword_exp_ok and eax,1 shl 23 - 1 inc bx fp_dword_exp_ok: shl ebx,23 or eax,ebx jz value_out_of_range fp_dword_store: mov bl,[esi+11] shl ebx,31 or eax,ebx mov [edi],eax xor eax,eax mov [edi+4],eax add esi,13 ret get_string_value: inc esi lods dword [esi] mov ecx,eax cmp ecx,8 ja value_out_of_range mov edx,edi xor eax,eax stos dword [edi] stos dword [edi] mov edi,edx rep movs byte [edi],[esi] mov edi,edx inc esi and word [edi+8],0 and word [edi+12],0 ret get_byte_value: mov [value_size],1 or [operand_flags],1 call calculate_value or al,al jz check_byte_value call recoverable_misuse check_byte_value: mov eax,[edi] mov edx,[edi+4] cmp byte [edi+13],0 je byte_positive cmp edx,-1 jne range_exceeded cmp eax,-100h jb range_exceeded ret byte_positive: test edx,edx jnz range_exceeded cmp eax,100h jae range_exceeded return_byte_value: ret range_exceeded: xor eax,eax xor edx,edx recoverable_overflow: cmp [error_line],0 jne ignore_overflow push [current_line] pop [error_line] mov [error],value_out_of_range or [value_undefined],-1 ignore_overflow: ret recoverable_misuse: cmp [error_line],0 jne ignore_misuse push [current_line] pop [error_line] mov [error],invalid_use_of_symbol ignore_misuse: ret get_word_value: mov [value_size],2 or [operand_flags],1 call calculate_value cmp al,2 jb check_word_value call recoverable_misuse check_word_value: mov eax,[edi] mov edx,[edi+4] cmp byte [edi+13],0 je word_positive cmp edx,-1 jne range_exceeded cmp eax,-10000h jb range_exceeded ret word_positive: test edx,edx jnz range_exceeded cmp eax,10000h jae range_exceeded ret get_dword_value: mov [value_size],4 or [operand_flags],1 call calculate_value cmp al,4 jne check_dword_value mov [value_type],2 mov eax,[edi] cdq cmp edx,[edi+4] jne range_exceeded mov ecx,edx sar ecx,31 cmp cl,[value_sign] jne range_exceeded ret check_dword_value: mov eax,[edi] mov edx,[edi+4] cmp byte [edi+13],0 je dword_positive cmp edx,-1 jne range_exceeded ret dword_positive: test edx,edx jne range_exceeded ret get_pword_value: mov [value_size],6 or [operand_flags],1 call calculate_value cmp al,4 jne check_pword_value call recoverable_misuse check_pword_value: mov eax,[edi] mov edx,[edi+4] cmp byte [edi+13],0 je pword_positive cmp edx,-10000h jb range_exceeded ret pword_positive: cmp edx,10000h jae range_exceeded ret get_qword_value: mov [value_size],8 or [operand_flags],1 call calculate_value check_qword_value: mov eax,[edi] mov edx,[edi+4] ret get_count_value: mov [value_size],8 or [operand_flags],1 call calculate_expression cmp word [edi+8],0 jne invalid_value mov [value_sign],0 mov al,[edi+12] or al,al jz check_count_value call recoverable_misuse check_count_value: cmp byte [edi+13],0 jne invalid_count_value mov eax,[edi] mov edx,[edi+4] or edx,edx jnz invalid_count_value ret invalid_count_value: cmp [error_line],0 jne zero_count mov eax,[current_line] mov [error_line],eax mov [error],invalid_value zero_count: xor eax,eax ret get_value: mov [operand_size],0 lods byte [esi] call get_size_operator cmp al,'(' jne invalid_value mov al,[operand_size] cmp al,1 je value_byte cmp al,2 je value_word cmp al,4 je value_dword cmp al,6 je value_pword cmp al,8 je value_qword or al,al jnz invalid_value mov [value_size],al call calculate_value mov eax,[edi] mov edx,[edi+4] ret calculate_value: call calculate_expression cmp word [edi+8],0 jne invalid_value mov eax,[edi+16] mov [symbol_identifier],eax mov al,[edi+13] mov [value_sign],al mov al,[edi+12] mov [value_type],al ret value_qword: call get_qword_value truncated_value: mov [value_sign],0 ret value_pword: call get_pword_value movzx edx,dx jmp truncated_value value_dword: call get_dword_value xor edx,edx jmp truncated_value value_word: call get_word_value xor edx,edx movzx eax,ax jmp truncated_value value_byte: call get_byte_value xor edx,edx movzx eax,al jmp truncated_value get_address_word_value: mov [address_size],2 mov [value_size],2 mov [free_address_range],0 jmp calculate_address get_address_dword_value: mov [address_size],4 mov [value_size],4 mov [free_address_range],0 jmp calculate_address get_address_qword_value: mov [address_size],8 mov [value_size],8 mov [free_address_range],0 jmp calculate_address get_address_value: mov [address_size],0 mov [value_size],8 or [free_address_range],-1 calculate_address: cmp byte [esi],'.' je invalid_address call calculate_expression mov eax,[edi+16] mov [address_symbol],eax mov al,[edi+13] mov [address_sign],al mov al,[edi+12] mov [value_type],al cmp al,0 je address_size_ok jg get_address_symbol_size neg al get_address_symbol_size: cmp al,6 je special_address_type_32bit cmp al,5 je special_address_type_32bit ja invalid_address_type test al,1 jnz invalid_address_type shl al,5 jmp address_symbol_ok invalid_address_type: call recoverable_misuse special_address_type_32bit: mov al,40h address_symbol_ok: mov ah,[address_size] or [address_size],al shr al,4 or ah,ah jz address_size_ok cmp al,ah je address_size_ok cmp ax,0408h je address_sizes_mixed cmp ax,0804h jne address_sizes_do_not_agree address_sizes_mixed: cmp [value_type],4 jne address_sizes_mixed_type_ok mov [value_type],2 address_sizes_mixed_type_ok: mov eax,[edi] cdq cmp edx,[edi+4] je address_size_ok cmp [error_line],0 jne address_size_ok call recoverable_overflow address_size_ok: xor ebx,ebx xor ecx,ecx mov cl,[value_type] shl ecx,16 mov ch,[address_size] cmp word [edi+8],0 je check_immediate_address mov al,[edi+8] mov dl,[edi+10] call get_address_register mov al,[edi+9] mov dl,[edi+11] call get_address_register mov ax,bx shr ah,4 shr al,4 or bh,bh jz check_address_registers or bl,bl jz check_address_registers cmp al,ah jne check_vsib check_address_registers: or al,ah cmp al,0Ch jae check_vsib cmp al,6 je check_vsib cmp al,7 je check_vsib mov ah,[address_size] and ah,0Fh jz address_registers_sizes_ok cmp al,ah jne invalid_address address_registers_sizes_ok: cmp al,4 je sib_allowed cmp al,8 je sib_allowed cmp al,9 je check_ip_relative_address cmp cl,1 ja invalid_address cmp [free_address_range],0 jne check_qword_value jmp check_word_value address_sizes_do_not_match: cmp al,0Fh jne invalid_address mov al,bh and al,0Fh cmp al,ah jne invalid_address check_ip_relative_address: or bl,bl jnz invalid_address cmp bh,98h je check_rip_relative_address cmp bh,94h jne invalid_address cmp [free_address_range],0 je check_dword_value mov eax,[edi] mov edx,[edi+4] ret check_rip_relative_address: mov eax,[edi] cdq cmp edx,[edi+4] jne range_exceeded cmp dl,[edi+13] jne range_exceeded ret get_address_register: or al,al jz address_register_ok cmp dl,1 jne scaled_register or bh,bh jnz scaled_register mov bh,al address_register_ok: ret scaled_register: or bl,bl jnz invalid_address mov bl,al mov cl,dl jmp address_register_ok sib_allowed: or bh,bh jnz check_index_with_base cmp cl,3 je special_index_scale cmp cl,5 je special_index_scale cmp cl,9 je special_index_scale cmp cl,2 jne check_index_scale cmp bl,45h jne special_index_scale cmp [code_type],64 je special_index_scale cmp [segment_register],4 jne special_index_scale cmp [value_type],0 jne check_index_scale mov al,[edi] cbw cwde cmp eax,[edi] jne check_index_scale cdq cmp edx,[edi+4] jne check_immediate_address special_index_scale: mov bh,bl dec cl check_immediate_address: cmp [free_address_range],0 jne check_qword_value mov al,[address_size] and al,0Fh cmp al,2 je check_word_value cmp al,4 je check_dword_value cmp al,8 je check_qword_value or al,al jnz invalid_value cmp [code_type],64 jne check_dword_value jmp check_qword_value check_index_with_base: cmp cl,1 jne check_index_scale cmp bl,44h je swap_base_with_index cmp bl,84h je swap_base_with_index cmp [code_type],64 je check_for_rbp_base cmp bl,45h jne check_for_ebp_base cmp [segment_register],3 je swap_base_with_index jmp check_immediate_address check_for_ebp_base: cmp bh,45h jne check_immediate_address cmp [segment_register],4 jne check_immediate_address swap_base_with_index: xchg bl,bh jmp check_immediate_address check_for_rbp_base: cmp bh,45h je swap_base_with_index cmp bh,85h je swap_base_with_index jmp check_immediate_address check_index_scale: test cl,not 1111b jnz invalid_address mov al,cl dec al and al,cl jz check_immediate_address jmp invalid_address check_vsib: xor ah,ah check_vsib_base: test bh,bh jz check_vsib_index mov al,bh shr al,4 cmp al,4 je check_vsib_base_size cmp [code_type],64 jne swap_vsib_registers cmp al,8 jne swap_vsib_registers check_vsib_base_size: mov ah,[address_size] and ah,0Fh jz check_vsib_index cmp al,ah jne invalid_address check_vsib_index: mov al,bl and al,0E0h cmp al,0C0h jae check_index_scale cmp al,60h je check_index_scale jmp invalid_address swap_vsib_registers: xor ah,-1 jz invalid_address cmp cl,1 ja invalid_address xchg bl,bh mov cl,1 jmp check_vsib_base calculate_relative_offset: cmp [value_undefined],0 jne relative_offset_ok test bh,bh setne ch cmp bx,[ds:ebp+10h] je origin_registers_ok xchg bh,bl xchg ch,cl cmp bx,[ds:ebp+10h] jne invalid_value origin_registers_ok: cmp cx,[ds:ebp+10h+2] jne invalid_value mov bl,[address_sign] add eax,[ds:ebp] adc edx,[ds:ebp+4] adc bl,[ds:ebp+8] sub eax,edi sbb edx,0 sbb bl,0 mov [value_sign],bl mov bl,[value_type] mov ecx,[address_symbol] mov [symbol_identifier],ecx test bl,1 jnz relative_offset_unallowed cmp bl,6 je plt_relative_offset mov bh,[ds:ebp+9] cmp bl,bh je set_relative_offset_type cmp bx,0402h je set_relative_offset_type relative_offset_unallowed: call recoverable_misuse set_relative_offset_type: cmp [value_type],0 je relative_offset_ok mov [value_type],0 cmp ecx,[ds:ebp+14h] je relative_offset_ok mov [value_type],3 relative_offset_ok: ret plt_relative_offset: mov [value_type],7 cmp byte [ds:ebp+9],2 je relative_offset_ok cmp byte [ds:ebp+9],4 jne recoverable_misuse ret calculate_logical_expression: xor al,al calculate_embedded_logical_expression: mov [logical_value_wrapping],al call get_logical_value logical_loop: cmp byte [esi],'|' je logical_or cmp byte [esi],'&' je logical_and ret logical_or: inc esi or al,al jnz logical_value_already_determined push eax call get_logical_value pop ebx or al,bl jmp logical_loop logical_and: inc esi or al,al jz logical_value_already_determined push eax call get_logical_value pop ebx and al,bl jmp logical_loop logical_value_already_determined: push eax call skip_logical_value jc invalid_expression pop eax jmp logical_loop get_value_for_comparison: mov [value_size],8 or [operand_flags],1 lods byte [esi] call calculate_expression cmp byte [edi+8],0 jne first_register_size_ok mov byte [edi+10],0 first_register_size_ok: cmp byte [edi+9],0 jne second_register_size_ok mov byte [edi+11],0 second_register_size_ok: mov eax,[edi+16] mov [symbol_identifier],eax mov al,[edi+13] mov [value_sign],al mov bl,[edi+12] mov eax,[edi] mov edx,[edi+4] mov ecx,[edi+8] ret get_logical_value: xor al,al check_for_negation: cmp byte [esi],'~' jne negation_ok inc esi xor al,-1 jmp check_for_negation negation_ok: push eax mov al,[esi] cmp al,91h je logical_expression cmp al,0FFh je invalid_expression cmp al,88h je check_for_defined cmp al,8Ah je check_for_earlier_defined cmp al,89h je check_for_used cmp al,'0' je given_false cmp al,'1' je given_true cmp al,'(' jne invalid_value call get_value_for_comparison mov bh,[value_sign] push eax edx push [symbol_identifier] push ebx ecx mov al,[esi] or al,al jz logical_number cmp al,0Fh je logical_number cmp al,92h je logical_number cmp al,'&' je logical_number cmp al,'|' je logical_number inc esi mov [compare_type],al cmp byte [esi],'(' jne invalid_value call get_value_for_comparison cmp bl,[esp+4] jne values_not_relative or bl,bl jz check_values_registers mov ebx,[symbol_identifier] cmp ebx,[esp+8] jne values_not_relative check_values_registers: cmp ecx,[esp] je values_relative ror ecx,16 xchg ch,cl ror ecx,16 xchg ch,cl cmp ecx,[esp] je values_relative values_not_relative: cmp [compare_type],0F8h jne invalid_comparison add esp,12+8 jmp return_false invalid_comparison: call recoverable_misuse values_relative: pop ebx shl ebx,16 mov bx,[esp] add esp,8 pop ecx ebp cmp [compare_type],'=' je check_equal cmp [compare_type],0F1h je check_not_equal cmp [compare_type],0F8h je return_true test ebx,0FFFF0000h jz check_less_or_greater call recoverable_misuse check_less_or_greater: cmp [compare_type],'>' je check_greater cmp [compare_type],'<' je check_less cmp [compare_type],0F2h je check_not_less cmp [compare_type],0F3h je check_not_greater jmp invalid_expression check_equal: cmp bh,[value_sign] jne return_false cmp eax,ebp jne return_false cmp edx,ecx jne return_false jmp return_true check_greater: cmp bh,[value_sign] jg return_true jl return_false cmp edx,ecx jb return_true ja return_false cmp eax,ebp jb return_true jae return_false check_less: cmp bh,[value_sign] jg return_false jl return_true cmp edx,ecx jb return_false ja return_true cmp eax,ebp jbe return_false ja return_true check_not_less: cmp bh,[value_sign] jg return_true jl return_false cmp edx,ecx jb return_true ja return_false cmp eax,ebp jbe return_true ja return_false check_not_greater: cmp bh,[value_sign] jg return_false jl return_true cmp edx,ecx jb return_false ja return_true cmp eax,ebp jb return_false jae return_true check_not_equal: cmp bh,[value_sign] jne return_true cmp eax,ebp jne return_true cmp edx,ecx jne return_true jmp return_false logical_number: pop ecx ebx eax edx eax or bl,bl jnz invalid_logical_number or cx,cx jz logical_number_ok invalid_logical_number: call recoverable_misuse logical_number_ok: test bh,bh jnz return_true or eax,edx jnz return_true jmp return_false check_for_earlier_defined: or bh,-1 jmp check_if_expression_defined check_for_defined: xor bh,bh check_if_expression_defined: or bl,-1 lods word [esi] cmp ah,'(' jne invalid_expression check_expression: lods byte [esi] or al,al jz defined_string cmp al,'.' je defined_fp_value cmp al,')' je expression_checked cmp al,'!' je invalid_expression cmp al,0Fh je check_expression cmp al,10h je defined_register cmp al,11h je check_if_symbol_defined cmp al,80h jae check_expression movzx eax,al add esi,eax jmp check_expression defined_register: inc esi jmp check_expression defined_fp_value: add esi,12+1 jmp expression_checked defined_string: lods dword [esi] add esi,eax inc esi jmp expression_checked check_if_symbol_defined: lods dword [esi] cmp eax,-1 je invalid_expression cmp eax,0Fh jb check_expression je reserved_word_used_as_symbol test bh,bh jnz no_prediction test byte [eax+8],4 jnz no_prediction test byte [eax+8],1 jz symbol_predicted_undefined mov cx,[current_pass] sub cx,[eax+16] jz check_expression cmp cx,1 ja symbol_predicted_undefined or byte [eax+8],40h+80h jmp check_expression no_prediction: test byte [eax+8],1 jz symbol_undefined mov cx,[current_pass] sub cx,[eax+16] jz check_expression jmp symbol_undefined symbol_predicted_undefined: or byte [eax+8],40h and byte [eax+8],not 80h symbol_undefined: xor bl,bl jmp check_expression expression_checked: mov al,bl jmp logical_value_ok check_for_used: lods word [esi] cmp ah,2 jne invalid_expression lods dword [esi] cmp eax,0Fh jb invalid_use_of_symbol je reserved_word_used_as_symbol inc esi test byte [eax+8],8 jz not_used mov cx,[current_pass] sub cx,[eax+18] jz return_true cmp cx,1 ja not_used or byte [eax+8],10h+20h jmp return_true not_used: or byte [eax+8],10h and byte [eax+8],not 20h jmp return_false given_false: inc esi return_false: xor al,al jmp logical_value_ok given_true: inc esi return_true: or al,-1 jmp logical_value_ok logical_expression: lods byte [esi] mov dl,[logical_value_wrapping] push edx call calculate_embedded_logical_expression pop edx mov [logical_value_wrapping],dl push eax lods byte [esi] cmp al,92h jne invalid_expression pop eax logical_value_ok: pop ebx xor al,bl ret skip_symbol: lods byte [esi] or al,al jz nothing_to_skip cmp al,0Fh je nothing_to_skip cmp al,1 je skip_instruction cmp al,2 je skip_label cmp al,3 je skip_label cmp al,4 je skip_special_label cmp al,20h jb skip_assembler_symbol cmp al,'(' je skip_expression cmp al,'[' je skip_address skip_done: clc ret skip_label: add esi,2 skip_instruction: add esi,2 skip_assembler_symbol: inc esi jmp skip_done skip_special_label: add esi,4 jmp skip_done skip_address: mov al,[esi] and al,11110000b cmp al,60h jb skip_expression cmp al,70h ja skip_expression inc esi jmp skip_address skip_expression: lods byte [esi] or al,al jz skip_string cmp al,'.' je skip_fp_value cmp al,')' je skip_done cmp al,']' je skip_done cmp al,'!' je skip_expression cmp al,0Fh je skip_expression cmp al,10h je skip_register cmp al,11h je skip_label_value cmp al,80h jae skip_expression movzx eax,al add esi,eax jmp skip_expression skip_label_value: add esi,3 skip_register: inc esi jmp skip_expression skip_fp_value: add esi,12 jmp skip_done skip_string: lods dword [esi] add esi,eax inc esi jmp skip_done nothing_to_skip: dec esi stc ret expand_path: lods byte [esi] cmp al,'%' je environment_variable stos byte [edi] or al,al jnz expand_path cmp edi,[memory_end] ja out_of_memory ret environment_variable: mov ebx,esi find_variable_end: lods byte [esi] or al,al jz not_environment_variable cmp al,'%' jne find_variable_end mov byte [esi-1],0 push esi mov esi,ebx call get_environment_variable pop esi mov byte [esi-1],'%' jmp expand_path not_environment_variable: mov al,'%' stos byte [edi] mov esi,ebx jmp expand_path get_include_directory: lods byte [esi] cmp al,';' je include_directory_ok stos byte [edi] or al,al jnz get_include_directory dec esi dec edi include_directory_ok: cmp byte [edi-1],'/' je path_separator_ok cmp byte [edi-1],'\' je path_separator_ok mov al,'/' stos byte [edi] path_separator_ok: ret fasm/source/exprpars.inc0000644000175000017500000005315214533376740016153 0ustar privalovprivalov ; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. convert_expression: push ebp call get_fp_value jnc fp_expression mov [current_offset],esp expression_loop: push edi mov edi,single_operand_operators call get_operator pop edi or al,al jz expression_element cmp al,82h je expression_loop push eax jmp expression_loop expression_element: mov al,[esi] cmp al,1Ah je expression_number cmp al,22h je expression_number cmp al,'(' je expression_number mov al,'!' stos byte [edi] jmp expression_operator expression_number: call convert_number expression_operator: push edi mov edi,operators call get_operator pop edi or al,al jz expression_end operators_loop: cmp esp,[current_offset] je push_operator mov bl,al and bl,0F0h mov bh,byte [esp] and bh,0F0h cmp bl,bh ja push_operator pop ebx mov byte [edi],bl inc edi jmp operators_loop push_operator: push eax jmp expression_loop expression_end: cmp esp,[current_offset] je expression_converted pop eax stos byte [edi] jmp expression_end expression_converted: pop ebp ret fp_expression: mov al,'.' stos byte [edi] mov eax,[fp_value] stos dword [edi] mov eax,[fp_value+4] stos dword [edi] mov eax,[fp_value+8] stos dword [edi] pop ebp ret convert_number: lea eax,[edi+20h] mov edx,[memory_end] cmp [source_start],0 je check_memory_for_number mov edx,[labels_list] check_memory_for_number: cmp eax,edx jae out_of_memory mov eax,esp sub eax,[stack_limit] cmp eax,100h jb stack_overflow cmp byte [esi],'(' je expression_value inc edi call get_number jc symbol_value or ebp,ebp jz valid_number mov byte [edi-1],0Fh ret valid_number: cmp dword [edi+4],0 jne qword_number cmp word [edi+2],0 jne dword_number cmp byte [edi+1],0 jne word_number byte_number: mov byte [edi-1],1 inc edi ret qword_number: mov byte [edi-1],8 add edi,8 ret dword_number: mov byte [edi-1],4 scas dword [edi] ret word_number: mov byte [edi-1],2 scas word [edi] ret expression_value: inc esi push [current_offset] call convert_expression pop [current_offset] lods byte [esi] cmp al,')' je subexpression_closed dec esi mov al,'!' stosb subexpression_closed: ret symbol_value: mov eax,[source_start] test eax,eax jz preprocessor_value cmp eax,-1 je invalid_value push edi esi lods word [esi] cmp al,1Ah jne no_address_register movzx ecx,ah call get_symbol jc no_address_register cmp al,10h jne no_address_register mov al,ah shr ah,4 cmp ah,4 je register_value and ah,not 1 cmp ah,8 je register_value cmp ah,0Ch jae register_value cmp ah,6 je register_value cmp al,23h je register_value cmp al,25h je register_value cmp al,26h je register_value cmp al,27h je register_value no_address_register: pop esi mov edi,directive_operators call get_operator pop edi or al,al jnz broken_value lods byte [esi] cmp al,1Ah jne invalid_value lods byte [esi] movzx ecx,al call get_label_id store_label_value: mov byte [edi-1],11h stos dword [edi] ret broken_value: mov eax,0Fh jmp store_label_value register_value: pop edx edi mov byte [edi-1],10h stos byte [edi] ret preprocessor_value: dec edi lods byte [esi] cmp al,1Ah jne invalid_value lods byte [esi] mov cl,al mov ch,10b call get_preprocessor_symbol jc invalid_value test edx,edx jz special_preprocessor_value push esi mov esi,[edx+8] push [current_offset] call convert_expression pop [current_offset] pop esi ret special_preprocessor_value: cmp eax,preprocessed_line_value jne invalid_value call get_current_line_from_file mov al,4 stos byte [edi] mov eax,[ebx+4] stos dword [edi] ret get_number: xor ebp,ebp lods byte [esi] cmp al,22h je get_text_number cmp al,1Ah jne not_number lods byte [esi] movzx ecx,al mov [number_start],esi mov al,[esi] cmp al,'$' je number_begin sub al,30h cmp al,9 ja invalid_number number_begin: mov ebx,esi add esi,ecx push esi dec esi mov dword [edi],0 mov dword [edi+4],0 cmp byte [ebx],'$' je pascal_hex_number cmp word [ebx],'0x' je get_hex_number mov al,[esi] dec esi cmp al,'h' je get_hex_number cmp al,'b' je get_bin_number cmp al,'d' je get_dec_number cmp al,'o' je get_oct_number cmp al,'q' je get_oct_number cmp al,'H' je get_hex_number cmp al,'B' je get_bin_number cmp al,'D' je get_dec_number cmp al,'O' je get_oct_number cmp al,'Q' je get_oct_number inc esi get_dec_number: mov ebx,esi mov esi,[number_start] get_dec_digit: cmp esi,ebx ja number_ok cmp byte [esi],27h je next_dec_digit cmp byte [esi],'_' je next_dec_digit xor edx,edx mov eax,[edi] shld edx,eax,2 shl eax,2 add eax,[edi] adc edx,0 add eax,eax adc edx,edx mov [edi],eax mov eax,[edi+4] add eax,eax jc dec_out_of_range add eax,eax jc dec_out_of_range add eax,[edi+4] jc dec_out_of_range add eax,eax jc dec_out_of_range add eax,edx jc dec_out_of_range mov [edi+4],eax movzx eax,byte [esi] sub al,30h jc bad_number cmp al,9 ja bad_number add [edi],eax adc dword [edi+4],0 jc dec_out_of_range next_dec_digit: inc esi jmp get_dec_digit dec_out_of_range: cmp esi,ebx ja dec_out_of_range_finished lods byte [esi] cmp al,27h je bad_number cmp al,'_' je bad_number sub al,30h jc bad_number cmp al,9 ja bad_number jmp dec_out_of_range dec_out_of_range_finished: or ebp,-1 jmp number_ok bad_number: pop eax invalid_number: mov esi,[number_start] dec esi not_number: dec esi stc ret get_bin_number: xor bl,bl get_bin_digit: cmp esi,[number_start] jb number_ok movzx eax,byte [esi] cmp al,27h je bin_digit_skip cmp al,'_' je bin_digit_skip sub al,30h cmp al,1 ja bad_number xor edx,edx mov cl,bl dec esi cmp bl,64 je bin_out_of_range inc bl cmp cl,32 jae bin_digit_high shl eax,cl or dword [edi],eax jmp get_bin_digit bin_digit_high: sub cl,32 shl eax,cl or dword [edi+4],eax jmp get_bin_digit bin_out_of_range: or al,al jz get_bin_digit or ebp,-1 jmp get_bin_digit bin_digit_skip: dec esi jmp get_bin_digit pascal_hex_number: cmp cl,1 je bad_number get_hex_number: xor bl,bl get_hex_digit: cmp esi,[number_start] jb number_ok movzx eax,byte [esi] cmp al,27h je hex_digit_skip cmp al,'_' je hex_digit_skip cmp al,'x' je hex_number_ok cmp al,'$' je pascal_hex_ok sub al,30h cmp al,9 jbe hex_digit_ok sub al,7 cmp al,15 jbe hex_letter_digit_ok sub al,20h cmp al,15 ja bad_number hex_letter_digit_ok: cmp al,10 jb bad_number hex_digit_ok: xor edx,edx mov cl,bl dec esi cmp bl,64 je hex_out_of_range add bl,4 cmp cl,32 jae hex_digit_high shl eax,cl or dword [edi],eax jmp get_hex_digit hex_digit_high: sub cl,32 shl eax,cl or dword [edi+4],eax jmp get_hex_digit hex_out_of_range: or al,al jz get_hex_digit or ebp,-1 jmp get_hex_digit hex_digit_skip: dec esi jmp get_hex_digit get_oct_number: xor bl,bl get_oct_digit: cmp esi,[number_start] jb number_ok movzx eax,byte [esi] cmp al,27h je oct_digit_skip cmp al,'_' je oct_digit_skip sub al,30h cmp al,7 ja bad_number oct_digit_ok: xor edx,edx mov cl,bl dec esi cmp bl,63 ja oct_out_of_range jne oct_range_ok cmp al,1 ja oct_out_of_range oct_range_ok: add bl,3 cmp cl,30 je oct_digit_wrap ja oct_digit_high shl eax,cl or dword [edi],eax jmp get_oct_digit oct_digit_wrap: shl eax,cl adc dword [edi+4],0 or dword [edi],eax jmp get_oct_digit oct_digit_high: sub cl,32 shl eax,cl or dword [edi+4],eax jmp get_oct_digit oct_digit_skip: dec esi jmp get_oct_digit oct_out_of_range: or al,al jz get_oct_digit or ebp,-1 jmp get_oct_digit hex_number_ok: dec esi pascal_hex_ok: cmp esi,[number_start] jne bad_number number_ok: pop esi number_done: clc ret get_text_number: lods dword [esi] mov edx,eax xor bl,bl mov dword [edi],0 mov dword [edi+4],0 get_text_character: sub edx,1 jc number_done movzx eax,byte [esi] inc esi mov cl,bl cmp bl,64 je text_out_of_range add bl,8 cmp cl,32 jae text_character_high shl eax,cl or dword [edi],eax jmp get_text_character text_character_high: sub cl,32 shl eax,cl or dword [edi+4],eax jmp get_text_character text_out_of_range: or ebp,-1 jmp get_text_character get_fp_value: push edi esi fp_value_start: lods byte [esi] cmp al,'-' je fp_value_start cmp al,'+' je fp_value_start cmp al,1Ah jne not_fp_value lods byte [esi] movzx ecx,al cmp cl,1 jbe not_fp_value lea edx,[esi+1] xor ah,ah check_fp_value: lods byte [esi] cmp al,'.' je fp_character_dot cmp al,'E' je fp_character_exp cmp al,'e' je fp_character_exp cmp al,'F' je fp_last_character cmp al,'f' je fp_last_character digit_expected: cmp al,'0' jb not_fp_value cmp al,'9' ja not_fp_value jmp fp_character_ok fp_character_dot: cmp esi,edx je not_fp_value or ah,ah jnz not_fp_value or ah,1 lods byte [esi] loop digit_expected not_fp_value: pop esi edi stc ret fp_last_character: cmp cl,1 jne not_fp_value or ah,4 jmp fp_character_ok fp_character_exp: cmp esi,edx je not_fp_value cmp ah,1 ja not_fp_value or ah,2 cmp ecx,1 jne fp_character_ok cmp byte [esi],'+' je fp_exp_sign cmp byte [esi],'-' jne fp_character_ok fp_exp_sign: inc esi cmp byte [esi],1Ah jne not_fp_value inc esi lods byte [esi] movzx ecx,al inc ecx fp_character_ok: dec ecx jnz check_fp_value or ah,ah jz not_fp_value pop esi mov [fp_sign],0 fp_get_sign: lods byte [esi] cmp al,1Ah je fp_get cmp al,'+' je fp_get_sign xor [fp_sign],1 jmp fp_get_sign fp_get: lods byte [esi] movzx ecx,al xor edx,edx mov edi,fp_value mov [edi],edx mov [edi+4],edx mov [edi+12],edx call fp_optimize mov [fp_format],0 mov al,[esi] fp_before_dot: lods byte [esi] cmp al,'.' je fp_dot cmp al,'E' je fp_exponent cmp al,'e' je fp_exponent cmp al,'F' je fp_done cmp al,'f' je fp_done sub al,30h mov edi,fp_value+16 xor edx,edx mov dword [edi+12],edx mov dword [edi],edx mov dword [edi+4],edx mov [edi+7],al mov dl,7 mov dword [edi+8],edx call fp_optimize mov edi,fp_value push ecx mov ecx,10 call fp_mul pop ecx mov ebx,fp_value+16 call fp_add loop fp_before_dot fp_dot: mov edi,fp_value+16 xor edx,edx mov [edi],edx mov [edi+4],edx mov byte [edi+7],80h mov [edi+8],edx mov dword [edi+12],edx dec ecx jz fp_done fp_after_dot: lods byte [esi] cmp al,'E' je fp_exponent cmp al,'e' je fp_exponent cmp al,'F' je fp_done cmp al,'f' je fp_done inc [fp_format] cmp [fp_format],80h jne fp_counter_ok mov [fp_format],7Fh fp_counter_ok: dec esi mov edi,fp_value+16 push ecx mov ecx,10 call fp_div push dword [edi] push dword [edi+4] push dword [edi+8] push dword [edi+12] lods byte [esi] sub al,30h movzx ecx,al call fp_mul mov ebx,edi mov edi,fp_value call fp_add mov edi,fp_value+16 pop dword [edi+12] pop dword [edi+8] pop dword [edi+4] pop dword [edi] pop ecx dec ecx jnz fp_after_dot jmp fp_done fp_exponent: or [fp_format],80h xor edx,edx xor ebp,ebp dec ecx jnz get_exponent cmp byte [esi],'+' je fp_exponent_sign cmp byte [esi],'-' jne fp_done not ebp fp_exponent_sign: add esi,2 lods byte [esi] movzx ecx,al get_exponent: movzx eax,byte [esi] inc esi sub al,30h cmp al,10 jae exponent_ok imul edx,10 cmp edx,8000h jae value_out_of_range add edx,eax loop get_exponent exponent_ok: mov edi,fp_value or edx,edx jz fp_done mov ecx,edx or ebp,ebp jnz fp_negative_power fp_power: push ecx mov ecx,10 call fp_mul pop ecx loop fp_power jmp fp_done fp_negative_power: push ecx mov ecx,10 call fp_div pop ecx loop fp_negative_power fp_done: mov edi,fp_value mov al,[fp_format] mov [edi+10],al mov al,[fp_sign] mov [edi+11],al test byte [edi+15],80h jz fp_ok add dword [edi],1 adc dword [edi+4],0 jnc fp_ok mov eax,[edi+4] shrd [edi],eax,1 shr eax,1 or eax,80000000h mov [edi+4],eax inc word [edi+8] fp_ok: pop edi clc ret fp_mul: or ecx,ecx jz fp_zero mov eax,[edi+12] mul ecx mov [edi+12],eax mov ebx,edx mov eax,[edi] mul ecx add eax,ebx adc edx,0 mov [edi],eax mov ebx,edx mov eax,[edi+4] mul ecx add eax,ebx adc edx,0 mov [edi+4],eax .loop: or edx,edx jz .done mov eax,[edi] shrd [edi+12],eax,1 mov eax,[edi+4] shrd [edi],eax,1 shrd eax,edx,1 mov [edi+4],eax shr edx,1 inc dword [edi+8] cmp dword [edi+8],8000h jge value_out_of_range jmp .loop .done: ret fp_div: mov eax,[edi+4] xor edx,edx div ecx mov [edi+4],eax mov eax,[edi] div ecx mov [edi],eax mov eax,[edi+12] div ecx mov [edi+12],eax mov ebx,eax or ebx,[edi] or ebx,[edi+4] jz fp_zero .loop: test byte [edi+7],80h jnz .exp_ok mov eax,[edi] shld [edi+4],eax,1 mov eax,[edi+12] shld [edi],eax,1 add eax,eax mov [edi+12],eax dec dword [edi+8] add edx,edx jmp .loop .exp_ok: mov eax,edx xor edx,edx div ecx add [edi+12],eax adc dword [edi],0 adc dword [edi+4],0 jnc .done mov eax,[edi+4] mov ebx,[edi] shrd [edi],eax,1 shrd [edi+12],ebx,1 shr eax,1 or eax,80000000h mov [edi+4],eax inc dword [edi+8] .done: ret fp_add: cmp dword [ebx+8],8000h je .done cmp dword [edi+8],8000h je .copy mov eax,[ebx+8] cmp eax,[edi+8] jge .exp_ok mov eax,[edi+8] .exp_ok: call .change_exp xchg ebx,edi call .change_exp xchg ebx,edi mov edx,[ebx+12] mov eax,[ebx] mov ebx,[ebx+4] add [edi+12],edx adc [edi],eax adc [edi+4],ebx jnc .done mov eax,[edi] shrd [edi+12],eax,1 mov eax,[edi+4] shrd [edi],eax,1 shr eax,1 or eax,80000000h mov [edi+4],eax inc dword [edi+8] .done: ret .copy: mov eax,[ebx] mov [edi],eax mov eax,[ebx+4] mov [edi+4],eax mov eax,[ebx+8] mov [edi+8],eax mov eax,[ebx+12] mov [edi+12],eax ret .change_exp: push ecx mov ecx,eax sub ecx,[ebx+8] mov edx,[ebx+4] jecxz .exp_done .exp_loop: mov ebp,[ebx] shrd [ebx+12],ebp,1 shrd [ebx],edx,1 shr edx,1 inc dword [ebx+8] loop .exp_loop .exp_done: mov [ebx+4],edx pop ecx ret fp_optimize: mov eax,[edi] mov ebp,[edi+4] or ebp,[edi] or ebp,[edi+12] jz fp_zero .loop: test byte [edi+7],80h jnz .done shld [edi+4],eax,1 mov ebp,[edi+12] shld eax,ebp,1 mov [edi],eax shl dword [edi+12],1 dec dword [edi+8] jmp .loop .done: ret fp_zero: mov dword [edi+8],8000h ret preevaluate_logical_expression: xor al,al preevaluate_embedded_logical_expression: mov [logical_value_wrapping],al push edi call preevaluate_logical_value preevaluation_loop: cmp al,0FFh je invalid_logical_expression mov dl,[esi] inc esi cmp dl,'|' je preevaluate_or cmp dl,'&' je preevaluate_and cmp dl,92h je preevaluation_done or dl,dl jnz invalid_logical_expression preevaluation_done: pop edx dec esi ret preevaluate_or: cmp al,'1' je quick_true cmp al,'0' je leave_only_following push edi mov al,dl stos byte [edi] call preevaluate_logical_value pop ebx cmp al,'0' je leave_only_preceding cmp al,'1' jne preevaluation_loop stos byte [edi] xor al,al jmp preevaluation_loop preevaluate_and: cmp al,'0' je quick_false cmp al,'1' je leave_only_following push edi mov al,dl stos byte [edi] call preevaluate_logical_value pop ebx cmp al,'1' je leave_only_preceding cmp al,'0' jne preevaluation_loop stos byte [edi] xor al,al jmp preevaluation_loop leave_only_following: mov edi,[esp] call preevaluate_logical_value jmp preevaluation_loop leave_only_preceding: mov edi,ebx xor al,al jmp preevaluation_loop quick_true: call skip_logical_value jc invalid_logical_expression mov edi,[esp] mov al,'1' jmp preevaluation_loop quick_false: call skip_logical_value jc invalid_logical_expression mov edi,[esp] mov al,'0' jmp preevaluation_loop invalid_logical_expression: pop edi mov esi,edi mov al,0FFh stos byte [edi] ret skip_logical_value: cmp byte [esi],'~' jne negation_skipped inc esi jmp skip_logical_value negation_skipped: mov al,[esi] cmp al,91h jne skip_simple_logical_value inc esi xchg al,[logical_value_wrapping] push eax skip_logical_expression: call skip_logical_value lods byte [esi] or al,al jz wrongly_structured_logical_expression cmp al,0Fh je wrongly_structured_logical_expression cmp al,'|' je skip_logical_expression cmp al,'&' je skip_logical_expression cmp al,92h jne wrongly_structured_logical_expression pop eax mov [logical_value_wrapping],al logical_value_skipped: clc ret wrongly_structured_logical_expression: pop eax stc ret skip_simple_logical_value: mov [logical_value_parentheses],0 find_simple_logical_value_end: mov al,[esi] or al,al jz logical_value_skipped cmp al,0Fh je logical_value_skipped cmp al,'|' je logical_value_skipped cmp al,'&' je logical_value_skipped cmp al,91h je skip_logical_value_internal_parenthesis cmp al,92h jne skip_logical_value_symbol sub [logical_value_parentheses],1 jnc skip_logical_value_symbol cmp [logical_value_wrapping],91h jne skip_logical_value_symbol jmp logical_value_skipped skip_logical_value_internal_parenthesis: inc [logical_value_parentheses] skip_logical_value_symbol: call skip_symbol jmp find_simple_logical_value_end preevaluate_logical_value: mov ebp,edi preevaluate_negation: cmp byte [esi],'~' jne preevaluate_negation_ok movs byte [edi],[esi] jmp preevaluate_negation preevaluate_negation_ok: mov ebx,esi cmp byte [esi],91h jne preevaluate_simple_logical_value lods byte [esi] stos byte [edi] push ebp mov dl,[logical_value_wrapping] push edx call preevaluate_embedded_logical_expression pop edx mov [logical_value_wrapping],dl pop ebp cmp al,0FFh je invalid_logical_value cmp byte [esi],92h jne invalid_logical_value or al,al jnz preevaluated_expression_value movs byte [edi],[esi] ret preevaluated_expression_value: inc esi lea edx,[edi-1] sub edx,ebp test edx,1 jz expression_negation_ok xor al,1 expression_negation_ok: mov edi,ebp ret invalid_logical_value: mov edi,ebp mov al,0FFh ret preevaluate_simple_logical_value: xor edx,edx mov [logical_value_parentheses],edx find_logical_value_boundaries: mov al,[esi] or al,al jz logical_value_boundaries_found cmp al,91h je logical_value_internal_parentheses cmp al,92h je logical_value_boundaries_parenthesis_close cmp al,'|' je logical_value_boundaries_found cmp al,'&' je logical_value_boundaries_found or edx,edx jnz next_symbol_in_logical_value cmp al,0F0h je preevaluable_logical_operator cmp al,0F7h je preevaluable_logical_operator cmp al,0F6h jne next_symbol_in_logical_value preevaluable_logical_operator: mov edx,esi next_symbol_in_logical_value: call skip_symbol jmp find_logical_value_boundaries logical_value_internal_parentheses: inc [logical_value_parentheses] jmp next_symbol_in_logical_value logical_value_boundaries_parenthesis_close: sub [logical_value_parentheses],1 jnc next_symbol_in_logical_value cmp [logical_value_wrapping],91h jne next_symbol_in_logical_value logical_value_boundaries_found: or edx,edx jz non_preevaluable_logical_value mov al,[edx] cmp al,0F0h je compare_symbols cmp al,0F7h je compare_symbol_types cmp al,0F6h je scan_symbols_list non_preevaluable_logical_value: mov ecx,esi mov esi,ebx sub ecx,esi jz invalid_logical_value cmp esi,edi je leave_logical_value_intact rep movs byte [edi],[esi] xor al,al ret leave_logical_value_intact: add edi,ecx add esi,ecx xor al,al ret compare_symbols: lea ecx,[esi-1] sub ecx,edx mov eax,edx sub eax,ebx cmp ecx,eax jne preevaluated_false push esi edi mov esi,ebx lea edi,[edx+1] repe cmps byte [esi],[edi] pop edi esi je preevaluated_true preevaluated_false: mov eax,edi sub eax,ebp test eax,1 jnz store_true store_false: mov edi,ebp mov al,'0' ret preevaluated_true: mov eax,edi sub eax,ebp test eax,1 jnz store_false store_true: mov edi,ebp mov al,'1' ret compare_symbol_types: push esi lea esi,[edx+1] type_comparison: cmp esi,[esp] je types_compared mov al,[esi] cmp al,[ebx] jne different_type cmp al,'(' jne equal_type mov al,[esi+1] mov ah,[ebx+1] cmp al,ah je equal_type or al,al jz different_type or ah,ah jz different_type cmp al,'.' je different_type cmp ah,'.' je different_type equal_type: call skip_symbol xchg esi,ebx call skip_symbol xchg esi,ebx jmp type_comparison types_compared: pop esi cmp byte [ebx],0F7h jne preevaluated_false jmp preevaluated_true different_type: pop esi jmp preevaluated_false scan_symbols_list: push edi esi lea esi,[edx+1] sub edx,ebx lods byte [esi] cmp al,'<' jne invalid_symbols_list get_next_from_list: mov edi,esi get_from_list: cmp byte [esi],',' je compare_in_list cmp byte [esi],'>' je compare_in_list cmp esi,[esp] jae invalid_symbols_list call skip_symbol jmp get_from_list compare_in_list: mov ecx,esi sub ecx,edi cmp ecx,edx jne not_equal_length_in_list mov esi,ebx repe cmps byte [esi],[edi] mov esi,edi jne not_equal_in_list skip_rest_of_list: cmp byte [esi],'>' je check_list_end cmp esi,[esp] jae invalid_symbols_list call skip_symbol jmp skip_rest_of_list check_list_end: inc esi cmp esi,[esp] jne invalid_symbols_list pop esi edi jmp preevaluated_true not_equal_in_list: add esi,ecx not_equal_length_in_list: lods byte [esi] cmp al,',' je get_next_from_list cmp esi,[esp] jne invalid_symbols_list pop esi edi jmp preevaluated_false invalid_symbols_list: pop esi edi jmp invalid_logical_value fasm/source/formats.inc0000644000175000017500000023757414533376740015776 0ustar privalovprivalov ; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. formatter: mov [current_offset],edi cmp [output_file],0 jne output_path_ok mov esi,[input_file] mov edi,[free_additional_memory] duplicate_output_path: lods byte [esi] cmp edi,[structures_buffer] jae out_of_memory stos byte [edi] or al,al jnz duplicate_output_path dec edi mov eax,edi find_extension: dec eax cmp eax,[free_additional_memory] jb extension_found cmp byte [eax],'\' je extension_found cmp byte [eax],'/' je extension_found cmp byte [eax],'.' jne find_extension mov edi,eax extension_found: lea eax,[edi+9] cmp eax,[structures_buffer] jae out_of_memory cmp [file_extension],0 jne extension_specified mov al,[output_format] cmp al,2 je exe_extension jb bin_extension cmp al,4 je obj_extension cmp al,5 je o_extension cmp al,3 jne no_extension cmp [subsystem],1 je sys_extension cmp [subsystem],10 jae efi_extension bt [format_flags],8 jnc exe_extension mov eax,'.dll' jmp make_extension sys_extension: mov eax,'.sys' jmp make_extension efi_extension: mov eax,'.efi' jmp make_extension bin_extension: mov eax,'.bin' bt [format_flags],0 jnc make_extension mov eax,'.com' jmp make_extension obj_extension: mov eax,'.obj' jmp make_extension o_extension: mov eax,'.o' bt [format_flags],0 jnc make_extension no_extension: xor eax,eax jmp make_extension exe_extension: mov eax,'.exe' make_extension: xchg eax,[edi] scas dword [edi] mov byte [edi],0 scas byte [edi] mov esi,edi stos dword [edi] sub edi,9 xor eax,eax mov ebx,characters adapt_case: mov al,[esi] or al,al jz adapt_next xlat byte [ebx] cmp al,[esi] je adapt_ok sub byte [edi],20h adapt_ok: inc esi adapt_next: inc edi cmp byte [edi],0 jne adapt_case jmp extension_ok extension_specified: mov al,'.' stos byte [edi] mov esi,[file_extension] copy_extension: lods byte [esi] stos byte [edi] test al,al jnz copy_extension dec edi extension_ok: mov esi,edi lea ecx,[esi+1] sub ecx,[free_additional_memory] mov edi,[structures_buffer] dec edi std rep movs byte [edi],[esi] cld inc edi mov [structures_buffer],edi mov [output_file],edi output_path_ok: cmp [symbols_file],0 je labels_table_ok mov ecx,[memory_end] sub ecx,[labels_list] mov edi,[tagged_blocks] sub edi,8 mov [edi],ecx or dword [edi+4],-1 sub edi,ecx cmp edi,[current_offset] jbe out_of_memory mov [tagged_blocks],edi mov esi,[memory_end] copy_labels: sub esi,32 cmp esi,[labels_list] jb labels_table_ok mov ecx,32 shr 2 rep movs dword [edi],[esi] sub esi,32 jmp copy_labels labels_table_ok: mov edi,[current_offset] cmp [output_format],4 je coff_formatter cmp [output_format],5 jne common_formatter bt [format_flags],0 jnc elf_formatter common_formatter: mov eax,edi sub eax,[code_start] mov [real_code_size],eax cmp edi,[undefined_data_end] jne calculate_code_size mov edi,[undefined_data_start] calculate_code_size: mov [current_offset],edi sub edi,[code_start] mov [code_size],edi and [written_size],0 mov edx,[output_file] call create jc write_failed cmp [output_format],3 jne stub_written mov edx,[code_start] mov ecx,[stub_size] sub edx,ecx add [written_size],ecx call write stub_written: cmp [output_format],2 jne write_output call write_mz_header write_output: call write_code output_written: call close cmp [symbols_file],0 jne dump_symbols ret write_code: mov eax,[written_size] mov [headers_size],eax mov edx,[code_start] mov ecx,[code_size] add [written_size],ecx lea eax,[edx+ecx] call write jc write_failed ret format_directive: cmp edi,[code_start] jne unexpected_instruction mov ebp,[addressing_space] test byte [ds:ebp+0Ah],1 jnz unexpected_instruction cmp [output_format],0 jne unexpected_instruction lods byte [esi] cmp al,1Ch je format_prefix cmp al,18h jne invalid_argument lods byte [esi] select_format: mov dl,al shr al,4 mov [output_format],al and edx,0Fh or [format_flags],edx cmp al,2 je format_mz cmp al,3 je format_pe cmp al,4 je format_coff cmp al,5 je format_elf format_defined: cmp byte [esi],86h jne instruction_assembled cmp word [esi+1],'(' jne invalid_argument mov eax,[esi+3] add esi,3+4 mov [file_extension],esi lea esi,[esi+eax+1] jmp instruction_assembled format_prefix: lods byte [esi] mov ah,al lods byte [esi] cmp al,18h jne invalid_argument lods byte [esi] mov edx,eax shr dl,4 shr dh,4 cmp dl,dh jne invalid_argument or al,ah jmp select_format entry_directive: bts [format_flags],10h jc setting_already_specified mov al,[output_format] cmp al,2 je mz_entry cmp al,3 je pe_entry cmp al,5 jne illegal_instruction bt [format_flags],0 jc elf_entry jmp illegal_instruction stack_directive: bts [format_flags],11h jc setting_already_specified mov al,[output_format] cmp al,2 je mz_stack cmp al,3 je pe_stack jmp illegal_instruction heap_directive: bts [format_flags],12h jc setting_already_specified mov al,[output_format] cmp al,2 je mz_heap cmp al,3 je pe_heap jmp illegal_instruction segment_directive: mov al,[output_format] cmp al,2 je mz_segment cmp al,5 je elf_segment jmp illegal_instruction section_directive: mov al,[output_format] cmp al,3 je pe_section cmp al,4 je coff_section cmp al,5 je elf_section jmp illegal_instruction public_directive: mov al,[output_format] cmp al,4 je public_allowed cmp al,5 jne illegal_instruction bt [format_flags],0 jc illegal_instruction public_allowed: mov [base_code],0C0h lods byte [esi] cmp al,2 je public_label cmp al,1Dh jne invalid_argument lods byte [esi] and al,7 add [base_code],al lods byte [esi] cmp al,2 jne invalid_argument public_label: lods dword [esi] cmp eax,0Fh jb invalid_use_of_symbol je reserved_word_used_as_symbol inc esi mov dx,[current_pass] mov [eax+18],dx or byte [eax+8],8 mov ebx,eax call store_label_reference mov eax,ebx mov ebx,[free_additional_memory] lea edx,[ebx+10h] cmp edx,[structures_buffer] jae out_of_memory mov [free_additional_memory],edx mov [ebx+8],eax mov eax,[current_line] mov [ebx+0Ch],eax lods byte [esi] cmp al,86h jne invalid_argument lods word [esi] cmp ax,'(' jne invalid_argument mov [ebx+4],esi lods dword [esi] lea esi,[esi+eax+1] mov al,[base_code] mov [ebx],al jmp instruction_assembled extrn_directive: mov al,[output_format] cmp al,4 je extrn_allowed cmp al,5 jne illegal_instruction bt [format_flags],0 jc illegal_instruction extrn_allowed: lods word [esi] cmp ax,'(' jne invalid_argument mov ebx,esi lods dword [esi] lea esi,[esi+eax+1] mov edx,[free_additional_memory] lea eax,[edx+0Ch] cmp eax,[structures_buffer] jae out_of_memory mov [free_additional_memory],eax mov byte [edx],80h mov [edx+4],ebx lods byte [esi] cmp al,86h jne invalid_argument lods byte [esi] cmp al,2 jne invalid_argument lods dword [esi] cmp eax,0Fh jb invalid_use_of_symbol je reserved_word_used_as_symbol inc esi mov ebx,eax xor ah,ah lods byte [esi] cmp al,':' je get_extrn_size dec esi cmp al,11h jne extrn_size_ok get_extrn_size: lods word [esi] cmp al,11h jne invalid_argument extrn_size_ok: mov [address_symbol],edx mov [label_size],ah movzx ecx,ah mov [edx+8],ecx xor eax,eax xor edx,edx xor ebp,ebp mov [address_sign],0 mov ch,2 test [format_flags],8 jz make_free_label mov ch,4 jmp make_free_label mark_relocation: cmp [value_type],0 je relocation_ok mov ebp,[addressing_space] test byte [ds:ebp+0Ah],1 jnz relocation_ok cmp [output_format],2 je mark_mz_relocation cmp [output_format],3 je mark_pe_relocation cmp [output_format],4 je mark_coff_relocation cmp [output_format],5 je mark_elf_relocation relocation_ok: ret close_pass: mov al,[output_format] cmp al,3 je close_pe cmp al,4 je close_coff cmp al,5 je close_elf ret format_mz: mov edx,[additional_memory] push edi mov edi,edx mov ecx,1Ch shr 2 xor eax,eax rep stos dword [edi] mov [free_additional_memory],edi pop edi mov word [edx+0Ch],0FFFFh mov word [edx+10h],1000h mov [code_type],16 jmp format_defined mark_mz_relocation: push eax ebx inc word [number_of_relocations] jz format_limitations_exceeded mov ebx,[free_additional_memory] mov eax,edi sub eax,[code_start] mov [ebx],ax shr eax,16 shl ax,12 mov [ebx+2],ax cmp word [ebx],0FFFFh jne mz_relocation_ok inc word [ebx+2] sub word [ebx],10h mz_relocation_ok: add ebx,4 cmp ebx,[structures_buffer] jae out_of_memory mov [free_additional_memory],ebx pop ebx eax ret mz_segment: lods byte [esi] cmp al,2 jne invalid_argument lods dword [esi] cmp eax,0Fh jb invalid_use_of_symbol je reserved_word_used_as_symbol inc esi mov ebx,eax mov eax,edi sub eax,[code_start] mov ecx,0Fh add eax,0Fh and eax,1111b sub ecx,eax mov edx,edi xor eax,eax rep stos byte [edi] mov eax,edx call undefined_data push ebx call create_addressing_space pop ebx mov eax,edi sub eax,[code_start] shr eax,4 cmp eax,10000h jae value_out_of_range mov edx,eax mov al,16 cmp byte [esi],13h jne segment_type_ok inc esi lods byte [esi] segment_type_ok: mov [code_type],al mov eax,edx mov ch,1 mov [address_sign],0 xor edx,edx xor ebp,ebp mov [label_size],0 mov [address_symbol],edx jmp make_free_label mz_entry: lods byte [esi] cmp al,'(' jne invalid_argument call get_word_value cmp [value_type],1 je initial_cs_ok call recoverable_invalid_address initial_cs_ok: mov edx,[additional_memory] mov [edx+16h],ax lods byte [esi] cmp al,':' jne invalid_argument lods byte [esi] cmp al,'(' jne invalid_argument ja invalid_address call get_word_value cmp [value_type],0 jne invalid_use_of_symbol mov edx,[additional_memory] mov [edx+14h],ax jmp instruction_assembled recoverable_invalid_address: cmp [error_line],0 jne ignore_invalid_address push [current_line] pop [error_line] mov [error],invalid_address ignore_invalid_address: ret mz_stack: lods byte [esi] cmp al,'(' jne invalid_argument call get_word_value cmp byte [esi],':' je stack_pointer cmp ax,10h jb invalid_value cmp [value_type],0 jne invalid_use_of_symbol mov edx,[additional_memory] mov [edx+10h],ax jmp instruction_assembled stack_pointer: cmp [value_type],1 je initial_ss_ok call recoverable_invalid_address initial_ss_ok: mov edx,[additional_memory] mov [edx+0Eh],ax lods byte [esi] cmp al,':' jne invalid_argument lods byte [esi] cmp al,'(' jne invalid_argument call get_word_value cmp [value_type],0 jne invalid_use_of_symbol mov edx,[additional_memory] mov [edx+10h],ax bts [format_flags],4 jmp instruction_assembled mz_heap: cmp [output_format],2 jne illegal_instruction lods byte [esi] call get_size_operator cmp ah,1 je invalid_value cmp ah,2 ja invalid_value cmp al,'(' jne invalid_argument call get_word_value cmp [value_type],0 jne invalid_use_of_symbol mov edx,[additional_memory] mov [edx+0Ch],ax jmp instruction_assembled write_mz_header: mov edx,[additional_memory] bt [format_flags],4 jc mz_stack_ok mov eax,[real_code_size] dec eax shr eax,4 inc eax mov [edx+0Eh],ax shl eax,4 movzx ecx,word [edx+10h] add eax,ecx mov [real_code_size],eax mz_stack_ok: mov edi,[free_additional_memory] mov eax,[number_of_relocations] shl eax,2 add eax,1Ch sub edi,eax xchg edi,[free_additional_memory] mov ecx,0Fh add eax,0Fh and eax,1111b sub ecx,eax xor al,al rep stos byte [edi] sub edi,[free_additional_memory] mov ecx,edi shr edi,4 mov word [edx],'MZ' ; signature mov [edx+8],di ; header size in paragraphs mov eax,[number_of_relocations] mov [edx+6],ax ; number of relocation entries mov eax,[code_size] add eax,ecx mov esi,eax shr esi,9 and eax,1FFh inc si or ax,ax jnz mz_size_ok dec si mz_size_ok: mov [edx+2],ax ; number of bytes in last page mov [edx+4],si ; number of pages mov eax,[real_code_size] dec eax shr eax,4 inc eax mov esi,[code_size] dec esi shr esi,4 inc esi sub eax,esi mov [edx+0Ah],ax ; minimum memory in addition to code add [edx+0Ch],ax ; maximum memory in addition to code salc mov ah,al or [edx+0Ch],ax mov word [edx+18h],1Ch ; offset of relocation table add [written_size],ecx call write jc write_failed ret make_stub: mov [stub_file],edx or edx,edx jnz stub_from_file push esi mov edx,edi xor eax,eax mov ecx,20h rep stos dword [edi] mov eax,40h+default_stub_end-default_stub mov cx,100h+default_stub_end-default_stub mov word [edx],'MZ' mov byte [edx+4],1 mov word [edx+2],ax mov byte [edx+8],4 mov byte [edx+0Ah],10h mov word [edx+0Ch],0FFFFh mov word [edx+10h],cx mov word [edx+3Ch],ax mov byte [edx+18h],40h lea edi,[edx+40h] mov esi,default_stub mov ecx,default_stub_end-default_stub rep movs byte [edi],[esi] pop esi jmp stub_ok default_stub: use16 push cs pop ds mov dx,stub_message-default_stub mov ah,9 int 21h mov ax,4C01h int 21h stub_message db 'This program cannot be run in DOS mode.',0Dh,0Ah,24h rq 1 default_stub_end: use32 stub_from_file: push esi mov esi,edx call open_binary_file mov edx,edi mov ecx,1Ch mov esi,edx call read jc binary_stub cmp word [esi],'MZ' jne binary_stub add edi,1Ch movzx ecx,word [esi+6] add ecx,11b and ecx,not 11b add ecx,(40h-1Ch) shr 2 lea eax,[edi+ecx*4] cmp edi,[tagged_blocks] jae out_of_memory xor eax,eax rep stos dword [edi] mov edx,40h xchg dx,[esi+18h] xor al,al call lseek movzx ecx,word [esi+6] shl ecx,2 lea edx,[esi+40h] call read mov edx,edi sub edx,esi shr edx,4 xchg dx,[esi+8] shl edx,4 xor al,al call lseek movzx ecx,word [esi+4] dec ecx js out_of_memory shl ecx,9 movzx edx,word [esi+2] test edx,edx jnz stub_header_size_ok mov dx,200h stub_header_size_ok: add ecx,edx mov edx,edi sub ecx,eax je read_stub_code jb stub_code_ok push ecx dec ecx shr ecx,3 inc ecx shl ecx,1 lea eax,[edi+ecx*4] cmp eax,[tagged_blocks] jae out_of_memory xor eax,eax rep stos dword [edi] pop ecx read_stub_code: call read stub_code_ok: call close mov edx,edi sub edx,esi mov ax,dx and ax,1FFh mov [esi+2],ax dec edx shr edx,9 inc edx mov [esi+4],dx mov eax,edi sub eax,esi mov [esi+3Ch],eax pop esi stub_ok: ret binary_stub: mov esi,edi mov ecx,40h shr 2 xor eax,eax rep stos dword [edi] mov al,2 xor edx,edx call lseek push eax xor al,al xor edx,edx call lseek mov ecx,[esp] add ecx,40h+111b and ecx,not 111b mov ax,cx and ax,1FFh mov [esi+2],ax lea eax,[ecx+1FFh] shr eax,9 mov [esi+4],ax mov [esi+3Ch],ecx sub ecx,40h mov eax,10000h sub eax,ecx jbe binary_heap_ok shr eax,4 mov [esi+0Ah],ax binary_heap_ok: mov word [esi],'MZ' mov byte [esi+8],4 mov ax,0FFFFh mov [esi+0Ch],ax dec ax mov [esi+10h],ax sub ax,0Eh mov [esi+0Eh],ax mov [esi+16h],ax mov word [esi+14h],100h mov byte [esi+18h],40h mov eax,[tagged_blocks] sub eax,ecx cmp edi,eax jae out_of_memory mov edx,edi shr ecx,2 xor eax,eax rep stos dword [edi] pop ecx call read call close pop esi ret format_pe: xor edx,edx mov [machine],14Ch mov [subsystem],3 mov [subsystem_version],3 + 10 shl 16 mov [image_base],400000h and [image_base_high],0 test [format_flags],8 jz pe_settings mov [machine],8664h mov [subsystem_version],5 + 0 shl 16 pe_settings: cmp byte [esi],84h je get_stub_name cmp byte [esi],80h je get_pe_base cmp byte [esi],1Bh jne pe_settings_ok lods byte [esi] lods byte [esi] test al,80h+40h jz subsystem_setting cmp al,80h je dll_flag cmp al,81h je wdm_flag cmp al,82h je large_flag cmp al,83h je nx_flag jmp pe_settings dll_flag: bts [format_flags],8 jc setting_already_specified jmp pe_settings wdm_flag: bts [format_flags],9 jc setting_already_specified jmp pe_settings large_flag: bts [format_flags],11 jc setting_already_specified test [format_flags],8 jnz invalid_argument jmp pe_settings nx_flag: bts [format_flags],12 jc setting_already_specified jmp pe_settings subsystem_setting: bts [format_flags],7 jc setting_already_specified and ax,3Fh mov [subsystem],ax cmp ax,10 jb subsystem_type_ok or [format_flags],4 subsystem_type_ok: cmp byte [esi],'(' jne pe_settings inc esi cmp byte [esi],'.' jne invalid_value inc esi push edx cmp byte [esi+11],0 jne invalid_value cmp byte [esi+10],2 ja invalid_value mov dx,[esi+8] cmp dx,8000h je zero_version mov eax,[esi+4] cmp dx,7 jg invalid_value mov cx,7 sub cx,dx mov eax,[esi+4] shr eax,cl mov ebx,eax shr ebx,24 cmp bl,100 jae invalid_value and eax,0FFFFFFh mov ecx,100 mul ecx shrd eax,edx,24 jnc version_value_ok inc eax version_value_ok: shl eax,16 mov ax,bx jmp subsystem_version_ok zero_version: xor eax,eax subsystem_version_ok: pop edx add esi,13 mov [subsystem_version],eax jmp pe_settings get_pe_base: bts [format_flags],10 jc setting_already_specified lods word [esi] cmp ah,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value push edx edi add edi,[stub_size] test [format_flags],4 jnz get_peplus_base call get_dword_value mov [image_base],eax jmp pe_base_ok get_peplus_base: call get_qword_value mov [image_base],eax mov [image_base_high],edx pe_base_ok: pop edi edx cmp [value_type],0 jne invalid_use_of_symbol cmp byte [esi],84h jne pe_settings_ok get_stub_name: lods byte [esi] lods word [esi] cmp ax,'(' jne invalid_argument lods dword [esi] mov edx,esi add esi,eax inc esi pe_settings_ok: mov ebp,[stub_size] or ebp,ebp jz make_pe_stub cmp edx,[stub_file] je pe_stub_ok sub edi,[stub_size] mov [code_start],edi make_pe_stub: call make_stub mov eax,edi sub eax,[code_start] mov [stub_size],eax mov [code_start],edi mov ebp,eax pe_stub_ok: mov edx,edi mov ecx,18h+0E0h test [format_flags],4 jz zero_pe_header add ecx,10h zero_pe_header: add ebp,ecx shr ecx,2 xor eax,eax rep stos dword [edi] mov word [edx],'PE' ; signature mov ax,[machine] mov word [edx+4],ax mov byte [edx+38h+1],10h ; section alignment mov byte [edx+3Ch+1],2 ; file alignment mov byte [edx+40h],1 ; OS version mov eax,[subsystem_version] mov [edx+48h],eax mov ax,[subsystem] mov [edx+5Ch],ax cmp ax,1 jne pe_alignment_ok mov eax,20h mov dword [edx+38h],eax mov dword [edx+3Ch],eax pe_alignment_ok: mov word [edx+1Ah],VERSION_MAJOR + VERSION_MINOR shl 8 test [format_flags],4 jnz init_peplus_specific mov byte [edx+14h],0E0h ; size of optional header mov dword [edx+16h],10B010Fh; flags and magic value mov eax,[image_base] mov [edx+34h],eax mov byte [edx+60h+1],10h ; stack reserve mov byte [edx+64h+1],10h ; stack commit mov byte [edx+68h+2],1 ; heap reserve mov byte [edx+74h],16 ; number of directories jmp pe_header_ok init_peplus_specific: mov byte [edx+14h],0F0h ; size of optional header mov dword [edx+16h],20B002Fh; flags and magic value mov eax,[image_base] mov [edx+30h],eax mov eax,[image_base_high] mov [edx+34h],eax mov byte [edx+60h+1],10h ; stack reserve mov byte [edx+68h+1],10h ; stack commit mov byte [edx+70h+2],1 ; heap reserve mov byte [edx+84h],16 ; number of directories pe_header_ok: bsf ecx,[edx+3Ch] imul ebx,[number_of_sections],28h or ebx,ebx jnz reserve_space_for_section_headers mov ebx,28h reserve_space_for_section_headers: add ebx,ebp dec ebx shr ebx,cl inc ebx shl ebx,cl sub ebx,ebp mov ecx,ebx mov eax,[tagged_blocks] sub eax,ecx cmp edi,eax jae out_of_memory shr ecx,2 xor eax,eax rep stos dword [edi] mov eax,edi sub eax,[code_start] add eax,[stub_size] mov [edx+54h],eax ; size of headers mov ecx,[edx+38h] dec ecx add eax,ecx not ecx and eax,ecx bt [format_flags],8 jc pe_entry_init_ok mov [edx+28h],eax ; entry point rva pe_entry_init_ok: and [number_of_sections],0 movzx ebx,word [edx+14h] lea ebx,[edx+18h+ebx] mov [current_section],ebx mov dword [ebx],'.fla' mov dword [ebx+4],'t' mov [ebx+14h],edi mov [ebx+0Ch],eax mov dword [ebx+24h],0E0000060h xor ecx,ecx xor bl,bl not eax not ecx not bl add eax,1 adc ecx,0 adc bl,0 add eax,edi adc ecx,0 adc bl,0 test [format_flags],4 jnz peplus_org sub eax,[edx+34h] sbb ecx,0 sbb bl,0 jmp pe_org_ok peplus_org: sub eax,[edx+30h] sbb ecx,[edx+34h] sbb bl,0 pe_org_ok: test [format_flags],8 jnz pe64_code mov bh,2 mov [code_type],32 jmp pe_code_type_ok pe64_code: mov bh,4 mov [code_type],64 pe_code_type_ok: bt [resolver_flags],0 jc pe_labels_type_ok xor bh,bh pe_labels_type_ok: push eax ebx call init_addressing_space mov ebp,ebx pop ebx eax mov [ds:ebp],eax mov [ds:ebp+4],ecx mov [ds:ebp+8],bx mov [ds:ebp+18h],edi bt [format_flags],8 jnc dll_flag_ok or byte [edx+16h+1],20h dll_flag_ok: bt [format_flags],9 jnc wdm_flag_ok or byte [edx+5Eh+1],20h wdm_flag_ok: bt [format_flags],11 jnc large_flag_ok or byte [edx+16h],20h large_flag_ok: bt [format_flags],12 jnc nx_ok or byte [edx+5Eh+1],1 nx_ok: jmp format_defined pe_section: call close_pe_section push eax ebx call create_addressing_space mov ebp,ebx pop ebx eax bts [format_flags],5 lea ecx,[ebx+28h] add edx,[edx+54h] sub edx,[stub_size] cmp ecx,edx jbe new_section lea ebx,[edx-28h] or [next_pass_needed],-1 push edi mov edi,ebx mov ecx,28h shr 4 xor eax,eax rep stos dword [edi] pop edi new_section: mov [ebx+0Ch],eax lods word [esi] cmp ax,'(' jne invalid_argument lea edx,[esi+4] mov ecx,[esi] lea esi,[esi+4+ecx+1] cmp ecx,8 ja name_too_long xor eax,eax mov [ebx],eax mov [ebx+4],eax push esi edi mov edi,ebx mov esi,edx rep movs byte [edi],[esi] pop edi esi and dword [ebx+24h],0 mov [ebx+14h],edi mov edx,[code_start] mov eax,edi xor ecx,ecx sub eax,[ebx+0Ch] sbb ecx,0 sbb byte [ds:ebp+8],0 mov byte [ds:ebp+9],2 mov [code_type],32 test [format_flags],8 jz pe_section_code_type_ok mov byte [ds:ebp+9],4 mov [code_type],64 pe_section_code_type_ok: test [format_flags],4 jnz peplus_section_org sub eax,[edx+34h] sbb ecx,0 sbb byte [ds:ebp+8],0 bt [resolver_flags],0 jc pe_section_org_ok mov byte [ds:ebp+9],0 jmp pe_section_org_ok peplus_section_org: sub eax,[edx+30h] sbb ecx,[edx+34h] sbb byte [ds:ebp+8],0 bt [resolver_flags],0 jc pe_section_org_ok mov byte [ds:ebp+9],0 pe_section_org_ok: mov [ds:ebp],eax mov [ds:ebp+4],ecx mov [ds:ebp+18h],edi get_section_flags: lods byte [esi] cmp al,1Ah je set_directory cmp al,19h je section_flag dec esi jmp instruction_assembled set_directory: movzx eax,byte [esi] inc esi mov ecx,ebx test [format_flags],4 jnz peplus_directory xchg ecx,[edx+78h+eax*8] mov dword [edx+78h+eax*8+4],-1 jmp pe_directory_set peplus_directory: xchg ecx,[edx+88h+eax*8] mov dword [edx+88h+eax*8+4],-1 pe_directory_set: or ecx,ecx jnz data_already_defined push ebx edx call generate_pe_data pop edx ebx jmp get_section_flags section_flag: lods byte [esi] cmp al,9 je invalid_argument cmp al,11 je invalid_argument mov cl,al mov eax,1 shl eax,cl test dword [ebx+24h],eax jnz setting_already_specified or dword [ebx+24h],eax jmp get_section_flags close_pe_section: mov ebx,[current_section] mov edx,[code_start] mov eax,edi sub eax,[ebx+14h] jnz finish_section bt [format_flags],5 jc finish_section mov eax,[ebx+0Ch] ret finish_section: mov [ebx+8],eax cmp edi,[undefined_data_end] jne align_section cmp dword [edx+38h],1000h jb align_section mov edi,[undefined_data_start] align_section: and [undefined_data_end],0 mov ebp,edi sub ebp,[ebx+14h] mov ecx,[edx+3Ch] dec ecx lea eax,[ebp+ecx] not ecx and eax,ecx mov [ebx+10h],eax sub eax,ebp mov ecx,eax xor al,al rep stos byte [edi] mov eax,[code_start] sub eax,[stub_size] sub [ebx+14h],eax mov ecx,[ebx+10h] test byte [ebx+24h],20h jz pe_code_sum_ok add [edx+1Ch],ecx cmp dword [edx+2Ch],0 jne pe_code_sum_ok mov eax,[ebx+0Ch] mov [edx+2Ch],eax pe_code_sum_ok: test byte [ebx+24h],40h jz pe_data_sum_ok add [edx+20h],ecx test [format_flags],4 jnz pe_data_sum_ok cmp dword [edx+30h],0 jne pe_data_sum_ok mov eax,[ebx+0Ch] mov [edx+30h],eax pe_data_sum_ok: mov eax,[ebx+8] or eax,eax jz udata_ok cmp dword [ebx+10h],0 jne udata_ok or byte [ebx+24h],80h add [edx+24h],ecx udata_ok: mov ecx,[edx+38h] dec ecx add eax,ecx not ecx and eax,ecx add eax,[ebx+0Ch] add ebx,28h mov [current_section],ebx inc word [number_of_sections] jz format_limitations_exceeded ret data_directive: cmp [output_format],3 jne illegal_instruction lods byte [esi] cmp al,1Ah je predefined_data_type cmp al,'(' jne invalid_argument call get_byte_value cmp al,16 jb data_type_ok jmp invalid_value predefined_data_type: movzx eax,byte [esi] inc esi data_type_ok: mov ebx,[current_section] mov ecx,edi sub ecx,[ebx+14h] add ecx,[ebx+0Ch] mov edx,[code_start] test [format_flags],4 jnz peplus_data xchg ecx,[edx+78h+eax*8] jmp init_pe_data peplus_data: xchg ecx,[edx+88h+eax*8] init_pe_data: or ecx,ecx jnz data_already_defined call allocate_structure_data mov word [ebx],data_directive-instruction_handler mov [ebx+2],al mov edx,[current_line] mov [ebx+4],edx call generate_pe_data jmp instruction_assembled end_data: cmp [output_format],3 jne illegal_instruction call find_structure_data jc unexpected_instruction movzx eax,byte [ebx+2] mov edx,[current_section] mov ecx,edi sub ecx,[edx+14h] add ecx,[edx+0Ch] mov edx,[code_start] test [format_flags],4 jnz end_peplus_data sub ecx,[edx+78h+eax*8] mov [edx+78h+eax*8+4],ecx jmp remove_structure_data end_peplus_data: sub ecx,[edx+88h+eax*8] mov [edx+88h+eax*8+4],ecx jmp remove_structure_data pe_entry: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value test [format_flags],8 jnz pe64_entry call get_dword_value mov bl,2 bt [resolver_flags],0 jc check_pe_entry_label_type xor bl,bl check_pe_entry_label_type: cmp [value_type],bl je pe_entry_ok call recoverable_invalid_address pe_entry_ok: cdq test [format_flags],4 jnz pe64_entry_type_ok mov edx,[code_start] sub eax,[edx+34h] mov [edx+28h],eax jmp instruction_assembled pe64_entry: call get_qword_value mov bl,4 bt [resolver_flags],0 jc check_pe64_entry_label_type xor bl,bl check_pe64_entry_label_type: cmp [value_type],bl je pe64_entry_type_ok call recoverable_invalid_address pe64_entry_type_ok: mov ecx,[code_start] sub eax,[ecx+30h] sbb edx,[ecx+34h] jz pe64_entry_range_ok call recoverable_overflow pe64_entry_range_ok: mov [ecx+28h],eax jmp instruction_assembled pe_stack: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value test [format_flags],4 jnz peplus_stack call get_count_value mov edx,[code_start] mov [edx+60h],eax cmp byte [esi],',' jne default_stack_commit lods byte [esi] lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov edx,[code_start] mov [edx+64h],eax cmp eax,[edx+60h] ja value_out_of_range jmp instruction_assembled default_stack_commit: mov dword [edx+64h],1000h mov eax,[edx+60h] cmp eax,1000h ja instruction_assembled mov dword [edx+64h],eax jmp instruction_assembled peplus_stack: call get_qword_value cmp [value_type],0 jne invalid_use_of_symbol mov ecx,[code_start] mov [ecx+60h],eax mov [ecx+64h],edx cmp byte [esi],',' jne default_peplus_stack_commit lods byte [esi] lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_qword_value cmp [value_type],0 jne invalid_use_of_symbol mov ecx,[code_start] mov [ecx+68h],eax mov [ecx+6Ch],edx cmp edx,[ecx+64h] ja value_out_of_range jb instruction_assembled cmp eax,[ecx+60h] ja value_out_of_range jmp instruction_assembled default_peplus_stack_commit: mov dword [ecx+68h],1000h cmp dword [ecx+64h],0 jne instruction_assembled mov eax,[ecx+60h] cmp eax,1000h ja instruction_assembled mov dword [ecx+68h],eax jmp instruction_assembled pe_heap: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value test [format_flags],4 jnz peplus_heap call get_count_value mov edx,[code_start] mov [edx+68h],eax cmp byte [esi],',' jne instruction_assembled lods byte [esi] lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_count_value mov edx,[code_start] mov [edx+6Ch],eax cmp eax,[edx+68h] ja value_out_of_range jmp instruction_assembled peplus_heap: call get_qword_value cmp [value_type],0 jne invalid_use_of_symbol mov ecx,[code_start] mov [ecx+70h],eax mov [ecx+74h],edx cmp byte [esi],',' jne instruction_assembled lods byte [esi] lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value call get_qword_value cmp [value_type],0 jne invalid_use_of_symbol mov ecx,[code_start] mov [ecx+78h],eax mov [ecx+7Ch],edx cmp edx,[ecx+74h] ja value_out_of_range jb instruction_assembled cmp eax,[ecx+70h] ja value_out_of_range jmp instruction_assembled mark_pe_relocation: push eax ebx test [format_flags],4 jz check_standard_pe_relocation_type cmp [value_type],4 je pe_relocation_type_ok check_standard_pe_relocation_type: cmp [value_type],2 je pe_relocation_type_ok call recoverable_misuse pe_relocation_type_ok: mov ebx,[current_section] mov eax,edi sub eax,[ebx+14h] add eax,[ebx+0Ch] mov ebx,[free_additional_memory] inc [number_of_relocations] add ebx,5 cmp ebx,[structures_buffer] jae out_of_memory mov [free_additional_memory],ebx mov [ebx-5],eax cmp [value_type],2 je fixup_32bit mov byte [ebx-1],0Ah jmp fixup_ok fixup_32bit: mov byte [ebx-1],3 fixup_ok: pop ebx eax ret generate_pe_data: cmp al,2 je make_pe_resource cmp al,5 je make_pe_fixups ret make_pe_fixups: mov edx,[code_start] and byte [edx+16h],not 1 or byte [edx+5Eh],40h bts [resolver_flags],0 jc fixups_ready or [next_pass_needed],-1 fixups_ready: and [last_fixup_base],0 call make_fixups xchg eax,[actual_fixups_size] sub eax,[actual_fixups_size] ja reserve_forward_fixups xor eax,eax reserve_forward_fixups: mov [reserved_fixups],edi add edi,eax mov [reserved_fixups_size],eax ret make_fixups: push esi xor ecx,ecx xchg ecx,[number_of_relocations] mov esi,[free_additional_memory] lea eax,[ecx*5] sub esi,eax mov [free_additional_memory],esi mov edx,[last_fixup_base] mov ebx,[last_fixup_header] mov ebp,edi jecxz fixups_done make_fixup: cmp [esi],edx jb store_fixup mov eax,edi sub eax,ebp test eax,11b jz fixups_block xor ax,ax stos word [edi] add dword [ebx],2 fixups_block: mov eax,edx add edx,1000h cmp [esi],edx jae fixups_block stos dword [edi] mov ebx,edi mov eax,8 stos dword [edi] store_fixup: add dword [ebx],2 mov ah,[esi+1] and ah,0Fh mov al,[esi+4] shl al,4 or ah,al mov al,[esi] stos word [edi] add esi,5 loop make_fixup fixups_done: mov [last_fixup_base],edx mov [last_fixup_header],ebx pop esi mov eax,edi sub eax,ebp ret make_pe_resource: cmp byte [esi],82h jne resource_done inc esi lods word [esi] cmp ax,'(' jne invalid_argument lods dword [esi] mov edx,esi lea esi,[esi+eax+1] cmp [next_pass_needed],0 je resource_from_file cmp [current_pass],0 jne reserve_space_for_resource and [resource_size],0 reserve_space_for_resource: add edi,[resource_size] cmp edi,[tagged_blocks] ja out_of_memory jmp resource_done resource_from_file: push esi mov esi,edx call open_binary_file push ebx mov esi,[free_additional_memory] lea eax,[esi+20h] cmp eax,[structures_buffer] ja out_of_memory mov edx,esi mov ecx,20h call read jc invalid_file_format xor eax,eax cmp [esi],eax jne invalid_file_format mov ax,0FFFFh cmp [esi+8],eax jne invalid_file_format cmp [esi+12],eax jne invalid_file_format mov eax,20h cmp [esi+4],eax jne invalid_file_format read_resource_headers: test eax,11b jz resource_file_alignment_ok mov edx,4 and eax,11b sub edx,eax mov al,1 call lseek jc resource_headers_ok resource_file_alignment_ok: mov [esi],eax lea edx,[esi+12] mov ecx,8 call read jc resource_headers_ok mov ecx,[esi+16] add [esi],ecx lea edx,[esi+20] sub ecx,8 mov [esi+16],ecx lea eax,[edx+ecx] cmp eax,[structures_buffer] ja out_of_memory call read jc invalid_file_format mov edx,[esi] add edx,[esi+12] mov eax,[esi+16] lea ecx,[esi+20] lea esi,[ecx+eax] add ecx,2 cmp word [ecx-2],0FFFFh je resource_header_type_ok check_resource_header_type: cmp ecx,esi jae invalid_file_format cmp word [ecx],0 je resource_header_type_ok add ecx,2 jmp check_resource_header_type resource_header_type_ok: add ecx,2 cmp word [ecx],0FFFFh je resource_header_name_ok check_resource_header_name: cmp ecx,esi jae invalid_file_format cmp word [ecx],0 je resource_header_name_ok add ecx,2 jmp check_resource_header_name resource_header_name_ok: xor al,al call lseek jnc read_resource_headers resource_headers_ok: cmp esi,[free_additional_memory] je invalid_file_format xor eax,eax mov [esi],eax mov [resource_data],edi lea eax,[edi+16] cmp eax,[tagged_blocks] jae out_of_memory xor eax,eax stos dword [edi] call make_timestamp stos dword [edi] xor eax,eax stos dword [edi] stos dword [edi] xor ebx,ebx make_type_name_directory: mov esi,[free_additional_memory] xor edx,edx find_type_name: cmp dword [esi],0 je type_name_ok add esi,20 cmp word [esi],0FFFFh je check_next_type_name or ebx,ebx jz check_this_type_name xor ecx,ecx compare_with_previous_type_name: mov ax,[esi+ecx] cmp ax,[ebx+ecx] ja check_this_type_name jb check_next_type_name add ecx,2 mov ax,[esi+ecx] or ax,[ebx+ecx] jnz compare_with_previous_type_name jmp check_next_type_name check_this_type_name: or edx,edx jz type_name_found xor ecx,ecx compare_with_current_type_name: mov ax,[esi+ecx] cmp ax,[edx+ecx] ja check_next_type_name jb type_name_found add ecx,2 mov ax,[esi+ecx] or ax,[edx+ecx] jnz compare_with_current_type_name jmp same_type_name type_name_found: mov edx,esi same_type_name: mov [esi-16],edi check_next_type_name: mov eax,[esi-4] add esi,eax jmp find_type_name type_name_ok: or edx,edx jz type_name_directory_done mov ebx,edx make_type_name_entry: mov eax,[resource_data] inc word [eax+12] lea eax,[edi+8] cmp eax,[tagged_blocks] jae out_of_memory mov eax,ebx stos dword [edi] xor eax,eax stos dword [edi] jmp make_type_name_directory type_name_directory_done: mov ebx,-1 make_type_id_directory: mov esi,[free_additional_memory] mov edx,10000h find_type_id: cmp dword [esi],0 je type_id_ok add esi,20 cmp word [esi],0FFFFh jne check_next_type_id movzx eax,word [esi+2] cmp eax,ebx jle check_next_type_id cmp eax,edx jg check_next_type_id mov edx,eax mov [esi-16],edi check_next_type_id: mov eax,[esi-4] add esi,eax jmp find_type_id type_id_ok: cmp edx,10000h je type_id_directory_done mov ebx,edx make_type_id_entry: mov eax,[resource_data] inc word [eax+14] lea eax,[edi+8] cmp eax,[tagged_blocks] jae out_of_memory mov eax,ebx stos dword [edi] xor eax,eax stos dword [edi] jmp make_type_id_directory type_id_directory_done: mov esi,[resource_data] add esi,10h mov ecx,[esi-4] or cx,cx jz resource_directories_ok make_resource_directories: push ecx push edi mov edx,edi sub edx,[resource_data] bts edx,31 mov [esi+4],edx lea eax,[edi+16] cmp eax,[tagged_blocks] jae out_of_memory xor eax,eax stos dword [edi] call make_timestamp stos dword [edi] xor eax,eax stos dword [edi] stos dword [edi] mov ebp,esi xor ebx,ebx make_resource_name_directory: mov esi,[free_additional_memory] xor edx,edx find_resource_name: cmp dword [esi],0 je resource_name_ok push esi cmp [esi+4],ebp jne check_next_resource_name add esi,20 call skip_resource_name cmp word [esi],0FFFFh je check_next_resource_name or ebx,ebx jz check_this_resource_name xor ecx,ecx compare_with_previous_resource_name: mov ax,[esi+ecx] cmp ax,[ebx+ecx] ja check_this_resource_name jb check_next_resource_name add ecx,2 mov ax,[esi+ecx] or ax,[ebx+ecx] jnz compare_with_previous_resource_name jmp check_next_resource_name skip_resource_name: cmp word [esi],0FFFFh jne skip_unicode_string add esi,4 ret skip_unicode_string: add esi,2 cmp word [esi-2],0 jne skip_unicode_string ret check_this_resource_name: or edx,edx jz resource_name_found xor ecx,ecx compare_with_current_resource_name: mov ax,[esi+ecx] cmp ax,[edx+ecx] ja check_next_resource_name jb resource_name_found add ecx,2 mov ax,[esi+ecx] or ax,[edx+ecx] jnz compare_with_current_resource_name jmp same_resource_name resource_name_found: mov edx,esi same_resource_name: mov eax,[esp] mov [eax+8],edi check_next_resource_name: pop esi mov eax,[esi+16] lea esi,[esi+20+eax] jmp find_resource_name resource_name_ok: or edx,edx jz resource_name_directory_done mov ebx,edx make_resource_name_entry: mov eax,[esp] inc word [eax+12] lea eax,[edi+8] cmp eax,[tagged_blocks] jae out_of_memory mov eax,ebx stos dword [edi] xor eax,eax stos dword [edi] jmp make_resource_name_directory resource_name_directory_done: mov ebx,-1 make_resource_id_directory: mov esi,[free_additional_memory] mov edx,10000h find_resource_id: cmp dword [esi],0 je resource_id_ok push esi cmp [esi+4],ebp jne check_next_resource_id add esi,20 call skip_resource_name cmp word [esi],0FFFFh jne check_next_resource_id movzx eax,word [esi+2] cmp eax,ebx jle check_next_resource_id cmp eax,edx jg check_next_resource_id mov edx,eax mov eax,[esp] mov [eax+8],edi check_next_resource_id: pop esi mov eax,[esi+16] lea esi,[esi+20+eax] jmp find_resource_id resource_id_ok: cmp edx,10000h je resource_id_directory_done mov ebx,edx make_resource_id_entry: mov eax,[esp] inc word [eax+14] lea eax,[edi+8] cmp eax,[tagged_blocks] jae out_of_memory mov eax,ebx stos dword [edi] xor eax,eax stos dword [edi] jmp make_resource_id_directory resource_id_directory_done: pop eax mov esi,ebp pop ecx add esi,8 dec cx jnz make_resource_directories resource_directories_ok: shr ecx,16 jnz make_resource_directories mov esi,[resource_data] add esi,10h movzx eax,word [esi-4] movzx edx,word [esi-2] add eax,edx lea esi,[esi+eax*8] push edi ; address of language directories update_resource_directories: cmp esi,[esp] je resource_directories_updated add esi,10h mov ecx,[esi-4] or cx,cx jz language_directories_ok make_language_directories: push ecx push edi mov edx,edi sub edx,[resource_data] bts edx,31 mov [esi+4],edx lea eax,[edi+16] cmp eax,[tagged_blocks] jae out_of_memory xor eax,eax stos dword [edi] call make_timestamp stos dword [edi] xor eax,eax stos dword [edi] stos dword [edi] mov ebp,esi mov ebx,-1 make_language_id_directory: mov esi,[free_additional_memory] mov edx,10000h find_language_id: cmp dword [esi],0 je language_id_ok push esi cmp [esi+8],ebp jne check_next_language_id add esi,20 mov eax,esi call skip_resource_name call skip_resource_name neg eax add eax,esi and eax,11b add esi,eax get_language_id: movzx eax,word [esi+6] cmp eax,ebx jle check_next_language_id cmp eax,edx jge check_next_language_id mov edx,eax mov eax,[esp] mov dword [value],eax check_next_language_id: pop esi mov eax,[esi+16] lea esi,[esi+20+eax] jmp find_language_id language_id_ok: cmp edx,10000h je language_id_directory_done mov ebx,edx make_language_id_entry: mov eax,[esp] inc word [eax+14] lea eax,[edi+8] cmp eax,[tagged_blocks] jae out_of_memory mov eax,ebx stos dword [edi] mov eax,dword [value] stos dword [edi] jmp make_language_id_directory language_id_directory_done: pop eax mov esi,ebp pop ecx add esi,8 dec cx jnz make_language_directories language_directories_ok: shr ecx,16 jnz make_language_directories jmp update_resource_directories resource_directories_updated: mov esi,[resource_data] push edi make_name_strings: add esi,10h movzx eax,word [esi-2] movzx ecx,word [esi-4] add eax,ecx lea eax,[esi+eax*8] push eax or ecx,ecx jz string_entries_processed process_string_entries: push ecx mov edx,edi sub edx,[resource_data] bts edx,31 xchg [esi],edx mov ebx,edi xor ax,ax stos word [edi] copy_string_data: lea eax,[edi+2] cmp eax,[tagged_blocks] jae out_of_memory mov ax,[edx] or ax,ax jz string_data_copied stos word [edi] inc word [ebx] add edx,2 jmp copy_string_data string_data_copied: add esi,8 pop ecx loop process_string_entries string_entries_processed: pop esi cmp esi,[esp] jb make_name_strings mov eax,edi sub eax,[resource_data] test al,11b jz resource_strings_alignment_ok xor ax,ax stos word [edi] resource_strings_alignment_ok: pop edx pop ebx ; address of language directories mov ebp,edi update_language_directories: add ebx,10h movzx eax,word [ebx-2] movzx ecx,word [ebx-4] add ecx,eax make_data_records: push ecx mov esi,edi sub esi,[resource_data] xchg esi,[ebx+4] lea eax,[edi+16] cmp eax,[tagged_blocks] jae out_of_memory mov eax,esi stos dword [edi] mov eax,[esi+12] stos dword [edi] xor eax,eax stos dword [edi] stos dword [edi] pop ecx add ebx,8 loop make_data_records cmp ebx,edx jb update_language_directories pop ebx ; file handle mov esi,ebp mov ebp,edi update_data_records: push ebp mov ecx,edi mov eax,[current_section] sub ecx,[eax+14h] add ecx,[eax+0Ch] xchg ecx,[esi] mov edx,[ecx] xor al,al call lseek mov edx,edi mov ecx,[esi+4] add edi,ecx cmp edi,[tagged_blocks] ja out_of_memory call read mov eax,edi sub eax,[resource_data] and eax,11b jz resource_data_alignment_ok mov ecx,4 sub ecx,eax xor al,al rep stos byte [edi] resource_data_alignment_ok: pop ebp add esi,16 cmp esi,ebp jb update_data_records pop esi call close mov eax,edi sub eax,[resource_data] mov [resource_size],eax resource_done: ret close_pe: call close_pe_section mov edx,[code_start] mov [edx+50h],eax call make_timestamp mov edx,[code_start] mov [edx+8],eax mov eax,[number_of_sections] mov [edx+6],ax imul eax,28h movzx ecx,word [edx+14h] lea eax,[eax+18h+ecx] add eax,[stub_size] mov ecx,[edx+3Ch] dec ecx add eax,ecx not ecx and eax,ecx cmp eax,[edx+54h] je pe_sections_ok or [next_pass_needed],-1 pe_sections_ok: xor ecx,ecx add edx,78h test [format_flags],4 jz process_directories add edx,10h process_directories: mov eax,[edx+ecx*8] or eax,eax jz directory_ok cmp dword [edx+ecx*8+4],-1 jne directory_ok section_data: mov ebx,[edx+ecx*8] mov eax,[ebx+0Ch] mov [edx+ecx*8],eax ; directory rva mov eax,[ebx+8] mov [edx+ecx*8+4],eax ; directory size directory_ok: inc cl cmp cl,10h jb process_directories cmp dword [edx+5*8],0 jne finish_pe_relocations mov eax,[number_of_relocations] shl eax,2 sub [free_additional_memory],eax btr [resolver_flags],0 jnc pe_relocations_ok or [next_pass_needed],-1 jmp pe_relocations_ok finish_pe_relocations: push edi mov edi,[reserved_fixups] call make_fixups pop edi add [actual_fixups_size],eax cmp eax,[reserved_fixups_size] je pe_relocations_ok or [next_pass_needed],-1 pe_relocations_ok: mov ebx,[code_start] sub ebx,[stub_size] mov ecx,edi sub ecx,ebx mov ebp,ecx shr ecx,1 xor eax,eax cdq calculate_checksum: mov dx,[ebx] add eax,edx mov dx,ax shr eax,16 add eax,edx add ebx,2 loop calculate_checksum add eax,ebp mov ebx,[code_start] mov [ebx+58h],eax ret format_coff: mov eax,[additional_memory] mov [symbols_stream],eax mov ebx,eax add eax,20h cmp eax,[structures_buffer] jae out_of_memory mov [free_additional_memory],eax xor eax,eax mov [ebx],al mov [ebx+4],eax mov [ebx+8],edi mov al,4 mov [ebx+10h],eax mov al,60h bt [format_flags],0 jnc flat_section_flags_ok or eax,0E0000000h flat_section_flags_ok: mov dword [ebx+14h],eax mov [current_section],ebx xor eax,eax mov [number_of_sections],eax mov edx,ebx call init_addressing_space mov [ebx+14h],edx mov byte [ebx+9],2 mov [code_type],32 test [format_flags],8 jz format_defined mov byte [ebx+9],4 mov [code_type],64 jmp format_defined coff_section: call close_coff_section mov ebx,[free_additional_memory] lea eax,[ebx+20h] cmp eax,[structures_buffer] jae out_of_memory mov [free_additional_memory],eax mov [current_section],ebx inc [number_of_sections] xor eax,eax mov [ebx],al mov [ebx+8],edi mov [ebx+10h],eax mov [ebx+14h],eax mov edx,ebx call create_addressing_space xchg edx,ebx mov [edx+14h],ebx mov byte [edx+9],2 test [format_flags],8 jz coff_labels_type_ok mov byte [edx+9],4 coff_labels_type_ok: lods word [esi] cmp ax,'(' jne invalid_argument mov [ebx+4],esi mov ecx,[esi] lea esi,[esi+4+ecx+1] cmp ecx,8 ja name_too_long coff_section_flags: cmp byte [esi],8Ch je coff_section_alignment cmp byte [esi],19h jne coff_section_settings_ok inc esi lods byte [esi] bt [format_flags],0 jc coff_section_flag_ok cmp al,7 ja invalid_argument coff_section_flag_ok: mov cl,al mov eax,1 shl eax,cl test dword [ebx+14h],eax jnz setting_already_specified or dword [ebx+14h],eax jmp coff_section_flags coff_section_alignment: bt [format_flags],0 jnc invalid_argument inc esi lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value push ebx call get_count_value pop ebx mov edx,eax dec edx test eax,edx jnz invalid_value or eax,eax jz invalid_value cmp eax,2000h ja invalid_value bsf edx,eax inc edx shl edx,20 or [ebx+14h],edx xchg [ebx+10h],eax or eax,eax jnz setting_already_specified jmp coff_section_flags coff_section_settings_ok: cmp dword [ebx+10h],0 jne instruction_assembled mov dword [ebx+10h],4 bt [format_flags],0 jnc instruction_assembled or dword [ebx+14h],300000h jmp instruction_assembled close_coff_section: mov ebx,[current_section] mov eax,edi mov edx,[ebx+8] sub eax,edx mov [ebx+0Ch],eax xor eax,eax xchg [undefined_data_end],eax cmp eax,edi jne coff_section_ok cmp edx,[undefined_data_start] jne coff_section_ok mov edi,edx or byte [ebx+14h],80h coff_section_ok: ret mark_coff_relocation: cmp [value_type],3 je coff_relocation_relative push ebx eax test [format_flags],8 jnz coff_64bit_relocation mov al,6 cmp [value_type],2 je coff_relocation cmp [value_type],5 jne invalid_use_of_symbol inc al jmp coff_relocation coff_64bit_relocation: mov al,1 cmp [value_type],4 je coff_relocation mov al,2 cmp [value_type],2 je coff_relocation cmp [value_type],5 jne invalid_use_of_symbol inc al jmp coff_relocation coff_relocation_relative: push ebx bt [format_flags],0 jnc relative_ok mov ebx,[current_section] mov ebx,[ebx+8] sub ebx,edi sub eax,ebx add eax,4 relative_ok: mov ebx,[addressing_space] push eax mov al,20 test [format_flags],8 jnz relative_coff_64bit_relocation cmp byte [ebx+9],2 jne invalid_use_of_symbol jmp coff_relocation relative_coff_64bit_relocation: mov al,4 cmp byte [ebx+9],4 jne invalid_use_of_symbol coff_relocation: mov ebx,[free_additional_memory] add ebx,0Ch cmp ebx,[structures_buffer] jae out_of_memory mov [free_additional_memory],ebx mov byte [ebx-0Ch],al mov eax,[current_section] mov eax,[eax+8] neg eax add eax,edi mov [ebx-0Ch+4],eax mov eax,[symbol_identifier] mov [ebx-0Ch+8],eax pop eax ebx ret close_coff: call close_coff_section cmp [next_pass_needed],0 je coff_closed mov eax,[symbols_stream] mov [free_additional_memory],eax coff_closed: ret coff_formatter: sub edi,[code_start] mov [code_size],edi call prepare_default_section mov edi,[free_additional_memory] mov ebx,edi mov ecx,28h shr 2 imul ecx,[number_of_sections] add ecx,14h shr 2 lea eax,[edi+ecx*4] cmp eax,[structures_buffer] jae out_of_memory xor eax,eax rep stos dword [edi] mov word [ebx],14Ch test [format_flags],8 jz coff_magic_ok mov word [ebx],8664h coff_magic_ok: mov word [ebx+12h],104h bt [format_flags],0 jnc coff_flags_ok or byte [ebx+12h],80h coff_flags_ok: push ebx call make_timestamp pop ebx mov [ebx+4],eax mov eax,[number_of_sections] mov [ebx+2],ax mov esi,[symbols_stream] xor eax,eax xor ecx,ecx enumerate_symbols: cmp esi,[free_additional_memory] je symbols_enumerated mov dl,[esi] or dl,dl jz enumerate_section cmp dl,0C0h jae enumerate_public cmp dl,80h jae enumerate_extrn add esi,0Ch jmp enumerate_symbols enumerate_section: mov edx,eax shl edx,8 mov [esi],edx inc eax inc ecx mov [esi+1Eh],cx add esi,20h jmp enumerate_symbols enumerate_public: mov edx,eax shl edx,8 mov dl,[esi] mov [esi],edx mov edx,[esi+8] add esi,10h inc eax cmp byte [edx+11],0 je enumerate_symbols mov edx,[edx+20] cmp byte [edx],0C0h jae enumerate_symbols cmp byte [edx],80h jb enumerate_symbols inc eax jmp enumerate_symbols enumerate_extrn: mov edx,eax shl edx,8 mov dl,[esi] mov [esi],edx add esi,0Ch inc eax jmp enumerate_symbols prepare_default_section: mov ebx,[symbols_stream] cmp dword [ebx+0Ch],0 jne default_section_ok cmp [number_of_sections],0 je default_section_ok mov edx,ebx find_references_to_default_section: cmp ebx,[free_additional_memory] jne check_reference add [symbols_stream],20h ret check_reference: mov al,[ebx] or al,al jz skip_other_section cmp al,0C0h jae check_public_reference cmp al,80h jae next_reference cmp edx,[ebx+8] je default_section_ok next_reference: add ebx,0Ch jmp find_references_to_default_section check_public_reference: mov eax,[ebx+8] add ebx,10h test byte [eax+8],1 jz find_references_to_default_section mov cx,[current_pass] cmp cx,[eax+16] jne find_references_to_default_section cmp edx,[eax+20] je default_section_ok jmp find_references_to_default_section skip_other_section: add ebx,20h jmp find_references_to_default_section default_section_ok: inc [number_of_sections] ret symbols_enumerated: mov [ebx+0Ch],eax mov ebp,edi sub ebp,ebx push ebp lea edi,[ebx+14h] mov esi,[symbols_stream] find_section: cmp esi,[free_additional_memory] je sections_finished mov al,[esi] or al,al jz section_found add esi,0Ch cmp al,0C0h jb find_section add esi,4 jmp find_section section_found: push esi edi mov esi,[esi+4] or esi,esi jz default_section mov ecx,[esi] add esi,4 rep movs byte [edi],[esi] jmp section_name_ok default_section: mov al,'.' stos byte [edi] mov eax,'flat' stos dword [edi] section_name_ok: pop edi esi mov eax,[esi+0Ch] mov [edi+10h],eax mov eax,[esi+14h] mov [edi+24h],eax test al,80h jnz section_ptr_ok mov eax,[esi+8] sub eax,[code_start] add eax,ebp mov [edi+14h],eax section_ptr_ok: mov ebx,[code_start] mov edx,[code_size] add ebx,edx add edx,ebp xor ecx,ecx add esi,20h find_relocations: cmp esi,[free_additional_memory] je section_relocations_done mov al,[esi] or al,al jz section_relocations_done cmp al,80h jb add_relocation cmp al,0C0h jb next_relocation add esi,10h jmp find_relocations add_relocation: lea eax,[ebx+0Ah] cmp eax,[tagged_blocks] ja out_of_memory mov eax,[esi+4] mov [ebx],eax mov eax,[esi+8] mov eax,[eax] shr eax,8 mov [ebx+4],eax movzx ax,byte [esi] mov [ebx+8],ax add ebx,0Ah inc ecx next_relocation: add esi,0Ch jmp find_relocations section_relocations_done: cmp ecx,10000h jb section_relocations_count_16bit bt [format_flags],0 jnc format_limitations_exceeded mov word [edi+20h],0FFFFh or dword [edi+24h],1000000h mov [edi+18h],edx push esi edi push ecx lea esi,[ebx-1] add ebx,0Ah lea edi,[ebx-1] imul ecx,0Ah std rep movs byte [edi],[esi] cld pop ecx inc esi inc ecx mov [esi],ecx xor eax,eax mov [esi+4],eax mov [esi+8],ax pop edi esi jmp section_relocations_ok section_relocations_count_16bit: mov [edi+20h],cx jcxz section_relocations_ok mov [edi+18h],edx section_relocations_ok: sub ebx,[code_start] mov [code_size],ebx add edi,28h jmp find_section sections_finished: mov edx,[free_additional_memory] mov ebx,[code_size] add ebp,ebx mov [edx+8],ebp add ebx,[code_start] mov edi,ebx mov ecx,[edx+0Ch] imul ecx,12h shr 1 xor eax,eax shr ecx,1 jnc zero_symbols_table stos word [edi] zero_symbols_table: rep stos dword [edi] mov edx,edi stos dword [edi] mov esi,[symbols_stream] make_symbols_table: cmp esi,[free_additional_memory] je symbols_table_ok mov al,[esi] cmp al,0C0h jae add_public_symbol cmp al,80h jae add_extrn_symbol or al,al jz add_section_symbol add esi,0Ch jmp make_symbols_table add_section_symbol: call store_symbol_name movzx eax,word [esi+1Eh] mov [ebx+0Ch],ax mov byte [ebx+10h],3 add esi,20h add ebx,12h jmp make_symbols_table add_extrn_symbol: call store_symbol_name mov byte [ebx+10h],2 add esi,0Ch add ebx,12h jmp make_symbols_table add_public_symbol: call store_symbol_name mov eax,[esi+0Ch] mov [current_line],eax mov eax,[esi+8] test byte [eax+8],1 jz undefined_coff_public mov cx,[current_pass] cmp cx,[eax+16] jne undefined_coff_public mov cl,[eax+11] or cl,cl jz public_constant test [format_flags],8 jnz check_64bit_public_symbol cmp cl,2 je public_symbol_type_ok jmp invalid_use_of_symbol undefined_coff_public: mov [error_info],eax jmp undefined_symbol check_64bit_public_symbol: cmp cl,4 jne invalid_use_of_symbol public_symbol_type_ok: mov ecx,[eax+20] cmp byte [ecx],80h je alias_symbol cmp byte [ecx],0 jne invalid_use_of_symbol mov cx,[ecx+1Eh] mov [ebx+0Ch],cx public_symbol_section_ok: movzx ecx,byte [eax+9] shr cl,1 and cl,1 neg ecx cmp ecx,[eax+4] jne value_out_of_range xor ecx,[eax] js value_out_of_range mov eax,[eax] mov [ebx+8],eax mov al,2 cmp byte [esi],0C0h je store_symbol_class inc al cmp byte [esi],0C1h je store_symbol_class mov al,105 store_symbol_class: mov byte [ebx+10h],al add esi,10h add ebx,12h jmp make_symbols_table alias_symbol: bt [format_flags],0 jnc invalid_use_of_symbol mov ecx,[eax] or ecx,[eax+4] jnz invalid_use_of_symbol mov byte [ebx+10h],69h mov byte [ebx+11h],1 add ebx,12h mov ecx,[eax+20] mov ecx,[ecx] shr ecx,8 mov [ebx],ecx mov byte [ebx+4],3 add esi,10h add ebx,12h jmp make_symbols_table public_constant: mov word [ebx+0Ch],0FFFFh jmp public_symbol_section_ok symbols_table_ok: mov eax,edi sub eax,edx mov [edx],eax sub edi,[code_start] mov [code_size],edi and [written_size],0 mov edx,[output_file] call create jc write_failed mov edx,[free_additional_memory] pop ecx add [written_size],ecx call write jc write_failed jmp write_output store_symbol_name: push esi mov esi,[esi+4] or esi,esi jz default_name lods dword [esi] mov ecx,eax cmp ecx,8 ja add_string push edi mov edi,ebx rep movs byte [edi],[esi] pop edi esi ret default_name: mov dword [ebx],'.fla' mov dword [ebx+4],'t' pop esi ret add_string: mov eax,edi sub eax,edx mov [ebx+4],eax inc ecx rep movs byte [edi],[esi] pop esi ret format_elf: test [format_flags],8 jnz format_elf64 mov edx,edi mov ecx,34h shr 2 lea eax,[edi+ecx*4] cmp eax,[tagged_blocks] jae out_of_memory xor eax,eax rep stos dword [edi] mov dword [edx],7Fh + 'ELF' shl 8 mov al,1 mov [edx+4],al mov [edx+5],al mov [edx+6],al mov [edx+14h],al mov byte [edx+12h],3 mov byte [edx+28h],34h mov byte [edx+2Eh],28h mov [code_type],32 mov byte [edx+10h],2 cmp word [esi],1D19h je format_elf_exe mov byte [edx+10h],3 cmp word [esi],021Eh je format_elf_exe elf_header_ok: mov byte [edx+10h],1 mov eax,[additional_memory] mov [symbols_stream],eax mov ebx,eax add eax,20h cmp eax,[structures_buffer] jae out_of_memory mov [free_additional_memory],eax xor eax,eax mov [current_section],ebx mov [number_of_sections],eax mov [ebx],al mov [ebx+4],eax mov [ebx+8],edi mov al,111b mov [ebx+14h],eax mov al,4 mov [ebx+10h],eax mov edx,ebx call init_addressing_space xchg edx,ebx mov [edx+14h],ebx mov byte [edx+9],2 test [format_flags],8 jz format_defined mov byte [edx+9],4 mov byte [ebx+10h],8 jmp format_defined format_elf64: mov edx,edi mov ecx,40h shr 2 lea eax,[edi+ecx*4] cmp eax,[tagged_blocks] jae out_of_memory xor eax,eax rep stos dword [edi] mov dword [edx],7Fh + 'ELF' shl 8 mov al,1 mov [edx+5],al mov [edx+6],al mov [edx+14h],al mov byte [edx+4],2 mov byte [edx+12h],62 mov byte [edx+34h],40h mov byte [edx+3Ah],40h mov [code_type],64 mov byte [edx+10h],2 cmp word [esi],1D19h je format_elf64_exe mov byte [edx+10h],3 cmp word [esi],021Eh je format_elf64_exe jmp elf_header_ok elf_section: bt [format_flags],0 jc illegal_instruction call close_coff_section mov ebx,[free_additional_memory] lea eax,[ebx+20h] cmp eax,[structures_buffer] jae out_of_memory mov [free_additional_memory],eax mov [current_section],ebx inc word [number_of_sections] jz format_limitations_exceeded xor eax,eax mov [ebx],al mov [ebx+8],edi mov [ebx+10h],eax mov al,10b mov [ebx+14h],eax mov edx,ebx call create_addressing_space xchg edx,ebx mov [edx+14h],ebx mov byte [edx+9],2 test [format_flags],8 jz elf_labels_type_ok mov byte [edx+9],4 elf_labels_type_ok: lods word [esi] cmp ax,'(' jne invalid_argument mov [ebx+4],esi mov ecx,[esi] lea esi,[esi+4+ecx+1] elf_section_flags: cmp byte [esi],8Ch je elf_section_alignment cmp byte [esi],19h jne elf_section_settings_ok inc esi lods byte [esi] sub al,28 xor al,11b test al,not 10b jnz invalid_argument mov cl,al mov al,1 shl al,cl test byte [ebx+14h],al jnz setting_already_specified or byte [ebx+14h],al jmp elf_section_flags elf_section_alignment: inc esi lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value push ebx call get_count_value pop ebx mov edx,eax dec edx test eax,edx jnz invalid_value or eax,eax jz invalid_value xchg [ebx+10h],eax or eax,eax jnz setting_already_specified jmp elf_section_flags elf_section_settings_ok: cmp dword [ebx+10h],0 jne instruction_assembled mov dword [ebx+10h],4 test [format_flags],8 jz instruction_assembled mov byte [ebx+10h],8 jmp instruction_assembled mark_elf_relocation: test [format_flags],1 jnz invalid_use_of_symbol push ebx mov ebx,[addressing_space] cmp [value_type],3 je elf_relocation_relative cmp [value_type],7 je elf_relocation_relative push eax cmp [value_type],5 je elf_gotoff_relocation ja invalid_use_of_symbol mov al,1 ; R_386_32 / R_AMD64_64 test [format_flags],8 jz coff_relocation cmp [value_type],4 je coff_relocation mov al,11 ; R_AMD64_32S jmp coff_relocation elf_gotoff_relocation: test [format_flags],8 jnz invalid_use_of_symbol mov al,9 ; R_386_GOTOFF jmp coff_relocation elf_relocation_relative: cmp byte [ebx+9],0 je invalid_use_of_symbol mov ebx,[current_section] mov ebx,[ebx+8] sub ebx,edi sub eax,ebx push eax mov al,2 ; R_386_PC32 / R_AMD64_PC32 cmp [value_type],3 je coff_relocation mov al,4 ; R_386_PLT32 / R_AMD64_PLT32 jmp coff_relocation close_elf: bt [format_flags],0 jc close_elf_exe call close_coff_section cmp [next_pass_needed],0 je elf_closed mov eax,[symbols_stream] mov [free_additional_memory],eax elf_closed: ret elf_formatter: mov ecx,edi sub ecx,[code_start] neg ecx and ecx,111b test [format_flags],8 jnz align_elf_structures and ecx,11b align_elf_structures: xor al,al rep stos byte [edi] push edi call prepare_default_section mov esi,[symbols_stream] mov edi,[free_additional_memory] xor eax,eax mov ecx,4 rep stos dword [edi] test [format_flags],8 jz find_first_section mov ecx,2 rep stos dword [edi] find_first_section: mov al,[esi] or al,al jz first_section_found cmp al,0C0h jb skip_other_symbol add esi,4 skip_other_symbol: add esi,0Ch jmp find_first_section first_section_found: mov ebx,esi mov ebp,esi add esi,20h xor ecx,ecx xor edx,edx find_next_section: cmp esi,[free_additional_memory] je make_section_symbol mov al,[esi] or al,al jz make_section_symbol cmp al,0C0h jae skip_public cmp al,80h jae skip_extrn or byte [ebx+14h],40h skip_extrn: add esi,0Ch jmp find_next_section skip_public: add esi,10h jmp find_next_section make_section_symbol: mov eax,edi xchg eax,[ebx+4] stos dword [edi] test [format_flags],8 jnz elf64_section_symbol xor eax,eax stos dword [edi] stos dword [edi] call store_section_index jmp section_symbol_ok store_section_index: inc ecx mov eax,ecx shl eax,8 mov [ebx],eax inc dx jz format_limitations_exceeded mov eax,edx shl eax,16 mov al,3 test byte [ebx+14h],40h jz section_index_ok or ah,-1 inc dx jz format_limitations_exceeded section_index_ok: stos dword [edi] ret elf64_section_symbol: call store_section_index xor eax,eax stos dword [edi] stos dword [edi] stos dword [edi] stos dword [edi] section_symbol_ok: mov ebx,esi add esi,20h cmp ebx,[free_additional_memory] jne find_next_section inc dx jz format_limitations_exceeded mov [current_section],edx mov esi,[symbols_stream] find_other_symbols: cmp esi,[free_additional_memory] je elf_symbol_table_ok mov al,[esi] or al,al jz skip_section cmp al,0C0h jae make_public_symbol cmp al,80h jae make_extrn_symbol add esi,0Ch jmp find_other_symbols skip_section: add esi,20h jmp find_other_symbols make_public_symbol: mov eax,[esi+0Ch] mov [current_line],eax cmp byte [esi],0C0h jne invalid_argument mov ebx,[esi+8] test byte [ebx+8],1 jz undefined_public mov ax,[current_pass] cmp ax,[ebx+16] jne undefined_public mov dl,[ebx+11] or dl,dl jz public_absolute mov eax,[ebx+20] cmp byte [eax],0 jne invalid_use_of_symbol mov eax,[eax+4] test [format_flags],8 jnz elf64_public cmp dl,2 jne invalid_use_of_symbol mov dx,[eax+0Eh] jmp section_for_public_ok undefined_public: mov [error_info],ebx jmp undefined_symbol elf64_public: cmp dl,4 jne invalid_use_of_symbol mov dx,[eax+6] jmp section_for_public_ok public_absolute: mov dx,0FFF1h section_for_public_ok: mov eax,[esi+4] stos dword [edi] test [format_flags],8 jnz elf64_public_symbol movzx eax,byte [ebx+9] shr al,1 and al,1 neg eax cmp eax,[ebx+4] jne value_out_of_range xor eax,[ebx] js value_out_of_range mov eax,[ebx] stos dword [edi] xor eax,eax mov al,[ebx+10] stos dword [edi] mov eax,edx shl eax,16 mov al,10h cmp byte [ebx+10],0 je elf_public_function or al,1 jmp store_elf_public_info elf_public_function: or al,2 store_elf_public_info: stos dword [edi] jmp public_symbol_ok elf64_public_symbol: mov eax,edx shl eax,16 mov al,10h cmp byte [ebx+10],0 je elf64_public_function or al,1 jmp store_elf64_public_info elf64_public_function: or al,2 store_elf64_public_info: stos dword [edi] mov al,[ebx+9] shl eax,31-1 xor eax,[ebx+4] js value_out_of_range mov eax,[ebx] stos dword [edi] mov eax,[ebx+4] stos dword [edi] mov al,[ebx+10] stos dword [edi] xor al,al stos dword [edi] public_symbol_ok: inc ecx mov eax,ecx shl eax,8 mov al,0C0h mov [esi],eax add esi,10h jmp find_other_symbols make_extrn_symbol: mov eax,[esi+4] stos dword [edi] test [format_flags],8 jnz elf64_extrn_symbol xor eax,eax stos dword [edi] mov eax,[esi+8] stos dword [edi] mov eax,10h stos dword [edi] jmp extrn_symbol_ok elf64_extrn_symbol: mov eax,10h stos dword [edi] xor al,al stos dword [edi] stos dword [edi] mov eax,[esi+8] stos dword [edi] xor eax,eax stos dword [edi] extrn_symbol_ok: inc ecx mov eax,ecx shl eax,8 mov al,80h mov [esi],eax add esi,0Ch jmp find_other_symbols elf_symbol_table_ok: mov edx,edi mov ebx,[free_additional_memory] xor al,al stos byte [edi] add edi,16 mov [edx+1],edx add ebx,10h test [format_flags],8 jz make_string_table add ebx,8 make_string_table: cmp ebx,edx je elf_string_table_ok test [format_flags],8 jnz make_elf64_string cmp byte [ebx+0Dh],0 je rel_prefix_ok mov byte [ebx+0Dh],0 mov eax,'.rel' stos dword [edi] rel_prefix_ok: mov esi,edi sub esi,edx xchg esi,[ebx] add ebx,10h make_elf_string: or esi,esi jz default_string lods dword [esi] mov ecx,eax rep movs byte [edi],[esi] xor al,al stos byte [edi] jmp make_string_table make_elf64_string: cmp byte [ebx+5],0 je elf64_rel_prefix_ok mov byte [ebx+5],0 mov eax,'.rel' stos dword [edi] mov al,'a' stos byte [edi] elf64_rel_prefix_ok: mov esi,edi sub esi,edx xchg esi,[ebx] add ebx,18h jmp make_elf_string default_string: mov eax,'.fla' stos dword [edi] mov ax,'t' stos word [edi] jmp make_string_table elf_string_table_ok: mov [edx+1+8],edi mov ebx,[code_start] mov eax,edi sub eax,[free_additional_memory] xor ecx,ecx sub ecx,eax test [format_flags],8 jnz finish_elf64_header and ecx,11b add eax,ecx mov [ebx+20h],eax mov eax,[current_section] inc ax jz format_limitations_exceeded mov [ebx+32h],ax inc ax jz format_limitations_exceeded mov [ebx+30h],ax jmp elf_header_finished finish_elf64_header: and ecx,111b add eax,ecx mov [ebx+28h],eax mov eax,[current_section] inc ax jz format_limitations_exceeded mov [ebx+3Eh],ax inc ax jz format_limitations_exceeded mov [ebx+3Ch],ax elf_header_finished: xor eax,eax add ecx,10*4 rep stos byte [edi] test [format_flags],8 jz elf_null_section_ok mov ecx,6*4 rep stos byte [edi] elf_null_section_ok: mov esi,ebp xor ecx,ecx make_section_entry: mov ebx,edi mov eax,[esi+4] mov eax,[eax] stos dword [edi] mov eax,1 cmp dword [esi+0Ch],0 je bss_section test byte [esi+14h],80h jz section_type_ok bss_section: mov al,8 section_type_ok: stos dword [edi] mov eax,[esi+14h] and al,3Fh call store_elf_machine_word xor eax,eax call store_elf_machine_word mov eax,[esi+8] mov [image_base],eax sub eax,[code_start] call store_elf_machine_word mov eax,[esi+0Ch] call store_elf_machine_word xor eax,eax stos dword [edi] stos dword [edi] mov eax,[esi+10h] call store_elf_machine_word xor eax,eax call store_elf_machine_word inc ecx add esi,20h xchg edi,[esp] mov ebp,edi convert_relocations: cmp esi,[free_additional_memory] je relocations_converted mov al,[esi] or al,al jz relocations_converted cmp al,80h jb make_relocation_entry cmp al,0C0h jb relocation_entry_ok add esi,10h jmp convert_relocations make_relocation_entry: test [format_flags],8 jnz make_elf64_relocation_entry mov eax,[esi+4] stos dword [edi] mov eax,[esi+8] mov eax,[eax] mov al,[esi] stos dword [edi] jmp relocation_entry_ok make_elf64_relocation_entry: mov eax,[esi+4] stos dword [edi] xor eax,eax stos dword [edi] movzx eax,byte [esi] stos dword [edi] mov eax,[esi+8] mov eax,[eax] shr eax,8 stos dword [edi] xor eax,eax push edx mov edx,[esi+4] add edx,[image_base] xchg eax,[edx] stos dword [edi] cmp byte [esi],1 je addend_64bit pop edx sar eax,31 stos dword [edi] jmp relocation_entry_ok addend_64bit: xor eax,eax xchg eax,[edx+4] stos dword [edi] pop edx relocation_entry_ok: add esi,0Ch jmp convert_relocations store_elf_machine_word: stos dword [edi] test [format_flags],8 jz elf_machine_word_ok and dword [edi],0 add edi,4 elf_machine_word_ok: ret relocations_converted: cmp edi,ebp xchg edi,[esp] je rel_section_ok mov eax,[ebx] sub eax,4 test [format_flags],8 jz store_relocations_name_offset dec eax store_relocations_name_offset: stos dword [edi] test [format_flags],8 jnz rela_section mov eax,9 jmp store_relocations_type rela_section: mov eax,4 store_relocations_type: stos dword [edi] xor al,al call store_elf_machine_word call store_elf_machine_word mov eax,ebp sub eax,[code_start] call store_elf_machine_word mov eax,[esp] sub eax,ebp call store_elf_machine_word mov eax,[current_section] stos dword [edi] mov eax,ecx stos dword [edi] inc ecx test [format_flags],8 jnz finish_elf64_rela_section mov eax,4 stos dword [edi] mov al,8 stos dword [edi] jmp rel_section_ok finish_elf64_rela_section: mov eax,8 stos dword [edi] xor al,al stos dword [edi] mov al,24 stos dword [edi] xor al,al stos dword [edi] rel_section_ok: cmp esi,[free_additional_memory] jne make_section_entry pop eax mov ebx,[code_start] sub eax,ebx mov [code_size],eax mov ecx,20h test [format_flags],8 jz adjust_elf_section_headers_offset mov ecx,28h adjust_elf_section_headers_offset: add [ebx+ecx],eax mov eax,1 stos dword [edi] mov al,2 stos dword [edi] xor al,al call store_elf_machine_word call store_elf_machine_word mov eax,[code_size] call store_elf_machine_word mov eax,[edx+1] sub eax,[free_additional_memory] call store_elf_machine_word mov eax,[current_section] inc eax stos dword [edi] mov eax,[number_of_sections] inc eax stos dword [edi] test [format_flags],8 jnz finish_elf64_sym_section mov eax,4 stos dword [edi] mov al,10h stos dword [edi] jmp sym_section_ok finish_elf64_sym_section: mov eax,8 stos dword [edi] xor al,al stos dword [edi] mov al,18h stos dword [edi] xor al,al stos dword [edi] sym_section_ok: mov al,1+8 stos dword [edi] mov al,3 stos dword [edi] xor al,al call store_elf_machine_word call store_elf_machine_word mov eax,[edx+1] sub eax,[free_additional_memory] add eax,[code_size] call store_elf_machine_word mov eax,[edx+1+8] sub eax,[edx+1] call store_elf_machine_word xor eax,eax stos dword [edi] stos dword [edi] mov al,1 call store_elf_machine_word xor eax,eax call store_elf_machine_word mov eax,'tab' mov dword [edx+1],'.sym' mov [edx+1+4],eax mov dword [edx+1+8],'.str' mov [edx+1+8+4],eax mov [resource_data],edx mov [written_size],0 mov edx,[output_file] call create jc write_failed call write_code mov ecx,edi mov edx,[free_additional_memory] sub ecx,edx add [written_size],ecx call write jc write_failed jmp output_written format_elf_exe: add esi,2 or [format_flags],1 cmp byte [esi],'(' jne elf_exe_brand_ok inc esi cmp byte [esi],'.' je invalid_value push edx call get_byte_value cmp [value_type],0 jne invalid_use_of_symbol pop edx mov [edx+7],al elf_exe_brand_ok: mov [image_base],8048000h cmp byte [esi],80h jne elf_exe_base_ok lods word [esi] cmp ah,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value push edx call get_dword_value cmp [value_type],0 jne invalid_use_of_symbol mov [image_base],eax pop edx elf_exe_base_ok: mov byte [edx+2Ah],20h mov ebx,edi mov ecx,20h shr 2 cmp [current_pass],0 je init_elf_segments imul ecx,[number_of_sections] init_elf_segments: xor eax,eax rep stos dword [edi] and [number_of_sections],0 mov byte [ebx],1 mov word [ebx+1Ch],1000h mov byte [ebx+18h],111b mov ebp,[image_base] and dword [ebx+4],0 mov [ebx+8],ebp mov [ebx+0Ch],ebp mov eax,edi sub eax,[code_start] add eax,ebp mov [edx+18h],eax and [image_base_high],0 elf_exe_addressing_setup: call init_addressing_space call setup_elf_exe_labels_type mov eax,[code_start] xor edx,edx xor cl,cl sub eax,[image_base] sbb edx,[image_base_high] sbb cl,0 mov [ebx],eax mov [ebx+4],edx mov [ebx+8],cl mov [symbols_stream],edi jmp format_defined format_elf64_exe: add esi,2 or [format_flags],1 cmp byte [esi],'(' jne elf64_exe_brand_ok inc esi cmp byte [esi],'.' je invalid_value push edx call get_byte_value cmp [value_type],0 jne invalid_use_of_symbol pop edx mov [edx+7],al elf64_exe_brand_ok: mov [image_base],400000h and [image_base_high],0 cmp byte [esi],80h jne elf64_exe_base_ok lods word [esi] cmp ah,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value push edx call get_qword_value cmp [value_type],0 jne invalid_use_of_symbol mov [image_base],eax mov [image_base_high],edx pop edx elf64_exe_base_ok: mov byte [edx+36h],38h mov ebx,edi mov ecx,38h shr 2 cmp [current_pass],0 je init_elf64_segments imul ecx,[number_of_sections] init_elf64_segments: xor eax,eax rep stos dword [edi] and [number_of_sections],0 mov byte [ebx],1 mov word [ebx+30h],1000h mov byte [ebx+4],111b mov ebp,[image_base] mov ecx,[image_base_high] and dword [ebx+8],0 mov [ebx+10h],ebp mov [ebx+10h+4],ecx mov [ebx+18h],ebp mov [ebx+18h+4],ecx mov eax,edi sub eax,[code_start] add eax,ebp adc ecx,0 mov [edx+18h],eax mov [edx+18h+4],ecx jmp elf_exe_addressing_setup setup_elf_exe_labels_type: mov eax,[code_start] cmp byte [eax+10h],3 jne elf_exe_labels_type_ok mov byte [ebx+9],2 test [format_flags],8 jz elf_exe_labels_type_ok mov byte [ebx+9],4 elf_exe_labels_type_ok: ret elf_entry: lods byte [esi] cmp al,'(' jne invalid_argument cmp byte [esi],'.' je invalid_value test [format_flags],8 jnz elf64_entry call get_dword_value mov edx,[code_start] mov [edx+18h],eax jmp instruction_assembled elf64_entry: call get_qword_value mov ebx,[code_start] mov [ebx+18h],eax mov [ebx+1Ch],edx jmp instruction_assembled elf_segment: bt [format_flags],0 jnc illegal_instruction test [format_flags],8 jnz elf64_segment call close_elf_segment push eax call create_addressing_space call setup_elf_exe_labels_type mov ebp,ebx mov ebx,[number_of_sections] shl ebx,5 add ebx,[code_start] add ebx,34h cmp ebx,[symbols_stream] jb new_elf_segment mov ebx,[symbols_stream] sub ebx,20h or [next_pass_needed],-1 new_elf_segment: mov byte [ebx],1 and dword [ebx+18h],0 mov word [ebx+1Ch],1000h elf_segment_flags: cmp byte [esi],1Eh je elf_segment_type cmp byte [esi],19h jne elf_segment_flags_ok lods word [esi] sub ah,28 jbe invalid_argument cmp ah,1 je mark_elf_segment_flag cmp ah,3 ja invalid_argument xor ah,1 cmp ah,2 je mark_elf_segment_flag inc ah mark_elf_segment_flag: test [ebx+18h],ah jnz setting_already_specified or [ebx+18h],ah jmp elf_segment_flags elf_segment_type: cmp byte [ebx],1 jne setting_already_specified lods word [esi] mov ecx,[number_of_sections] jecxz elf_segment_type_ok mov edx,[code_start] add edx,34h scan_elf_segment_types: cmp edx,[symbols_stream] jae elf_segment_type_ok cmp [edx],ah je data_already_defined add edx,20h loop scan_elf_segment_types elf_segment_type_ok: mov [ebx],ah mov word [ebx+1Ch],1 cmp ah,50h jb elf_segment_flags or dword [ebx],6474E500h jmp elf_segment_flags elf_segment_flags_ok: pop edx cmp byte [ebx],1 jne no_elf_segment_merging cmp [merge_segment],0 jne merge_elf_segment no_elf_segment_merging: mov eax,edi sub eax,[code_start] mov [ebx+4],eax and eax,0FFFh add eax,edx mov [ebx+8],eax mov [ebx+0Ch],eax xor edx,edx elf_segment_addressing_setup: xor cl,cl not eax not edx not cl add eax,1 adc edx,0 adc cl,0 add eax,edi adc edx,0 adc cl,0 mov [ds:ebp],eax mov [ds:ebp+4],edx mov [ds:ebp+8],cl inc [number_of_sections] jmp instruction_assembled merge_elf_segment: xor ecx,ecx xchg ecx,[merge_segment] cmp ecx,-1 je merge_elf_header mov eax,[ecx+8] mov ecx,[ecx+4] elf_segment_separated_base: mov [ebx+8],eax mov [ebx+0Ch],eax mov [ebx+4],ecx sub eax,ecx add eax,edi sub eax,[code_start] xor edx,edx jmp elf_segment_addressing_setup merge_elf_header: mov eax,[image_base] xor ecx,ecx jmp elf_segment_separated_base close_elf_segment: cmp [number_of_sections],0 jne finish_elf_segment cmp edi,[symbols_stream] jne first_elf_segment_ok or [merge_segment],-1 mov eax,[image_base] ret first_elf_segment_ok: and [merge_segment],0 inc [number_of_sections] finish_elf_segment: mov ebx,[number_of_sections] dec ebx shl ebx,5 add ebx,[code_start] add ebx,34h mov eax,edi sub eax,[code_start] sub eax,[ebx+4] mov edx,edi cmp edi,[undefined_data_end] jne elf_segment_size_ok cmp byte [ebx],1 jne elf_segment_size_ok mov edi,[undefined_data_start] elf_segment_size_ok: mov [ebx+14h],eax add eax,edi sub eax,edx mov [ebx+10h],eax and [undefined_data_end],0 mov eax,[ebx+8] cmp byte [ebx],1 je elf_segment_position_move_and_align cmp [merge_segment],0 jne elf_segment_position_move cmp byte [ebx],4 je elf_segment_position_ok cmp byte [ebx],51h je elf_segment_position_ok mov [merge_segment],ebx elf_segment_position_move: add eax,[ebx+14h] jmp elf_segment_position_ok elf_segment_position_move_and_align: add eax,[ebx+14h] add eax,0FFFh elf_segment_position_ok: and eax,not 0FFFh ret elf64_segment: call close_elf64_segment push eax edx call create_addressing_space call setup_elf_exe_labels_type mov ebp,ebx mov ebx,[number_of_sections] imul ebx,38h add ebx,[code_start] add ebx,40h cmp ebx,[symbols_stream] jb new_elf64_segment or [next_pass_needed],-1 new_elf64_segment: mov byte [ebx],1 and dword [ebx+4],0 mov word [ebx+30h],1000h elf64_segment_flags: cmp byte [esi],1Eh je elf64_segment_type cmp byte [esi],19h jne elf64_segment_flags_ok lods word [esi] sub ah,28 jbe invalid_argument cmp ah,1 je mark_elf64_segment_flag cmp ah,3 ja invalid_argument xor ah,1 cmp ah,2 je mark_elf64_segment_flag inc ah mark_elf64_segment_flag: test [ebx+4],ah jnz setting_already_specified or [ebx+4],ah jmp elf64_segment_flags elf64_segment_type: cmp byte [ebx],1 jne setting_already_specified lods word [esi] mov ecx,[number_of_sections] jecxz elf64_segment_type_ok mov edx,[code_start] add edx,40h scan_elf64_segment_types: cmp edx,[symbols_stream] jae elf64_segment_type_ok cmp [edx],ah je data_already_defined add edx,38h loop scan_elf64_segment_types elf64_segment_type_ok: mov [ebx],ah mov word [ebx+30h],1 cmp ah,50h jb elf64_segment_flags or dword [ebx],6474E500h jmp elf64_segment_flags elf64_segment_flags_ok: pop edx eax cmp byte [ebx],1 jne no_elf64_segment_merging cmp [merge_segment],0 jne merge_elf64_segment no_elf64_segment_merging: mov ecx,edi sub ecx,[code_start] mov [ebx+8],ecx and ecx,0FFFh add eax,ecx adc edx,0 mov [ebx+10h],eax mov [ebx+10h+4],edx mov [ebx+18h],eax mov [ebx+18h+4],edx jmp elf_segment_addressing_setup merge_elf64_segment: xor ecx,ecx xchg ecx,[merge_segment] cmp ecx,-1 je merge_elf64_header mov eax,[ecx+10h] mov edx,[ecx+10h+4] mov ecx,[ecx+8] elf64_segment_separated_base: mov [ebx+10h],eax mov [ebx+10h+4],edx mov [ebx+18h],eax mov [ebx+18h+4],edx mov [ebx+8],ecx neg ecx add ecx,edi sub ecx,[code_start] add eax,ecx adc edx,0 jmp elf_segment_addressing_setup merge_elf64_header: mov eax,[image_base] mov edx,[image_base_high] xor ecx,ecx jmp elf64_segment_separated_base close_elf64_segment: cmp [number_of_sections],0 jne finish_elf64_segment cmp edi,[symbols_stream] jne first_elf64_segment_ok or [merge_segment],-1 mov eax,[image_base] mov edx,[image_base_high] ret first_elf64_segment_ok: and [merge_segment],0 inc [number_of_sections] finish_elf64_segment: mov ebx,[number_of_sections] dec ebx imul ebx,38h add ebx,[code_start] add ebx,40h mov eax,edi sub eax,[code_start] sub eax,[ebx+8] mov edx,edi cmp edi,[undefined_data_end] jne elf64_segment_size_ok cmp byte [ebx],1 jne elf64_segment_size_ok mov edi,[undefined_data_start] elf64_segment_size_ok: mov [ebx+28h],eax add eax,edi sub eax,edx mov [ebx+20h],eax and [undefined_data_end],0 mov eax,[ebx+10h] mov edx,[ebx+10h+4] cmp byte [ebx],1 je elf64_segment_position_move_and_align cmp [merge_segment],0 jne elf64_segment_position_move cmp byte [ebx],4 je elf64_segment_position_ok cmp byte [ebx],51h je elf64_segment_position_ok mov [merge_segment],ebx elf64_segment_position_move: add eax,[ebx+28h] adc edx,0 jmp elf64_segment_position_ok elf64_segment_position_move_and_align: add eax,[ebx+28h] adc edx,0 add eax,0FFFh adc edx,0 elf64_segment_position_ok: and eax,not 0FFFh ret close_elf_exe: test [format_flags],8 jnz close_elf64_exe call close_elf_segment mov edx,[code_start] mov eax,[number_of_sections] mov byte [edx+1Ch],34h mov [edx+2Ch],ax shl eax,5 add eax,edx add eax,34h cmp eax,[symbols_stream] je elf_exe_ok or [next_pass_needed],-1 elf_exe_ok: ret close_elf64_exe: call close_elf64_segment mov edx,[code_start] mov eax,[number_of_sections] mov byte [edx+20h],40h mov [edx+38h],ax imul eax,38h add eax,edx add eax,40h cmp eax,[symbols_stream] je elf64_exe_ok or [next_pass_needed],-1 elf64_exe_ok: ret fasm/source/libc/0000755000175000017500000000000014533376740014517 5ustar privalovprivalovfasm/source/libc/fasm.asm0000644000175000017500000001456714533376740016164 0ustar privalovprivalov ; flat assembler interface for Unix/libc ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. format ELF public main macro ccall proc,[arg] { common local size size = 0 mov ebp,esp if ~ arg eq forward size = size + 4 common sub esp,size end if and esp,-16 if ~ arg eq add esp,size reverse pushd arg common end if call proc mov esp,ebp } extrn gettimeofday section '.text' executable align 16 main: mov ecx,[esp+4] mov [argc],ecx mov ebx,[esp+8] mov [argv],ebx push ebp mov [stack_frame],esp mov [con_handle],1 mov esi,_logo call display_string call get_params jc information call init_memory mov esi,_memory_prefix call display_string mov eax,[memory_end] sub eax,[memory_start] add eax,[additional_memory_end] sub eax,[additional_memory] shr eax,10 call display_number mov esi,_memory_suffix call display_string ccall gettimeofday,buffer,0 mov eax,dword [buffer] mov ecx,1000 mul ecx mov ebx,eax mov eax,dword [buffer+4] div ecx add eax,ebx mov [start_time],eax and [preprocessing_done],0 call preprocessor or [preprocessing_done],-1 call parser call assembler call formatter call display_user_messages movzx eax,[current_pass] inc eax call display_number mov esi,_passes_suffix call display_string ccall gettimeofday,buffer,0 mov eax,dword [buffer] mov ecx,1000 mul ecx mov ebx,eax mov eax,dword [buffer+4] div ecx add eax,ebx sub eax,[start_time] jnc time_ok add eax,3600000 time_ok: xor edx,edx mov ebx,100 div ebx or eax,eax jz display_bytes_count xor edx,edx mov ebx,10 div ebx push edx call display_number mov dl,'.' call display_character pop eax call display_number mov esi,_seconds_suffix call display_string display_bytes_count: mov eax,[written_size] call display_number mov esi,_bytes_suffix call display_string xor al,al jmp exit_program information: mov esi,_usage call display_string mov al,1 jmp exit_program get_params: mov [input_file],0 mov [output_file],0 mov [symbols_file],0 mov [memory_setting],0 mov [passes_limit],100 mov ecx,[argc] mov ebx,[argv] add ebx,4 dec ecx jz bad_params mov [definitions_pointer],predefinitions get_param: mov esi,[ebx] mov al,[esi] cmp al,'-' je option_param cmp [input_file],0 jne get_output_file mov [input_file],esi jmp next_param get_output_file: cmp [output_file],0 jne bad_params mov [output_file],esi jmp next_param option_param: inc esi lodsb cmp al,'m' je memory_option cmp al,'M' je memory_option cmp al,'p' je passes_option cmp al,'P' je passes_option cmp al,'d' je definition_option cmp al,'D' je definition_option cmp al,'s' je symbols_option cmp al,'S' je symbols_option bad_params: stc ret memory_option: cmp byte [esi],0 jne get_memory_setting dec ecx jz bad_params add ebx,4 mov esi,[ebx] get_memory_setting: call get_option_value or edx,edx jz bad_params cmp edx,1 shl (32-10) jae bad_params mov [memory_setting],edx jmp next_param passes_option: cmp byte [esi],0 jne get_passes_setting dec ecx jz bad_params add ebx,4 mov esi,[ebx] get_passes_setting: call get_option_value or edx,edx jz bad_params cmp edx,10000h ja bad_params mov [passes_limit],dx next_param: add ebx,4 dec ecx jnz get_param cmp [input_file],0 je bad_params mov eax,[definitions_pointer] mov byte [eax],0 mov [initial_definitions],predefinitions clc ret definition_option: cmp byte [esi],0 jne get_definition dec ecx jz bad_params add ebx,4 mov esi,[ebx] get_definition: push edi mov edi,[definitions_pointer] call convert_definition_option mov [definitions_pointer],edi pop edi jc bad_params jmp next_param symbols_option: cmp byte [esi],0 jne get_symbols_setting dec ecx jz bad_params add ebx,4 mov esi,[ebx] get_symbols_setting: mov [symbols_file],esi jmp next_param get_option_value: xor eax,eax mov edx,eax get_option_digit: lodsb cmp al,20h je option_value_ok cmp al,0Dh je option_value_ok or al,al jz option_value_ok sub al,30h jc invalid_option_value cmp al,9 ja invalid_option_value imul edx,10 jo invalid_option_value add edx,eax jc invalid_option_value jmp get_option_digit option_value_ok: dec esi clc ret invalid_option_value: stc ret convert_definition_option: mov edx,edi cmp edi,predefinitions+1000h jae bad_definition_option xor al,al stosb copy_definition_name: lodsb cmp al,'=' je copy_definition_value cmp al,20h je bad_definition_option or al,al jz bad_definition_option cmp edi,predefinitions+1000h jae bad_definition_option stosb inc byte [edx] jnz copy_definition_name bad_definition_option: stc ret copy_definition_value: lodsb cmp al,20h je definition_value_end or al,al jz definition_value_end cmp edi,predefinitions+1000h jae bad_definition_option stosb jmp copy_definition_value definition_value_end: dec esi cmp edi,predefinitions+1000h jae bad_definition_option xor al,al stosb clc ret include 'system.inc' include '..\version.inc' _copyright db 'Copyright (c) 1999-2022, Tomasz Grysztar',0xA,0 _logo db 'flat assembler version ',VERSION_STRING,0 _usage db 0xA db 'usage: fasm [output]',0xA db 'optional settings:',0xA db ' -m set the limit in kilobytes for the available memory',0xA db ' -p set the maximum allowed number of passes',0xA db ' -d = define symbolic variable',0xA db ' -s dump symbolic information for debugging',0xA db 0 _memory_prefix db ' (',0 _memory_suffix db ' kilobytes memory)',0xA,0 _passes_suffix db ' passes, ',0 _seconds_suffix db ' seconds, ',0 _bytes_suffix db ' bytes.',0xA,0 include '..\errors.inc' include '..\symbdump.inc' include '..\preproce.inc' include '..\parser.inc' include '..\exprpars.inc' include '..\assemble.inc' include '..\exprcalc.inc' include '..\formats.inc' include '..\x86_64.inc' include '..\avx.inc' include '..\tables.inc' include '..\messages.inc' section '.bss' writeable align 4 include '..\variable.inc' argc dd ? argv dd ? stack_frame dd ? memory_setting dd ? definitions_pointer dd ? start_time dd ? timestamp dq ? con_handle dd ? displayed_count dd ? last_displayed db ? character db ? preprocessing_done db ? predefinitions rb 1000h buffer rb 1000h fasm/source/libc/system.inc0000644000175000017500000001503714533376740016544 0ustar privalovprivalov ; flat assembler interface for Unix/libc ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. extrn malloc extrn free extrn getenv extrn fopen extrn fclose extrn fread extrn fwrite extrn fseek extrn ftell extrn time extrn exit extrn 'write' as libc_write init_memory: mov eax,esp and eax,not 0FFFh add eax,1000h-10000h mov [stack_limit],eax mov ecx,[memory_setting] shl ecx,10 jnz allocate_memory mov ecx,1000000h allocate_memory: mov [memory_setting],ecx ccall malloc,ecx or eax,eax jz out_of_memory mov [additional_memory],eax add eax,[memory_setting] mov [memory_end],eax mov eax,[memory_setting] shr eax,2 add eax,[additional_memory] mov [additional_memory_end],eax mov [memory_start],eax ret exit_program: movzx eax,al push eax ccall free,[additional_memory] pop eax ccall exit,eax mov esp,[stack_frame] pop ebp ret get_environment_variable: ccall getenv,esi mov esi,eax or eax,eax jz no_environment_variable copy_variable_value: lodsb cmp edi,[memory_end] jae out_of_memory stosb or al,al jnz copy_variable_value dec edi ret no_environment_variable: stosb dec edi ret open: push esi edi ebp call adapt_path ccall fopen,buffer,open_mode pop ebp edi esi or eax,eax jz file_error mov ebx,eax clc ret adapt_path: mov esi,edx mov edi,buffer copy_path: lods byte [esi] cmp al,'\' jne path_char_ok mov al,'/' path_char_ok: stos byte [edi] or al,al jnz copy_path cmp edi,buffer+1000h ja out_of_memory ret create: push esi edi ebp call adapt_path ccall fopen,buffer,create_mode pop ebp edi esi or eax,eax jz file_error mov ebx,eax clc ret close: ccall fclose,ebx ret read: push ebx ecx edx esi edi ebp ccall fread,edx,1,ecx,ebx pop ebp edi esi edx ecx ebx cmp eax,ecx jne file_error clc ret file_error: stc ret write: push ebx ecx edx esi edi ebp ccall fwrite,edx,1,ecx,ebx pop ebp edi esi edx ecx ebx cmp eax,ecx jne file_error clc ret lseek: push ebx movzx eax,al ccall fseek,ebx,edx,eax test eax,eax jnz lseek_error mov ebx,[esp] ccall ftell,ebx pop ebx clc ret lseek_error: pop ebx stc ret display_string: lodsb or al,al jz string_displayed mov dl,al call display_character jmp display_string string_displayed: ret display_character: mov [character],dl ccall libc_write,[con_handle],character,1 ret display_number: push ebx mov ecx,1000000000 xor edx,edx xor bl,bl display_loop: div ecx push edx cmp ecx,1 je display_digit or bl,bl jnz display_digit or al,al jz digit_ok not bl display_digit: mov dl,al add dl,30h push ebx ecx call display_character pop ecx ebx digit_ok: mov eax,ecx xor edx,edx mov ecx,10 div ecx mov ecx,eax pop eax or ecx,ecx jnz display_loop pop ebx ret display_user_messages: mov [displayed_count],0 call show_display_buffer cmp [displayed_count],0 je line_break_ok cmp [last_displayed],0Ah je line_break_ok mov dl,0Ah call display_character line_break_ok: ret display_block: jecxz block_displayed add [displayed_count],ecx mov al,[esi+ecx-1] mov [last_displayed],al display_characters: lodsb mov dl,al push ecx esi call display_character pop esi ecx loop display_characters block_displayed: ret fatal_error: mov [con_handle],2 mov esi,error_prefix call display_string pop esi call display_string mov esi,error_suffix call display_string mov al,0FFh jmp exit_program assembler_error: mov [con_handle],2 call display_user_messages mov ebx,[current_line] test ebx,ebx jz display_error_message push dword 0 get_error_lines: mov eax,[ebx] cmp byte [eax],0 je get_next_error_line push ebx test byte [ebx+7],80h jz display_error_line mov edx,ebx find_definition_origin: mov edx,[edx+12] test byte [edx+7],80h jnz find_definition_origin push edx get_next_error_line: mov ebx,[ebx+8] jmp get_error_lines display_error_line: mov esi,[ebx] call display_string mov esi,line_number_start call display_string mov eax,[ebx+4] and eax,7FFFFFFFh call display_number mov dl,']' call display_character pop esi cmp ebx,esi je line_number_ok mov dl,20h call display_character push esi mov esi,[esi] movzx ecx,byte [esi] inc esi call display_block mov esi,line_number_start call display_string pop esi mov eax,[esi+4] and eax,7FFFFFFFh call display_number mov dl,']' call display_character line_number_ok: mov esi,line_data_start call display_string mov esi,ebx mov edx,[esi] call open mov al,2 xor edx,edx call lseek mov edx,[esi+8] sub eax,edx jz line_data_displayed push eax xor al,al call lseek mov ecx,[esp] mov edx,[additional_memory] lea eax,[edx+ecx] cmp eax,[additional_memory_end] ja out_of_memory call read call close pop ecx mov esi,[additional_memory] get_line_data: mov al,[esi] cmp al,0Ah je display_line_data cmp al,0Dh je display_line_data cmp al,1Ah je display_line_data or al,al jz display_line_data inc esi loop get_line_data display_line_data: mov ecx,esi mov esi,[additional_memory] sub ecx,esi call display_block line_data_displayed: mov esi,lf call display_string pop ebx or ebx,ebx jnz display_error_line cmp [preprocessing_done],0 je display_error_message mov esi,preprocessed_instruction_prefix call display_string mov esi,[current_line] add esi,16 mov edi,[additional_memory] xor dl,dl convert_instruction: lodsb cmp al,1Ah je copy_symbol cmp al,22h je copy_symbol cmp al,3Bh je instruction_converted stosb or al,al jz instruction_converted xor dl,dl jmp convert_instruction copy_symbol: or dl,dl jz space_ok mov byte [edi],20h inc edi space_ok: cmp al,22h je quoted lodsb movzx ecx,al rep movsb or dl,-1 jmp convert_instruction quoted: mov al,27h stosb lodsd mov ecx,eax jecxz quoted_copied copy_quoted: lodsb stosb cmp al,27h jne quote_ok stosb quote_ok: loop copy_quoted quoted_copied: mov al,27h stosb or dl,-1 jmp convert_instruction instruction_converted: xor al,al stosb mov esi,[additional_memory] call display_string mov esi,lf call display_string display_error_message: mov esi,error_prefix call display_string pop esi call display_string mov esi,error_suffix call display_string mov al,2 jmp exit_program make_timestamp: ccall time,timestamp mov eax,dword [timestamp] mov edx,dword [timestamp+4] ret open_mode db 'r',0 create_mode db 'w',0 error_prefix db 'error: ',0 error_suffix db '.' lf db 0xA,0 line_number_start db ' [',0 line_data_start db ':',0xA,0 preprocessed_instruction_prefix db 'processed: ',0 fasm/source/messages.inc0000644000175000017500000000456114533376740016116 0ustar privalovprivalov ; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. _out_of_memory db 'out of memory',0 _stack_overflow db 'out of stack space',0 _main_file_not_found db 'source file not found',0 _code_cannot_be_generated db 'code cannot be generated',0 _format_limitations_exceeded db 'format limitations exceeded',0 _invalid_definition db 'invalid definition provided',0 _write_failed db 'write failed',0 _file_not_found db 'file not found',0 _error_reading_file db 'error reading file',0 _invalid_file_format db 'invalid file format',0 _invalid_macro_arguments db 'invalid macro arguments',0 _incomplete_macro db 'incomplete macro',0 _unexpected_characters db 'unexpected characters',0 _invalid_argument db 'invalid argument',0 _illegal_instruction db 'illegal instruction',0 _invalid_operand db 'invalid operand',0 _invalid_operand_size db 'invalid size of operand',0 _operand_size_not_specified db 'operand size not specified',0 _operand_sizes_do_not_match db 'operand sizes do not match',0 _invalid_address_size db 'invalid size of address value',0 _address_sizes_do_not_agree db 'address sizes do not agree',0 _disallowed_combination_of_registers db 'disallowed combination of registers',0 _long_immediate_not_encodable db 'not encodable with long immediate',0 _relative_jump_out_of_range db 'relative jump out of range',0 _invalid_expression db 'invalid expression',0 _invalid_address db 'invalid address',0 _invalid_value db 'invalid value',0 _value_out_of_range db 'value out of range',0 _undefined_symbol db 'undefined symbol',0 _symbol_out_of_scope_1 db 'symbol',0 _symbol_out_of_scope_2 db 'out of scope',0 _invalid_use_of_symbol db 'invalid use of symbol',0 _name_too_long db 'name too long',0 _invalid_name db 'invalid name',0 _reserved_word_used_as_symbol db 'reserved word used as symbol',0 _symbol_already_defined db 'symbol already defined',0 _missing_end_quote db 'missing end quote',0 _missing_end_directive db 'missing end directive',0 _unexpected_instruction db 'unexpected instruction',0 _extra_characters_on_line db 'extra characters on line',0 _section_not_aligned_enough db 'section is not aligned enough',0 _setting_already_specified db 'setting already specified',0 _data_already_defined db 'data already defined',0 _too_many_repeats db 'too many repeats',0 _invoked_error db 'error directive encountered in source file',0 _assertion_failed db 'assertion failed',0 fasm/source/parser.inc0000644000175000017500000006567514533376740015620 0ustar privalovprivalov ; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. parser: mov eax,[memory_end] mov [labels_list],eax mov eax,[additional_memory] mov [free_additional_memory],eax xor eax,eax mov [current_locals_prefix],eax mov [anonymous_reverse],eax mov [anonymous_forward],eax mov [hash_tree],eax mov [blocks_stack],eax mov [parsed_lines],eax mov esi,[memory_start] mov edi,[source_start] parser_loop: mov [current_line],esi lea eax,[edi+100h] cmp eax,[labels_list] jae out_of_memory cmp byte [esi+16],0 je empty_line cmp byte [esi+16],3Bh je empty_line mov al,0Fh stos byte [edi] mov eax,esi stos dword [edi] inc [parsed_lines] add esi,16 parse_line: mov [formatter_symbols_allowed],0 mov [decorator_symbols_allowed],0 cmp byte [esi],1Ah jne empty_instruction push edi add esi,2 movzx ecx,byte [esi-1] cmp byte [esi+ecx],':' je simple_label cmp byte [esi+ecx],'=' je constant_label call get_instruction jnc main_instruction_identified cmp byte [esi+ecx],1Ah jne no_data_label push esi ecx lea esi,[esi+ecx+2] movzx ecx,byte [esi-1] call get_data_directive jnc data_label pop ecx esi no_data_label: call get_data_directive jnc main_instruction_identified pop edi sub esi,2 xor bx,bx call parse_line_contents jmp parse_next_line simple_label: pop edi call identify_label cmp byte [esi+1],':' je block_label mov byte [edi],2 inc edi stos dword [edi] inc esi xor al,al stos byte [edi] jmp parse_line block_label: mov byte [edi],4 inc edi stos dword [edi] add esi,2 jmp parse_line constant_label: pop edi call get_label_id mov byte [edi],3 inc edi stos dword [edi] xor al,al stos byte [edi] inc esi xor bx,bx call parse_line_contents jmp parse_next_line data_label: pop ecx edx pop edi push eax ebx esi mov esi,edx movzx ecx,byte [esi-1] call identify_label mov byte [edi],2 inc edi stos dword [edi] pop esi ebx eax stos byte [edi] push edi main_instruction_identified: pop edi mov dl,al mov al,1 stos byte [edi] mov ax,bx stos word [edi] mov al,dl stos byte [edi] cmp bx,if_directive-instruction_handler je parse_block cmp bx,repeat_directive-instruction_handler je parse_block cmp bx,while_directive-instruction_handler je parse_block cmp bx,end_directive-instruction_handler je parse_end_directive cmp bx,else_directive-instruction_handler je parse_else cmp bx,assert_directive-instruction_handler je parse_assert common_parse: call parse_line_contents jmp parse_next_line empty_instruction: lods byte [esi] or al,al jz parse_next_line cmp al,':' je invalid_name dec esi mov [parenthesis_stack],0 call parse_argument jmp parse_next_line empty_line: add esi,16 skip_rest_of_line: call skip_foreign_line parse_next_line: cmp esi,[source_start] jb parser_loop source_parsed: cmp [blocks_stack],0 je blocks_stack_ok pop eax pop [current_line] jmp missing_end_directive blocks_stack_ok: xor al,al stos byte [edi] add edi,0Fh and edi,not 0Fh mov [code_start],edi ret parse_block: mov eax,esp sub eax,[stack_limit] cmp eax,100h jb stack_overflow push [current_line] mov ax,bx shl eax,16 push eax inc [blocks_stack] cmp bx,if_directive-instruction_handler je parse_if cmp bx,while_directive-instruction_handler je parse_while call parse_line_contents jmp parse_next_line parse_end_directive: cmp byte [esi],1Ah jne common_parse push edi inc esi movzx ecx,byte [esi] inc esi call get_instruction pop edi jnc parse_end_block sub esi,2 jmp common_parse parse_end_block: mov dl,al mov al,1 stos byte [edi] mov ax,bx stos word [edi] mov al,dl stos byte [edi] lods byte [esi] or al,al jnz extra_characters_on_line cmp bx,if_directive-instruction_handler je close_parsing_block cmp bx,repeat_directive-instruction_handler je close_parsing_block cmp bx,while_directive-instruction_handler je close_parsing_block jmp parse_next_line close_parsing_block: cmp [blocks_stack],0 je unexpected_instruction cmp bx,[esp+2] jne unexpected_instruction dec [blocks_stack] pop eax edx cmp bx,if_directive-instruction_handler jne parse_next_line test al,1100b jz parse_next_line test al,10000b jnz parse_next_line sub edi,8 jmp parse_next_line parse_if: push edi call parse_line_contents xor al,al stos byte [edi] xchg esi,[esp] mov edi,esi call preevaluate_logical_expression pop esi cmp al,'0' je parse_false_condition_block cmp al,'1' je parse_true_condition_block or byte [esp],10000b jmp parse_next_line parse_while: push edi call parse_line_contents xor al,al stos byte [edi] xchg esi,[esp] mov edi,esi call preevaluate_logical_expression pop esi cmp al,'0' je parse_false_condition_block cmp al,'1' jne parse_next_line stos byte [edi] jmp parse_next_line parse_false_condition_block: or byte [esp],1 sub edi,4 jmp skip_parsing parse_true_condition_block: or byte [esp],100b sub edi,4 jmp parse_next_line parse_else: cmp [blocks_stack],0 je unexpected_instruction cmp word [esp+2],if_directive-instruction_handler jne unexpected_instruction lods byte [esi] or al,al jz parse_pure_else cmp al,1Ah jne extra_characters_on_line push edi movzx ecx,byte [esi] inc esi call get_instruction jc extra_characters_on_line pop edi cmp bx,if_directive-instruction_handler jne extra_characters_on_line test byte [esp],100b jnz skip_true_condition_else mov dl,al mov al,1 stos byte [edi] mov ax,bx stos word [edi] mov al,dl stos byte [edi] jmp parse_if parse_assert: push edi call parse_line_contents xor al,al stos byte [edi] xchg esi,[esp] mov edi,esi call preevaluate_logical_expression pop esi or al,al jz parse_next_line stos byte [edi] jmp parse_next_line skip_true_condition_else: sub edi,4 or byte [esp],1 jmp skip_parsing_contents parse_pure_else: bts dword [esp],1 jc unexpected_instruction test byte [esp],100b jz parse_next_line sub edi,4 or byte [esp],1 jmp skip_parsing skip_parsing: cmp esi,[source_start] jae source_parsed mov [current_line],esi add esi,16 skip_parsing_line: cmp byte [esi],1Ah jne skip_parsing_contents inc esi movzx ecx,byte [esi] inc esi cmp byte [esi+ecx],':' je skip_parsing_label push edi call get_instruction pop edi jnc skip_parsing_instruction add esi,ecx jmp skip_parsing_contents skip_parsing_label: lea esi,[esi+ecx+1] jmp skip_parsing_line skip_parsing_instruction: cmp bx,if_directive-instruction_handler je skip_parsing_block cmp bx,repeat_directive-instruction_handler je skip_parsing_block cmp bx,while_directive-instruction_handler je skip_parsing_block cmp bx,end_directive-instruction_handler je skip_parsing_end_directive cmp bx,else_directive-instruction_handler je skip_parsing_else skip_parsing_contents: lods byte [esi] or al,al jz skip_parsing cmp al,1Ah je skip_parsing_symbol cmp al,3Bh je skip_parsing_symbol cmp al,22h je skip_parsing_string jmp skip_parsing_contents skip_parsing_symbol: lods byte [esi] movzx eax,al add esi,eax jmp skip_parsing_contents skip_parsing_string: lods dword [esi] add esi,eax jmp skip_parsing_contents skip_parsing_block: mov eax,esp sub eax,[stack_limit] cmp eax,100h jb stack_overflow push [current_line] mov ax,bx shl eax,16 push eax inc [blocks_stack] jmp skip_parsing_contents skip_parsing_end_directive: cmp byte [esi],1Ah jne skip_parsing_contents push edi inc esi movzx ecx,byte [esi] inc esi call get_instruction pop edi jnc skip_parsing_end_block add esi,ecx jmp skip_parsing_contents skip_parsing_end_block: lods byte [esi] or al,al jnz extra_characters_on_line cmp bx,if_directive-instruction_handler je close_skip_parsing_block cmp bx,repeat_directive-instruction_handler je close_skip_parsing_block cmp bx,while_directive-instruction_handler je close_skip_parsing_block jmp skip_parsing close_skip_parsing_block: cmp [blocks_stack],0 je unexpected_instruction cmp bx,[esp+2] jne unexpected_instruction dec [blocks_stack] pop eax edx test al,1 jz skip_parsing cmp bx,if_directive-instruction_handler jne parse_next_line test al,10000b jz parse_next_line mov al,0Fh stos byte [edi] mov eax,[current_line] stos dword [edi] inc [parsed_lines] mov eax,1 + (end_directive-instruction_handler) shl 8 stos dword [edi] mov eax,1 + (if_directive-instruction_handler) shl 8 stos dword [edi] jmp parse_next_line skip_parsing_else: cmp [blocks_stack],0 je unexpected_instruction cmp word [esp+2],if_directive-instruction_handler jne unexpected_instruction lods byte [esi] or al,al jz skip_parsing_pure_else cmp al,1Ah jne extra_characters_on_line push edi movzx ecx,byte [esi] inc esi call get_instruction jc extra_characters_on_line pop edi cmp bx,if_directive-instruction_handler jne extra_characters_on_line mov al,[esp] test al,1 jz skip_parsing_contents test al,100b jnz skip_parsing_contents test al,10000b jnz parse_else_if xor al,al mov [esp],al mov al,0Fh stos byte [edi] mov eax,[current_line] stos dword [edi] inc [parsed_lines] parse_else_if: mov eax,1 + (if_directive-instruction_handler) shl 8 stos dword [edi] jmp parse_if skip_parsing_pure_else: bts dword [esp],1 jc unexpected_instruction mov al,[esp] test al,1 jz skip_parsing test al,100b jnz skip_parsing and al,not 1 or al,1000b mov [esp],al jmp parse_next_line parse_line_contents: mov [parenthesis_stack],0 parse_instruction_arguments: cmp bx,prefix_instruction-instruction_handler je allow_embedded_instruction cmp bx,times_directive-instruction_handler je parse_times_directive cmp bx,end_directive-instruction_handler je allow_embedded_instruction cmp bx,label_directive-instruction_handler je parse_label_directive cmp bx,segment_directive-instruction_handler je parse_segment_directive cmp bx,load_directive-instruction_handler je parse_load_directive cmp bx,extrn_directive-instruction_handler je parse_extrn_directive cmp bx,public_directive-instruction_handler je parse_public_directive cmp bx,section_directive-instruction_handler je parse_formatter_argument cmp bx,format_directive-instruction_handler je parse_formatter_argument cmp bx,data_directive-instruction_handler je parse_formatter_argument jmp parse_argument parse_formatter_argument: or [formatter_symbols_allowed],-1 parse_argument: lea eax,[edi+100h] cmp eax,[labels_list] jae out_of_memory lods byte [esi] cmp al,':' je instruction_separator cmp al,',' je separator cmp al,'=' je expression_comparator cmp al,'|' je separator cmp al,'&' je separator cmp al,'~' je separator cmp al,'>' je greater cmp al,'<' je less cmp al,')' je close_parenthesis or al,al jz contents_parsed cmp al,'[' je address_argument cmp al,']' je separator cmp al,'{' je open_decorator cmp al,'}' je close_decorator cmp al,'#' je unallowed_character cmp al,'`' je unallowed_character cmp al,3Bh je foreign_argument cmp [decorator_symbols_allowed],0 je not_a_separator cmp al,'-' je separator not_a_separator: dec esi cmp al,1Ah jne expression_argument push edi mov edi,directive_operators call get_operator or al,al jnz operator_argument inc esi movzx ecx,byte [esi] inc esi call get_symbol jnc symbol_argument cmp ecx,1 jne check_argument cmp byte [esi],'?' jne check_argument pop edi movs byte [edi],[esi] jmp argument_parsed foreign_argument: dec esi call skip_foreign_line jmp contents_parsed symbol_argument: pop edi stos word [edi] cmp byte [esi],'+' jne argument_parsed and ax,0F0FFh cmp ax,6010h jne argument_parsed movs byte [edi],[esi] jmp argument_parsed operator_argument: pop edi cmp al,85h je ptr_argument stos byte [edi] cmp al,8Ch je forced_expression cmp al,81h je forced_parenthesis cmp al,80h je parse_at_operator cmp al,82h je parse_from_operator cmp al,89h je parse_label_operator cmp al,0F8h je forced_expression jmp argument_parsed instruction_separator: stos byte [edi] allow_embedded_instruction: cmp byte [esi],1Ah jne parse_argument push edi inc esi movzx ecx,byte [esi] inc esi call get_instruction jnc embedded_instruction call get_data_directive jnc embedded_instruction pop edi sub esi,2 jmp parse_argument embedded_instruction: pop edi mov dl,al mov al,1 stos byte [edi] mov ax,bx stos word [edi] mov al,dl stos byte [edi] jmp parse_instruction_arguments parse_times_directive: mov al,'(' stos byte [edi] call convert_expression mov al,')' stos byte [edi] cmp byte [esi],':' jne allow_embedded_instruction movs byte [edi],[esi] jmp allow_embedded_instruction parse_segment_directive: or [formatter_symbols_allowed],-1 parse_label_directive: cmp byte [esi],1Ah jne argument_parsed push esi inc esi movzx ecx,byte [esi] inc esi call identify_label pop ebx cmp eax,0Fh je non_label_identified mov byte [edi],2 inc edi stos dword [edi] xor al,al stos byte [edi] jmp argument_parsed non_label_identified: mov esi,ebx jmp argument_parsed parse_load_directive: cmp byte [esi],1Ah jne argument_parsed push esi inc esi movzx ecx,byte [esi] inc esi call get_label_id pop ebx cmp eax,0Fh je non_label_identified mov byte [edi],2 inc edi stos dword [edi] xor al,al stos byte [edi] jmp argument_parsed parse_public_directive: cmp byte [esi],1Ah jne parse_argument inc esi push esi movzx ecx,byte [esi] inc esi push esi ecx push edi or [formatter_symbols_allowed],-1 call get_symbol mov [formatter_symbols_allowed],0 pop edi jc parse_public_label cmp al,1Dh jne parse_public_label add esp,12 stos word [edi] jmp parse_public_directive parse_public_label: pop ecx esi mov al,2 stos byte [edi] call get_label_id stos dword [edi] mov ax,8600h stos word [edi] pop ebx push ebx esi edi mov edi,directive_operators call get_operator pop edi edx ebx cmp al,86h je argument_parsed mov esi,edx xchg esi,ebx movzx ecx,byte [esi] inc esi mov ax,'(' stos word [edi] mov eax,ecx stos dword [edi] rep movs byte [edi],[esi] xor al,al stos byte [edi] xchg esi,ebx jmp argument_parsed parse_extrn_directive: cmp byte [esi],22h je parse_quoted_extrn cmp byte [esi],1Ah jne parse_argument push esi movzx ecx,byte [esi+1] add esi,2 mov ax,'(' stos word [edi] mov eax,ecx stos dword [edi] rep movs byte [edi],[esi] mov ax,8600h stos word [edi] pop esi parse_label_operator: cmp byte [esi],1Ah jne argument_parsed inc esi movzx ecx,byte [esi] inc esi mov al,2 stos byte [edi] call get_label_id stos dword [edi] xor al,al stos byte [edi] jmp argument_parsed parse_from_operator: cmp byte [esi],22h je argument_parsed parse_at_operator: cmp byte [esi],':' je argument_parsed jmp forced_multipart_expression parse_quoted_extrn: inc esi mov ax,'(' stos word [edi] lods dword [esi] mov ecx,eax stos dword [edi] rep movs byte [edi],[esi] xor al,al stos byte [edi] push esi edi mov edi,directive_operators call get_operator mov edx,esi pop edi esi cmp al,86h jne argument_parsed stos byte [edi] mov esi,edx jmp parse_label_operator ptr_argument: call parse_address jmp address_parsed check_argument: push esi ecx sub esi,2 mov edi,single_operand_operators call get_operator pop ecx esi or al,al jnz not_instruction call get_instruction jnc embedded_instruction call get_data_directive jnc embedded_instruction not_instruction: pop edi sub esi,2 expression_argument: cmp byte [esi],22h jne not_string mov eax,[esi+1] lea ebx,[esi+5+eax] push ebx ecx esi edi call parse_expression pop eax edx ecx ebx cmp esi,ebx jne expression_argument_parsed mov edi,eax mov esi,edx string_argument: inc esi mov ax,'(' stos word [edi] lods dword [esi] mov ecx,eax stos dword [edi] shr ecx,1 jnc string_movsb_ok movs byte [edi],[esi] string_movsb_ok: shr ecx,1 jnc string_movsw_ok movs word [edi],[esi] string_movsw_ok: rep movs dword [edi],[esi] xor al,al stos byte [edi] jmp expression_argument_parsed parse_expression: mov al,'(' stos byte [edi] call convert_expression mov al,')' stos byte [edi] ret not_string: cmp byte [esi],'(' jne expression mov eax,esp sub eax,[stack_limit] cmp eax,100h jb stack_overflow push esi edi inc esi mov al,91h stos byte [edi] inc [parenthesis_stack] jmp parse_argument expression_comparator: stos byte [edi] jmp forced_expression greater: cmp byte [esi],'=' jne separator inc esi mov al,0F2h jmp separator less: cmp byte [edi-1],0F6h je separator cmp byte [esi],'>' je not_equal cmp byte [esi],'=' jne separator inc esi mov al,0F3h jmp separator not_equal: inc esi mov al,0F1h jmp expression_comparator expression: call parse_expression jmp expression_argument_parsed forced_expression: xor al,al xchg al,[formatter_symbols_allowed] push eax call parse_expression forced_expression_parsed: pop eax mov [formatter_symbols_allowed],al jmp argument_parsed forced_multipart_expression: xor al,al xchg al,[formatter_symbols_allowed] push eax call parse_expression cmp byte [esi],':' jne forced_expression_parsed movs byte [edi],[esi] call parse_expression jmp forced_expression_parsed address_argument: call parse_address lods byte [esi] cmp al,']' je address_parsed cmp al,',' je divided_address dec esi mov al,')' stos byte [edi] jmp argument_parsed divided_address: mov ax,'),' stos word [edi] jmp expression address_parsed: mov al,']' stos byte [edi] jmp argument_parsed parse_address: mov al,'[' stos byte [edi] cmp word [esi],021Ah jne convert_address push esi add esi,4 lea ebx,[esi+1] cmp byte [esi],':' pop esi jne convert_address add esi,2 mov ecx,2 push ebx edi call get_symbol pop edi esi jc unknown_segment_prefix cmp al,10h jne unknown_segment_prefix mov al,ah and ah,11110000b cmp ah,30h jne unknown_segment_prefix add al,30h stos byte [edi] jmp convert_address unknown_segment_prefix: sub esi,5 convert_address: push edi mov edi,address_sizes call get_operator pop edi or al,al jz convert_expression add al,70h stos byte [edi] jmp convert_expression forced_parenthesis: cmp byte [esi],'(' jne argument_parsed inc esi mov al,91h jmp separator unallowed_character: mov al,0FFh jmp separator open_decorator: inc [decorator_symbols_allowed] jmp separator close_decorator: dec [decorator_symbols_allowed] jmp separator close_parenthesis: mov al,92h separator: stos byte [edi] argument_parsed: cmp [parenthesis_stack],0 je parse_argument dec [parenthesis_stack] add esp,8 jmp argument_parsed expression_argument_parsed: cmp [parenthesis_stack],0 je parse_argument cmp byte [esi],')' jne argument_parsed dec [parenthesis_stack] pop edi esi jmp expression contents_parsed: cmp [parenthesis_stack],0 je contents_ok dec [parenthesis_stack] add esp,8 jmp contents_parsed contents_ok: ret identify_label: cmp byte [esi],'.' je local_label_name call get_label_id cmp eax,10h jb label_identified or ebx,ebx jz anonymous_label_name dec ebx mov [current_locals_prefix],ebx label_identified: ret anonymous_label_name: cmp byte [esi-1],'@' je anonymous_label_name_ok mov eax,0Fh anonymous_label_name_ok: ret local_label_name: call get_label_id ret get_operator: cmp byte [esi],1Ah jne get_simple_operator mov edx,esi push ebp inc esi lods byte [esi] movzx ebp,al push edi mov ecx,ebp call lower_case pop edi check_operator: mov esi,converted movzx ecx,byte [edi] jecxz no_operator inc edi mov ebx,edi add ebx,ecx cmp ecx,ebp jne next_operator repe cmps byte [esi],[edi] je operator_found jb no_operator next_operator: mov edi,ebx inc edi jmp check_operator no_operator: mov esi,edx mov ecx,ebp pop ebp no_simple_operator: xor al,al ret operator_found: lea esi,[edx+2+ebp] mov ecx,ebp pop ebp mov al,[edi] ret get_simple_operator: mov al,[esi] cmp al,22h je no_simple_operator simple_operator: cmp byte [edi],1 jb no_simple_operator ja simple_next_operator cmp al,[edi+1] je simple_operator_found simple_next_operator: movzx ecx,byte [edi] lea edi,[edi+1+ecx+1] jmp simple_operator simple_operator_found: inc esi mov al,[edi+2] ret get_symbol: push esi mov ebp,ecx call lower_case mov ecx,ebp cmp cl,11 ja no_symbol sub cl,1 jc no_symbol movzx ebx,word [symbols+ecx*4] add ebx,symbols movzx edx,word [symbols+ecx*4+2] scan_symbols: or edx,edx jz no_symbol mov eax,edx shr eax,1 lea edi,[ebp+2] imul eax,edi lea edi,[ebx+eax] mov esi,converted mov ecx,ebp repe cmps byte [esi],[edi] ja symbols_up jb symbols_down mov ax,[edi] cmp al,18h jb symbol_ok cmp al,1Fh je decorator_symbol cmp [formatter_symbols_allowed],0 je no_symbol symbol_ok: pop esi add esi,ebp clc ret decorator_symbol: cmp [decorator_symbols_allowed],0 jne symbol_ok no_symbol: pop esi mov ecx,ebp stc ret symbols_down: shr edx,1 jmp scan_symbols symbols_up: lea ebx,[edi+ecx+2] shr edx,1 adc edx,-1 jmp scan_symbols get_data_directive: push esi mov ebp,ecx call lower_case mov ecx,ebp cmp cl,4 ja no_instruction sub cl,2 jc no_instruction movzx ebx,word [data_directives+ecx*4] add ebx,data_directives movzx edx,word [data_directives+ecx*4+2] jmp scan_instructions get_instruction: push esi mov ebp,ecx call lower_case mov ecx,ebp cmp cl,17 ja no_instruction sub cl,2 jc no_instruction movzx ebx,word [instructions+ecx*4] add ebx,instructions movzx edx,word [instructions+ecx*4+2] scan_instructions: or edx,edx jz no_instruction mov eax,edx shr eax,1 lea edi,[ebp+3] imul eax,edi lea edi,[ebx+eax] mov esi,converted mov ecx,ebp repe cmps byte [esi],[edi] ja instructions_up jb instructions_down pop esi add esi,ebp mov al,[edi] mov bx,[edi+1] clc ret no_instruction: pop esi mov ecx,ebp stc ret instructions_down: shr edx,1 jmp scan_instructions instructions_up: lea ebx,[edi+ecx+3] shr edx,1 adc edx,-1 jmp scan_instructions get_label_id: cmp ecx,100h jae name_too_long cmp byte [esi],'@' je anonymous_label cmp byte [esi],'.' jne standard_label cmp byte [esi+1],'.' je standard_label cmp [current_locals_prefix],0 je standard_label push edi mov edi,[additional_memory_end] sub edi,2 sub edi,ecx push ecx esi mov esi,[current_locals_prefix] lods byte [esi] movzx ecx,al sub edi,ecx cmp edi,[free_additional_memory] jb out_of_memory mov word [edi],0 add edi,2 mov ebx,edi rep movs byte [edi],[esi] pop esi ecx add al,cl jc name_too_long rep movs byte [edi],[esi] pop edi push ebx esi movzx ecx,al mov byte [ebx-1],al mov esi,ebx call get_label_id pop esi ebx cmp ebx,[eax+24] jne composed_label_id_ok lea edx,[ebx-2] mov [additional_memory_end],edx composed_label_id_ok: ret anonymous_label: cmp ecx,2 jne standard_label mov al,[esi+1] mov ebx,characters xlat byte [ebx] cmp al,'@' je new_anonymous cmp al,'b' je anonymous_back cmp al,'r' je anonymous_back cmp al,'f' jne standard_label add esi,2 mov eax,[anonymous_forward] or eax,eax jnz anonymous_ok mov eax,[current_line] mov [error_line],eax call allocate_label mov [anonymous_forward],eax anonymous_ok: xor ebx,ebx ret anonymous_back: mov eax,[anonymous_reverse] add esi,2 or eax,eax jz bogus_anonymous jmp anonymous_ok bogus_anonymous: call allocate_label mov [anonymous_reverse],eax jmp anonymous_ok new_anonymous: add esi,2 mov eax,[anonymous_forward] or eax,eax jnz new_anonymous_ok call allocate_label new_anonymous_ok: mov [anonymous_reverse],eax mov [anonymous_forward],0 jmp anonymous_ok standard_label: cmp byte [esi],'%' je get_predefined_id cmp byte [esi],'$' je current_address_label cmp byte [esi],'?' jne find_label cmp ecx,1 jne find_label inc esi mov eax,0Fh ret current_address_label: cmp ecx,3 je current_address_label_3_characters ja find_label inc esi cmp ecx,1 jbe get_current_offset_id inc esi cmp byte [esi-1],'$' je get_org_origin_id cmp byte [esi-1],'%' je get_file_offset_id sub esi,2 jmp find_label get_current_offset_id: xor eax,eax ret get_counter_id: mov eax,1 ret get_timestamp_id: mov eax,2 ret get_org_origin_id: mov eax,3 ret get_file_offset_id: mov eax,4 ret current_address_label_3_characters: cmp word [esi+1],'%%' jne find_label add esi,3 get_actual_file_offset_id: mov eax,5 ret get_predefined_id: cmp ecx,2 ja find_label inc esi cmp cl,1 je get_counter_id lods byte [esi] mov ebx,characters xlat [ebx] cmp al,'t' je get_timestamp_id sub esi,2 find_label: xor ebx,ebx mov eax,2166136261 mov ebp,16777619 hash_label: xor al,[esi+ebx] mul ebp inc bl cmp bl,cl jb hash_label mov ebp,eax shl eax,8 and ebp,0FFh shl 24 xor ebp,eax or ebp,ebx mov [label_hash],ebp push edi esi push ecx mov ecx,32 mov ebx,hash_tree follow_tree: mov edx,[ebx] or edx,edx jz extend_tree xor eax,eax shl ebp,1 adc eax,0 lea ebx,[edx+eax*4] dec ecx jnz follow_tree mov [label_leaf],ebx pop edx mov eax,[ebx] or eax,eax jz add_label mov ebx,esi mov ebp,[label_hash] compare_labels: mov esi,ebx mov ecx,edx mov edi,[eax+4] mov edi,[edi+24] repe cmps byte [esi],[edi] je label_found mov eax,[eax] or eax,eax jnz compare_labels jmp add_label label_found: add esp,4 pop edi mov eax,[eax+4] ret extend_tree: mov edx,[free_additional_memory] lea eax,[edx+8] cmp eax,[additional_memory_end] ja out_of_memory mov [free_additional_memory],eax xor eax,eax mov [edx],eax mov [edx+4],eax shl ebp,1 adc eax,0 mov [ebx],edx lea ebx,[edx+eax*4] dec ecx jnz extend_tree mov [label_leaf],ebx pop edx add_label: mov ecx,edx pop esi cmp byte [esi-2],0 je label_name_ok mov al,[esi] cmp al,30h jb name_first_char_ok cmp al,39h jbe numeric_name name_first_char_ok: cmp al,'$' jne check_for_reserved_word numeric_name: add esi,ecx reserved_word: mov eax,0Fh pop edi ret check_for_reserved_word: call get_instruction jnc reserved_word call get_data_directive jnc reserved_word call get_symbol jnc reserved_word sub esi,2 mov edi,operators call get_operator or al,al jnz reserved_word mov edi,single_operand_operators call get_operator or al,al jnz reserved_word mov edi,directive_operators call get_operator or al,al jnz reserved_word inc esi movzx ecx,byte [esi] inc esi label_name_ok: mov edx,[free_additional_memory] lea eax,[edx+8] cmp eax,[additional_memory_end] ja out_of_memory mov [free_additional_memory],eax mov ebx,esi add esi,ecx mov eax,[label_leaf] mov edi,[eax] mov [edx],edi mov [eax],edx call allocate_label mov [edx+4],eax mov [eax+24],ebx pop edi ret allocate_label: mov eax,[labels_list] mov ecx,LABEL_STRUCTURE_SIZE shr 2 initialize_label: sub eax,4 mov dword [eax],0 loop initialize_label mov [labels_list],eax ret LABEL_STRUCTURE_SIZE = 32 fasm/source/preproce.inc0000644000175000017500000015457414533376740016140 0ustar privalovprivalov ; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. preprocessor: mov edi,characters xor al,al make_characters_table: stosb inc al jnz make_characters_table mov esi,characters+'a' mov edi,characters+'A' mov ecx,26 rep movsb mov edi,characters mov esi,symbol_characters+1 movzx ecx,byte [esi-1] xor eax,eax mark_symbol_characters: lodsb mov byte [edi+eax],0 loop mark_symbol_characters mov edi,locals_counter mov ax,1 + '0' shl 8 stos word [edi] mov edi,[memory_start] mov [include_paths],edi mov esi,include_variable call get_environment_variable xor al,al stos byte [edi] mov [memory_start],edi mov eax,[additional_memory] mov [free_additional_memory],eax mov eax,[additional_memory_end] mov [labels_list],eax xor eax,eax mov [source_start],eax mov [tagged_blocks],eax mov [hash_tree],eax mov [error],eax mov [macro_status],al mov [current_line],eax mov esi,[initial_definitions] test esi,esi jz predefinitions_ok process_predefinitions: movzx ecx,byte [esi] test ecx,ecx jz predefinitions_ok inc esi lea eax,[esi+ecx] push eax mov ch,10b call add_preprocessor_symbol pop esi mov edi,[memory_start] mov [edx+8],edi convert_predefinition: cmp edi,[memory_end] jae out_of_memory lods byte [esi] or al,al jz predefinition_converted cmp al,20h je convert_predefinition mov ah,al mov ebx,characters xlat byte [ebx] or al,al jz predefinition_separator cmp ah,27h je predefinition_string cmp ah,22h je predefinition_string mov byte [edi],1Ah scas word [edi] xchg al,ah stos byte [edi] mov ebx,characters xor ecx,ecx predefinition_symbol: lods byte [esi] stos byte [edi] xlat byte [ebx] or al,al loopnzd predefinition_symbol neg ecx cmp ecx,255 ja invalid_definition mov ebx,edi sub ebx,ecx mov byte [ebx-2],cl found_predefinition_separator: dec edi mov ah,[esi-1] predefinition_separator: xchg al,ah or al,al jz predefinition_converted cmp al,20h je convert_predefinition cmp al,3Bh je invalid_definition cmp al,5Ch je predefinition_backslash stos byte [edi] jmp convert_predefinition predefinition_string: mov al,22h stos byte [edi] scas dword [edi] mov ebx,edi copy_predefinition_string: lods byte [esi] stos byte [edi] or al,al jz invalid_definition cmp al,ah jne copy_predefinition_string lods byte [esi] cmp al,ah je copy_predefinition_string dec esi dec edi mov eax,edi sub eax,ebx mov [ebx-4],eax jmp convert_predefinition predefinition_backslash: mov byte [edi],0 lods byte [esi] or al,al jz invalid_definition cmp al,20h je invalid_definition cmp al,3Bh je invalid_definition mov al,1Ah stos byte [edi] mov ecx,edi mov ax,5C01h stos word [edi] dec esi group_predefinition_backslashes: lods byte [esi] cmp al,5Ch jne predefinition_backslashed_symbol stos byte [edi] inc byte [ecx] jmp group_predefinition_backslashes predefinition_backslashed_symbol: cmp al,20h je invalid_definition cmp al,22h je invalid_definition cmp al,27h je invalid_definition cmp al,3Bh je invalid_definition mov ah,al mov ebx,characters xlat byte [ebx] or al,al jz predefinition_backslashed_symbol_character mov al,ah convert_predefinition_backslashed_symbol: stos byte [edi] xlat byte [ebx] or al,al jz found_predefinition_separator inc byte [ecx] jz invalid_definition lods byte [esi] jmp convert_predefinition_backslashed_symbol predefinition_backslashed_symbol_character: mov al,ah stos byte [edi] inc byte [ecx] jmp convert_predefinition predefinition_converted: mov [memory_start],edi sub edi,[edx+8] mov [edx+12],edi jmp process_predefinitions predefinitions_ok: mov esi,[input_file] mov edx,esi call open jc main_file_not_found mov edi,[memory_start] call preprocess_file cmp [macro_status],0 je process_postponed mov eax,[error_line] mov [current_line],eax jmp incomplete_macro process_postponed: mov edx,hash_tree mov ecx,32 find_postponed_list: mov edx,[edx] or edx,edx loopnz find_postponed_list jz preprocessing_finished process_postponed_list: mov eax,[edx] or eax,eax jz preprocessing_finished push edx mov ebx,edx find_earliest_postponed: mov eax,[edx] or eax,eax jz earliest_postponed_found mov ebx,edx mov edx,eax jmp find_earliest_postponed earliest_postponed_found: mov [ebx],eax call use_postponed_macro pop edx cmp [macro_status],0 je process_postponed_list mov eax,[error_line] mov [current_line],eax jmp incomplete_macro preprocessing_finished: mov [source_start],edi ret use_postponed_macro: lea esi,[edi-1] push ecx esi mov [struc_name],0 jmp use_macro preprocess_file: push [memory_end] push esi mov al,2 xor edx,edx call lseek push eax xor al,al xor edx,edx call lseek pop ecx mov edx,[memory_end] dec edx mov byte [edx],1Ah sub edx,ecx jc out_of_memory mov esi,edx cmp edx,edi jbe out_of_memory mov [memory_end],edx call read call close pop edx xor ecx,ecx mov ebx,esi preprocess_source: inc ecx mov [current_line],edi mov eax,edx stos dword [edi] mov eax,ecx stos dword [edi] mov eax,esi sub eax,ebx stos dword [edi] xor eax,eax stos dword [edi] push ebx edx call convert_line call preprocess_line pop edx ebx next_line: cmp byte [esi-1],0 je file_end cmp byte [esi-1],1Ah jne preprocess_source file_end: pop [memory_end] clc ret convert_line: push ecx test [macro_status],0Fh jz convert_line_data mov ax,3Bh stos word [edi] convert_line_data: cmp edi,[memory_end] jae out_of_memory lods byte [esi] cmp al,20h je convert_line_data cmp al,9 je convert_line_data mov ah,al mov ebx,characters xlat byte [ebx] or al,al jz convert_separator cmp ah,27h je convert_string cmp ah,22h je convert_string mov byte [edi],1Ah scas word [edi] xchg al,ah stos byte [edi] mov ebx,characters xor ecx,ecx convert_symbol: lods byte [esi] stos byte [edi] xlat byte [ebx] or al,al loopnzd convert_symbol neg ecx cmp ecx,255 ja name_too_long mov ebx,edi sub ebx,ecx mov byte [ebx-2],cl found_separator: dec edi mov ah,[esi-1] convert_separator: xchg al,ah cmp al,20h jb control_character je convert_line_data symbol_character: cmp al,3Bh je ignore_comment cmp al,5Ch je backslash_character stos byte [edi] jmp convert_line_data control_character: cmp al,1Ah je line_end cmp al,0Dh je cr_character cmp al,0Ah je lf_character cmp al,9 je convert_line_data or al,al jnz symbol_character jmp line_end lf_character: lods byte [esi] cmp al,0Dh je line_end dec esi jmp line_end cr_character: lods byte [esi] cmp al,0Ah je line_end dec esi jmp line_end convert_string: mov al,22h stos byte [edi] scas dword [edi] mov ebx,edi copy_string: lods byte [esi] stos byte [edi] cmp al,0Ah je no_end_quote cmp al,0Dh je no_end_quote or al,al jz no_end_quote cmp al,1Ah je no_end_quote cmp al,ah jne copy_string lods byte [esi] cmp al,ah je copy_string dec esi dec edi mov eax,edi sub eax,ebx mov [ebx-4],eax jmp convert_line_data backslash_character: mov byte [edi],0 lods byte [esi] cmp al,20h je concatenate_lines cmp al,9 je concatenate_lines cmp al,1Ah je line_end or al,al jz line_end cmp al,0Ah je concatenate_lf cmp al,0Dh je concatenate_cr cmp al,3Bh je find_concatenated_line mov al,1Ah stos byte [edi] mov ecx,edi mov ax,5C01h stos word [edi] dec esi group_backslashes: lods byte [esi] cmp al,5Ch jne backslashed_symbol stos byte [edi] inc byte [ecx] jz name_too_long jmp group_backslashes no_end_quote: mov byte [ebx-5],0 jmp missing_end_quote backslashed_symbol: cmp al,1Ah je extra_characters_on_line or al,al jz extra_characters_on_line cmp al,0Ah je extra_characters_on_line cmp al,0Dh je extra_characters_on_line cmp al,20h je extra_characters_on_line cmp al,9 je extra_characters_on_line cmp al,22h je extra_characters_on_line cmp al,27h je extra_characters_on_line cmp al,3Bh je extra_characters_on_line mov ah,al mov ebx,characters xlat byte [ebx] or al,al jz backslashed_symbol_character mov al,ah convert_backslashed_symbol: stos byte [edi] xlat byte [ebx] or al,al jz found_separator inc byte [ecx] jz name_too_long lods byte [esi] jmp convert_backslashed_symbol backslashed_symbol_character: mov al,ah stos byte [edi] inc byte [ecx] jmp convert_line_data concatenate_lines: lods byte [esi] cmp al,20h je concatenate_lines cmp al,9 je concatenate_lines cmp al,1Ah je line_end or al,al jz line_end cmp al,0Ah je concatenate_lf cmp al,0Dh je concatenate_cr cmp al,3Bh jne extra_characters_on_line find_concatenated_line: lods byte [esi] cmp al,0Ah je concatenate_lf cmp al,0Dh je concatenate_cr or al,al jz concatenate_ok cmp al,1Ah jne find_concatenated_line jmp line_end concatenate_lf: lods byte [esi] cmp al,0Dh je concatenate_ok dec esi jmp concatenate_ok concatenate_cr: lods byte [esi] cmp al,0Ah je concatenate_ok dec esi concatenate_ok: inc dword [esp] jmp convert_line_data ignore_comment: lods byte [esi] cmp al,0Ah je lf_character cmp al,0Dh je cr_character or al,al jz line_end cmp al,1Ah jne ignore_comment line_end: xor al,al stos byte [edi] pop ecx ret lower_case: mov edi,converted mov ebx,characters convert_case: lods byte [esi] xlat byte [ebx] stos byte [edi] loop convert_case case_ok: ret get_directive: push edi mov edx,esi mov ebp,ecx call lower_case pop edi scan_directives: mov esi,converted movzx eax,byte [edi] or al,al jz no_directive mov ecx,ebp inc edi mov ebx,edi add ebx,eax mov ah,[esi] cmp ah,[edi] jb no_directive ja next_directive cmp cl,al jne next_directive repe cmps byte [esi],[edi] jb no_directive je directive_found next_directive: mov edi,ebx add edi,2 jmp scan_directives no_directive: mov esi,edx mov ecx,ebp stc ret directive_found: call get_directive_handler_base directive_handler: lea esi,[edx+ebp] movzx ecx,word [ebx] add eax,ecx clc ret get_directive_handler_base: mov eax,[esp] ret preprocess_line: mov eax,esp sub eax,[stack_limit] cmp eax,100h jb stack_overflow push ecx esi preprocess_current_line: mov esi,[current_line] add esi,16 cmp word [esi],3Bh jne line_start_ok add esi,2 line_start_ok: test [macro_status],0F0h jnz macro_preprocessing cmp byte [esi],1Ah jne not_fix_constant movzx edx,byte [esi+1] lea edx,[esi+2+edx] cmp word [edx],031Ah jne not_fix_constant mov ebx,characters movzx eax,byte [edx+2] xlat byte [ebx] ror eax,8 mov al,[edx+3] xlat byte [ebx] ror eax,8 mov al,[edx+4] xlat byte [ebx] ror eax,16 cmp eax,'fix' je define_fix_constant not_fix_constant: call process_fix_constants jmp initial_preprocessing_ok macro_preprocessing: call process_macro_operators initial_preprocessing_ok: mov esi,[current_line] add esi,16 mov al,[macro_status] test al,2 jnz skip_macro_block test al,1 jnz find_macro_block preprocess_instruction: mov [current_offset],esi lods byte [esi] movzx ecx,byte [esi] inc esi cmp al,1Ah jne not_preprocessor_symbol cmp cl,3 jb not_preprocessor_directive push edi mov edi,preprocessor_directives call get_directive pop edi jc not_preprocessor_directive mov byte [edx-2],3Bh jmp near eax not_preprocessor_directive: xor ch,ch call get_preprocessor_symbol jc not_macro mov byte [ebx-2],3Bh mov [struc_name],0 jmp use_macro not_macro: mov [struc_name],esi add esi,ecx lods byte [esi] cmp al,':' je preprocess_label cmp al,1Ah jne not_preprocessor_symbol lods byte [esi] cmp al,3 jne not_symbolic_constant mov ebx,characters movzx eax,byte [esi] xlat byte [ebx] ror eax,8 mov al,[esi+1] xlat byte [ebx] ror eax,8 mov al,[esi+2] xlat byte [ebx] ror eax,16 cmp eax,'equ' je define_equ_constant mov al,3 not_symbolic_constant: mov ch,1 mov cl,al call get_preprocessor_symbol jc not_preprocessor_symbol push edx esi mov esi,[struc_name] mov [struc_label],esi sub [struc_label],2 mov cl,[esi-1] mov ch,10b call get_preprocessor_symbol jc struc_name_ok test edx,edx jz reserved_word_used_as_symbol mov ecx,[edx+12] add ecx,3 lea ebx,[edi+ecx] mov ecx,edi sub ecx,[struc_label] lea esi,[edi-1] lea edi,[ebx-1] std rep movs byte [edi],[esi] cld mov edi,[struc_label] mov esi,[edx+8] mov ecx,[edx+12] add [struc_name],ecx add [struc_name],3 call move_data mov al,3Ah stos byte [edi] mov ax,3Bh stos word [edi] mov edi,ebx pop esi add esi,[edx+12] add esi,3 pop edx jmp use_macro struc_name_ok: mov edx,[struc_name] movzx eax,byte [edx-1] add edx,eax push edi lea esi,[edi-1] mov ecx,edi sub ecx,edx std rep movs byte [edi],[esi] cld pop edi inc edi mov al,3Ah mov [edx],al inc al mov [edx+1],al pop esi edx inc esi jmp use_macro preprocess_label: dec esi sub esi,ecx lea ebp,[esi-2] mov ch,10b call get_preprocessor_symbol jnc symbolic_constant_in_label lea esi,[esi+ecx+1] cmp byte [esi],':' jne preprocess_instruction inc esi jmp preprocess_instruction symbolic_constant_in_label: test edx,edx jz reserved_word_used_as_symbol mov ebx,[edx+8] mov ecx,[edx+12] add ecx,ebx check_for_broken_label: cmp ebx,ecx je label_broken cmp byte [ebx],1Ah jne label_broken movzx eax,byte [ebx+1] lea ebx,[ebx+2+eax] cmp ebx,ecx je label_constant_ok cmp byte [ebx],':' jne label_broken inc ebx cmp byte [ebx],':' jne check_for_broken_label inc ebx jmp check_for_broken_label label_broken: call replace_symbolic_constant jmp line_preprocessed label_constant_ok: mov ecx,edi sub ecx,esi mov edi,[edx+12] add edi,ebp push edi lea eax,[edi+ecx] push eax cmp esi,edi je replace_label jb move_rest_of_line_up rep movs byte [edi],[esi] jmp replace_label move_rest_of_line_up: lea esi,[esi+ecx-1] lea edi,[edi+ecx-1] std rep movs byte [edi],[esi] cld replace_label: mov ecx,[edx+12] mov edi,[esp+4] sub edi,ecx mov esi,[edx+8] rep movs byte [edi],[esi] pop edi esi inc esi jmp preprocess_instruction not_preprocessor_symbol: mov esi,[current_offset] call process_equ_constants line_preprocessed: pop esi ecx ret get_preprocessor_symbol: push ebp edi esi mov ebp,ecx shl ebp,22 mov al,ch and al,11b movzx ecx,cl cmp al,10b jne no_preprocessor_special_symbol cmp cl,4 jbe no_preprocessor_special_symbol mov ax,'__' cmp ax,[esi] jne no_preprocessor_special_symbol cmp ax,[esi+ecx-2] jne no_preprocessor_special_symbol add esi,2 sub ecx,4 push ebp mov edi,preprocessor_special_symbols call get_directive pop ebp jc preprocessor_special_symbol_not_recognized add esi,2 xor edx,edx jmp preprocessor_symbol_found preprocessor_special_symbol_not_recognized: add ecx,4 sub esi,2 no_preprocessor_special_symbol: mov ebx,hash_tree mov edi,10 follow_hashes_roots: mov edx,[ebx] or edx,edx jz preprocessor_symbol_not_found xor eax,eax shl ebp,1 adc eax,0 lea ebx,[edx+eax*4] dec edi jnz follow_hashes_roots mov edi,ebx call calculate_hash mov ebp,eax and ebp,3FFh shl ebp,10 xor ebp,eax mov ebx,edi mov edi,22 follow_hashes_tree: mov edx,[ebx] or edx,edx jz preprocessor_symbol_not_found xor eax,eax shl ebp,1 adc eax,0 lea ebx,[edx+eax*4] dec edi jnz follow_hashes_tree mov al,cl mov edx,[ebx] or edx,edx jz preprocessor_symbol_not_found compare_with_preprocessor_symbol: mov edi,[edx+4] cmp edi,1 jbe next_equal_hash repe cmps byte [esi],[edi] je preprocessor_symbol_found mov cl,al mov esi,[esp] next_equal_hash: mov edx,[edx] or edx,edx jnz compare_with_preprocessor_symbol preprocessor_symbol_not_found: pop esi edi ebp stc ret preprocessor_symbol_found: pop ebx edi ebp clc ret calculate_hash: xor ebx,ebx mov eax,2166136261 mov ebp,16777619 fnv1a_hash: xor al,[esi+ebx] mul ebp inc bl cmp bl,cl jb fnv1a_hash ret add_preprocessor_symbol: push edi esi xor eax,eax or cl,cl jz reshape_hash cmp ch,11b je preprocessor_symbol_name_ok push ecx movzx ecx,cl mov edi,preprocessor_directives call get_directive jnc reserved_word_used_as_symbol pop ecx preprocessor_symbol_name_ok: call calculate_hash reshape_hash: mov ebp,eax and ebp,3FFh shr eax,10 xor ebp,eax shl ecx,22 or ebp,ecx mov ebx,hash_tree mov ecx,32 find_leave_for_symbol: mov edx,[ebx] or edx,edx jz extend_hashes_tree xor eax,eax rol ebp,1 adc eax,0 lea ebx,[edx+eax*4] dec ecx jnz find_leave_for_symbol mov edx,[ebx] or edx,edx jz add_symbol_entry shr ebp,30 cmp ebp,11b je reuse_symbol_entry cmp dword [edx+4],0 jne add_symbol_entry find_entry_to_reuse: mov edi,[edx] or edi,edi jz reuse_symbol_entry cmp dword [edi+4],0 jne reuse_symbol_entry mov edx,edi jmp find_entry_to_reuse add_symbol_entry: mov eax,edx mov edx,[labels_list] sub edx,16 cmp edx,[free_additional_memory] jb out_of_memory mov [labels_list],edx mov [edx],eax mov [ebx],edx reuse_symbol_entry: pop esi edi mov [edx+4],esi ret extend_hashes_tree: mov edx,[labels_list] sub edx,8 cmp edx,[free_additional_memory] jb out_of_memory mov [labels_list],edx xor eax,eax mov [edx],eax mov [edx+4],eax shl ebp,1 adc eax,0 mov [ebx],edx lea ebx,[edx+eax*4] dec ecx jnz extend_hashes_tree mov edx,[labels_list] sub edx,16 cmp edx,[free_additional_memory] jb out_of_memory mov [labels_list],edx mov dword [edx],0 mov [ebx],edx pop esi edi mov [edx+4],esi ret define_fix_constant: add edx,5 add esi,2 push edx mov ch,11b jmp define_preprocessor_constant define_equ_constant: add esi,3 push esi call process_equ_constants mov esi,[struc_name] mov ch,10b define_preprocessor_constant: mov byte [esi-2],3Bh mov cl,[esi-1] call add_preprocessor_symbol pop ebx mov ecx,edi dec ecx sub ecx,ebx mov [edx+8],ebx mov [edx+12],ecx jmp line_preprocessed define_symbolic_constant: lods byte [esi] cmp al,1Ah jne invalid_name lods byte [esi] mov cl,al mov ch,10b call add_preprocessor_symbol movzx eax,byte [esi-1] add esi,eax lea ecx,[edi-1] sub ecx,esi mov [edx+8],esi mov [edx+12],ecx jmp line_preprocessed define_struc: mov ch,1 jmp make_macro define_macro: xor ch,ch make_macro: lods byte [esi] cmp al,1Ah jne invalid_name lods byte [esi] mov cl,al call add_preprocessor_symbol mov eax,[current_line] mov [edx+12],eax movzx eax,byte [esi-1] add esi,eax mov [edx+8],esi mov al,[macro_status] and al,0F0h or al,1 mov [macro_status],al mov eax,[current_line] mov [error_line],eax xor ebp,ebp lods byte [esi] or al,al jz line_preprocessed cmp al,'{' je found_macro_block dec esi skip_macro_arguments: lods byte [esi] cmp al,1Ah je skip_macro_argument cmp al,'[' jne invalid_macro_arguments or ebp,-1 jz invalid_macro_arguments lods byte [esi] cmp al,1Ah jne invalid_macro_arguments skip_macro_argument: movzx eax,byte [esi] inc esi add esi,eax lods byte [esi] cmp al,':' je macro_argument_with_default_value cmp al,'=' je macro_argument_with_default_value cmp al,'*' jne macro_argument_end lods byte [esi] macro_argument_end: cmp al,',' je skip_macro_arguments cmp al,'&' je macro_arguments_finisher cmp al,']' jne end_macro_arguments not ebp macro_arguments_finisher: lods byte [esi] end_macro_arguments: or ebp,ebp jnz invalid_macro_arguments or al,al jz line_preprocessed cmp al,'{' je found_macro_block jmp invalid_macro_arguments macro_argument_with_default_value: or [skip_default_argument_value],-1 call skip_macro_argument_value inc esi jmp macro_argument_end skip_macro_argument_value: cmp byte [esi],'<' jne simple_argument mov ecx,1 inc esi enclosed_argument: lods byte [esi] or al,al jz invalid_macro_arguments cmp al,1Ah je enclosed_symbol cmp al,22h je enclosed_string cmp al,'>' je enclosed_argument_end cmp al,'<' jne enclosed_argument inc ecx jmp enclosed_argument enclosed_symbol: movzx eax,byte [esi] inc esi add esi,eax jmp enclosed_argument enclosed_string: lods dword [esi] add esi,eax jmp enclosed_argument enclosed_argument_end: loop enclosed_argument lods byte [esi] or al,al jz argument_value_end cmp al,',' je argument_value_end cmp [skip_default_argument_value],0 je invalid_macro_arguments cmp al,'{' je argument_value_end cmp al,'&' je argument_value_end or ebp,ebp jz invalid_macro_arguments cmp al,']' je argument_value_end jmp invalid_macro_arguments simple_argument: lods byte [esi] or al,al jz argument_value_end cmp al,',' je argument_value_end cmp al,22h je argument_string cmp al,1Ah je argument_symbol cmp [skip_default_argument_value],0 je simple_argument cmp al,'{' je argument_value_end cmp al,'&' je argument_value_end or ebp,ebp jz simple_argument cmp al,']' je argument_value_end argument_symbol: movzx eax,byte [esi] inc esi add esi,eax jmp simple_argument argument_string: lods dword [esi] add esi,eax jmp simple_argument argument_value_end: dec esi ret find_macro_block: add esi,2 lods byte [esi] or al,al jz line_preprocessed cmp al,'{' jne unexpected_characters found_macro_block: or [macro_status],2 skip_macro_block: lods byte [esi] cmp al,1Ah je skip_macro_symbol cmp al,3Bh je skip_macro_symbol cmp al,22h je skip_macro_string or al,al jz line_preprocessed cmp al,'}' jne skip_macro_block mov al,[macro_status] and [macro_status],0F0h test al,8 jnz use_instant_macro cmp byte [esi],0 je line_preprocessed mov ecx,edi sub ecx,esi mov edx,esi lea esi,[esi+ecx-1] lea edi,[edi+1+16] mov ebx,edi dec edi std rep movs byte [edi],[esi] cld mov edi,edx xor al,al stos byte [edi] mov esi,[current_line] mov [current_line],edi mov ecx,4 rep movs dword [edi],[esi] mov edi,ebx jmp initial_preprocessing_ok skip_macro_symbol: movzx eax,byte [esi] inc esi add esi,eax jmp skip_macro_block skip_macro_string: lods dword [esi] add esi,eax jmp skip_macro_block postpone_directive: push esi mov esi,edx xor ecx,ecx call add_preprocessor_symbol mov eax,[current_line] mov [error_line],eax mov [edx+12],eax pop esi mov [edx+8],esi mov al,[macro_status] and al,0F0h or al,1 mov [macro_status],al lods byte [esi] or al,al jz line_preprocessed cmp al,'{' jne unexpected_characters jmp found_macro_block rept_directive: mov [base_code],0 jmp define_instant_macro irp_directive: mov [base_code],1 jmp define_instant_macro irps_directive: mov [base_code],2 jmp define_instant_macro irpv_directive: mov [base_code],3 jmp define_instant_macro match_directive: mov [base_code],10h define_instant_macro: mov al,[macro_status] and al,0F0h or al,8+1 mov [macro_status],al mov eax,[current_line] mov [error_line],eax mov [instant_macro_start],esi cmp [base_code],10h je prepare_match skip_parameters: lods byte [esi] or al,al jz parameters_skipped cmp al,'{' je parameters_skipped cmp al,22h je skip_quoted_parameter cmp al,1Ah jne skip_parameters lods byte [esi] movzx eax,al add esi,eax jmp skip_parameters skip_quoted_parameter: lods dword [esi] add esi,eax jmp skip_parameters parameters_skipped: dec esi mov [parameters_end],esi lods byte [esi] cmp al,'{' je found_macro_block or al,al jnz invalid_macro_arguments jmp line_preprocessed prepare_match: call skip_pattern mov [value_type],80h+10b call process_symbolic_constants jmp parameters_skipped skip_pattern: lods byte [esi] or al,al jz invalid_macro_arguments cmp al,',' je pattern_skipped cmp al,22h je skip_quoted_string_in_pattern cmp al,1Ah je skip_symbol_in_pattern cmp al,'=' jne skip_pattern mov al,[esi] cmp al,1Ah je skip_pattern cmp al,22h je skip_pattern inc esi jmp skip_pattern skip_symbol_in_pattern: lods byte [esi] movzx eax,al add esi,eax jmp skip_pattern skip_quoted_string_in_pattern: lods dword [esi] add esi,eax jmp skip_pattern pattern_skipped: ret purge_macro: xor ch,ch jmp restore_preprocessor_symbol purge_struc: mov ch,1 jmp restore_preprocessor_symbol restore_equ_constant: mov ch,10b restore_preprocessor_symbol: push ecx lods byte [esi] cmp al,1Ah jne invalid_name lods byte [esi] mov cl,al call get_preprocessor_symbol jc no_symbol_to_restore test edx,edx jz symbol_restored mov dword [edx+4],0 jmp symbol_restored no_symbol_to_restore: add esi,ecx symbol_restored: pop ecx lods byte [esi] cmp al,',' je restore_preprocessor_symbol or al,al jnz extra_characters_on_line jmp line_preprocessed process_fix_constants: mov [value_type],11b jmp process_symbolic_constants process_equ_constants: mov [value_type],10b process_symbolic_constants: mov ebp,esi lods byte [esi] cmp al,1Ah je check_symbol cmp al,22h je ignore_string cmp al,'{' je check_brace or al,al jnz process_symbolic_constants ret ignore_string: lods dword [esi] add esi,eax jmp process_symbolic_constants check_brace: test [value_type],80h jz process_symbolic_constants ret no_replacing: movzx ecx,byte [esi-1] add esi,ecx jmp process_symbolic_constants check_symbol: mov cl,[esi] inc esi mov ch,[value_type] call get_preprocessor_symbol jc no_replacing mov [current_section],edi replace_symbolic_constant: test edx,edx jz replace_special_symbolic_constant mov ecx,[edx+12] mov edx,[edx+8] xchg esi,edx call move_data mov esi,edx process_after_replaced: lods byte [esi] cmp al,1Ah je symbol_after_replaced stos byte [edi] cmp al,22h je string_after_replaced cmp al,'{' je brace_after_replaced or al,al jnz process_after_replaced mov ecx,edi sub ecx,esi mov edi,ebp call move_data mov esi,edi ret move_data: lea eax,[edi+ecx] cmp eax,[memory_end] jae out_of_memory shr ecx,1 jnc movsb_ok movs byte [edi],[esi] movsb_ok: shr ecx,1 jnc movsw_ok movs word [edi],[esi] movsw_ok: rep movs dword [edi],[esi] ret string_after_replaced: lods dword [esi] stos dword [edi] mov ecx,eax call move_data jmp process_after_replaced brace_after_replaced: test [value_type],80h jz process_after_replaced mov edx,edi mov ecx,[current_section] sub edx,ecx sub ecx,esi rep movs byte [edi],[esi] mov ecx,edi sub ecx,esi mov edi,ebp call move_data lea esi,[ebp+edx] ret symbol_after_replaced: mov cl,[esi] inc esi mov ch,[value_type] call get_preprocessor_symbol jnc replace_symbolic_constant movzx ecx,byte [esi-1] mov al,1Ah mov ah,cl stos word [edi] call move_data jmp process_after_replaced replace_special_symbolic_constant: jmp near eax preprocessed_file_value: call get_current_line_from_file test ebx,ebx jz process_after_replaced push esi edi mov esi,[ebx] mov edi,esi xor al,al or ecx,-1 repne scas byte [edi] add ecx,2 neg ecx pop edi lea eax,[edi+1+4+ecx] cmp eax,[memory_end] ja out_of_memory mov al,22h stos byte [edi] mov eax,ecx stos dword [edi] rep movs byte [edi],[esi] pop esi jmp process_after_replaced preprocessed_line_value: call get_current_line_from_file test ebx,ebx jz process_after_replaced lea eax,[edi+1+4+20] cmp eax,[memory_end] ja out_of_memory mov ecx,[ebx+4] call store_number_symbol jmp process_after_replaced get_current_line_from_file: mov ebx,[current_line] find_line_from_file: test ebx,ebx jz line_from_file_found test byte [ebx+7],80h jz line_from_file_found mov ebx,[ebx+8] jmp find_line_from_file line_from_file_found: ret process_macro_operators: xor dl,dl mov ebp,edi before_macro_operators: mov edi,esi lods byte [esi] cmp al,'`' je symbol_conversion cmp al,'#' je concatenation cmp al,1Ah je symbol_before_macro_operators cmp al,3Bh je no_more_macro_operators cmp al,22h je string_before_macro_operators xor dl,dl or al,al jnz before_macro_operators mov edi,esi ret no_more_macro_operators: mov edi,ebp ret symbol_before_macro_operators: mov dl,1Ah mov ebx,esi lods byte [esi] movzx ecx,al jecxz symbol_before_macro_operators_ok mov edi,esi cmp byte [esi],'\' je escaped_symbol symbol_before_macro_operators_ok: add esi,ecx jmp before_macro_operators string_before_macro_operators: mov dl,22h mov ebx,esi lods dword [esi] add esi,eax jmp before_macro_operators escaped_symbol: dec byte [edi-1] dec ecx inc esi cmp ecx,1 rep movs byte [edi],[esi] jne after_macro_operators mov al,[esi-1] mov ecx,ebx mov ebx,characters xlat byte [ebx] mov ebx,ecx or al,al jnz after_macro_operators sub edi,3 mov al,[esi-1] stos byte [edi] xor dl,dl jmp after_macro_operators reduce_symbol_conversion: inc esi symbol_conversion: mov edx,esi mov al,[esi] cmp al,1Ah jne symbol_character_conversion lods word [esi] movzx ecx,ah lea ebx,[edi+3] jecxz convert_to_quoted_string cmp byte [esi],'\' jne convert_to_quoted_string inc esi dec ecx dec ebx jmp convert_to_quoted_string symbol_character_conversion: cmp al,22h je after_macro_operators cmp al,'`' je reduce_symbol_conversion lea ebx,[edi+5] xor ecx,ecx or al,al jz convert_to_quoted_string cmp al,'#' je convert_to_quoted_string inc ecx convert_to_quoted_string: sub ebx,edx ja shift_line_data mov al,22h mov dl,al stos byte [edi] mov ebx,edi mov eax,ecx stos dword [edi] rep movs byte [edi],[esi] cmp edi,esi je before_macro_operators jmp after_macro_operators shift_line_data: push ecx mov edx,esi lea esi,[ebp-1] add ebp,ebx lea edi,[ebp-1] lea ecx,[esi+1] sub ecx,edx std rep movs byte [edi],[esi] cld pop eax sub edi,3 mov dl,22h mov [edi-1],dl mov ebx,edi mov [edi],eax lea esi,[edi+4+eax] jmp before_macro_operators concatenation: cmp dl,1Ah je symbol_concatenation cmp dl,22h je string_concatenation no_concatenation: cmp esi,edi je before_macro_operators jmp after_macro_operators symbol_concatenation: cmp byte [esi],1Ah jne no_concatenation inc esi lods byte [esi] movzx ecx,al jecxz do_symbol_concatenation cmp byte [esi],'\' je concatenate_escaped_symbol do_symbol_concatenation: add [ebx],cl jc name_too_long rep movs byte [edi],[esi] jmp after_macro_operators concatenate_escaped_symbol: inc esi dec ecx jz do_symbol_concatenation movzx eax,byte [esi] cmp byte [characters+eax],0 jne do_symbol_concatenation sub esi,3 jmp no_concatenation string_concatenation: cmp byte [esi],22h je do_string_concatenation cmp byte [esi],'`' jne no_concatenation concatenate_converted_symbol: inc esi mov al,[esi] cmp al,'`' je concatenate_converted_symbol cmp al,22h je do_string_concatenation cmp al,1Ah jne concatenate_converted_symbol_character inc esi lods byte [esi] movzx ecx,al jecxz finish_concatenating_converted_symbol cmp byte [esi],'\' jne finish_concatenating_converted_symbol inc esi dec ecx finish_concatenating_converted_symbol: add [ebx],ecx rep movs byte [edi],[esi] jmp after_macro_operators concatenate_converted_symbol_character: or al,al jz after_macro_operators cmp al,'#' je after_macro_operators inc dword [ebx] movs byte [edi],[esi] jmp after_macro_operators do_string_concatenation: inc esi lods dword [esi] mov ecx,eax add [ebx],eax rep movs byte [edi],[esi] after_macro_operators: lods byte [esi] cmp al,'`' je symbol_conversion cmp al,'#' je concatenation stos byte [edi] cmp al,1Ah je symbol_after_macro_operators cmp al,3Bh je no_more_macro_operators cmp al,22h je string_after_macro_operators xor dl,dl or al,al jnz after_macro_operators ret symbol_after_macro_operators: mov dl,1Ah mov ebx,edi lods byte [esi] stos byte [edi] movzx ecx,al jecxz symbol_after_macro_operatorss_ok cmp byte [esi],'\' je escaped_symbol symbol_after_macro_operatorss_ok: rep movs byte [edi],[esi] jmp after_macro_operators string_after_macro_operators: mov dl,22h mov ebx,edi lods dword [esi] stos dword [edi] mov ecx,eax rep movs byte [edi],[esi] jmp after_macro_operators use_macro: push [free_additional_memory] push [macro_symbols] mov [macro_symbols],0 push [counter_limit] push dword [edx+4] mov dword [edx+4],1 push edx mov ebx,esi mov esi,[edx+8] mov eax,[edx+12] mov [macro_line],eax mov [counter_limit],0 xor ebp,ebp process_macro_arguments: mov al,[esi] or al,al jz arguments_end cmp al,'{' je arguments_end inc esi cmp al,'[' jne get_macro_arguments mov ebp,esi inc esi inc [counter_limit] get_macro_arguments: call get_macro_argument lods byte [esi] cmp al,',' je next_argument cmp al,']' je next_arguments_group cmp al,'&' je arguments_end dec esi jmp arguments_end next_argument: cmp byte [ebx],',' jne process_macro_arguments inc ebx jmp process_macro_arguments next_arguments_group: cmp byte [ebx],',' jne arguments_end inc ebx inc [counter_limit] mov esi,ebp jmp process_macro_arguments get_macro_argument: lods byte [esi] movzx ecx,al mov eax,[counter_limit] call add_macro_symbol add esi,ecx xor eax,eax mov [default_argument_value],eax cmp byte [esi],'*' je required_value cmp byte [esi],':' je get_default_value cmp byte [esi],'=' jne default_value_ok get_default_value: inc esi mov [default_argument_value],esi or [skip_default_argument_value],-1 call skip_macro_argument_value jmp default_value_ok required_value: inc esi or [default_argument_value],-1 default_value_ok: xchg esi,ebx mov [edx+12],esi mov [skip_default_argument_value],0 cmp byte [ebx],'&' je greedy_macro_argument call skip_macro_argument_value call finish_macro_argument jmp got_macro_argument greedy_macro_argument: call skip_foreign_line dec esi mov eax,[edx+12] mov ecx,esi sub ecx,eax mov [edx+8],ecx got_macro_argument: xchg esi,ebx cmp dword [edx+8],0 jne macro_argument_ok mov eax,[default_argument_value] or eax,eax jz macro_argument_ok cmp eax,-1 je invalid_macro_arguments mov [edx+12],eax call finish_macro_argument macro_argument_ok: ret finish_macro_argument: mov eax,[edx+12] mov ecx,esi sub ecx,eax cmp byte [eax],'<' jne argument_value_length_ok inc dword [edx+12] sub ecx,2 or ecx,80000000h argument_value_length_ok: mov [edx+8],ecx ret arguments_end: cmp byte [ebx],0 jne invalid_macro_arguments mov eax,[esp+4] dec eax call process_macro pop edx pop dword [edx+4] pop [counter_limit] pop [macro_symbols] pop [free_additional_memory] jmp line_preprocessed use_instant_macro: push edi push [current_line] push esi mov eax,[error_line] mov [current_line],eax mov [macro_line],eax mov esi,[instant_macro_start] cmp [base_code],10h jae do_match cmp [base_code],0 jne do_irp call precalculate_value cmp eax,0 jl value_out_of_range push [free_additional_memory] push [macro_symbols] mov [macro_symbols],0 push [counter_limit] mov [struc_name],0 mov [counter_limit],eax lods byte [esi] or al,al jz rept_counters_ok cmp al,'{' je rept_counters_ok cmp al,1Ah jne invalid_macro_arguments add_rept_counter: lods byte [esi] movzx ecx,al xor eax,eax call add_macro_symbol add esi,ecx xor eax,eax mov dword [edx+12],eax inc eax mov dword [edx+8],eax lods byte [esi] cmp al,':' jne rept_counter_added push edx call precalculate_value mov edx,eax add edx,[counter_limit] jo value_out_of_range pop edx mov dword [edx+8],eax lods byte [esi] rept_counter_added: cmp al,',' jne rept_counters_ok lods byte [esi] cmp al,1Ah jne invalid_macro_arguments jmp add_rept_counter rept_counters_ok: dec esi cmp [counter_limit],0 je instant_macro_finish instant_macro_parameters_ok: xor eax,eax call process_macro instant_macro_finish: pop [counter_limit] pop [macro_symbols] pop [free_additional_memory] instant_macro_done: pop ebx esi edx cmp byte [ebx],0 je line_preprocessed mov [current_line],edi mov ecx,4 rep movs dword [edi],[esi] test [macro_status],0Fh jz instant_macro_attached_line mov ax,3Bh stos word [edi] instant_macro_attached_line: mov esi,ebx sub edx,ebx mov ecx,edx call move_data jmp initial_preprocessing_ok precalculate_value: push edi call convert_expression mov al,')' stosb push esi mov esi,[esp+4] mov [error_line],0 mov [value_size],0 call calculate_expression cmp [error_line],0 je value_precalculated jmp [error] value_precalculated: mov eax,[edi] mov ecx,[edi+4] cdq cmp edx,ecx jne value_out_of_range cmp dl,[edi+13] jne value_out_of_range pop esi edi ret do_irp: cmp byte [esi],1Ah jne invalid_macro_arguments movzx eax,byte [esi+1] lea esi,[esi+2+eax] lods byte [esi] cmp [base_code],1 ja irps_name_ok cmp al,':' je irp_with_default_value cmp al,'=' je irp_with_default_value cmp al,'*' jne irp_name_ok lods byte [esi] irp_name_ok: cmp al,',' jne invalid_macro_arguments jmp irp_parameters_start irp_with_default_value: xor ebp,ebp or [skip_default_argument_value],-1 call skip_macro_argument_value cmp byte [esi],',' jne invalid_macro_arguments inc esi jmp irp_parameters_start irps_name_ok: cmp al,',' jne invalid_macro_arguments cmp [base_code],3 je irp_parameters_start mov al,[esi] or al,al jz instant_macro_done cmp al,'{' je instant_macro_done irp_parameters_start: xor eax,eax push [free_additional_memory] push [macro_symbols] mov [macro_symbols],eax push [counter_limit] mov [counter_limit],eax mov [struc_name],eax cmp [base_code],3 je get_irpv_parameter mov ebx,esi cmp [base_code],2 je get_irps_parameter mov edx,[parameters_end] mov al,[edx] push eax mov byte [edx],0 get_irp_parameter: inc [counter_limit] mov esi,[instant_macro_start] inc esi call get_macro_argument cmp byte [ebx],',' jne irp_parameters_end inc ebx jmp get_irp_parameter irp_parameters_end: mov esi,ebx pop eax mov [esi],al jmp instant_macro_parameters_ok get_irps_parameter: mov esi,[instant_macro_start] inc esi lods byte [esi] movzx ecx,al inc [counter_limit] mov eax,[counter_limit] call add_macro_symbol mov [edx+12],ebx cmp byte [ebx],1Ah je irps_symbol cmp byte [ebx],22h je irps_quoted_string mov eax,1 jmp irps_parameter_ok irps_quoted_string: mov eax,[ebx+1] add eax,1+4 jmp irps_parameter_ok irps_symbol: movzx eax,byte [ebx+1] add eax,1+1 irps_parameter_ok: mov [edx+8],eax add ebx,eax cmp byte [ebx],0 je irps_parameters_end cmp byte [ebx],'{' jne get_irps_parameter irps_parameters_end: mov esi,ebx jmp instant_macro_parameters_ok get_irpv_parameter: lods byte [esi] cmp al,1Ah jne invalid_macro_arguments lods byte [esi] mov ebp,esi mov cl,al mov ch,10b call get_preprocessor_symbol jc instant_macro_finish test edx,edx jz invalid_use_of_symbol push edx mark_variable_value: inc [counter_limit] mov [edx+4],ebp next_variable_value: mov edx,[edx] or edx,edx jz variable_values_marked mov eax,[edx+4] cmp eax,1 jbe next_variable_value mov esi,ebp movzx ecx,byte [esi-1] xchg edi,eax repe cmps byte [esi],[edi] xchg edi,eax je mark_variable_value jmp next_variable_value variable_values_marked: pop edx push [counter_limit] add_irpv_value: push edx mov esi,[instant_macro_start] inc esi lods byte [esi] movzx ecx,al mov eax,[esp+4] call add_macro_symbol mov ebx,edx pop edx mov ecx,[edx+12] mov eax,[edx+8] mov [ebx+12],eax mov [ebx+8],ecx collect_next_variable_value: mov edx,[edx] or edx,edx jz variable_values_collected cmp ebp,[edx+4] jne collect_next_variable_value dec dword [esp] jnz add_irpv_value variable_values_collected: pop eax mov esi,ebp movzx ecx,byte [esi-1] add esi,ecx cmp byte [esi],0 je instant_macro_parameters_ok cmp byte [esi],'{' jne invalid_macro_arguments jmp instant_macro_parameters_ok do_match: mov ebx,esi call skip_pattern call exact_match mov edx,edi mov al,[ebx] cmp al,1Ah je free_match cmp al,',' jne instant_macro_done cmp esi,[parameters_end] je matched_pattern jmp instant_macro_done free_match: add edx,12 cmp edx,[memory_end] ja out_of_memory mov [edx-12],ebx mov [edx-8],esi call skip_match_element jc try_different_matching mov [edx-4],esi movzx eax,byte [ebx+1] lea ebx,[ebx+2+eax] cmp byte [ebx],1Ah je free_match find_exact_match: call exact_match cmp esi,[parameters_end] je end_matching cmp byte [ebx],1Ah je free_match mov ebx,[edx-12] movzx eax,byte [ebx+1] lea ebx,[ebx+2+eax] mov esi,[edx-4] jmp match_more_elements try_different_matching: sub edx,12 cmp edx,edi je instant_macro_done mov ebx,[edx-12] movzx eax,byte [ebx+1] lea ebx,[ebx+2+eax] cmp byte [ebx],1Ah je try_different_matching mov esi,[edx-4] match_more_elements: call skip_match_element jc try_different_matching mov [edx-4],esi jmp find_exact_match skip_match_element: cmp esi,[parameters_end] je cannot_match mov al,[esi] cmp al,1Ah je skip_match_symbol cmp al,22h je skip_match_quoted_string add esi,1 ret skip_match_quoted_string: mov eax,[esi+1] add esi,5 jmp skip_match_ok skip_match_symbol: movzx eax,byte [esi+1] add esi,2 skip_match_ok: add esi,eax ret cannot_match: stc ret exact_match: cmp esi,[parameters_end] je exact_match_complete mov ah,[esi] mov al,[ebx] cmp al,',' je exact_match_complete cmp al,1Ah je exact_match_complete cmp al,'=' je match_verbatim call match_elements je exact_match exact_match_complete: ret match_verbatim: inc ebx call match_elements je exact_match dec ebx ret match_elements: mov al,[ebx] cmp al,1Ah je match_symbols cmp al,22h je match_quoted_strings cmp al,ah je symbol_characters_matched ret symbol_characters_matched: lea ebx,[ebx+1] lea esi,[esi+1] ret match_quoted_strings: mov ecx,[ebx+1] add ecx,5 jmp compare_elements match_symbols: movzx ecx,byte [ebx+1] add ecx,2 compare_elements: mov eax,esi mov ebp,edi mov edi,ebx repe cmps byte [esi],[edi] jne elements_mismatch mov ebx,edi mov edi,ebp ret elements_mismatch: mov esi,eax mov edi,ebp ret end_matching: cmp byte [ebx],',' jne instant_macro_done matched_pattern: xor eax,eax push [free_additional_memory] push [macro_symbols] mov [macro_symbols],eax push [counter_limit] mov [counter_limit],eax mov [struc_name],eax push esi edi edx add_matched_symbol: cmp edi,[esp] je matched_symbols_ok mov esi,[edi] inc esi lods byte [esi] movzx ecx,al xor eax,eax call add_macro_symbol mov eax,[edi+4] mov dword [edx+12],eax mov ecx,[edi+8] sub ecx,eax mov dword [edx+8],ecx add edi,12 jmp add_matched_symbol matched_symbols_ok: pop edx edi esi jmp instant_macro_parameters_ok process_macro: push dword [macro_status] or [macro_status],10h push [counter] push [macro_block] push [macro_block_line] push [macro_block_line_number] push [struc_label] push [struc_name] push eax push [current_line] lods byte [esi] cmp al,'{' je macro_instructions_start or al,al jnz unexpected_characters find_macro_instructions: mov [macro_line],esi add esi,16+2 lods byte [esi] or al,al jz find_macro_instructions cmp al,'{' je macro_instructions_start cmp al,3Bh jne unexpected_characters call skip_foreign_symbol jmp find_macro_instructions macro_instructions_start: mov ecx,80000000h mov [macro_block],esi mov eax,[macro_line] mov [macro_block_line],eax mov [macro_block_line_number],ecx xor eax,eax mov [counter],eax cmp [counter_limit],eax je process_macro_line inc [counter] process_macro_line: lods byte [esi] or al,al jz process_next_line cmp al,'}' je macro_block_processed dec esi mov [current_line],edi lea eax,[edi+10h] cmp eax,[memory_end] jae out_of_memory mov eax,[esp+4] or eax,eax jz instant_macro_line_header stos dword [edi] mov eax,ecx stos dword [edi] mov eax,[esp] stos dword [edi] mov eax,[macro_line] stos dword [edi] jmp macro_line_header_ok instant_macro_line_header: mov eax,[esp] add eax,16 find_defining_directive: inc eax cmp byte [eax-1],3Bh je defining_directive_ok cmp byte [eax-1],1Ah jne find_defining_directive push eax movzx eax,byte [eax] inc eax add [esp],eax pop eax jmp find_defining_directive defining_directive_ok: stos dword [edi] mov eax,ecx stos dword [edi] mov eax,[macro_line] stos dword [edi] stos dword [edi] macro_line_header_ok: or [macro_status],20h push ebx ecx test [macro_status],0Fh jz process_macro_line_element mov ax,3Bh stos word [edi] process_macro_line_element: lea eax,[edi+100h] cmp eax,[memory_end] jae out_of_memory lods byte [esi] cmp al,'}' je macro_line_processed or al,al jz macro_line_processed cmp al,1Ah je process_macro_symbol cmp al,3Bh je macro_foreign_line and [macro_status],not 20h stos byte [edi] cmp al,22h jne process_macro_line_element copy_macro_string: mov ecx,[esi] add ecx,4 call move_data jmp process_macro_line_element process_macro_symbol: push esi edi test [macro_status],20h jz not_macro_directive movzx ecx,byte [esi] inc esi mov edi,macro_directives call get_directive jnc process_macro_directive dec esi jmp not_macro_directive process_macro_directive: mov edx,eax pop edi eax mov byte [edi],0 inc edi pop ecx ebx jmp near edx not_macro_directive: and [macro_status],not 20h movzx ecx,byte [esi] inc esi mov eax,[counter] call get_macro_symbol jnc group_macro_symbol xor eax,eax cmp [counter],eax je multiple_macro_symbol_values call get_macro_symbol jc not_macro_symbol replace_macro_symbol: pop edi eax mov ecx,[edx+8] mov edx,[edx+12] or edx,edx jz replace_macro_counter and ecx,not 80000000h xchg esi,edx call move_data mov esi,edx jmp process_macro_line_element group_macro_symbol: xor eax,eax cmp [counter],eax je replace_macro_symbol push esi edx sub esi,ecx call get_macro_symbol mov ebx,edx pop edx esi jc replace_macro_symbol cmp edx,ebx ja replace_macro_symbol mov edx,ebx jmp replace_macro_symbol multiple_macro_symbol_values: inc eax push eax call get_macro_symbol pop eax jc not_macro_symbol pop edi push ecx mov ecx,[edx+8] mov edx,[edx+12] xchg esi,edx btr ecx,31 jc enclose_macro_symbol_value rep movs byte [edi],[esi] jmp macro_symbol_value_ok enclose_macro_symbol_value: mov byte [edi],'<' inc edi rep movs byte [edi],[esi] mov byte [edi],'>' inc edi macro_symbol_value_ok: cmp eax,[counter_limit] je multiple_macro_symbol_values_ok mov byte [edi],',' inc edi mov esi,edx pop ecx push edi sub esi,ecx jmp multiple_macro_symbol_values multiple_macro_symbol_values_ok: pop ecx eax mov esi,edx jmp process_macro_line_element replace_macro_counter: mov eax,[counter] and eax,not 80000000h jz group_macro_counter add ecx,eax dec ecx call store_number_symbol jmp process_macro_line_element group_macro_counter: mov edx,ecx xor ecx,ecx multiple_macro_counter_values: push ecx edx add ecx,edx call store_number_symbol pop edx ecx inc ecx cmp ecx,[counter_limit] je process_macro_line_element mov byte [edi],',' inc edi jmp multiple_macro_counter_values store_number_symbol: cmp ecx,0 jge numer_symbol_sign_ok neg ecx mov al,'-' stos byte [edi] numer_symbol_sign_ok: mov ax,1Ah stos word [edi] push edi mov eax,ecx mov ecx,1000000000 xor edx,edx xor bl,bl store_number_digits: div ecx push edx or bl,bl jnz store_number_digit cmp ecx,1 je store_number_digit or al,al jz number_digit_ok not bl store_number_digit: add al,30h stos byte [edi] number_digit_ok: mov eax,ecx xor edx,edx mov ecx,10 div ecx mov ecx,eax pop eax or ecx,ecx jnz store_number_digits pop ebx mov eax,edi sub eax,ebx mov [ebx-1],al ret not_macro_symbol: pop edi esi mov al,1Ah stos byte [edi] mov al,[esi] inc esi stos byte [edi] cmp byte [esi],'.' jne copy_raw_symbol mov ebx,[esp+8+8] or ebx,ebx jz copy_raw_symbol cmp al,1 je copy_struc_name xchg esi,ebx movzx ecx,byte [esi-1] add [edi-1],cl jc name_too_long rep movs byte [edi],[esi] xchg esi,ebx copy_raw_symbol: movzx ecx,al rep movs byte [edi],[esi] jmp process_macro_line_element copy_struc_name: inc esi xchg esi,ebx movzx ecx,byte [esi-1] mov [edi-1],cl rep movs byte [edi],[esi] xchg esi,ebx mov eax,[esp+8+12] cmp byte [eax],3Bh je process_macro_line_element cmp byte [eax],1Ah jne disable_replaced_struc_name mov byte [eax],3Bh jmp process_macro_line_element disable_replaced_struc_name: mov ebx,[esp+8+8] push esi edi lea edi,[ebx-3] lea esi,[edi-2] lea ecx,[esi+1] sub ecx,eax std rep movs byte [edi],[esi] cld mov word [eax],3Bh pop edi esi jmp process_macro_line_element skip_foreign_symbol: lods byte [esi] movzx eax,al add esi,eax skip_foreign_line: lods byte [esi] cmp al,1Ah je skip_foreign_symbol cmp al,3Bh je skip_foreign_symbol cmp al,22h je skip_foreign_string or al,al jnz skip_foreign_line ret skip_foreign_string: lods dword [esi] add esi,eax jmp skip_foreign_line macro_foreign_line: call skip_foreign_symbol macro_line_processed: mov byte [edi],0 inc edi push eax call preprocess_line pop eax pop ecx ebx cmp al,'}' je macro_block_processed process_next_line: inc ecx mov [macro_line],esi add esi,16+2 jmp process_macro_line macro_block_processed: call close_macro_block jc process_macro_line pop [current_line] add esp,12 pop [macro_block_line_number] pop [macro_block_line] pop [macro_block] pop [counter] pop eax and al,0F0h and [macro_status],0Fh or [macro_status],al ret local_symbols: lods byte [esi] cmp al,1Ah jne invalid_argument mov byte [edi-1],3Bh xor al,al stos byte [edi] make_local_symbol: push ecx lods byte [esi] movzx ecx,al mov eax,[counter] call add_macro_symbol mov [edx+12],edi movzx eax,[locals_counter] add eax,ecx inc eax cmp eax,100h jae name_too_long lea ebp,[edi+2+eax] cmp ebp,[memory_end] jae out_of_memory mov ah,al mov al,1Ah stos word [edi] rep movs byte [edi],[esi] mov al,'?' stos byte [edi] push esi mov esi,locals_counter+1 movzx ecx,[locals_counter] rep movs byte [edi],[esi] pop esi mov eax,edi sub eax,[edx+12] mov [edx+8],eax xor al,al stos byte [edi] mov eax,locals_counter movzx ecx,byte [eax] counter_loop: inc byte [eax+ecx] cmp byte [eax+ecx],'9'+1 jb counter_ok jne letter_digit mov byte [eax+ecx],'A' jmp counter_ok letter_digit: cmp byte [eax+ecx],'Z'+1 jb counter_ok jne small_letter_digit mov byte [eax+ecx],'a' jmp counter_ok small_letter_digit: cmp byte [eax+ecx],'z'+1 jb counter_ok mov byte [eax+ecx],'0' loop counter_loop inc byte [eax] movzx ecx,byte [eax] mov byte [eax+ecx],'0' counter_ok: pop ecx lods byte [esi] cmp al,'}' je macro_block_processed or al,al jz process_next_line cmp al,',' jne extra_characters_on_line dec edi lods byte [esi] cmp al,1Ah je make_local_symbol jmp invalid_argument common_block: call close_macro_block jc process_macro_line mov [counter],0 jmp new_macro_block forward_block: cmp [counter_limit],0 je common_block call close_macro_block jc process_macro_line mov [counter],1 jmp new_macro_block reverse_block: cmp [counter_limit],0 je common_block call close_macro_block jc process_macro_line mov eax,[counter_limit] or eax,80000000h mov [counter],eax new_macro_block: mov [macro_block],esi mov eax,[macro_line] mov [macro_block_line],eax mov [macro_block_line_number],ecx jmp process_macro_line close_macro_block: cmp esi,[macro_block] je block_closed cmp [counter],0 je block_closed jl reverse_counter mov eax,[counter] cmp eax,[counter_limit] je block_closed inc [counter] jmp continue_block reverse_counter: mov eax,[counter] dec eax cmp eax,80000000h je block_closed mov [counter],eax continue_block: mov esi,[macro_block] mov eax,[macro_block_line] mov [macro_line],eax mov ecx,[macro_block_line_number] stc ret block_closed: clc ret get_macro_symbol: push ecx call find_macro_symbol_leaf jc macro_symbol_not_found mov edx,[ebx] mov ebx,esi try_macro_symbol: or edx,edx jz macro_symbol_not_found mov ecx,[esp] mov edi,[edx+4] repe cmps byte [esi],[edi] je macro_symbol_found mov esi,ebx mov edx,[edx] jmp try_macro_symbol macro_symbol_found: pop ecx clc ret macro_symbol_not_found: pop ecx stc ret find_macro_symbol_leaf: shl eax,8 mov al,cl mov ebp,eax mov ebx,macro_symbols follow_macro_symbols_tree: mov edx,[ebx] or edx,edx jz no_such_macro_symbol xor eax,eax shr ebp,1 adc eax,0 lea ebx,[edx+eax*4] or ebp,ebp jnz follow_macro_symbols_tree add ebx,8 clc ret no_such_macro_symbol: stc ret add_macro_symbol: push ebx ebp call find_macro_symbol_leaf jc extend_macro_symbol_tree mov eax,[ebx] make_macro_symbol: mov edx,[free_additional_memory] add edx,16 cmp edx,[labels_list] ja out_of_memory xchg edx,[free_additional_memory] mov [ebx],edx mov [edx],eax mov [edx+4],esi pop ebp ebx ret extend_macro_symbol_tree: mov edx,[free_additional_memory] add edx,16 cmp edx,[labels_list] ja out_of_memory xchg edx,[free_additional_memory] xor eax,eax mov [edx],eax mov [edx+4],eax mov [edx+8],eax mov [edx+12],eax shr ebp,1 adc eax,0 mov [ebx],edx lea ebx,[edx+eax*4] or ebp,ebp jnz extend_macro_symbol_tree add ebx,8 xor eax,eax jmp make_macro_symbol include_file: lods byte [esi] cmp al,22h jne invalid_argument lods dword [esi] cmp byte [esi+eax],0 jne extra_characters_on_line push esi push edi mov ebx,[current_line] find_current_file_path: mov esi,[ebx] test byte [ebx+7],80h jz copy_current_file_path mov ebx,[ebx+8] jmp find_current_file_path copy_current_file_path: lods byte [esi] stos byte [edi] or al,al jnz copy_current_file_path cut_current_file_name: cmp edi,[esp] je current_file_path_ok cmp byte [edi-1],'\' je current_file_path_ok cmp byte [edi-1],'/' je current_file_path_ok dec edi jmp cut_current_file_name current_file_path_ok: mov esi,[esp+4] call expand_path pop edx mov esi,edx call open jnc include_path_ok mov ebp,[include_paths] try_include_directories: mov edi,esi mov esi,ebp cmp byte [esi],0 je try_in_current_directory push ebp push edi call get_include_directory mov [esp+4],esi mov esi,[esp+8] call expand_path pop edx mov esi,edx call open pop ebp jnc include_path_ok jmp try_include_directories mov edi,esi try_in_current_directory: mov esi,[esp] push edi call expand_path pop edx mov esi,edx call open jc file_not_found include_path_ok: mov edi,[esp] copy_preprocessed_path: lods byte [esi] stos byte [edi] or al,al jnz copy_preprocessed_path pop esi lea ecx,[edi-1] sub ecx,esi mov [esi-4],ecx push dword [macro_status] and [macro_status],0Fh call preprocess_file pop eax and al,0F0h and [macro_status],0Fh or [macro_status],al jmp line_preprocessed fasm/source/symbdump.inc0000644000175000017500000002200514533376740016140 0ustar privalovprivalov ; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. dump_symbols: mov edi,[code_start] call setup_dump_header mov esi,[input_file] call copy_asciiz cmp edi,[tagged_blocks] jae out_of_memory mov eax,edi sub eax,ebx mov [ebx-40h+0Ch],eax mov esi,[output_file] call copy_asciiz cmp edi,[tagged_blocks] jae out_of_memory mov edx,[symbols_stream] mov ebp,[free_additional_memory] and [number_of_sections],0 cmp [output_format],4 je prepare_strings_table cmp [output_format],5 jne strings_table_ready bt [format_flags],0 jc strings_table_ready prepare_strings_table: cmp edx,ebp je strings_table_ready mov al,[edx] test al,al jz prepare_string cmp al,80h je prepare_string add edx,0Ch cmp al,0C0h jb prepare_strings_table add edx,4 jmp prepare_strings_table prepare_string: mov esi,edi sub esi,ebx xchg esi,[edx+4] test al,al jz prepare_section_string or dword [edx+4],1 shl 31 add edx,0Ch prepare_external_string: mov ecx,[esi] add esi,4 rep movs byte [edi],[esi] mov byte [edi],0 inc edi cmp edi,[tagged_blocks] jae out_of_memory jmp prepare_strings_table prepare_section_string: mov ecx,[number_of_sections] mov eax,ecx inc eax mov [number_of_sections],eax xchg eax,[edx+4] shl ecx,2 add ecx,[free_additional_memory] mov [ecx],eax add edx,20h test esi,esi jz prepare_default_section_string cmp [output_format],5 jne prepare_external_string bt [format_flags],0 jc prepare_external_string mov esi,[esi] add esi,[resource_data] copy_elf_section_name: lods byte [esi] cmp edi,[tagged_blocks] jae out_of_memory stos byte [edi] test al,al jnz copy_elf_section_name jmp prepare_strings_table prepare_default_section_string: mov eax,'.fla' stos dword [edi] mov ax,'t' stos word [edi] cmp edi,[tagged_blocks] jae out_of_memory jmp prepare_strings_table strings_table_ready: mov edx,[tagged_blocks] mov ebp,[memory_end] sub ebp,[labels_list] add ebp,edx prepare_labels_dump: cmp edx,ebp je labels_dump_ok mov eax,[edx+24] test eax,eax jz label_dump_name_ok cmp eax,[memory_start] jb label_name_outside_source cmp eax,[source_start] ja label_name_outside_source sub eax,[memory_start] dec eax mov [edx+24],eax jmp label_dump_name_ok label_name_outside_source: mov esi,eax mov eax,edi sub eax,ebx or eax,1 shl 31 mov [edx+24],eax movzx ecx,byte [esi-1] lea eax,[edi+ecx+1] cmp edi,[tagged_blocks] jae out_of_memory rep movsb xor al,al stosb label_dump_name_ok: mov eax,[edx+28] test eax,eax jz label_dump_line_ok sub eax,[memory_start] mov [edx+28],eax label_dump_line_ok: test byte [edx+9],4 jz convert_base_symbol_for_label xor eax,eax mov [edx],eax mov [edx+4],eax jmp base_symbol_for_label_ok convert_base_symbol_for_label: mov eax,[edx+20] test eax,eax jz base_symbol_for_label_ok cmp eax,[symbols_stream] mov eax,[eax+4] jae base_symbol_for_label_ok xor eax,eax base_symbol_for_label_ok: mov [edx+20],eax mov ax,[current_pass] cmp ax,[edx+16] je label_defined_flag_ok and byte [edx+8],not 1 label_defined_flag_ok: cmp ax,[edx+18] je label_used_flag_ok and byte [edx+8],not 8 label_used_flag_ok: add edx,LABEL_STRUCTURE_SIZE jmp prepare_labels_dump labels_dump_ok: mov eax,edi sub eax,ebx mov [ebx-40h+14h],eax add eax,40h mov [ebx-40h+18h],eax mov ecx,[memory_end] sub ecx,[labels_list] mov [ebx-40h+1Ch],ecx add eax,ecx mov [ebx-40h+20h],eax mov ecx,[source_start] sub ecx,[memory_start] mov [ebx-40h+24h],ecx add eax,ecx mov [ebx-40h+28h],eax mov eax,[number_of_sections] shl eax,2 mov [ebx-40h+34h],eax call prepare_preprocessed_source mov esi,[labels_list] mov ebp,edi make_lines_dump: cmp esi,[tagged_blocks] je lines_dump_ok mov eax,[esi-4] mov ecx,[esi-8] sub esi,8 sub esi,ecx cmp eax,1 je process_line_dump cmp eax,2 jne make_lines_dump add dword [ebx-40h+3Ch],8 jmp make_lines_dump process_line_dump: push ebx mov ebx,[esi+8] mov eax,[esi+4] sub eax,[code_start] add eax,[headers_size] test byte [ebx+0Ah],1 jz store_offset xor eax,eax store_offset: stos dword [edi] mov eax,[esi] sub eax,[memory_start] stos dword [edi] mov eax,[esi+4] xor edx,edx xor cl,cl sub eax,[ebx] sbb edx,[ebx+4] sbb cl,[ebx+8] stos dword [edi] mov eax,edx stos dword [edi] mov eax,[ebx+10h] stos dword [edi] mov eax,[ebx+14h] test eax,eax jz base_symbol_for_line_ok cmp eax,[symbols_stream] mov eax,[eax+4] jae base_symbol_for_line_ok xor eax,eax base_symbol_for_line_ok: stos dword [edi] mov al,[ebx+9] stos byte [edi] mov al,[esi+10h] stos byte [edi] mov al,[ebx+0Ah] and al,1 stos byte [edi] mov al,cl stos byte [edi] pop ebx cmp edi,[tagged_blocks] jae out_of_memory mov eax,edi sub eax,1Ch sub eax,ebp mov [esi],eax jmp make_lines_dump lines_dump_ok: mov edx,edi mov eax,[current_offset] sub eax,[code_start] add eax,[headers_size] stos dword [edi] mov ecx,edi sub ecx,ebx sub ecx,[ebx-40h+14h] mov [ebx-40h+2Ch],ecx add ecx,[ebx-40h+28h] mov [ebx-40h+30h],ecx add ecx,[ebx-40h+34h] mov [ebx-40h+38h],ecx find_inexisting_offsets: sub edx,1Ch cmp edx,ebp jb write_symbols test byte [edx+1Ah],1 jnz find_inexisting_offsets cmp eax,[edx] jb correct_inexisting_offset mov eax,[edx] jmp find_inexisting_offsets correct_inexisting_offset: and dword [edx],0 or byte [edx+1Ah],2 jmp find_inexisting_offsets write_symbols: mov edx,[symbols_file] call create jc write_failed mov edx,[code_start] mov ecx,[edx+14h] add ecx,40h call write jc write_failed mov edx,[tagged_blocks] mov ecx,[memory_end] sub ecx,[labels_list] call write jc write_failed mov edx,[memory_start] mov ecx,[source_start] sub ecx,edx call write jc write_failed mov edx,ebp mov ecx,edi sub ecx,edx call write jc write_failed mov edx,[free_additional_memory] mov ecx,[number_of_sections] shl ecx,2 call write jc write_failed mov esi,[labels_list] mov edi,[memory_start] make_references_dump: cmp esi,[tagged_blocks] je references_dump_ok mov eax,[esi-4] mov ecx,[esi-8] sub esi,8 sub esi,ecx cmp eax,2 je dump_reference cmp eax,1 jne make_references_dump mov edx,[esi] jmp make_references_dump dump_reference: mov eax,[memory_end] sub eax,[esi] sub eax,LABEL_STRUCTURE_SIZE stosd mov eax,edx stosd cmp edi,[tagged_blocks] jb make_references_dump jmp out_of_memory references_dump_ok: mov edx,[memory_start] mov ecx,edi sub ecx,edx call write jc write_failed call close ret setup_dump_header: xor eax,eax mov ecx,40h shr 2 rep stos dword [edi] mov ebx,edi mov dword [ebx-40h],'fas'+1Ah shl 24 mov dword [ebx-40h+4],VERSION_MAJOR + VERSION_MINOR shl 8 + 40h shl 16 mov dword [ebx-40h+10h],40h ret prepare_preprocessed_source: mov esi,[memory_start] mov ebp,[source_start] test ebp,ebp jnz prepare_preprocessed_line mov ebp,[current_line] inc ebp prepare_preprocessed_line: cmp esi,ebp jae preprocessed_source_ok mov eax,[memory_start] mov edx,[input_file] cmp [esi],edx jne line_not_from_main_input mov [esi],eax line_not_from_main_input: sub [esi],eax test byte [esi+7],1 shl 7 jz prepare_next_preprocessed_line sub [esi+8],eax sub [esi+12],eax prepare_next_preprocessed_line: call skip_preprocessed_line jmp prepare_preprocessed_line preprocessed_source_ok: ret skip_preprocessed_line: add esi,16 skip_preprocessed_line_content: lods byte [esi] cmp al,1Ah je skip_preprocessed_symbol cmp al,3Bh je skip_preprocessed_symbol cmp al,22h je skip_preprocessed_string or al,al jnz skip_preprocessed_line_content ret skip_preprocessed_string: lods dword [esi] add esi,eax jmp skip_preprocessed_line_content skip_preprocessed_symbol: lods byte [esi] movzx eax,al add esi,eax jmp skip_preprocessed_line_content restore_preprocessed_source: mov esi,[memory_start] mov ebp,[source_start] test ebp,ebp jnz restore_preprocessed_line mov ebp,[current_line] inc ebp restore_preprocessed_line: cmp esi,ebp jae preprocessed_source_restored mov eax,[memory_start] add [esi],eax cmp [esi],eax jne preprocessed_line_source_restored mov edx,[input_file] mov [esi],edx preprocessed_line_source_restored: test byte [esi+7],1 shl 7 jz restore_next_preprocessed_line add [esi+8],eax add [esi+12],eax restore_next_preprocessed_line: call skip_preprocessed_line jmp restore_preprocessed_line preprocessed_source_restored: ret dump_preprocessed_source: mov edi,[free_additional_memory] call setup_dump_header mov esi,[input_file] call copy_asciiz cmp edi,[additional_memory_end] jae out_of_memory mov eax,edi sub eax,ebx dec eax mov [ebx-40h+0Ch],eax mov eax,edi sub eax,ebx mov [ebx-40h+14h],eax add eax,40h mov [ebx-40h+20h],eax call prepare_preprocessed_source sub esi,[memory_start] mov [ebx-40h+24h],esi mov edx,[symbols_file] call create jc write_failed mov edx,[free_additional_memory] mov ecx,[edx+14h] add ecx,40h call write jc write_failed mov edx,[memory_start] mov ecx,esi call write jc write_failed call close ret fasm/source/tables.inc0000644000175000017500000041417614533376740015570 0ustar privalovprivalov ; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. include_variable db 'INCLUDE',0 symbol_characters db 27 db 9,0Ah,0Dh,1Ah,20h,'+-/*=<>()[]{}:,|&~#`;\' preprocessor_directives: db 6,'define' dw define_symbolic_constant-directive_handler db 7,'include' dw include_file-directive_handler db 3,'irp' dw irp_directive-directive_handler db 4,'irps' dw irps_directive-directive_handler db 4,'irpv' dw irpv_directive-directive_handler db 5,'macro' dw define_macro-directive_handler db 5,'match' dw match_directive-directive_handler db 8,'postpone' dw postpone_directive-directive_handler db 5,'purge' dw purge_macro-directive_handler db 4,'rept' dw rept_directive-directive_handler db 7,'restore' dw restore_equ_constant-directive_handler db 7,'restruc' dw purge_struc-directive_handler db 5,'struc' dw define_struc-directive_handler db 0 macro_directives: db 6,'common' dw common_block-directive_handler db 7,'forward' dw forward_block-directive_handler db 5,'local' dw local_symbols-directive_handler db 7,'reverse' dw reverse_block-directive_handler db 0 preprocessor_special_symbols: db 4,'file' dw preprocessed_file_value-directive_handler db 4,'line' dw preprocessed_line_value-directive_handler db 0 operators: db 1,'+',80h db 1,'-',81h db 1,'*',90h db 1,'/',91h db 3,'and',0B0h db 3,'mod',0A0h db 2,'or',0B1h db 3,'shl',0C0h db 3,'shr',0C1h db 3,'xor',0B2h db 0 single_operand_operators: db 1,'+',82h db 1,'-',83h db 3,'bsf',0E0h db 3,'bsr',0E1h db 3,'not',0D0h db 3,'plt',0F1h db 3,'rva',0F0h db 0 directive_operators: db 5,'align',8Ch db 2,'as',86h db 2,'at',80h db 7,'defined',88h db 8,'definite',8Ah db 3,'dup',81h db 2,'eq',0F0h db 6,'eqtype',0F7h db 4,'from',82h db 2,'in',0F6h db 2,'on',84h db 3,'ptr',85h db 10,'relativeto',0F8h db 4,'used',89h db 0 address_sizes: db 4,'byte',1 db 5,'dword',4 db 5,'qword',8 db 4,'word',2 db 0 symbols: dw symbols_1-symbols,(symbols_2-symbols_1)/(1+2) dw symbols_2-symbols,(symbols_3-symbols_2)/(2+2) dw symbols_3-symbols,(symbols_4-symbols_3)/(3+2) dw symbols_4-symbols,(symbols_5-symbols_4)/(4+2) dw symbols_5-symbols,(symbols_6-symbols_5)/(5+2) dw symbols_6-symbols,(symbols_7-symbols_6)/(6+2) dw symbols_7-symbols,(symbols_8-symbols_7)/(7+2) dw symbols_8-symbols,(symbols_9-symbols_8)/(8+2) dw symbols_9-symbols,(symbols_10-symbols_9)/(9+2) dw symbols_10-symbols,(symbols_11-symbols_10)/(10+2) dw symbols_11-symbols,(symbols_end-symbols_11)/(11+2) symbols_1: db 'z',1Fh,0 symbols_2: db 'ah',10h,04h db 'al',10h,10h db 'ax',10h,20h db 'bh',10h,07h db 'bl',10h,13h db 'bp',10h,25h db 'bx',10h,23h db 'ch',10h,05h db 'cl',10h,11h db 'cs',10h,32h db 'cx',10h,21h db 'dh',10h,06h db 'di',10h,27h db 'dl',10h,12h db 'ds',10h,34h db 'dx',10h,22h db 'es',10h,31h db 'fs',10h,35h db 'gs',10h,36h db 'k0',14h,50h db 'k1',14h,51h db 'k2',14h,52h db 'k3',14h,53h db 'k4',14h,54h db 'k5',14h,55h db 'k6',14h,56h db 'k7',14h,57h db 'ms',1Ch,41h db 'mz',18h,20h db 'nx',1Bh,83h db 'pe',18h,30h db 'r8',10h,88h db 'r9',10h,89h db 'rd',1Fh,21h db 'rn',1Fh,20h db 'ru',1Fh,22h db 'rz',1Fh,23h db 'si',10h,26h db 'sp',10h,24h db 'ss',10h,33h db 'st',10h,0A0h symbols_3: db 'bpl',10h,15h db 'cr0',14h,00h db 'cr1',14h,01h db 'cr2',14h,02h db 'cr3',14h,03h db 'cr4',14h,04h db 'cr5',14h,05h db 'cr6',14h,06h db 'cr7',14h,07h db 'cr8',14h,08h db 'cr9',14h,09h db 'dil',10h,17h db 'dll',1Bh,80h db 'dr0',14h,10h db 'dr1',14h,11h db 'dr2',14h,12h db 'dr3',14h,13h db 'dr4',14h,14h db 'dr5',14h,15h db 'dr6',14h,16h db 'dr7',14h,17h db 'dr8',14h,18h db 'dr9',14h,19h db 'eax',10h,40h db 'ebp',10h,45h db 'ebx',10h,43h db 'ecx',10h,41h db 'edi',10h,47h db 'edx',10h,42h db 'efi',1Bh,10 db 'eip',10h,94h db 'elf',18h,50h db 'esi',10h,46h db 'esp',10h,44h db 'far',12h,3 db 'gui',1Bh,2 db 'mm0',10h,0B0h db 'mm1',10h,0B1h db 'mm2',10h,0B2h db 'mm3',10h,0B3h db 'mm4',10h,0B4h db 'mm5',10h,0B5h db 'mm6',10h,0B6h db 'mm7',10h,0B7h db 'r10',10h,8Ah db 'r11',10h,8Bh db 'r12',10h,8Ch db 'r13',10h,8Dh db 'r14',10h,8Eh db 'r15',10h,8Fh db 'r8b',10h,18h db 'r8d',10h,48h db 'r8l',10h,18h db 'r8w',10h,28h db 'r9b',10h,19h db 'r9d',10h,49h db 'r9l',10h,19h db 'r9w',10h,29h db 'rax',10h,80h db 'rbp',10h,85h db 'rbx',10h,83h db 'rcx',10h,81h db 'rdi',10h,87h db 'rdx',10h,82h db 'rip',10h,98h db 'rsi',10h,86h db 'rsp',10h,84h db 'sae',1Fh,30h db 'sil',10h,16h db 'spl',10h,14h db 'st0',10h,0A0h db 'st1',10h,0A1h db 'st2',10h,0A2h db 'st3',10h,0A3h db 'st4',10h,0A4h db 'st5',10h,0A5h db 'st6',10h,0A6h db 'st7',10h,0A7h db 'tr0',14h,40h db 'tr1',14h,41h db 'tr2',14h,42h db 'tr3',14h,43h db 'tr4',14h,44h db 'tr5',14h,45h db 'tr6',14h,46h db 'tr7',14h,47h db 'wdm',1Bh,81h symbols_4: db '1to2',1Fh,11h db '1to4',1Fh,12h db '1to8',1Fh,13h db 'bnd0',14h,60h db 'bnd1',14h,61h db 'bnd2',14h,62h db 'bnd3',14h,63h db 'byte',11h,1 db 'code',19h,5 db 'coff',18h,40h db 'cr10',14h,0Ah db 'cr11',14h,0Bh db 'cr12',14h,0Ch db 'cr13',14h,0Dh db 'cr14',14h,0Eh db 'cr15',14h,0Fh db 'data',19h,6 db 'dr10',14h,1Ah db 'dr11',14h,1Bh db 'dr12',14h,1Ch db 'dr13',14h,1Dh db 'dr14',14h,1Eh db 'dr15',14h,1Fh db 'ms64',1Ch,49h db 'near',12h,2 db 'note',1Eh,4 db 'pe64',18h,3Ch db 'r10b',10h,1Ah db 'r10d',10h,4Ah db 'r10l',10h,1Ah db 'r10w',10h,2Ah db 'r11b',10h,1Bh db 'r11d',10h,4Bh db 'r11l',10h,1Bh db 'r11w',10h,2Bh db 'r12b',10h,1Ch db 'r12d',10h,4Ch db 'r12l',10h,1Ch db 'r12w',10h,2Ch db 'r13b',10h,1Dh db 'r13d',10h,4Dh db 'r13l',10h,1Dh db 'r13w',10h,2Dh db 'r14b',10h,1Eh db 'r14d',10h,4Eh db 'r14l',10h,1Eh db 'r14w',10h,2Eh db 'r15b',10h,1Fh db 'r15d',10h,4Fh db 'r15l',10h,1Fh db 'r15w',10h,2Fh db 'word',11h,2 db 'xmm0',10h,0C0h db 'xmm1',10h,0C1h db 'xmm2',10h,0C2h db 'xmm3',10h,0C3h db 'xmm4',10h,0C4h db 'xmm5',10h,0C5h db 'xmm6',10h,0C6h db 'xmm7',10h,0C7h db 'xmm8',10h,0C8h db 'xmm9',10h,0C9h db 'ymm0',10h,0E0h db 'ymm1',10h,0E1h db 'ymm2',10h,0E2h db 'ymm3',10h,0E3h db 'ymm4',10h,0E4h db 'ymm5',10h,0E5h db 'ymm6',10h,0E6h db 'ymm7',10h,0E7h db 'ymm8',10h,0E8h db 'ymm9',10h,0E9h db 'zmm0',10h,60h db 'zmm1',10h,61h db 'zmm2',10h,62h db 'zmm3',10h,63h db 'zmm4',10h,64h db 'zmm5',10h,65h db 'zmm6',10h,66h db 'zmm7',10h,67h db 'zmm8',10h,68h db 'zmm9',10h,69h symbols_5: db '1to16',1Fh,14h db 'dword',11h,4 db 'elf64',18h,58h db 'fword',11h,6 db 'large',1Bh,82h db 'pword',11h,6 db 'qword',11h,8 db 'short',12h,1 db 'tbyte',11h,0Ah db 'tword',11h,0Ah db 'use16',13h,16 db 'use32',13h,32 db 'use64',13h,64 db 'xmm10',10h,0CAh db 'xmm11',10h,0CBh db 'xmm12',10h,0CCh db 'xmm13',10h,0CDh db 'xmm14',10h,0CEh db 'xmm15',10h,0CFh db 'xmm16',10h,0D0h db 'xmm17',10h,0D1h db 'xmm18',10h,0D2h db 'xmm19',10h,0D3h db 'xmm20',10h,0D4h db 'xmm21',10h,0D5h db 'xmm22',10h,0D6h db 'xmm23',10h,0D7h db 'xmm24',10h,0D8h db 'xmm25',10h,0D9h db 'xmm26',10h,0DAh db 'xmm27',10h,0DBh db 'xmm28',10h,0DCh db 'xmm29',10h,0DDh db 'xmm30',10h,0DEh db 'xmm31',10h,0DFh db 'xword',11h,16 db 'ymm10',10h,0EAh db 'ymm11',10h,0EBh db 'ymm12',10h,0ECh db 'ymm13',10h,0EDh db 'ymm14',10h,0EEh db 'ymm15',10h,0EFh db 'ymm16',10h,0F0h db 'ymm17',10h,0F1h db 'ymm18',10h,0F2h db 'ymm19',10h,0F3h db 'ymm20',10h,0F4h db 'ymm21',10h,0F5h db 'ymm22',10h,0F6h db 'ymm23',10h,0F7h db 'ymm24',10h,0F8h db 'ymm25',10h,0F9h db 'ymm26',10h,0FAh db 'ymm27',10h,0FBh db 'ymm28',10h,0FCh db 'ymm29',10h,0FDh db 'ymm30',10h,0FEh db 'ymm31',10h,0FFh db 'yword',11h,32 db 'zmm10',10h,6Ah db 'zmm11',10h,6Bh db 'zmm12',10h,6Ch db 'zmm13',10h,6Dh db 'zmm14',10h,6Eh db 'zmm15',10h,6Fh db 'zmm16',10h,70h db 'zmm17',10h,71h db 'zmm18',10h,72h db 'zmm19',10h,73h db 'zmm20',10h,74h db 'zmm21',10h,75h db 'zmm22',10h,76h db 'zmm23',10h,77h db 'zmm24',10h,78h db 'zmm25',10h,79h db 'zmm26',10h,7Ah db 'zmm27',10h,7Bh db 'zmm28',10h,7Ch db 'zmm29',10h,7Dh db 'zmm30',10h,7Eh db 'zmm31',10h,7Fh db 'zword',11h,64 symbols_6: db 'binary',18h,10h db 'dqword',11h,16 db 'export',1Ah,0 db 'fixups',1Ah,5 db 'import',1Ah,1 db 'native',1Bh,1 db 'qqword',11h,32 db 'static',1Dh,1 symbols_7: db 'console',1Bh,3 db 'dqqword',11h,64 db 'dynamic',1Eh,2 db 'efiboot',1Bh,11 symbols_8: db 'gnurelro',1Eh,52h db 'gnustack',1Eh,51h db 'linkinfo',19h,9 db 'readable',19h,30 db 'resource',1Ah,2 db 'writable',19h,31 symbols_9: db 'shareable',19h,28 db 'writeable',19h,31 symbols_10: db 'efiruntime',1Bh,12 db 'executable',19h,29 db 'gnuehframe',1Eh,50h db 'linkremove',19h,11 symbols_11: db 'discardable',19h,25 db 'interpreter',1Eh,3 db 'notpageable',19h,27 symbols_end: instructions: dw instructions_2-instructions,(instructions_3-instructions_2)/(2+3) dw instructions_3-instructions,(instructions_4-instructions_3)/(3+3) dw instructions_4-instructions,(instructions_5-instructions_4)/(4+3) dw instructions_5-instructions,(instructions_6-instructions_5)/(5+3) dw instructions_6-instructions,(instructions_7-instructions_6)/(6+3) dw instructions_7-instructions,(instructions_8-instructions_7)/(7+3) dw instructions_8-instructions,(instructions_9-instructions_8)/(8+3) dw instructions_9-instructions,(instructions_10-instructions_9)/(9+3) dw instructions_10-instructions,(instructions_11-instructions_10)/(10+3) dw instructions_11-instructions,(instructions_12-instructions_11)/(11+3) dw instructions_12-instructions,(instructions_13-instructions_12)/(12+3) dw instructions_13-instructions,(instructions_14-instructions_13)/(13+3) dw instructions_14-instructions,(instructions_15-instructions_14)/(14+3) dw instructions_15-instructions,(instructions_16-instructions_15)/(15+3) dw instructions_16-instructions,(instructions_17-instructions_16)/(16+3) dw instructions_17-instructions,(instructions_end-instructions_17)/(17+3) instructions_2: db 'bt',4 dw bt_instruction-instruction_handler db 'if',0 dw if_directive-instruction_handler db 'in',0 dw in_instruction-instruction_handler db 'ja',77h dw conditional_jump-instruction_handler db 'jb',72h dw conditional_jump-instruction_handler db 'jc',72h dw conditional_jump-instruction_handler db 'je',74h dw conditional_jump-instruction_handler db 'jg',7Fh dw conditional_jump-instruction_handler db 'jl',7Ch dw conditional_jump-instruction_handler db 'jo',70h dw conditional_jump-instruction_handler db 'jp',7Ah dw conditional_jump-instruction_handler db 'js',78h dw conditional_jump-instruction_handler db 'jz',74h dw conditional_jump-instruction_handler db 'or',08h dw basic_instruction-instruction_handler instructions_3: db 'aaa',37h dw simple_instruction_except64-instruction_handler db 'aad',0D5h dw aa_instruction-instruction_handler db 'aam',0D4h dw aa_instruction-instruction_handler db 'aas',3Fh dw simple_instruction_except64-instruction_handler db 'adc',10h dw basic_instruction-instruction_handler db 'add',00h dw basic_instruction-instruction_handler db 'and',20h dw basic_instruction-instruction_handler db 'bnd',0F2h dw bnd_prefix_instruction-instruction_handler db 'bsf',0BCh dw bs_instruction-instruction_handler db 'bsr',0BDh dw bs_instruction-instruction_handler db 'btc',7 dw bt_instruction-instruction_handler db 'btr',6 dw bt_instruction-instruction_handler db 'bts',5 dw bt_instruction-instruction_handler db 'cbw',98h dw simple_instruction_16bit-instruction_handler db 'cdq',99h dw simple_instruction_32bit-instruction_handler db 'clc',0F8h dw simple_instruction-instruction_handler db 'cld',0FCh dw simple_instruction-instruction_handler db 'cli',0FAh dw simple_instruction-instruction_handler db 'cmc',0F5h dw simple_instruction-instruction_handler db 'cmp',38h dw basic_instruction-instruction_handler db 'cqo',99h dw simple_instruction_64bit-instruction_handler db 'cwd',99h dw simple_instruction_16bit-instruction_handler db 'daa',27h dw simple_instruction_except64-instruction_handler db 'das',2Fh dw simple_instruction_except64-instruction_handler db 'dec',1 dw inc_instruction-instruction_handler db 'div',6 dw single_operand_instruction-instruction_handler db 'end',0 dw end_directive-instruction_handler db 'err',0 dw err_directive-instruction_handler db 'fld',0 dw fld_instruction-instruction_handler db 'fst',2 dw fld_instruction-instruction_handler db 'hlt',0F4h dw simple_instruction-instruction_handler db 'inc',0 dw inc_instruction-instruction_handler db 'ins',6Ch dw ins_instruction-instruction_handler db 'int',0CDh dw int_instruction-instruction_handler db 'jae',73h dw conditional_jump-instruction_handler db 'jbe',76h dw conditional_jump-instruction_handler db 'jge',7Dh dw conditional_jump-instruction_handler db 'jle',7Eh dw conditional_jump-instruction_handler db 'jmp',0 dw jmp_instruction-instruction_handler db 'jna',76h dw conditional_jump-instruction_handler db 'jnb',73h dw conditional_jump-instruction_handler db 'jnc',73h dw conditional_jump-instruction_handler db 'jne',75h dw conditional_jump-instruction_handler db 'jng',7Eh dw conditional_jump-instruction_handler db 'jnl',7Dh dw conditional_jump-instruction_handler db 'jno',71h dw conditional_jump-instruction_handler db 'jnp',7Bh dw conditional_jump-instruction_handler db 'jns',79h dw conditional_jump-instruction_handler db 'jnz',75h dw conditional_jump-instruction_handler db 'jpe',7Ah dw conditional_jump-instruction_handler db 'jpo',7Bh dw conditional_jump-instruction_handler db 'lar',2 dw lar_instruction-instruction_handler db 'lds',3 dw ls_instruction-instruction_handler db 'lea',0 dw lea_instruction-instruction_handler db 'les',0 dw ls_instruction-instruction_handler db 'lfs',4 dw ls_instruction-instruction_handler db 'lgs',5 dw ls_instruction-instruction_handler db 'lsl',3 dw lar_instruction-instruction_handler db 'lss',2 dw ls_instruction-instruction_handler db 'ltr',3 dw pm_word_instruction-instruction_handler db 'mov',0 dw mov_instruction-instruction_handler db 'mul',4 dw single_operand_instruction-instruction_handler db 'neg',3 dw single_operand_instruction-instruction_handler db 'nop',90h dw nop_instruction-instruction_handler db 'not',2 dw single_operand_instruction-instruction_handler db 'org',0 dw org_directive-instruction_handler db 'out',0 dw out_instruction-instruction_handler db 'pop',0 dw pop_instruction-instruction_handler db 'por',0EBh dw basic_mmx_instruction-instruction_handler db 'rcl',2 dw sh_instruction-instruction_handler db 'rcr',3 dw sh_instruction-instruction_handler db 'rep',0F3h dw prefix_instruction-instruction_handler db 'ret',0C2h dw ret_instruction-instruction_handler db 'rol',0 dw sh_instruction-instruction_handler db 'ror',1 dw sh_instruction-instruction_handler db 'rsm',0AAh dw simple_extended_instruction-instruction_handler db 'sal',4 dw sh_instruction-instruction_handler db 'sar',7 dw sh_instruction-instruction_handler db 'sbb',18h dw basic_instruction-instruction_handler db 'shl',4 dw sh_instruction-instruction_handler db 'shr',5 dw sh_instruction-instruction_handler db 'stc',0F9h dw simple_instruction-instruction_handler db 'std',0FDh dw simple_instruction-instruction_handler db 'sti',0FBh dw simple_instruction-instruction_handler db 'str',1 dw pm_store_word_instruction-instruction_handler db 'sub',28h dw basic_instruction-instruction_handler db 'ud0',0FFh dw ud_instruction-instruction_handler db 'ud1',0B9h dw ud_instruction-instruction_handler db 'ud2',0Bh dw simple_extended_instruction-instruction_handler db 'xor',30h dw basic_instruction-instruction_handler instructions_4: db 'adcx',66h dw adx_instruction-instruction_handler db 'adox',0F3h dw adx_instruction-instruction_handler db 'andn',0F2h dw andn_instruction-instruction_handler db 'arpl',0 dw arpl_instruction-instruction_handler db 'blci',26h dw tbm_instruction-instruction_handler db 'blcs',13h dw tbm_instruction-instruction_handler db 'blsi',3 dw bmi_instruction-instruction_handler db 'blsr',1 dw bmi_instruction-instruction_handler db 'bzhi',0F5h dw bzhi_instruction-instruction_handler db 'call',0 dw call_instruction-instruction_handler db 'cdqe',98h dw simple_instruction_64bit-instruction_handler db 'clac',0CAh dw simple_instruction_0f_01-instruction_handler db 'clgi',0DDh dw simple_instruction_0f_01-instruction_handler db 'clts',6 dw simple_extended_instruction-instruction_handler db 'clwb',6 dw clflushopt_instruction-instruction_handler db 'cmps',0A6h dw cmps_instruction-instruction_handler db 'cwde',98h dw simple_instruction_32bit-instruction_handler db 'data',0 dw data_directive-instruction_handler db 'dppd',41h dw sse4_instruction_66_3a_imm8-instruction_handler db 'dpps',40h dw sse4_instruction_66_3a_imm8-instruction_handler db 'else',0 dw else_directive-instruction_handler db 'emms',77h dw simple_extended_instruction-instruction_handler db 'fabs',100001b dw simple_fpu_instruction-instruction_handler db 'fadd',0 dw basic_fpu_instruction-instruction_handler db 'fbld',4 dw fbld_instruction-instruction_handler db 'fchs',100000b dw simple_fpu_instruction-instruction_handler db 'fcom',2 dw basic_fpu_instruction-instruction_handler db 'fcos',111111b dw simple_fpu_instruction-instruction_handler db 'fdiv',6 dw basic_fpu_instruction-instruction_handler db 'feni',0E0h dw finit_instruction-instruction_handler db 'fild',0 dw fild_instruction-instruction_handler db 'fist',2 dw fild_instruction-instruction_handler db 'fld1',101000b dw simple_fpu_instruction-instruction_handler db 'fldz',101110b dw simple_fpu_instruction-instruction_handler db 'fmul',1 dw basic_fpu_instruction-instruction_handler db 'fnop',010000b dw simple_fpu_instruction-instruction_handler db 'fsin',111110b dw simple_fpu_instruction-instruction_handler db 'fstp',3 dw fld_instruction-instruction_handler db 'fsub',4 dw basic_fpu_instruction-instruction_handler db 'ftst',100100b dw simple_fpu_instruction-instruction_handler db 'fxam',100101b dw simple_fpu_instruction-instruction_handler db 'fxch',0 dw fxch_instruction-instruction_handler db 'heap',0 dw heap_directive-instruction_handler db 'idiv',7 dw single_operand_instruction-instruction_handler db 'imul',0 dw imul_instruction-instruction_handler db 'insb',6Ch dw simple_instruction-instruction_handler db 'insd',6Dh dw simple_instruction_32bit-instruction_handler db 'insw',6Dh dw simple_instruction_16bit-instruction_handler db 'int1',0F1h dw simple_instruction-instruction_handler db 'int3',0CCh dw simple_instruction-instruction_handler db 'into',0CEh dw simple_instruction_except64-instruction_handler db 'invd',8 dw simple_extended_instruction-instruction_handler db 'iret',0CFh dw iret_instruction-instruction_handler db 'jcxz',0E3h dw loop_instruction_16bit-instruction_handler db 'jnae',72h dw conditional_jump-instruction_handler db 'jnbe',77h dw conditional_jump-instruction_handler db 'jnge',7Ch dw conditional_jump-instruction_handler db 'jnle',7Fh dw conditional_jump-instruction_handler db 'korb',45h dw mask_instruction_b-instruction_handler db 'kord',45h dw mask_instruction_d-instruction_handler db 'korq',45h dw mask_instruction_q-instruction_handler db 'korw',45h dw mask_instruction_w-instruction_handler db 'lahf',9Fh dw simple_instruction-instruction_handler db 'lgdt',2 dw lgdt_instruction-instruction_handler db 'lidt',3 dw lgdt_instruction-instruction_handler db 'lldt',2 dw pm_word_instruction-instruction_handler db 'lmsw',16h dw pm_word_instruction-instruction_handler db 'load',0 dw load_directive-instruction_handler db 'lock',0F0h dw prefix_instruction-instruction_handler db 'lods',0ACh dw lods_instruction-instruction_handler db 'loop',0E2h dw loop_instruction-instruction_handler db 'movd',0 dw movd_instruction-instruction_handler db 'movq',0 dw movq_instruction-instruction_handler db 'movs',0A4h dw movs_instruction-instruction_handler db 'mulx',0F6h dw pdep_instruction-instruction_handler db 'orpd',56h dw sse_pd_instruction-instruction_handler db 'orps',56h dw sse_ps_instruction-instruction_handler db 'outs',6Eh dw outs_instruction-instruction_handler db 'pand',0DBh dw basic_mmx_instruction-instruction_handler db 'pdep',0F5h dw pdep_instruction-instruction_handler db 'pext',0F5h dw pext_instruction-instruction_handler db 'popa',61h dw simple_instruction_except64-instruction_handler db 'popd',4 dw pop_instruction-instruction_handler db 'popf',9Dh dw simple_instruction-instruction_handler db 'popq',8 dw pop_instruction-instruction_handler db 'popw',2 dw pop_instruction-instruction_handler db 'push',0 dw push_instruction-instruction_handler db 'pxor',0EFh dw basic_mmx_instruction-instruction_handler db 'repe',0F3h dw prefix_instruction-instruction_handler db 'repz',0F3h dw prefix_instruction-instruction_handler db 'retd',0C2h dw ret_instruction_32bit_except64-instruction_handler db 'retf',0CAh dw retf_instruction-instruction_handler db 'retn',0C2h dw ret_instruction-instruction_handler db 'retq',0C2h dw ret_instruction_only64-instruction_handler db 'retw',0C2h dw ret_instruction_16bit-instruction_handler db 'rorx',0F0h dw rorx_instruction-instruction_handler db 'sahf',9Eh dw simple_instruction-instruction_handler db 'salc',0D6h dw simple_instruction_except64-instruction_handler db 'sarx',0F7h dw sarx_instruction-instruction_handler db 'scas',0AEh dw stos_instruction-instruction_handler db 'seta',97h dw set_instruction-instruction_handler db 'setb',92h dw set_instruction-instruction_handler db 'setc',92h dw set_instruction-instruction_handler db 'sete',94h dw set_instruction-instruction_handler db 'setg',9Fh dw set_instruction-instruction_handler db 'setl',9Ch dw set_instruction-instruction_handler db 'seto',90h dw set_instruction-instruction_handler db 'setp',9Ah dw set_instruction-instruction_handler db 'sets',98h dw set_instruction-instruction_handler db 'setz',94h dw set_instruction-instruction_handler db 'sgdt',0 dw lgdt_instruction-instruction_handler db 'shld',0A4h dw shd_instruction-instruction_handler db 'shlx',0F7h dw shlx_instruction-instruction_handler db 'shrd',0ACh dw shd_instruction-instruction_handler db 'shrx',0F7h dw shrx_instruction-instruction_handler db 'sidt',1 dw lgdt_instruction-instruction_handler db 'sldt',0 dw pm_store_word_instruction-instruction_handler db 'smsw',14h dw pm_store_word_instruction-instruction_handler db 'stac',0CBh dw simple_instruction_0f_01-instruction_handler db 'stgi',0DCh dw simple_instruction_0f_01-instruction_handler db 'stos',0AAh dw stos_instruction-instruction_handler db 'test',0 dw test_instruction-instruction_handler db 'verr',4 dw pm_word_instruction-instruction_handler db 'verw',5 dw pm_word_instruction-instruction_handler db 'vpor',0EBh dw avx_pd_instruction_noevex-instruction_handler db 'wait',9Bh dw simple_instruction-instruction_handler db 'xadd',0C0h dw basic_486_instruction-instruction_handler db 'xchg',0 dw xchg_instruction-instruction_handler db 'xend',0D5h dw simple_instruction_0f_01-instruction_handler db 'xlat',0D7h dw xlat_instruction-instruction_handler instructions_5: db 'addpd',58h dw sse_pd_instruction-instruction_handler db 'addps',58h dw sse_ps_instruction-instruction_handler db 'addsd',58h dw sse_sd_instruction-instruction_handler db 'addss',58h dw sse_ss_instruction-instruction_handler db 'align',0 dw align_directive-instruction_handler db 'andpd',54h dw sse_pd_instruction-instruction_handler db 'andps',54h dw sse_ps_instruction-instruction_handler db 'bextr',0F7h dw bextr_instruction-instruction_handler db 'blcic',15h dw tbm_instruction-instruction_handler db 'blsic',16h dw tbm_instruction-instruction_handler db 'bndcl',1Ah dw bndcl_instruction-instruction_handler db 'bndcn',1Bh dw bndcu_instruction-instruction_handler db 'bndcu',1Ah dw bndcu_instruction-instruction_handler db 'bndmk',1Bh dw bndmk_instruction-instruction_handler db 'bound',0 dw bound_instruction-instruction_handler db 'break',0 dw break_directive-instruction_handler db 'bswap',0 dw bswap_instruction-instruction_handler db 'cmova',47h dw bs_instruction-instruction_handler db 'cmovb',42h dw bs_instruction-instruction_handler db 'cmovc',42h dw bs_instruction-instruction_handler db 'cmove',44h dw bs_instruction-instruction_handler db 'cmovg',4Fh dw bs_instruction-instruction_handler db 'cmovl',4Ch dw bs_instruction-instruction_handler db 'cmovo',40h dw bs_instruction-instruction_handler db 'cmovp',4Ah dw bs_instruction-instruction_handler db 'cmovs',48h dw bs_instruction-instruction_handler db 'cmovz',44h dw bs_instruction-instruction_handler db 'cmppd',-1 dw cmp_pd_instruction-instruction_handler db 'cmpps',-1 dw cmp_ps_instruction-instruction_handler db 'cmpsb',0A6h dw simple_instruction-instruction_handler db 'cmpsd',-1 dw cmpsd_instruction-instruction_handler db 'cmpsq',0A7h dw simple_instruction_64bit-instruction_handler db 'cmpss',-1 dw cmp_ss_instruction-instruction_handler db 'cmpsw',0A7h dw simple_instruction_16bit-instruction_handler db 'cpuid',0A2h dw simple_extended_instruction-instruction_handler db 'crc32',0 dw crc32_instruction-instruction_handler db 'divpd',5Eh dw sse_pd_instruction-instruction_handler db 'divps',5Eh dw sse_ps_instruction-instruction_handler db 'divsd',5Eh dw sse_sd_instruction-instruction_handler db 'divss',5Eh dw sse_ss_instruction-instruction_handler db 'enter',0 dw enter_instruction-instruction_handler db 'entry',0 dw entry_directive-instruction_handler db 'extrn',0 dw extrn_directive-instruction_handler db 'extrq',0 dw extrq_instruction-instruction_handler db 'f2xm1',110000b dw simple_fpu_instruction-instruction_handler db 'faddp',0 dw faddp_instruction-instruction_handler db 'fbstp',6 dw fbld_instruction-instruction_handler db 'fclex',0E2h dw finit_instruction-instruction_handler db 'fcomi',0F0h dw fcomi_instruction-instruction_handler db 'fcomp',3 dw basic_fpu_instruction-instruction_handler db 'fdisi',0E1h dw finit_instruction-instruction_handler db 'fdivp',7 dw faddp_instruction-instruction_handler db 'fdivr',7 dw basic_fpu_instruction-instruction_handler db 'femms',0Eh dw simple_extended_instruction-instruction_handler db 'ffree',0 dw ffree_instruction-instruction_handler db 'fiadd',0 dw fi_instruction-instruction_handler db 'ficom',2 dw fi_instruction-instruction_handler db 'fidiv',6 dw fi_instruction-instruction_handler db 'fimul',1 dw fi_instruction-instruction_handler db 'finit',0E3h dw finit_instruction-instruction_handler db 'fistp',3 dw fild_instruction-instruction_handler db 'fisub',4 dw fi_instruction-instruction_handler db 'fldcw',5 dw fldcw_instruction-instruction_handler db 'fldpi',101011b dw simple_fpu_instruction-instruction_handler db 'fmulp',1 dw faddp_instruction-instruction_handler db 'fneni',0E0h dw fninit_instruction-instruction_handler db 'fprem',111000b dw simple_fpu_instruction-instruction_handler db 'fptan',110010b dw simple_fpu_instruction-instruction_handler db 'fsave',6 dw fsave_instruction-instruction_handler db 'fsqrt',111010b dw simple_fpu_instruction-instruction_handler db 'fstcw',7 dw fstcw_instruction-instruction_handler db 'fstsw',0 dw fstsw_instruction-instruction_handler db 'fsubp',5 dw faddp_instruction-instruction_handler db 'fsubr',5 dw basic_fpu_instruction-instruction_handler db 'fucom',4 dw ffree_instruction-instruction_handler db 'fwait',9Bh dw simple_instruction-instruction_handler db 'fyl2x',110001b dw simple_fpu_instruction-instruction_handler db 'icebp',0F1h dw simple_instruction-instruction_handler db 'iretd',0CFh dw simple_instruction_32bit-instruction_handler db 'iretq',0CFh dw simple_instruction_64bit-instruction_handler db 'iretw',0CFh dw simple_instruction_16bit-instruction_handler db 'jecxz',0E3h dw loop_instruction_32bit-instruction_handler db 'jrcxz',0E3h dw loop_instruction_64bit-instruction_handler db 'kaddb',4Ah dw mask_instruction_b-instruction_handler db 'kaddd',4Ah dw mask_instruction_d-instruction_handler db 'kaddq',4Ah dw mask_instruction_q-instruction_handler db 'kaddw',4Ah dw mask_instruction_w-instruction_handler db 'kandb',41h dw mask_instruction_b-instruction_handler db 'kandd',41h dw mask_instruction_d-instruction_handler db 'kandq',41h dw mask_instruction_q-instruction_handler db 'kandw',41h dw mask_instruction_w-instruction_handler db 'kmovb',1 dw kmov_instruction-instruction_handler db 'kmovd',4 dw kmov_instruction-instruction_handler db 'kmovq',8 dw kmov_instruction-instruction_handler db 'kmovw',2 dw kmov_instruction-instruction_handler db 'knotb',44h dw mask_instruction_single_source_b-instruction_handler db 'knotd',44h dw mask_instruction_single_source_d-instruction_handler db 'knotq',44h dw mask_instruction_single_source_q-instruction_handler db 'knotw',44h dw mask_instruction_single_source_w-instruction_handler db 'kxorb',47h dw mask_instruction_b-instruction_handler db 'kxord',47h dw mask_instruction_d-instruction_handler db 'kxorq',47h dw mask_instruction_q-instruction_handler db 'kxorw',47h dw mask_instruction_w-instruction_handler db 'label',0 dw label_directive-instruction_handler db 'lddqu',0 dw lddqu_instruction-instruction_handler db 'leave',0C9h dw simple_instruction-instruction_handler db 'lodsb',0ACh dw simple_instruction-instruction_handler db 'lodsd',0ADh dw simple_instruction_32bit-instruction_handler db 'lodsq',0ADh dw simple_instruction_64bit-instruction_handler db 'lodsw',0ADh dw simple_instruction_16bit-instruction_handler db 'loopd',0E2h dw loop_instruction_32bit-instruction_handler db 'loope',0E1h dw loop_instruction-instruction_handler db 'loopq',0E2h dw loop_instruction_64bit-instruction_handler db 'loopw',0E2h dw loop_instruction_16bit-instruction_handler db 'loopz',0E1h dw loop_instruction-instruction_handler db 'lzcnt',0BDh dw popcnt_instruction-instruction_handler db 'maxpd',5Fh dw sse_pd_instruction-instruction_handler db 'maxps',5Fh dw sse_ps_instruction-instruction_handler db 'maxsd',5Fh dw sse_sd_instruction-instruction_handler db 'maxss',5Fh dw sse_ss_instruction-instruction_handler db 'minpd',5Dh dw sse_pd_instruction-instruction_handler db 'minps',5Dh dw sse_ps_instruction-instruction_handler db 'minsd',5Dh dw sse_sd_instruction-instruction_handler db 'minss',5Dh dw sse_ss_instruction-instruction_handler db 'movbe',0F0h dw movbe_instruction-instruction_handler db 'movsb',0A4h dw simple_instruction-instruction_handler db 'movsd',0 dw movsd_instruction-instruction_handler db 'movsq',0A5h dw simple_instruction_64bit-instruction_handler db 'movss',0 dw movss_instruction-instruction_handler db 'movsw',0A5h dw simple_instruction_16bit-instruction_handler db 'movsx',0BEh dw movx_instruction-instruction_handler db 'movzx',0B6h dw movx_instruction-instruction_handler db 'mulpd',59h dw sse_pd_instruction-instruction_handler db 'mulps',59h dw sse_ps_instruction-instruction_handler db 'mulsd',59h dw sse_sd_instruction-instruction_handler db 'mulss',59h dw sse_ss_instruction-instruction_handler db 'mwait',0C9h dw monitor_instruction-instruction_handler db 'outsb',6Eh dw simple_instruction-instruction_handler db 'outsd',6Fh dw simple_instruction_32bit-instruction_handler db 'outsw',6Fh dw simple_instruction_16bit-instruction_handler db 'pabsb',1Ch dw ssse3_instruction-instruction_handler db 'pabsd',1Eh dw ssse3_instruction-instruction_handler db 'pabsw',1Dh dw ssse3_instruction-instruction_handler db 'paddb',0FCh dw basic_mmx_instruction-instruction_handler db 'paddd',0FEh dw basic_mmx_instruction-instruction_handler db 'paddq',0D4h dw basic_mmx_instruction-instruction_handler db 'paddw',0FDh dw basic_mmx_instruction-instruction_handler db 'pandn',0DFh dw basic_mmx_instruction-instruction_handler db 'pause',0 dw pause_instruction-instruction_handler db 'pavgb',0E0h dw basic_mmx_instruction-instruction_handler db 'pavgw',0E3h dw basic_mmx_instruction-instruction_handler db 'pf2id',1Dh dw amd3dnow_instruction-instruction_handler db 'pf2iw',1Ch dw amd3dnow_instruction-instruction_handler db 'pfacc',0AEh dw amd3dnow_instruction-instruction_handler db 'pfadd',9Eh dw amd3dnow_instruction-instruction_handler db 'pfmax',0A4h dw amd3dnow_instruction-instruction_handler db 'pfmin',94h dw amd3dnow_instruction-instruction_handler db 'pfmul',0B4h dw amd3dnow_instruction-instruction_handler db 'pfrcp',96h dw amd3dnow_instruction-instruction_handler db 'pfsub',9Ah dw amd3dnow_instruction-instruction_handler db 'pi2fd',0Dh dw amd3dnow_instruction-instruction_handler db 'pi2fw',0Ch dw amd3dnow_instruction-instruction_handler db 'popad',61h dw simple_instruction_32bit_except64-instruction_handler db 'popaw',61h dw simple_instruction_16bit_except64-instruction_handler db 'popfd',9Dh dw simple_instruction_32bit_except64-instruction_handler db 'popfq',9Dh dw simple_instruction_only64-instruction_handler db 'popfw',9Dh dw simple_instruction_16bit-instruction_handler db 'pslld',0F2h dw mmx_bit_shift_instruction-instruction_handler db 'psllq',0F3h dw mmx_bit_shift_instruction-instruction_handler db 'psllw',0F1h dw mmx_bit_shift_instruction-instruction_handler db 'psrad',0E2h dw mmx_bit_shift_instruction-instruction_handler db 'psraw',0E1h dw mmx_bit_shift_instruction-instruction_handler db 'psrld',0D2h dw mmx_bit_shift_instruction-instruction_handler db 'psrlq',0D3h dw mmx_bit_shift_instruction-instruction_handler db 'psrlw',0D1h dw mmx_bit_shift_instruction-instruction_handler db 'psubb',0F8h dw basic_mmx_instruction-instruction_handler db 'psubd',0FAh dw basic_mmx_instruction-instruction_handler db 'psubq',0FBh dw basic_mmx_instruction-instruction_handler db 'psubw',0F9h dw basic_mmx_instruction-instruction_handler db 'ptest',17h dw sse4_instruction_66_38-instruction_handler db 'pusha',60h dw simple_instruction_except64-instruction_handler db 'pushd',4 dw push_instruction-instruction_handler db 'pushf',9Ch dw simple_instruction-instruction_handler db 'pushq',8 dw push_instruction-instruction_handler db 'pushw',2 dw push_instruction-instruction_handler db 'rcpps',53h dw sse_ps_instruction-instruction_handler db 'rcpss',53h dw sse_ss_instruction-instruction_handler db 'rdmsr',32h dw simple_extended_instruction-instruction_handler db 'rdpid',7 dw rdpid_instruction-instruction_handler db 'rdpmc',33h dw simple_extended_instruction-instruction_handler db 'rdpru',0FDh dw simple_instruction_0f_01-instruction_handler db 'rdtsc',31h dw simple_extended_instruction-instruction_handler db 'repne',0F2h dw prefix_instruction-instruction_handler db 'repnz',0F2h dw prefix_instruction-instruction_handler db 'retfd',0CAh dw retf_instruction_32bit-instruction_handler db 'retfq',0CAh dw retf_instruction_64bit-instruction_handler db 'retfw',0CAh dw retf_instruction_16bit-instruction_handler db 'retnd',0C2h dw ret_instruction_32bit_except64-instruction_handler db 'retnq',0C2h dw ret_instruction_only64-instruction_handler db 'retnw',0C2h dw ret_instruction_16bit-instruction_handler db 'scasb',0AEh dw simple_instruction-instruction_handler db 'scasd',0AFh dw simple_instruction_32bit-instruction_handler db 'scasq',0AFh dw simple_instruction_64bit-instruction_handler db 'scasw',0AFh dw simple_instruction_16bit-instruction_handler db 'setae',93h dw set_instruction-instruction_handler db 'setbe',96h dw set_instruction-instruction_handler db 'setge',9Dh dw set_instruction-instruction_handler db 'setle',9Eh dw set_instruction-instruction_handler db 'setna',96h dw set_instruction-instruction_handler db 'setnb',93h dw set_instruction-instruction_handler db 'setnc',93h dw set_instruction-instruction_handler db 'setne',95h dw set_instruction-instruction_handler db 'setng',9Eh dw set_instruction-instruction_handler db 'setnl',9Dh dw set_instruction-instruction_handler db 'setno',91h dw set_instruction-instruction_handler db 'setnp',9Bh dw set_instruction-instruction_handler db 'setns',99h dw set_instruction-instruction_handler db 'setnz',95h dw set_instruction-instruction_handler db 'setpe',9Ah dw set_instruction-instruction_handler db 'setpo',9Bh dw set_instruction-instruction_handler db 'stack',0 dw stack_directive-instruction_handler db 'store',0 dw store_directive-instruction_handler db 'stosb',0AAh dw simple_instruction-instruction_handler db 'stosd',0ABh dw simple_instruction_32bit-instruction_handler db 'stosq',0ABh dw simple_instruction_64bit-instruction_handler db 'stosw',0ABh dw simple_instruction_16bit-instruction_handler db 'subpd',5Ch dw sse_pd_instruction-instruction_handler db 'subps',5Ch dw sse_ps_instruction-instruction_handler db 'subsd',5Ch dw sse_sd_instruction-instruction_handler db 'subss',5Ch dw sse_ss_instruction-instruction_handler db 'times',0 dw times_directive-instruction_handler db 'tzcnt',0BCh dw popcnt_instruction-instruction_handler db 'tzmsk',14h dw tbm_instruction-instruction_handler db 'vdppd',41h dw avx_128bit_instruction_3a_imm8_noevex-instruction_handler db 'vdpps',40h dw avx_pi_instruction_3a_imm8_noevex-instruction_handler db 'vmovd',0 dw avx_movd_instruction-instruction_handler db 'vmovq',0 dw avx_movq_instruction-instruction_handler db 'vmrun',0D8h dw simple_svm_instruction-instruction_handler db 'vmxon',6 dw vmxon_instruction-instruction_handler db 'vorpd',56h dw avx_pd_instruction-instruction_handler db 'vorps',56h dw avx_ps_instruction-instruction_handler db 'vpand',0DBh dw avx_pd_instruction_noevex-instruction_handler db 'vpord',0EBh dw avx_d_instruction_evex-instruction_handler db 'vporq',0EBh dw avx_q_instruction_evex-instruction_handler db 'vpxor',0EFh dw avx_pd_instruction_noevex-instruction_handler db 'while',0 dw while_directive-instruction_handler db 'wrmsr',30h dw simple_extended_instruction-instruction_handler db 'wrssd',0F6h dw wrssd_instruction-instruction_handler db 'wrssq',0F6h dw wrssq_instruction-instruction_handler db 'xlatb',0D7h dw simple_instruction-instruction_handler db 'xorpd',57h dw sse_pd_instruction-instruction_handler db 'xorps',57h dw sse_ps_instruction-instruction_handler db 'xsave',100b dw fxsave_instruction-instruction_handler db 'xtest',0D6h dw simple_instruction_0f_01-instruction_handler instructions_6: db 'aesdec',0DEh dw sse4_instruction_66_38-instruction_handler db 'aesenc',0DCh dw sse4_instruction_66_38-instruction_handler db 'aesimc',0DBh dw sse4_instruction_66_38-instruction_handler db 'andnpd',55h dw sse_pd_instruction-instruction_handler db 'andnps',55h dw sse_ps_instruction-instruction_handler db 'assert',0 dw assert_directive-instruction_handler db 'blcmsk',21h dw tbm_instruction-instruction_handler db 'blsmsk',2 dw bmi_instruction-instruction_handler db 'bndldx',1Ah dw bndldx_instruction-instruction_handler db 'bndmov',1Ah dw bndmov_instruction-instruction_handler db 'bndstx',1Bh dw bndstx_instruction-instruction_handler db 'clzero',0 dw clzero_instruction-instruction_handler db 'cmovae',43h dw bs_instruction-instruction_handler db 'cmovbe',46h dw bs_instruction-instruction_handler db 'cmovge',4Dh dw bs_instruction-instruction_handler db 'cmovle',4Eh dw bs_instruction-instruction_handler db 'cmovna',46h dw bs_instruction-instruction_handler db 'cmovnb',43h dw bs_instruction-instruction_handler db 'cmovnc',43h dw bs_instruction-instruction_handler db 'cmovne',45h dw bs_instruction-instruction_handler db 'cmovng',4Eh dw bs_instruction-instruction_handler db 'cmovnl',4Dh dw bs_instruction-instruction_handler db 'cmovno',41h dw bs_instruction-instruction_handler db 'cmovnp',4Bh dw bs_instruction-instruction_handler db 'cmovns',49h dw bs_instruction-instruction_handler db 'cmovnz',45h dw bs_instruction-instruction_handler db 'cmovpe',4Ah dw bs_instruction-instruction_handler db 'cmovpo',4Bh dw bs_instruction-instruction_handler db 'comisd',2Fh dw comisd_instruction-instruction_handler db 'comiss',2Fh dw comiss_instruction-instruction_handler db 'fcmovb',0C0h dw fcmov_instruction-instruction_handler db 'fcmove',0C8h dw fcmov_instruction-instruction_handler db 'fcmovu',0D8h dw fcmov_instruction-instruction_handler db 'fcomip',0F0h dw fcomip_instruction-instruction_handler db 'fcompp',0 dw fcompp_instruction-instruction_handler db 'fdivrp',6 dw faddp_instruction-instruction_handler db 'ffreep',0 dw ffreep_instruction-instruction_handler db 'ficomp',3 dw fi_instruction-instruction_handler db 'fidivr',7 dw fi_instruction-instruction_handler db 'fisttp',1 dw fild_instruction-instruction_handler db 'fisubr',5 dw fi_instruction-instruction_handler db 'fldenv',4 dw fldenv_instruction-instruction_handler db 'fldl2e',101010b dw simple_fpu_instruction-instruction_handler db 'fldl2t',101001b dw simple_fpu_instruction-instruction_handler db 'fldlg2',101100b dw simple_fpu_instruction-instruction_handler db 'fldln2',101101b dw simple_fpu_instruction-instruction_handler db 'fnclex',0E2h dw fninit_instruction-instruction_handler db 'fndisi',0E1h dw fninit_instruction-instruction_handler db 'fninit',0E3h dw fninit_instruction-instruction_handler db 'fnsave',6 dw fnsave_instruction-instruction_handler db 'fnstcw',7 dw fldcw_instruction-instruction_handler db 'fnstsw',0 dw fnstsw_instruction-instruction_handler db 'format',0 dw format_directive-instruction_handler db 'fpatan',110011b dw simple_fpu_instruction-instruction_handler db 'fprem1',110101b dw simple_fpu_instruction-instruction_handler db 'frstor',4 dw fnsave_instruction-instruction_handler db 'frstpm',0E5h dw fninit_instruction-instruction_handler db 'fsaved',6 dw fsave_instruction_32bit-instruction_handler db 'fsavew',6 dw fsave_instruction_16bit-instruction_handler db 'fscale',111101b dw simple_fpu_instruction-instruction_handler db 'fsetpm',0E4h dw fninit_instruction-instruction_handler db 'fstenv',6 dw fstenv_instruction-instruction_handler db 'fsubrp',4 dw faddp_instruction-instruction_handler db 'fucomi',0E8h dw fcomi_instruction-instruction_handler db 'fucomp',5 dw ffree_instruction-instruction_handler db 'fxsave',0 dw fxsave_instruction-instruction_handler db 'getsec',37h dw simple_extended_instruction-instruction_handler db 'haddpd',07Ch dw sse_pd_instruction-instruction_handler db 'haddps',07Ch dw cvtpd2dq_instruction-instruction_handler db 'hsubpd',07Dh dw sse_pd_instruction-instruction_handler db 'hsubps',07Dh dw cvtpd2dq_instruction-instruction_handler db 'invept',80h dw vmx_inv_instruction-instruction_handler db 'invlpg',0 dw invlpg_instruction-instruction_handler db 'kandnb',42h dw mask_instruction_b-instruction_handler db 'kandnd',42h dw mask_instruction_d-instruction_handler db 'kandnq',42h dw mask_instruction_q-instruction_handler db 'kandnw',42h dw mask_instruction_w-instruction_handler db 'ktestb',99h dw mask_instruction_single_source_b-instruction_handler db 'ktestd',99h dw mask_instruction_single_source_d-instruction_handler db 'ktestq',99h dw mask_instruction_single_source_q-instruction_handler db 'ktestw',99h dw mask_instruction_single_source_w-instruction_handler db 'kxnorb',46h dw mask_instruction_b-instruction_handler db 'kxnord',46h dw mask_instruction_d-instruction_handler db 'kxnorq',46h dw mask_instruction_q-instruction_handler db 'kxnorw',46h dw mask_instruction_w-instruction_handler db 'lfence',0E8h dw fence_instruction-instruction_handler db 'llwpcb',0 dw llwpcb_instruction-instruction_handler db 'looped',0E1h dw loop_instruction_32bit-instruction_handler db 'loopeq',0E1h dw loop_instruction_64bit-instruction_handler db 'loopew',0E1h dw loop_instruction_16bit-instruction_handler db 'loopne',0E0h dw loop_instruction-instruction_handler db 'loopnz',0E0h dw loop_instruction-instruction_handler db 'loopzd',0E1h dw loop_instruction_32bit-instruction_handler db 'loopzq',0E1h dw loop_instruction_64bit-instruction_handler db 'loopzw',0E1h dw loop_instruction_16bit-instruction_handler db 'lwpins',0 dw lwpins_instruction-instruction_handler db 'lwpval',1 dw lwpins_instruction-instruction_handler db 'mfence',0F0h dw fence_instruction-instruction_handler db 'movapd',28h dw movpd_instruction-instruction_handler db 'movaps',28h dw movps_instruction-instruction_handler db 'movdqa',66h dw movdq_instruction-instruction_handler db 'movdqu',0F3h dw movdq_instruction-instruction_handler db 'movhpd',16h dw movlpd_instruction-instruction_handler db 'movhps',16h dw movlps_instruction-instruction_handler db 'movlpd',12h dw movlpd_instruction-instruction_handler db 'movlps',12h dw movlps_instruction-instruction_handler db 'movnti',0C3h dw movnti_instruction-instruction_handler db 'movntq',0E7h dw movntq_instruction-instruction_handler db 'movsxd',63h dw movsxd_instruction-instruction_handler db 'movupd',10h dw movpd_instruction-instruction_handler db 'movups',10h dw movps_instruction-instruction_handler db 'mwaitx',0FBh dw monitor_instruction-instruction_handler db 'paddsb',0ECh dw basic_mmx_instruction-instruction_handler db 'paddsw',0EDh dw basic_mmx_instruction-instruction_handler db 'pextrb',14h dw pextrb_instruction-instruction_handler db 'pextrd',16h dw pextrd_instruction-instruction_handler db 'pextrq',16h dw pextrq_instruction-instruction_handler db 'pextrw',15h dw pextrw_instruction-instruction_handler db 'pfnacc',8Ah dw amd3dnow_instruction-instruction_handler db 'pfsubr',0AAh dw amd3dnow_instruction-instruction_handler db 'phaddd',2 dw ssse3_instruction-instruction_handler db 'phaddw',1 dw ssse3_instruction-instruction_handler db 'phsubd',6 dw ssse3_instruction-instruction_handler db 'phsubw',5 dw ssse3_instruction-instruction_handler db 'pinsrb',20h dw pinsrb_instruction-instruction_handler db 'pinsrd',22h dw pinsrd_instruction-instruction_handler db 'pinsrq',22h dw pinsrq_instruction-instruction_handler db 'pinsrw',0C4h dw pinsrw_instruction-instruction_handler db 'pmaxsb',3Ch dw sse4_instruction_66_38-instruction_handler db 'pmaxsd',3Dh dw sse4_instruction_66_38-instruction_handler db 'pmaxsw',0EEh dw basic_mmx_instruction-instruction_handler db 'pmaxub',0DEh dw basic_mmx_instruction-instruction_handler db 'pmaxud',3Fh dw sse4_instruction_66_38-instruction_handler db 'pmaxuw',3Eh dw sse4_instruction_66_38-instruction_handler db 'pminsb',38h dw sse4_instruction_66_38-instruction_handler db 'pminsd',39h dw sse4_instruction_66_38-instruction_handler db 'pminsw',0EAh dw basic_mmx_instruction-instruction_handler db 'pminub',0DAh dw basic_mmx_instruction-instruction_handler db 'pminud',3Bh dw sse4_instruction_66_38-instruction_handler db 'pminuw',3Ah dw sse4_instruction_66_38-instruction_handler db 'pmuldq',28h dw sse4_instruction_66_38-instruction_handler db 'pmulhw',0E5h dw basic_mmx_instruction-instruction_handler db 'pmulld',40h dw sse4_instruction_66_38-instruction_handler db 'pmullw',0D5h dw basic_mmx_instruction-instruction_handler db 'popcnt',0B8h dw popcnt_instruction-instruction_handler db 'psadbw',0F6h dw basic_mmx_instruction-instruction_handler db 'pshufb',0 dw ssse3_instruction-instruction_handler db 'pshufd',66h dw pshufd_instruction-instruction_handler db 'pshufw',0 dw pshufw_instruction-instruction_handler db 'psignb',8 dw ssse3_instruction-instruction_handler db 'psignd',0Ah dw ssse3_instruction-instruction_handler db 'psignw',9 dw ssse3_instruction-instruction_handler db 'pslldq',111b dw pslldq_instruction-instruction_handler db 'psmash',0FFh dw simple_instruction_f3_0f_01-instruction_handler db 'psrldq',011b dw pslldq_instruction-instruction_handler db 'psubsb',0E8h dw basic_mmx_instruction-instruction_handler db 'psubsw',0E9h dw basic_mmx_instruction-instruction_handler db 'pswapd',0BBh dw amd3dnow_instruction-instruction_handler db 'public',0 dw public_directive-instruction_handler db 'pushad',60h dw simple_instruction_32bit_except64-instruction_handler db 'pushaw',60h dw simple_instruction_16bit_except64-instruction_handler db 'pushfd',9Ch dw simple_instruction_32bit_except64-instruction_handler db 'pushfq',9Ch dw simple_instruction_only64-instruction_handler db 'pushfw',9Ch dw simple_instruction_16bit-instruction_handler db 'rdmsrq',32h dw simple_extended_instruction_64bit-instruction_handler db 'rdpkru',0EEh dw simple_instruction_0f_01-instruction_handler db 'rdrand',110b dw rdrand_instruction-instruction_handler db 'rdseed',111b dw rdrand_instruction-instruction_handler db 'rdsspd',1 dw rdsspd_instruction-instruction_handler db 'rdsspq',1 dw rdsspq_instruction-instruction_handler db 'rdtscp',0F9h dw simple_instruction_0f_01-instruction_handler db 'repeat',0 dw repeat_directive-instruction_handler db 'setalc',0D6h dw simple_instruction_except64-instruction_handler db 'setnae',92h dw set_instruction-instruction_handler db 'setnbe',97h dw set_instruction-instruction_handler db 'setnge',9Ch dw set_instruction-instruction_handler db 'setnle',9Fh dw set_instruction-instruction_handler db 'sfence',0F8h dw fence_instruction-instruction_handler db 'shufpd',0C6h dw sse_pd_instruction_imm8-instruction_handler db 'shufps',0C6h dw sse_ps_instruction_imm8-instruction_handler db 'skinit',0 dw skinit_instruction-instruction_handler db 'slwpcb',1 dw llwpcb_instruction-instruction_handler db 'sqrtpd',51h dw sse_pd_instruction-instruction_handler db 'sqrtps',51h dw sse_ps_instruction-instruction_handler db 'sqrtsd',51h dw sse_sd_instruction-instruction_handler db 'sqrtss',51h dw sse_ss_instruction-instruction_handler db 'swapgs',0F8h dw swapgs_instruction-instruction_handler db 'sysret',07h dw simple_extended_instruction-instruction_handler db 't1mskc',17h dw tbm_instruction-instruction_handler db 'tpause',66h dw tpause_instruction-instruction_handler db 'umwait',0F2h dw tpause_instruction-instruction_handler db 'vaddpd',58h dw avx_pd_instruction_er-instruction_handler db 'vaddps',58h dw avx_ps_instruction_er-instruction_handler db 'vaddsd',58h dw avx_sd_instruction_er-instruction_handler db 'vaddss',58h dw avx_ss_instruction_er-instruction_handler db 'vandpd',54h dw avx_pd_instruction-instruction_handler db 'vandps',54h dw avx_ps_instruction-instruction_handler db 'vcmppd',-1 dw avx_cmp_pd_instruction-instruction_handler db 'vcmpps',-1 dw avx_cmp_ps_instruction-instruction_handler db 'vcmpsd',-1 dw avx_cmp_sd_instruction-instruction_handler db 'vcmpss',-1 dw avx_cmp_ss_instruction-instruction_handler db 'vdivpd',5Eh dw avx_pd_instruction_er-instruction_handler db 'vdivps',5Eh dw avx_ps_instruction_er-instruction_handler db 'vdivsd',5Eh dw avx_sd_instruction_er-instruction_handler db 'vdivss',5Eh dw avx_ss_instruction_er-instruction_handler db 'vlddqu',0F0h dw avx_lddqu_instruction-instruction_handler db 'vmaxpd',5Fh dw avx_pd_instruction_sae-instruction_handler db 'vmaxps',5Fh dw avx_ps_instruction_sae-instruction_handler db 'vmaxsd',5Fh dw avx_sd_instruction_sae-instruction_handler db 'vmaxss',5Fh dw avx_ss_instruction_sae-instruction_handler db 'vmcall',0C1h dw simple_instruction_0f_01-instruction_handler db 'vmfunc',0D4h dw simple_instruction_0f_01-instruction_handler db 'vminpd',5Dh dw avx_pd_instruction_sae-instruction_handler db 'vminps',5Dh dw avx_ps_instruction_sae-instruction_handler db 'vminsd',5Dh dw avx_sd_instruction_sae-instruction_handler db 'vminss',5Dh dw avx_ss_instruction_sae-instruction_handler db 'vmload',0DAh dw simple_svm_instruction-instruction_handler db 'vmovsd',0 dw avx_movsd_instruction-instruction_handler db 'vmovss',0 dw avx_movss_instruction-instruction_handler db 'vmread',0 dw vmread_instruction-instruction_handler db 'vmsave',0DBh dw simple_svm_instruction-instruction_handler db 'vmulpd',59h dw avx_pd_instruction_er-instruction_handler db 'vmulps',59h dw avx_ps_instruction_er-instruction_handler db 'vmulsd',59h dw avx_sd_instruction_er-instruction_handler db 'vmulss',59h dw avx_ss_instruction_er-instruction_handler db 'vmxoff',0C4h dw simple_instruction_0f_01-instruction_handler db 'vpabsb',1Ch dw avx_single_source_bw_instruction_38-instruction_handler db 'vpabsd',1Eh dw avx_single_source_d_instruction_38-instruction_handler db 'vpabsq',1Fh dw avx_single_source_q_instruction_38_evex-instruction_handler db 'vpabsw',1Dh dw avx_single_source_bw_instruction_38-instruction_handler db 'vpaddb',0FCh dw avx_bw_instruction-instruction_handler db 'vpaddd',0FEh dw avx_d_instruction-instruction_handler db 'vpaddq',0D4h dw avx_q_instruction-instruction_handler db 'vpaddw',0FDh dw avx_bw_instruction-instruction_handler db 'vpandd',0DBh dw avx_d_instruction_evex-instruction_handler db 'vpandn',0DFh dw avx_pd_instruction_noevex-instruction_handler db 'vpandq',0DBh dw avx_q_instruction_evex-instruction_handler db 'vpavgb',0E0h dw avx_bw_instruction-instruction_handler db 'vpavgw',0E3h dw avx_bw_instruction-instruction_handler db 'vpcmov',0A2h dw vpcmov_instruction-instruction_handler db 'vpcmpb',-1 dw avx512_cmp_b_instruction-instruction_handler db 'vpcmpd',-1 dw avx512_cmp_d_instruction-instruction_handler db 'vpcmpq',-1 dw avx512_cmp_q_instruction-instruction_handler db 'vpcmpw',-1 dw avx512_cmp_w_instruction-instruction_handler db 'vpcomb',-1 dw xop_pcom_b_instruction-instruction_handler db 'vpcomd',-1 dw xop_pcom_d_instruction-instruction_handler db 'vpcomq',-1 dw xop_pcom_q_instruction-instruction_handler db 'vpcomw',-1 dw xop_pcom_w_instruction-instruction_handler db 'vpermb',8Dh dw avx_bw_instruction_38_evex-instruction_handler db 'vpermd',36h dw avx_permd_instruction-instruction_handler db 'vpermq',0 dw avx_permq_instruction-instruction_handler db 'vpermw',8Dh dw avx_bw_instruction_38_w1_evex-instruction_handler db 'vpperm',0A3h dw xop_128bit_instruction-instruction_handler db 'vprold',1 dw avx512_rotate_d_instruction-instruction_handler db 'vprolq',1 dw avx512_rotate_q_instruction-instruction_handler db 'vprord',0 dw avx512_rotate_d_instruction-instruction_handler db 'vprorq',0 dw avx512_rotate_q_instruction-instruction_handler db 'vprotb',90h dw xop_shift_instruction-instruction_handler db 'vprotd',92h dw xop_shift_instruction-instruction_handler db 'vprotq',93h dw xop_shift_instruction-instruction_handler db 'vprotw',91h dw xop_shift_instruction-instruction_handler db 'vpshab',98h dw xop_shift_instruction-instruction_handler db 'vpshad',9Ah dw xop_shift_instruction-instruction_handler db 'vpshaq',9Bh dw xop_shift_instruction-instruction_handler db 'vpshaw',99h dw xop_shift_instruction-instruction_handler db 'vpshlb',94h dw xop_shift_instruction-instruction_handler db 'vpshld',96h dw xop_shift_instruction-instruction_handler db 'vpshlq',97h dw xop_shift_instruction-instruction_handler db 'vpshlw',95h dw xop_shift_instruction-instruction_handler db 'vpslld',0F2h dw avx_shift_d_instruction-instruction_handler db 'vpsllq',0F3h dw avx_shift_q_instruction-instruction_handler db 'vpsllw',0F1h dw avx_shift_bw_instruction-instruction_handler db 'vpsrad',0E2h dw avx_shift_d_instruction-instruction_handler db 'vpsraq',0E2h dw avx_shift_q_instruction_evex-instruction_handler db 'vpsraw',0E1h dw avx_shift_bw_instruction-instruction_handler db 'vpsrld',0D2h dw avx_shift_d_instruction-instruction_handler db 'vpsrlq',0D3h dw avx_shift_q_instruction-instruction_handler db 'vpsrlw',0D1h dw avx_shift_bw_instruction-instruction_handler db 'vpsubb',0F8h dw avx_bw_instruction-instruction_handler db 'vpsubd',0FAh dw avx_d_instruction-instruction_handler db 'vpsubq',0FBh dw avx_q_instruction-instruction_handler db 'vpsubw',0F9h dw avx_bw_instruction-instruction_handler db 'vptest',17h dw avx_single_source_instruction_38_noevex-instruction_handler db 'vpxord',0EFh dw avx_d_instruction_evex-instruction_handler db 'vpxorq',0EFh dw avx_q_instruction_evex-instruction_handler db 'vrcpps',53h dw avx_single_source_ps_instruction_noevex-instruction_handler db 'vrcpss',53h dw avx_ss_instruction_noevex-instruction_handler db 'vsubpd',5Ch dw avx_pd_instruction_er-instruction_handler db 'vsubps',5Ch dw avx_ps_instruction_er-instruction_handler db 'vsubsd',5Ch dw avx_sd_instruction_er-instruction_handler db 'vsubss',5Ch dw avx_ss_instruction_er-instruction_handler db 'vxorpd',57h dw avx_pd_instruction-instruction_handler db 'vxorps',57h dw avx_ps_instruction-instruction_handler db 'wbinvd',9 dw simple_extended_instruction-instruction_handler db 'wrmsrq',30h dw simple_extended_instruction_64bit-instruction_handler db 'wrpkru',0EFh dw simple_instruction_0f_01-instruction_handler db 'wrussd',0F5h dw wrussd_instruction-instruction_handler db 'wrussq',0F5h dw wrussq_instruction-instruction_handler db 'xabort',0 dw xabort_instruction-instruction_handler db 'xbegin',0 dw xbegin_instruction-instruction_handler db 'xgetbv',0D0h dw simple_instruction_0f_01-instruction_handler db 'xrstor',101b dw fxsave_instruction-instruction_handler db 'xsavec',4 dw xsaves_instruction-instruction_handler db 'xsaves',5 dw xsaves_instruction-instruction_handler db 'xsetbv',0D1h dw simple_instruction_0f_01-instruction_handler instructions_7: db 'blcfill',11h dw tbm_instruction-instruction_handler db 'blendpd',0Dh dw sse4_instruction_66_3a_imm8-instruction_handler db 'blendps',0Ch dw sse4_instruction_66_3a_imm8-instruction_handler db 'blsfill',12h dw tbm_instruction-instruction_handler db 'clflush',111b dw clflush_instruction-instruction_handler db 'cmovnae',42h dw bs_instruction-instruction_handler db 'cmovnbe',47h dw bs_instruction-instruction_handler db 'cmovnge',4Ch dw bs_instruction-instruction_handler db 'cmovnle',4Fh dw bs_instruction-instruction_handler db 'cmpeqpd',0 dw cmp_pd_instruction-instruction_handler db 'cmpeqps',0 dw cmp_ps_instruction-instruction_handler db 'cmpeqsd',0 dw cmp_sd_instruction-instruction_handler db 'cmpeqss',0 dw cmp_ss_instruction-instruction_handler db 'cmplepd',2 dw cmp_pd_instruction-instruction_handler db 'cmpleps',2 dw cmp_ps_instruction-instruction_handler db 'cmplesd',2 dw cmp_sd_instruction-instruction_handler db 'cmpless',2 dw cmp_ss_instruction-instruction_handler db 'cmpltpd',1 dw cmp_pd_instruction-instruction_handler db 'cmpltps',1 dw cmp_ps_instruction-instruction_handler db 'cmpltsd',1 dw cmp_sd_instruction-instruction_handler db 'cmpltss',1 dw cmp_ss_instruction-instruction_handler db 'cmpxchg',0B0h dw basic_486_instruction-instruction_handler db 'display',0 dw display_directive-instruction_handler db 'endbr32',0FBh dw endbr_instruction-instruction_handler db 'endbr64',0FAh dw endbr_instruction-instruction_handler db 'fcmovbe',0D0h dw fcmov_instruction-instruction_handler db 'fcmovnb',0C0h dw fcomi_instruction-instruction_handler db 'fcmovne',0C8h dw fcomi_instruction-instruction_handler db 'fcmovnu',0D8h dw fcomi_instruction-instruction_handler db 'fdecstp',110110b dw simple_fpu_instruction-instruction_handler db 'fincstp',110111b dw simple_fpu_instruction-instruction_handler db 'fldenvd',4 dw fldenv_instruction_32bit-instruction_handler db 'fldenvw',4 dw fldenv_instruction_16bit-instruction_handler db 'fnsaved',6 dw fnsave_instruction_32bit-instruction_handler db 'fnsavew',6 dw fnsave_instruction_16bit-instruction_handler db 'fnstenv',6 dw fldenv_instruction-instruction_handler db 'frndint',111100b dw simple_fpu_instruction-instruction_handler db 'frstord',4 dw fnsave_instruction_32bit-instruction_handler db 'frstorw',4 dw fnsave_instruction_16bit-instruction_handler db 'fsincos',111011b dw simple_fpu_instruction-instruction_handler db 'fstenvd',6 dw fstenv_instruction_32bit-instruction_handler db 'fstenvw',6 dw fstenv_instruction_16bit-instruction_handler db 'fucomip',0E8h dw fcomip_instruction-instruction_handler db 'fucompp',0 dw fucompp_instruction-instruction_handler db 'fxrstor',1 dw fxsave_instruction-instruction_handler db 'fxtract',110100b dw simple_fpu_instruction-instruction_handler db 'fyl2xp1',111001b dw simple_fpu_instruction-instruction_handler db 'incsspd',5 dw incsspd_instruction-instruction_handler db 'incsspq',5 dw incsspq_instruction-instruction_handler db 'insertq',0 dw insertq_instruction-instruction_handler db 'invlpga',0DFh dw invlpga_instruction-instruction_handler db 'invlpgb',0FEh dw simple_instruction_0f_01-instruction_handler db 'invpcid',82h dw vmx_inv_instruction-instruction_handler db 'invvpid',81h dw vmx_inv_instruction-instruction_handler db 'ldmxcsr',10b dw stmxcsr_instruction-instruction_handler db 'loopned',0E0h dw loop_instruction_32bit-instruction_handler db 'loopneq',0E0h dw loop_instruction_64bit-instruction_handler db 'loopnew',0E0h dw loop_instruction_16bit-instruction_handler db 'loopnzd',0E0h dw loop_instruction_32bit-instruction_handler db 'loopnzq',0E0h dw loop_instruction_64bit-instruction_handler db 'loopnzw',0E0h dw loop_instruction_16bit-instruction_handler db 'mcommit',0FAh dw simple_instruction_f3_0f_01-instruction_handler db 'monitor',0C8h dw monitor_instruction-instruction_handler db 'movddup',12h dw sse_sd_instruction-instruction_handler db 'movdiri',0F9h dw movdiri_instruction-instruction_handler db 'movdq2q',0 dw movdq2q_instruction-instruction_handler db 'movhlps',12h dw movhlps_instruction-instruction_handler db 'movlhps',16h dw movhlps_instruction-instruction_handler db 'movntdq',0E7h dw movntpd_instruction-instruction_handler db 'movntpd',2Bh dw movntpd_instruction-instruction_handler db 'movntps',2Bh dw movntps_instruction-instruction_handler db 'movntsd',2Bh dw movntsd_instruction-instruction_handler db 'movntss',2Bh dw movntss_instruction-instruction_handler db 'movq2dq',0 dw movq2dq_instruction-instruction_handler db 'mpsadbw',42h dw sse4_instruction_66_3a_imm8-instruction_handler db 'paddusb',0DCh dw basic_mmx_instruction-instruction_handler db 'paddusw',0DDh dw basic_mmx_instruction-instruction_handler db 'palignr',0 dw palignr_instruction-instruction_handler db 'pavgusb',0BFh dw amd3dnow_instruction-instruction_handler db 'pblendw',0Eh dw sse4_instruction_66_3a_imm8-instruction_handler db 'pcmpeqb',74h dw basic_mmx_instruction-instruction_handler db 'pcmpeqd',76h dw basic_mmx_instruction-instruction_handler db 'pcmpeqq',29h dw sse4_instruction_66_38-instruction_handler db 'pcmpeqw',75h dw basic_mmx_instruction-instruction_handler db 'pcmpgtb',64h dw basic_mmx_instruction-instruction_handler db 'pcmpgtd',66h dw basic_mmx_instruction-instruction_handler db 'pcmpgtq',37h dw sse4_instruction_66_38-instruction_handler db 'pcmpgtw',65h dw basic_mmx_instruction-instruction_handler db 'pcommit',0F8h dw pcommit_instruction-instruction_handler db 'pconfig',0C5h dw pconfig_instruction-instruction_handler db 'pfcmpeq',0B0h dw amd3dnow_instruction-instruction_handler db 'pfcmpge',90h dw amd3dnow_instruction-instruction_handler db 'pfcmpgt',0A0h dw amd3dnow_instruction-instruction_handler db 'pfpnacc',8Eh dw amd3dnow_instruction-instruction_handler db 'pfrsqrt',97h dw amd3dnow_instruction-instruction_handler db 'phaddsw',3 dw ssse3_instruction-instruction_handler db 'phsubsw',7 dw ssse3_instruction-instruction_handler db 'pmaddwd',0F5h dw basic_mmx_instruction-instruction_handler db 'pmulhrw',0B7h dw amd3dnow_instruction-instruction_handler db 'pmulhuw',0E4h dw basic_mmx_instruction-instruction_handler db 'pmuludq',0F4h dw basic_mmx_instruction-instruction_handler db 'pshufhw',0F3h dw pshufd_instruction-instruction_handler db 'pshuflw',0F2h dw pshufd_instruction-instruction_handler db 'psubusb',0D8h dw basic_mmx_instruction-instruction_handler db 'psubusw',0D9h dw basic_mmx_instruction-instruction_handler db 'ptwrite',4 dw ptwrite_instruction-instruction_handler db 'roundpd',9 dw sse4_instruction_66_3a_imm8-instruction_handler db 'roundps',8 dw sse4_instruction_66_3a_imm8-instruction_handler db 'roundsd',0Bh dw sse4_sd_instruction_66_3a_imm8-instruction_handler db 'roundss',0Ah dw sse4_ss_instruction_66_3a_imm8-instruction_handler db 'rsqrtps',52h dw sse_ps_instruction-instruction_handler db 'rsqrtss',52h dw sse_ss_instruction-instruction_handler db 'section',0 dw section_directive-instruction_handler db 'segment',0 dw segment_directive-instruction_handler db 'stmxcsr',11b dw stmxcsr_instruction-instruction_handler db 'syscall',05h dw simple_extended_instruction-instruction_handler db 'sysexit',35h dw simple_extended_instruction-instruction_handler db 'sysretq',07h dw simple_extended_instruction_64bit-instruction_handler db 'tlbsync',0FFh dw simple_instruction_0f_01-instruction_handler db 'ucomisd',2Eh dw comisd_instruction-instruction_handler db 'ucomiss',2Eh dw comiss_instruction-instruction_handler db 'vaesdec',0DEh dw avx_instruction_38_nomask-instruction_handler db 'vaesenc',0DCh dw avx_instruction_38_nomask-instruction_handler db 'vaesimc',0DBh dw avx_single_source_128bit_instruction_38_noevex-instruction_handler db 'valignd',3 dw avx_d_instruction_3a_imm8_evex-instruction_handler db 'valignq',3 dw avx_q_instruction_3a_imm8_evex-instruction_handler db 'vandnpd',55h dw avx_pd_instruction-instruction_handler db 'vandnps',55h dw avx_ps_instruction-instruction_handler db 'vcomisd',2Fh dw avx_comisd_instruction-instruction_handler db 'vcomiss',2Fh dw avx_comiss_instruction-instruction_handler db 'vexp2pd',0C8h dw avx512_exp2pd_instruction-instruction_handler db 'vexp2ps',0C8h dw avx512_exp2ps_instruction-instruction_handler db 'vfrczpd',81h dw xop_single_source_instruction-instruction_handler db 'vfrczps',80h dw xop_single_source_instruction-instruction_handler db 'vfrczsd',83h dw xop_single_source_sd_instruction-instruction_handler db 'vfrczss',82h dw xop_single_source_ss_instruction-instruction_handler db 'vhaddpd',07Ch dw avx_pd_instruction_noevex-instruction_handler db 'vhaddps',07Ch dw avx_ps_instruction_noevex-instruction_handler db 'vhsubpd',07Dh dw avx_pd_instruction_noevex-instruction_handler db 'vhsubps',07Dh dw avx_ps_instruction_noevex-instruction_handler db 'virtual',0 dw virtual_directive-instruction_handler db 'vmclear',6 dw vmclear_instruction-instruction_handler db 'vmmcall',0D9h dw simple_instruction_0f_01-instruction_handler db 'vmovapd',28h dw avx_movpd_instruction-instruction_handler db 'vmovaps',28h dw avx_movps_instruction-instruction_handler db 'vmovdqa',6Fh dw avx_movdqa_instruction-instruction_handler db 'vmovdqu',6Fh dw avx_movdqu_instruction-instruction_handler db 'vmovhpd',16h dw avx_movlpd_instruction-instruction_handler db 'vmovhps',16h dw avx_movlps_instruction-instruction_handler db 'vmovlpd',12h dw avx_movlpd_instruction-instruction_handler db 'vmovlps',12h dw avx_movlps_instruction-instruction_handler db 'vmovupd',10h dw avx_movpd_instruction-instruction_handler db 'vmovups',10h dw avx_movps_instruction-instruction_handler db 'vmptrld',6 dw vmx_instruction-instruction_handler db 'vmptrst',7 dw vmx_instruction-instruction_handler db 'vmwrite',0 dw vmwrite_instruction-instruction_handler db 'vpaddsb',0ECh dw avx_bw_instruction-instruction_handler db 'vpaddsw',0EDh dw avx_bw_instruction-instruction_handler db 'vpandnd',0DFh dw avx_d_instruction_evex-instruction_handler db 'vpandnq',0DFh dw avx_q_instruction_evex-instruction_handler db 'vpcmpub',-1 dw avx512_cmp_ub_instruction-instruction_handler db 'vpcmpud',-1 dw avx512_cmp_ud_instruction-instruction_handler db 'vpcmpuq',-1 dw avx512_cmp_uq_instruction-instruction_handler db 'vpcmpuw',-1 dw avx512_cmp_uw_instruction-instruction_handler db 'vpcomub',-1 dw xop_pcom_ub_instruction-instruction_handler db 'vpcomud',-1 dw xop_pcom_ud_instruction-instruction_handler db 'vpcomuq',-1 dw xop_pcom_uq_instruction-instruction_handler db 'vpcomuw',-1 dw xop_pcom_uw_instruction-instruction_handler db 'vpermpd',1 dw avx_permq_instruction-instruction_handler db 'vpermps',16h dw avx_permd_instruction-instruction_handler db 'vpextrb',14h dw avx_extract_b_instruction-instruction_handler db 'vpextrd',16h dw avx_extract_d_instruction-instruction_handler db 'vpextrq',16h dw avx_extract_q_instruction-instruction_handler db 'vpextrw',15h dw avx_extract_w_instruction-instruction_handler db 'vphaddd',2 dw avx_pi_instruction_38_noevex-instruction_handler db 'vphaddw',1 dw avx_pi_instruction_38_noevex-instruction_handler db 'vphsubd',6 dw avx_pi_instruction_38_noevex-instruction_handler db 'vphsubw',5 dw avx_pi_instruction_38_noevex-instruction_handler db 'vpinsrb',20h dw avx_pinsrb_instruction-instruction_handler db 'vpinsrd',22h dw avx_pinsrd_instruction-instruction_handler db 'vpinsrq',22h dw avx_pinsrq_instruction-instruction_handler db 'vpinsrw',0C4h dw avx_pinsrw_instruction-instruction_handler db 'vpmaxsb',3Ch dw avx_bw_instruction_38-instruction_handler db 'vpmaxsd',3Dh dw avx_d_instruction_38-instruction_handler db 'vpmaxsq',3Dh dw avx_q_instruction_38_evex-instruction_handler db 'vpmaxsw',0EEh dw avx_bw_instruction-instruction_handler db 'vpmaxub',0DEh dw avx_bw_instruction-instruction_handler db 'vpmaxud',3Fh dw avx_d_instruction_38-instruction_handler db 'vpmaxuq',3Fh dw avx_q_instruction_38_evex-instruction_handler db 'vpmaxuw',3Eh dw avx_bw_instruction_38-instruction_handler db 'vpminsb',38h dw avx_bw_instruction_38-instruction_handler db 'vpminsd',39h dw avx_d_instruction_38-instruction_handler db 'vpminsq',39h dw avx_q_instruction_38_evex-instruction_handler db 'vpminsw',0EAh dw avx_bw_instruction-instruction_handler db 'vpminub',0DAh dw avx_bw_instruction-instruction_handler db 'vpminud',3Bh dw avx_d_instruction_38-instruction_handler db 'vpminuq',3Bh dw avx_q_instruction_38_evex-instruction_handler db 'vpminuw',3Ah dw avx_bw_instruction_38-instruction_handler db 'vpmovdb',31h dw avx512_pmovdb_instruction-instruction_handler db 'vpmovdw',33h dw avx512_pmovwb_instruction-instruction_handler db 'vpmovqb',32h dw avx512_pmovqb_instruction-instruction_handler db 'vpmovqd',35h dw avx512_pmovwb_instruction-instruction_handler db 'vpmovqw',34h dw avx512_pmovdb_instruction-instruction_handler db 'vpmovwb',30h dw avx512_pmovwb_instruction-instruction_handler db 'vpmuldq',28h dw avx_q_instruction_38-instruction_handler db 'vpmulhw',0E5h dw avx_bw_instruction-instruction_handler db 'vpmulld',40h dw avx_d_instruction_38-instruction_handler db 'vpmullq',40h dw avx_q_instruction_38_evex-instruction_handler db 'vpmullw',0D5h dw avx_bw_instruction-instruction_handler db 'vprolvd',15h dw avx_d_instruction_38_evex-instruction_handler db 'vprolvq',15h dw avx_q_instruction_38_evex-instruction_handler db 'vprorvd',14h dw avx_d_instruction_38_evex-instruction_handler db 'vprorvq',14h dw avx_q_instruction_38_evex-instruction_handler db 'vpsadbw',0F6h dw avx_bw_instruction-instruction_handler db 'vpshldd',71h dw avx_d_instruction_3a_imm8_evex-instruction_handler db 'vpshldq',71h dw avx_q_instruction_3a_imm8_evex-instruction_handler db 'vpshldw',70h dw avx_bw_instruction_3a_imm8_w1_evex-instruction_handler db 'vpshrdd',73h dw avx_d_instruction_3a_imm8_evex-instruction_handler db 'vpshrdq',73h dw avx_q_instruction_3a_imm8_evex-instruction_handler db 'vpshrdw',72h dw avx_bw_instruction_3a_imm8_w1_evex-instruction_handler db 'vpshufb',0 dw avx_bw_instruction_38-instruction_handler db 'vpshufd',70h dw avx_single_source_d_instruction_imm8-instruction_handler db 'vpsignb',8 dw avx_pi_instruction_38_noevex-instruction_handler db 'vpsignd',0Ah dw avx_pi_instruction_38_noevex-instruction_handler db 'vpsignw',9 dw avx_pi_instruction_38_noevex-instruction_handler db 'vpslldq',111b dw avx_shift_dq_instruction-instruction_handler db 'vpsllvd',47h dw avx_d_instruction_38-instruction_handler db 'vpsllvq',47h dw avx_q_instruction_38_w1-instruction_handler db 'vpsllvw',12h dw avx_bw_instruction_38_w1_evex-instruction_handler db 'vpsravd',46h dw avx_d_instruction_38-instruction_handler db 'vpsravq',46h dw avx_q_instruction_38_w1_evex-instruction_handler db 'vpsravw',11h dw avx_bw_instruction_38_w1_evex-instruction_handler db 'vpsrldq',011b dw avx_shift_dq_instruction-instruction_handler db 'vpsrlvd',45h dw avx_d_instruction_38-instruction_handler db 'vpsrlvq',45h dw avx_q_instruction_38_w1-instruction_handler db 'vpsrlvw',10h dw avx_bw_instruction_38_w1_evex-instruction_handler db 'vpsubsb',0E8h dw avx_bw_instruction-instruction_handler db 'vpsubsw',0E9h dw avx_bw_instruction-instruction_handler db 'vshufpd',0C6h dw avx_pd_instruction_imm8-instruction_handler db 'vshufps',0C6h dw avx_ps_instruction_imm8-instruction_handler db 'vsqrtpd',51h dw avx_single_source_pd_instruction_er-instruction_handler db 'vsqrtps',51h dw avx_single_source_ps_instruction_er-instruction_handler db 'vsqrtsd',51h dw avx_sd_instruction_er-instruction_handler db 'vsqrtss',51h dw avx_ss_instruction_er-instruction_handler db 'vtestpd',0Fh dw avx_single_source_instruction_38_noevex-instruction_handler db 'vtestps',0Eh dw avx_single_source_instruction_38_noevex-instruction_handler db 'xrstors',3 dw xsaves_instruction-instruction_handler db 'xsave64',100b dw fxsave_instruction_64bit-instruction_handler instructions_8: db 'addsubpd',0D0h dw sse_pd_instruction-instruction_handler db 'addsubps',0D0h dw cvtpd2dq_instruction-instruction_handler db 'blendvpd',15h dw sse4_instruction_66_38_xmm0-instruction_handler db 'blendvps',14h dw sse4_instruction_66_38_xmm0-instruction_handler db 'cldemote',0 dw cldemote_instruction-instruction_handler db 'clrssbsy',6 dw clrssbsy_instruction-instruction_handler db 'cmpneqpd',4 dw cmp_pd_instruction-instruction_handler db 'cmpneqps',4 dw cmp_ps_instruction-instruction_handler db 'cmpneqsd',4 dw cmp_sd_instruction-instruction_handler db 'cmpneqss',4 dw cmp_ss_instruction-instruction_handler db 'cmpnlepd',6 dw cmp_pd_instruction-instruction_handler db 'cmpnleps',6 dw cmp_ps_instruction-instruction_handler db 'cmpnlesd',6 dw cmp_sd_instruction-instruction_handler db 'cmpnless',6 dw cmp_ss_instruction-instruction_handler db 'cmpnltpd',5 dw cmp_pd_instruction-instruction_handler db 'cmpnltps',5 dw cmp_ps_instruction-instruction_handler db 'cmpnltsd',5 dw cmp_sd_instruction-instruction_handler db 'cmpnltss',5 dw cmp_ss_instruction-instruction_handler db 'cmpordpd',7 dw cmp_pd_instruction-instruction_handler db 'cmpordps',7 dw cmp_ps_instruction-instruction_handler db 'cmpordsd',7 dw cmp_sd_instruction-instruction_handler db 'cmpordss',7 dw cmp_ss_instruction-instruction_handler db 'cvtdq2pd',0E6h dw cvtdq2pd_instruction-instruction_handler db 'cvtdq2ps',5Bh dw sse_ps_instruction-instruction_handler db 'cvtpd2dq',0E6h dw cvtpd2dq_instruction-instruction_handler db 'cvtpd2pi',2Dh dw cvtpd2pi_instruction-instruction_handler db 'cvtpd2ps',5Ah dw sse_pd_instruction-instruction_handler db 'cvtpi2pd',2Ah dw cvtpi2pd_instruction-instruction_handler db 'cvtpi2ps',2Ah dw cvtpi2ps_instruction-instruction_handler db 'cvtps2dq',5Bh dw sse_pd_instruction-instruction_handler db 'cvtps2pd',5Ah dw cvtps2pd_instruction-instruction_handler db 'cvtps2pi',2Dh dw cvtps2pi_instruction-instruction_handler db 'cvtsd2si',2Dh dw cvtsd2si_instruction-instruction_handler db 'cvtsd2ss',5Ah dw sse_sd_instruction-instruction_handler db 'cvtsi2sd',2Ah dw cvtsi2sd_instruction-instruction_handler db 'cvtsi2ss',2Ah dw cvtsi2ss_instruction-instruction_handler db 'cvtss2sd',5Ah dw sse_ss_instruction-instruction_handler db 'cvtss2si',2Dh dw cvtss2si_instruction-instruction_handler db 'fcmovnbe',0D0h dw fcomi_instruction-instruction_handler db 'fnstenvd',6 dw fldenv_instruction_32bit-instruction_handler db 'fnstenvw',6 dw fldenv_instruction_16bit-instruction_handler db 'fxsave64',0 dw fxsave_instruction_64bit-instruction_handler db 'insertps',21h dw insertps_instruction-instruction_handler db 'kortestb',98h dw mask_instruction_single_source_b-instruction_handler db 'kortestd',98h dw mask_instruction_single_source_d-instruction_handler db 'kortestq',98h dw mask_instruction_single_source_q-instruction_handler db 'kortestw',98h dw mask_instruction_single_source_w-instruction_handler db 'kshiftlb',32h dw mask_shift_instruction_d-instruction_handler db 'kshiftld',33h dw mask_shift_instruction_d-instruction_handler db 'kshiftlq',33h dw mask_shift_instruction_q-instruction_handler db 'kshiftlw',32h dw mask_shift_instruction_q-instruction_handler db 'kshiftrb',30h dw mask_shift_instruction_d-instruction_handler db 'kshiftrd',31h dw mask_shift_instruction_d-instruction_handler db 'kshiftrq',31h dw mask_shift_instruction_q-instruction_handler db 'kshiftrw',30h dw mask_shift_instruction_q-instruction_handler db 'kunpckbw',4Bh dw mask_instruction_b-instruction_handler db 'kunpckdq',4Bh dw mask_instruction_q-instruction_handler db 'kunpckwd',4Bh dw mask_instruction_w-instruction_handler db 'maskmovq',0 dw maskmovq_instruction-instruction_handler db 'monitorx',0FAh dw monitor_instruction-instruction_handler db 'movmskpd',0 dw movmskpd_instruction-instruction_handler db 'movmskps',0 dw movmskps_instruction-instruction_handler db 'movntdqa',2Ah dw movntdqa_instruction-instruction_handler db 'movshdup',16h dw movshdup_instruction-instruction_handler db 'movsldup',12h dw movshdup_instruction-instruction_handler db 'packssdw',6Bh dw basic_mmx_instruction-instruction_handler db 'packsswb',63h dw basic_mmx_instruction-instruction_handler db 'packusdw',2Bh dw sse4_instruction_66_38-instruction_handler db 'packuswb',67h dw basic_mmx_instruction-instruction_handler db 'pblendvb',10h dw sse4_instruction_66_38_xmm0-instruction_handler db 'pfrcpit1',0A6h dw amd3dnow_instruction-instruction_handler db 'pfrcpit2',0B6h dw amd3dnow_instruction-instruction_handler db 'pfrsqit1',0A7h dw amd3dnow_instruction-instruction_handler db 'pmovmskb',0D7h dw pmovmskb_instruction-instruction_handler db 'pmovsxbd',21h dw pmovsxbd_instruction-instruction_handler db 'pmovsxbq',22h dw pmovsxbq_instruction-instruction_handler db 'pmovsxbw',20h dw pmovsxbw_instruction-instruction_handler db 'pmovsxdq',25h dw pmovsxdq_instruction-instruction_handler db 'pmovsxwd',23h dw pmovsxwd_instruction-instruction_handler db 'pmovsxwq',24h dw pmovsxwq_instruction-instruction_handler db 'pmovzxbd',31h dw pmovsxbd_instruction-instruction_handler db 'pmovzxbq',32h dw pmovsxbq_instruction-instruction_handler db 'pmovzxbw',30h dw pmovsxbw_instruction-instruction_handler db 'pmovzxdq',35h dw pmovsxdq_instruction-instruction_handler db 'pmovzxwd',33h dw pmovsxwd_instruction-instruction_handler db 'pmovzxwq',34h dw pmovsxwq_instruction-instruction_handler db 'pmulhrsw',0Bh dw ssse3_instruction-instruction_handler db 'prefetch',0 dw amd_prefetch_instruction-instruction_handler db 'rdfsbase',0 dw rdfsbase_instruction-instruction_handler db 'rdgsbase',1 dw rdfsbase_instruction-instruction_handler db 'rstorssp',5 dw rstorssp_instruction-instruction_handler db 'setssbsy',0E8h dw setssbsy_instruction-instruction_handler db 'sha1msg1',0C9h dw sse4_instruction_38-instruction_handler db 'sha1msg2',0CAh dw sse4_instruction_38-instruction_handler db 'sysenter',34h dw simple_extended_instruction-instruction_handler db 'sysexitq',35h dw simple_extended_instruction_64bit-instruction_handler db 'umonitor',0 dw umonitor_instruction-instruction_handler db 'unpckhpd',15h dw sse_pd_instruction-instruction_handler db 'unpckhps',15h dw sse_ps_instruction-instruction_handler db 'unpcklpd',14h dw sse_pd_instruction-instruction_handler db 'unpcklps',14h dw sse_ps_instruction-instruction_handler db 'vblendpd',0Dh dw avx_pi_instruction_3a_imm8_noevex-instruction_handler db 'vblendps',0Ch dw avx_pi_instruction_3a_imm8_noevex-instruction_handler db 'vcmpeqpd',0 dw avx_cmp_pd_instruction-instruction_handler db 'vcmpeqps',0 dw avx_cmp_ps_instruction-instruction_handler db 'vcmpeqsd',0 dw avx_cmp_sd_instruction-instruction_handler db 'vcmpeqss',0 dw avx_cmp_ss_instruction-instruction_handler db 'vcmpgepd',0Dh dw avx_cmp_pd_instruction-instruction_handler db 'vcmpgeps',0Dh dw avx_cmp_ps_instruction-instruction_handler db 'vcmpgesd',0Dh dw avx_cmp_sd_instruction-instruction_handler db 'vcmpgess',0Dh dw avx_cmp_ss_instruction-instruction_handler db 'vcmpgtpd',0Eh dw avx_cmp_pd_instruction-instruction_handler db 'vcmpgtps',0Eh dw avx_cmp_ps_instruction-instruction_handler db 'vcmpgtsd',0Eh dw avx_cmp_sd_instruction-instruction_handler db 'vcmpgtss',0Eh dw avx_cmp_ss_instruction-instruction_handler db 'vcmplepd',2 dw avx_cmp_pd_instruction-instruction_handler db 'vcmpleps',2 dw avx_cmp_ps_instruction-instruction_handler db 'vcmplesd',2 dw avx_cmp_sd_instruction-instruction_handler db 'vcmpless',2 dw avx_cmp_ss_instruction-instruction_handler db 'vcmpltpd',1 dw avx_cmp_pd_instruction-instruction_handler db 'vcmpltps',1 dw avx_cmp_ps_instruction-instruction_handler db 'vcmpltsd',1 dw avx_cmp_sd_instruction-instruction_handler db 'vcmpltss',1 dw avx_cmp_ss_instruction-instruction_handler db 'vfmaddpd',69h dw fma4_instruction_p-instruction_handler db 'vfmaddps',68h dw fma4_instruction_p-instruction_handler db 'vfmaddsd',6Bh dw fma4_instruction_sd-instruction_handler db 'vfmaddss',6Ah dw fma4_instruction_ss-instruction_handler db 'vfmsubpd',6Dh dw fma4_instruction_p-instruction_handler db 'vfmsubps',6Ch dw fma4_instruction_p-instruction_handler db 'vfmsubsd',6Fh dw fma4_instruction_sd-instruction_handler db 'vfmsubss',6Eh dw fma4_instruction_ss-instruction_handler db 'vldmxcsr',10b dw vstmxcsr_instruction-instruction_handler db 'vmlaunch',0C2h dw simple_instruction_0f_01-instruction_handler db 'vmovddup',12h dw avx_movddup_instruction-instruction_handler db 'vmovdqu8',6Fh dw avx512_movdqu8_instruction-instruction_handler db 'vmovhlps',12h dw avx_movhlps_instruction-instruction_handler db 'vmovlhps',16h dw avx_movhlps_instruction-instruction_handler db 'vmovntdq',0E7h dw avx_movntdq_instruction-instruction_handler db 'vmovntpd',2Bh dw avx_movntpd_instruction-instruction_handler db 'vmovntps',2Bh dw avx_movntps_instruction-instruction_handler db 'vmpsadbw',42h dw avx_pi_instruction_3a_imm8_noevex-instruction_handler db 'vmresume',0C3h dw simple_instruction_0f_01-instruction_handler db 'vpaddusb',0DCh dw avx_bw_instruction-instruction_handler db 'vpaddusw',0DDh dw avx_bw_instruction-instruction_handler db 'vpalignr',0Fh dw avx_pi_instruction_3a_imm8-instruction_handler db 'vpblendd',2 dw avx_pi_instruction_3a_imm8_noevex-instruction_handler db 'vpblendw',0Eh dw avx_pi_instruction_3a_imm8_noevex-instruction_handler db 'vpcmpeqb',74h dw avx_cmpeqb_instruction-instruction_handler db 'vpcmpeqd',76h dw avx_cmpeqd_instruction-instruction_handler db 'vpcmpeqq',29h dw avx_cmpeqq_instruction-instruction_handler db 'vpcmpeqw',75h dw avx_cmpeqb_instruction-instruction_handler db 'vpcmpgtb',64h dw avx_cmpeqb_instruction-instruction_handler db 'vpcmpgtd',66h dw avx_cmpeqd_instruction-instruction_handler db 'vpcmpgtq',37h dw avx_cmpeqq_instruction-instruction_handler db 'vpcmpgtw',65h dw avx_cmpeqb_instruction-instruction_handler db 'vpcmpleb',2 dw avx512_cmp_b_instruction-instruction_handler db 'vpcmpled',2 dw avx512_cmp_d_instruction-instruction_handler db 'vpcmpleq',2 dw avx512_cmp_q_instruction-instruction_handler db 'vpcmplew',2 dw avx512_cmp_w_instruction-instruction_handler db 'vpcmpltb',1 dw avx512_cmp_b_instruction-instruction_handler db 'vpcmpltd',1 dw avx512_cmp_d_instruction-instruction_handler db 'vpcmpltq',1 dw avx512_cmp_q_instruction-instruction_handler db 'vpcmpltw',1 dw avx512_cmp_w_instruction-instruction_handler db 'vpcomeqb',4 dw xop_pcom_b_instruction-instruction_handler db 'vpcomeqd',4 dw xop_pcom_d_instruction-instruction_handler db 'vpcomeqq',4 dw xop_pcom_q_instruction-instruction_handler db 'vpcomeqw',4 dw xop_pcom_w_instruction-instruction_handler db 'vpcomgeb',3 dw xop_pcom_b_instruction-instruction_handler db 'vpcomged',3 dw xop_pcom_d_instruction-instruction_handler db 'vpcomgeq',3 dw xop_pcom_q_instruction-instruction_handler db 'vpcomgew',3 dw xop_pcom_w_instruction-instruction_handler db 'vpcomgtb',2 dw xop_pcom_b_instruction-instruction_handler db 'vpcomgtd',2 dw xop_pcom_d_instruction-instruction_handler db 'vpcomgtq',2 dw xop_pcom_q_instruction-instruction_handler db 'vpcomgtw',2 dw xop_pcom_w_instruction-instruction_handler db 'vpcomleb',1 dw xop_pcom_b_instruction-instruction_handler db 'vpcomled',1 dw xop_pcom_d_instruction-instruction_handler db 'vpcomleq',1 dw xop_pcom_q_instruction-instruction_handler db 'vpcomlew',1 dw xop_pcom_w_instruction-instruction_handler db 'vpcomltb',0 dw xop_pcom_b_instruction-instruction_handler db 'vpcomltd',0 dw xop_pcom_d_instruction-instruction_handler db 'vpcomltq',0 dw xop_pcom_q_instruction-instruction_handler db 'vpcomltw',0 dw xop_pcom_w_instruction-instruction_handler db 'vpdpbusd',50h dw avx_d_instruction_38_evex-instruction_handler db 'vpdpwssd',52h dw avx_d_instruction_38_evex-instruction_handler db 'vpermi2b',75h dw avx_bw_instruction_38_evex-instruction_handler db 'vpermi2d',76h dw avx_d_instruction_38_evex-instruction_handler db 'vpermi2q',76h dw avx_q_instruction_38_evex-instruction_handler db 'vpermi2w',75h dw avx_bw_instruction_38_w1_evex-instruction_handler db 'vpermt2b',7Dh dw avx_bw_instruction_38_evex-instruction_handler db 'vpermt2d',7Eh dw avx_d_instruction_38_evex-instruction_handler db 'vpermt2q',7Eh dw avx_q_instruction_38_evex-instruction_handler db 'vpermt2w',7Dh dw avx_bw_instruction_38_w1_evex-instruction_handler db 'vphaddbd',0C2h dw xop_single_source_128bit_instruction-instruction_handler db 'vphaddbq',0C3h dw xop_single_source_128bit_instruction-instruction_handler db 'vphaddbw',0C1h dw xop_single_source_128bit_instruction-instruction_handler db 'vphadddq',0CBh dw xop_single_source_128bit_instruction-instruction_handler db 'vphaddsw',3 dw avx_pi_instruction_38_noevex-instruction_handler db 'vphaddwd',0C6h dw xop_single_source_128bit_instruction-instruction_handler db 'vphaddwq',0C7h dw xop_single_source_128bit_instruction-instruction_handler db 'vphsubbw',0E1h dw xop_single_source_128bit_instruction-instruction_handler db 'vphsubdq',0E3h dw xop_single_source_128bit_instruction-instruction_handler db 'vphsubsw',7 dw avx_pi_instruction_38_noevex-instruction_handler db 'vphsubwd',0E2h dw xop_single_source_128bit_instruction-instruction_handler db 'vplzcntd',44h dw avx_single_source_d_instruction_38_evex-instruction_handler db 'vplzcntq',44h dw avx_single_source_q_instruction_38_evex-instruction_handler db 'vpmacsdd',9Eh dw xop_triple_source_128bit_instruction-instruction_handler db 'vpmacswd',96h dw xop_triple_source_128bit_instruction-instruction_handler db 'vpmacsww',95h dw xop_triple_source_128bit_instruction-instruction_handler db 'vpmaddwd',0F5h dw avx_bw_instruction-instruction_handler db 'vpmovb2m',29h dw avx512_pmov_2m_instruction-instruction_handler db 'vpmovd2m',39h dw avx512_pmov_2m_instruction-instruction_handler db 'vpmovm2b',28h dw avx512_pmov_m2_instruction-instruction_handler db 'vpmovm2d',38h dw avx512_pmov_m2_instruction-instruction_handler db 'vpmovm2q',38h dw avx512_pmov_m2_instruction_w1-instruction_handler db 'vpmovm2w',28h dw avx512_pmov_m2_instruction_w1-instruction_handler db 'vpmovq2m',39h dw avx512_pmov_2m_instruction_w1-instruction_handler db 'vpmovsdb',21h dw avx512_pmovdb_instruction-instruction_handler db 'vpmovsdw',23h dw avx512_pmovwb_instruction-instruction_handler db 'vpmovsqb',22h dw avx512_pmovqb_instruction-instruction_handler db 'vpmovsqd',25h dw avx512_pmovwb_instruction-instruction_handler db 'vpmovsqw',24h dw avx512_pmovdb_instruction-instruction_handler db 'vpmovswb',20h dw avx512_pmovwb_instruction-instruction_handler db 'vpmovw2m',29h dw avx512_pmov_2m_instruction_w1-instruction_handler db 'vpmulhuw',0E4h dw avx_bw_instruction-instruction_handler db 'vpmuludq',0F4h dw avx_q_instruction-instruction_handler db 'vpopcntb',54h dw avx_single_source_d_instruction_38_evex-instruction_handler db 'vpopcntd',55h dw avx512_single_source_ps_instruction-instruction_handler db 'vpopcntq',55h dw avx512_single_source_pd_instruction-instruction_handler db 'vpopcntw',54h dw avx_single_source_d_instruction_38_evex_w1-instruction_handler db 'vpshldvd',71h dw avx_d_instruction_38_evex-instruction_handler db 'vpshldvq',71h dw avx_q_instruction_38_evex-instruction_handler db 'vpshldvw',70h dw avx_bw_instruction_38_w1_evex-instruction_handler db 'vpshrdvd',73h dw avx_d_instruction_38_evex-instruction_handler db 'vpshrdvq',73h dw avx_q_instruction_38_evex-instruction_handler db 'vpshrdvw',72 dw avx_bw_instruction_38_w1_evex-instruction_handler db 'vpshufhw',0F3h dw avx_pshuf_w_instruction-instruction_handler db 'vpshuflw',0F2h dw avx_pshuf_w_instruction-instruction_handler db 'vpsubusb',0D8h dw avx_bw_instruction-instruction_handler db 'vpsubusw',0D9h dw avx_bw_instruction-instruction_handler db 'vptestmb',26h dw avx512_ptestmb_instruction-instruction_handler db 'vptestmd',27h dw avx512_ptestmd_instruction-instruction_handler db 'vptestmq',27h dw avx512_ptestmq_instruction-instruction_handler db 'vptestmw',26h dw avx512_ptestmw_instruction-instruction_handler db 'vrangepd',50h dw avx512_pd_instruction_sae_imm8-instruction_handler db 'vrangeps',50h dw avx512_ps_instruction_sae_imm8-instruction_handler db 'vrangesd',51h dw avx512_sd_instruction_sae_imm8-instruction_handler db 'vrangess',51h dw avx512_ss_instruction_sae_imm8-instruction_handler db 'vrcp14pd',4Ch dw avx512_single_source_pd_instruction-instruction_handler db 'vrcp14ps',4Ch dw avx512_single_source_ps_instruction-instruction_handler db 'vrcp14sd',4Dh dw avx512_sd_instruction-instruction_handler db 'vrcp14ss',4Dh dw avx512_ss_instruction-instruction_handler db 'vrcp28pd',0CAh dw avx512_exp2pd_instruction-instruction_handler db 'vrcp28ps',0CAh dw avx512_exp2ps_instruction-instruction_handler db 'vrcp28sd',0CBh dw avx512_sd_instruction_sae-instruction_handler db 'vrcp28ss',0CBh dw avx512_ss_instruction_sae-instruction_handler db 'vroundpd',9 dw avx_single_source_instruction_3a_imm8_noevex-instruction_handler db 'vroundps',8 dw avx_single_source_instruction_3a_imm8_noevex-instruction_handler db 'vroundsd',0Bh dw avx_sd_instruction_3a_imm8_noevex-instruction_handler db 'vroundss',0Ah dw avx_ss_instruction_3a_imm8_noevex-instruction_handler db 'vrsqrtps',52h dw avx_single_source_ps_instruction_noevex-instruction_handler db 'vrsqrtss',52h dw avx_ss_instruction_noevex-instruction_handler db 'vstmxcsr',11b dw vstmxcsr_instruction-instruction_handler db 'vucomisd',2Eh dw avx_comisd_instruction-instruction_handler db 'vucomiss',2Eh dw avx_comiss_instruction-instruction_handler db 'vzeroall',77h dw vzeroall_instruction-instruction_handler db 'wbnoinvd',9 dw simple_extended_instruction_f3-instruction_handler db 'wrfsbase',2 dw rdfsbase_instruction-instruction_handler db 'wrgsbase',3 dw rdfsbase_instruction-instruction_handler db 'xacquire',0F2h dw prefix_instruction-instruction_handler db 'xrelease',0F3h dw prefix_instruction-instruction_handler db 'xrstor64',101b dw fxsave_instruction_64bit-instruction_handler db 'xsavec64',4 dw xsaves_instruction_64bit-instruction_handler db 'xsaveopt',110b dw fxsave_instruction-instruction_handler db 'xsaves64',5 dw xsaves_instruction_64bit-instruction_handler instructions_9: db 'cmpxchg8b',8 dw cmpxchgx_instruction-instruction_handler db 'cvttpd2dq',0E6h dw sse_pd_instruction-instruction_handler db 'cvttpd2pi',2Ch dw cvtpd2pi_instruction-instruction_handler db 'cvttps2dq',5Bh dw movshdup_instruction-instruction_handler db 'cvttps2pi',2Ch dw cvtps2pi_instruction-instruction_handler db 'cvttsd2si',2Ch dw cvtsd2si_instruction-instruction_handler db 'cvttss2si',2Ch dw cvtss2si_instruction-instruction_handler db 'extractps',17h dw extractps_instruction-instruction_handler db 'fxrstor64',1 dw fxsave_instruction_64bit-instruction_handler db 'gf2p8mulb',0CFh dw sse4_instruction_66_38-instruction_handler db 'movdir64b',0F8h dw movdir64b_instruction-instruction_handler db 'pclmulqdq',-1 dw pclmulqdq_instruction-instruction_handler db 'pcmpestri',61h dw sse4_instruction_66_3a_imm8-instruction_handler db 'pcmpestrm',60h dw sse4_instruction_66_3a_imm8-instruction_handler db 'pcmpistri',63h dw sse4_instruction_66_3a_imm8-instruction_handler db 'pcmpistrm',62h dw sse4_instruction_66_3a_imm8-instruction_handler db 'pmaddubsw',4 dw ssse3_instruction-instruction_handler db 'prefetchw',1 dw amd_prefetch_instruction-instruction_handler db 'punpckhbw',68h dw basic_mmx_instruction-instruction_handler db 'punpckhdq',6Ah dw basic_mmx_instruction-instruction_handler db 'punpckhwd',69h dw basic_mmx_instruction-instruction_handler db 'punpcklbw',60h dw basic_mmx_instruction-instruction_handler db 'punpckldq',62h dw basic_mmx_instruction-instruction_handler db 'punpcklwd',61h dw basic_mmx_instruction-instruction_handler db 'pvalidate',0FFh dw simple_instruction_f2_0f_01-instruction_handler db 'rmpadjust',0FEh dw simple_instruction_f3_0f_01-instruction_handler db 'rmpupdate',0FEh dw simple_instruction_f2_0f_01-instruction_handler db 'sha1nexte',0C8h dw sse4_instruction_38-instruction_handler db 'sha1rnds4',0CCh dw sse4_instruction_3a_imm8-instruction_handler db 'useavx256',0 dw set_evex_mode-instruction_handler db 'useavx512',1 dw set_evex_mode-instruction_handler db 'vaddsubpd',0D0h dw avx_pd_instruction_noevex-instruction_handler db 'vaddsubps',0D0h dw avx_ps_instruction_noevex-instruction_handler db 'vblendmpd',65h dw avx_pd_instruction_38_evex-instruction_handler db 'vblendmps',65h dw avx_ps_instruction_66_38_evex-instruction_handler db 'vblendvpd',4Bh dw avx_triple_source_instruction_3a_noevex-instruction_handler db 'vblendvps',4Ah dw avx_triple_source_instruction_3a_noevex-instruction_handler db 'vcmpneqpd',4 dw avx_cmp_pd_instruction-instruction_handler db 'vcmpneqps',4 dw avx_cmp_ps_instruction-instruction_handler db 'vcmpneqsd',4 dw avx_cmp_sd_instruction-instruction_handler db 'vcmpneqss',4 dw avx_cmp_ss_instruction-instruction_handler db 'vcmpngepd',9 dw avx_cmp_pd_instruction-instruction_handler db 'vcmpngeps',9 dw avx_cmp_ps_instruction-instruction_handler db 'vcmpngesd',9 dw avx_cmp_sd_instruction-instruction_handler db 'vcmpngess',9 dw avx_cmp_ss_instruction-instruction_handler db 'vcmpngtpd',0Ah dw avx_cmp_pd_instruction-instruction_handler db 'vcmpngtps',0Ah dw avx_cmp_ps_instruction-instruction_handler db 'vcmpngtsd',0Ah dw avx_cmp_sd_instruction-instruction_handler db 'vcmpngtss',0Ah dw avx_cmp_ss_instruction-instruction_handler db 'vcmpnlepd',6 dw avx_cmp_pd_instruction-instruction_handler db 'vcmpnleps',6 dw avx_cmp_ps_instruction-instruction_handler db 'vcmpnlesd',6 dw avx_cmp_sd_instruction-instruction_handler db 'vcmpnless',6 dw avx_cmp_ss_instruction-instruction_handler db 'vcmpnltpd',5 dw avx_cmp_pd_instruction-instruction_handler db 'vcmpnltps',5 dw avx_cmp_ps_instruction-instruction_handler db 'vcmpnltsd',5 dw avx_cmp_sd_instruction-instruction_handler db 'vcmpnltss',5 dw avx_cmp_ss_instruction-instruction_handler db 'vcmpordpd',7 dw avx_cmp_pd_instruction-instruction_handler db 'vcmpordps',7 dw avx_cmp_ps_instruction-instruction_handler db 'vcmpordsd',7 dw avx_cmp_sd_instruction-instruction_handler db 'vcmpordss',7 dw avx_cmp_ss_instruction-instruction_handler db 'vcvtdq2pd',0E6h dw avx_cvtdq2pd_instruction-instruction_handler db 'vcvtdq2ps',5Bh dw avx_single_source_ps_instruction_er-instruction_handler db 'vcvtpd2dq',0E6h dw avx_cvtpd2dq_instruction-instruction_handler db 'vcvtpd2ps',5Ah dw avx_cvtpd2ps_instruction-instruction_handler db 'vcvtpd2qq',7Bh dw avx_single_source_pd_instruction_er_evex-instruction_handler db 'vcvtph2ps',13h dw avx_cvtph2ps_instruction-instruction_handler db 'vcvtps2dq',5Bh dw avx_cvtps2dq_instruction-instruction_handler db 'vcvtps2pd',5Ah dw avx_cvtps2pd_instruction-instruction_handler db 'vcvtps2ph',1Dh dw avx_cvtps2ph_instruction-instruction_handler db 'vcvtps2qq',7Bh dw avx_cvtps2qq_instruction-instruction_handler db 'vcvtqq2pd',0E6h dw avx_cvtqq2pd_instruction-instruction_handler db 'vcvtqq2ps',5Bh dw avx_cvtpd2udq_instruction-instruction_handler db 'vcvtsd2si',2Dh dw avx_cvtsd2si_instruction-instruction_handler db 'vcvtsd2ss',5Ah dw avx_sd_instruction_er-instruction_handler db 'vcvtsi2sd',2Ah dw avx_cvtsi2sd_instruction-instruction_handler db 'vcvtsi2ss',2Ah dw avx_cvtsi2ss_instruction-instruction_handler db 'vcvtss2sd',5Ah dw avx_ss_instruction_sae-instruction_handler db 'vcvtss2si',2Dh dw avx_cvtss2si_instruction-instruction_handler db 'vdbpsadbw',42h dw avx_bw_instruction_3a_imm8_evex-instruction_handler db 'vexpandpd',88h dw avx_single_source_q_instruction_38_evex-instruction_handler db 'vexpandps',88h dw avx_single_source_d_instruction_38_evex-instruction_handler db 'vfnmaddpd',79h dw fma4_instruction_p-instruction_handler db 'vfnmaddps',78h dw fma4_instruction_p-instruction_handler db 'vfnmaddsd',7Bh dw fma4_instruction_sd-instruction_handler db 'vfnmaddss',7Ah dw fma4_instruction_ss-instruction_handler db 'vfnmsubpd',7Dh dw fma4_instruction_p-instruction_handler db 'vfnmsubps',7Ch dw fma4_instruction_p-instruction_handler db 'vfnmsubsd',7Fh dw fma4_instruction_sd-instruction_handler db 'vfnmsubss',7Eh dw fma4_instruction_ss-instruction_handler db 'vgetexppd',42h dw avx512_single_source_pd_instruction_sae-instruction_handler db 'vgetexpps',42h dw avx512_single_source_ps_instruction_sae-instruction_handler db 'vgetexpsd',43h dw avx512_sd_instruction_sae-instruction_handler db 'vgetexpss',43h dw avx512_ss_instruction_sae-instruction_handler db 'vinsertps',21h dw avx_insertps_instruction-instruction_handler db 'vmovdqa32',6Fh dw avx512_movdqa32_instruction-instruction_handler db 'vmovdqa64',6Fh dw avx512_movdqa64_instruction-instruction_handler db 'vmovdqu16',6Fh dw avx512_movdqu16_instruction-instruction_handler db 'vmovdqu32',6Fh dw avx512_movdqu32_instruction-instruction_handler db 'vmovdqu64',6Fh dw avx512_movdqu64_instruction-instruction_handler db 'vmovmskpd',0 dw avx_movmskpd_instruction-instruction_handler db 'vmovmskps',0 dw avx_movmskps_instruction-instruction_handler db 'vmovntdqa',2Ah dw avx_movntdqa_instruction-instruction_handler db 'vmovshdup',16h dw avx_movshdup_instruction-instruction_handler db 'vmovsldup',12h dw avx_movshdup_instruction-instruction_handler db 'vp4dpwssd',52h dw avx512_4vnniw_instruction-instruction_handler db 'vpackssdw',6Bh dw avx_d_instruction-instruction_handler db 'vpacksswb',63h dw avx_bw_instruction-instruction_handler db 'vpackusdw',2Bh dw avx_d_instruction_38-instruction_handler db 'vpackuswb',67h dw avx_bw_instruction-instruction_handler db 'vpblendmb',66h dw avx_bw_instruction_38_evex-instruction_handler db 'vpblendmd',64h dw avx_d_instruction_38_evex-instruction_handler db 'vpblendmq',64h dw avx_q_instruction_38_evex-instruction_handler db 'vpblendmw',66h dw avx_bw_instruction_38_w1_evex-instruction_handler db 'vpblendvb',4Ch dw avx_triple_source_instruction_3a_noevex-instruction_handler db 'vpcmpleub',2 dw avx512_cmp_ub_instruction-instruction_handler db 'vpcmpleud',2 dw avx512_cmp_ud_instruction-instruction_handler db 'vpcmpleuq',2 dw avx512_cmp_uq_instruction-instruction_handler db 'vpcmpleuw',2 dw avx512_cmp_uw_instruction-instruction_handler db 'vpcmpltub',1 dw avx512_cmp_ub_instruction-instruction_handler db 'vpcmpltud',1 dw avx512_cmp_ud_instruction-instruction_handler db 'vpcmpltuq',1 dw avx512_cmp_uq_instruction-instruction_handler db 'vpcmpltuw',1 dw avx512_cmp_uw_instruction-instruction_handler db 'vpcmpneqb',4 dw avx512_cmp_b_instruction-instruction_handler db 'vpcmpneqd',4 dw avx512_cmp_d_instruction-instruction_handler db 'vpcmpneqq',4 dw avx512_cmp_q_instruction-instruction_handler db 'vpcmpneqw',4 dw avx512_cmp_b_instruction-instruction_handler db 'vpcmpnleb',6 dw avx512_cmp_b_instruction-instruction_handler db 'vpcmpnled',6 dw avx512_cmp_d_instruction-instruction_handler db 'vpcmpnleq',6 dw avx512_cmp_q_instruction-instruction_handler db 'vpcmpnlew',6 dw avx512_cmp_b_instruction-instruction_handler db 'vpcmpnltb',5 dw avx512_cmp_b_instruction-instruction_handler db 'vpcmpnltd',5 dw avx512_cmp_d_instruction-instruction_handler db 'vpcmpnltq',5 dw avx512_cmp_q_instruction-instruction_handler db 'vpcmpnltw',5 dw avx512_cmp_b_instruction-instruction_handler db 'vpcomequb',4 dw xop_pcom_ub_instruction-instruction_handler db 'vpcomequd',4 dw xop_pcom_ud_instruction-instruction_handler db 'vpcomequq',4 dw xop_pcom_uq_instruction-instruction_handler db 'vpcomequw',4 dw xop_pcom_uw_instruction-instruction_handler db 'vpcomgeub',3 dw xop_pcom_ub_instruction-instruction_handler db 'vpcomgeud',3 dw xop_pcom_ud_instruction-instruction_handler db 'vpcomgeuq',3 dw xop_pcom_uq_instruction-instruction_handler db 'vpcomgeuw',3 dw xop_pcom_uw_instruction-instruction_handler db 'vpcomgtub',2 dw xop_pcom_ub_instruction-instruction_handler db 'vpcomgtud',2 dw xop_pcom_ud_instruction-instruction_handler db 'vpcomgtuq',2 dw xop_pcom_uq_instruction-instruction_handler db 'vpcomgtuw',2 dw xop_pcom_uw_instruction-instruction_handler db 'vpcomleub',1 dw xop_pcom_ub_instruction-instruction_handler db 'vpcomleud',1 dw xop_pcom_ud_instruction-instruction_handler db 'vpcomleuq',1 dw xop_pcom_uq_instruction-instruction_handler db 'vpcomleuw',1 dw xop_pcom_uw_instruction-instruction_handler db 'vpcomltub',0 dw xop_pcom_ub_instruction-instruction_handler db 'vpcomltud',0 dw xop_pcom_ud_instruction-instruction_handler db 'vpcomltuq',0 dw xop_pcom_uq_instruction-instruction_handler db 'vpcomltuw',0 dw xop_pcom_uw_instruction-instruction_handler db 'vpcomneqb',5 dw xop_pcom_b_instruction-instruction_handler db 'vpcomneqd',5 dw xop_pcom_d_instruction-instruction_handler db 'vpcomneqq',5 dw xop_pcom_q_instruction-instruction_handler db 'vpcomneqw',5 dw xop_pcom_w_instruction-instruction_handler db 'vpdpbusds',51h dw avx_d_instruction_38_evex-instruction_handler db 'vpdpwssds',53h dw avx_d_instruction_38_evex-instruction_handler db 'vpermi2pd',77h dw avx_q_instruction_38_evex-instruction_handler db 'vpermi2ps',77h dw avx_d_instruction_38_evex-instruction_handler db 'vpermilpd',5 dw avx_permilpd_instruction-instruction_handler db 'vpermilps',4 dw avx_permilps_instruction-instruction_handler db 'vpermt2pd',7Fh dw avx_q_instruction_38_evex-instruction_handler db 'vpermt2ps',7Fh dw avx_d_instruction_38_evex-instruction_handler db 'vpexpandb',62h dw avx_single_source_d_instruction_38_evex-instruction_handler db 'vpexpandd',89h dw avx_single_source_d_instruction_38_evex-instruction_handler db 'vpexpandq',89h dw avx_single_source_q_instruction_38_evex-instruction_handler db 'vpexpandw',62h dw avx_single_source_q_instruction_38_evex-instruction_handler db 'vphaddubd',0D2h dw xop_single_source_128bit_instruction-instruction_handler db 'vphaddubq',0D3h dw xop_single_source_128bit_instruction-instruction_handler db 'vphaddubw',0D1h dw xop_single_source_128bit_instruction-instruction_handler db 'vphaddudq',0DBh dw xop_single_source_128bit_instruction-instruction_handler db 'vphadduwd',0D6h dw xop_single_source_128bit_instruction-instruction_handler db 'vphadduwq',0D7h dw xop_single_source_128bit_instruction-instruction_handler db 'vpmacsdqh',9Fh dw xop_triple_source_128bit_instruction-instruction_handler db 'vpmacsdql',97h dw xop_triple_source_128bit_instruction-instruction_handler db 'vpmacssdd',8Eh dw xop_triple_source_128bit_instruction-instruction_handler db 'vpmacsswd',86h dw xop_triple_source_128bit_instruction-instruction_handler db 'vpmacssww',85h dw xop_triple_source_128bit_instruction-instruction_handler db 'vpmadcswd',0B6h dw xop_triple_source_128bit_instruction-instruction_handler db 'vpmovmskb',0D7h dw avx_pmovmskb_instruction-instruction_handler db 'vpmovsxbd',21h dw avx_pmovsxbd_instruction-instruction_handler db 'vpmovsxbq',22h dw avx_pmovsxbq_instruction-instruction_handler db 'vpmovsxbw',20h dw avx_pmovsxbw_instruction-instruction_handler db 'vpmovsxdq',25h dw avx_pmovsxbw_instruction-instruction_handler db 'vpmovsxwd',23h dw avx_pmovsxbw_instruction-instruction_handler db 'vpmovsxwq',24h dw avx_pmovsxbd_instruction-instruction_handler db 'vpmovusdb',11h dw avx512_pmovdb_instruction-instruction_handler db 'vpmovusdw',13h dw avx512_pmovwb_instruction-instruction_handler db 'vpmovusqb',12h dw avx512_pmovqb_instruction-instruction_handler db 'vpmovusqd',15h dw avx512_pmovwb_instruction-instruction_handler db 'vpmovusqw',14h dw avx512_pmovdb_instruction-instruction_handler db 'vpmovuswb',10h dw avx512_pmovwb_instruction-instruction_handler db 'vpmovzxbd',31h dw avx_pmovsxbd_instruction-instruction_handler db 'vpmovzxbq',32h dw avx_pmovsxbq_instruction-instruction_handler db 'vpmovzxbw',30h dw avx_pmovsxbw_instruction-instruction_handler db 'vpmovzxdq',35h dw avx_pmovsxbw_instruction-instruction_handler db 'vpmovzxwd',33h dw avx_pmovsxbw_instruction-instruction_handler db 'vpmovzxwq',34h dw avx_pmovsxbd_instruction-instruction_handler db 'vpmulhrsw',0Bh dw avx_bw_instruction_38-instruction_handler db 'vptestnmb',26h dw avx512_ptestnmb_instruction-instruction_handler db 'vptestnmd',27h dw avx512_ptestnmd_instruction-instruction_handler db 'vptestnmq',27h dw avx512_ptestnmq_instruction-instruction_handler db 'vptestnmw',26h dw avx512_ptestnmw_instruction-instruction_handler db 'vreducepd',56h dw avx512_single_source_pd_instruction_sae_imm8-instruction_handler db 'vreduceps',56h dw avx512_single_source_ps_instruction_sae_imm8-instruction_handler db 'vreducesd',57h dw avx512_sd_instruction_sae_imm8-instruction_handler db 'vreducess',57h dw avx512_ss_instruction_sae_imm8-instruction_handler db 'vscalefpd',2Ch dw avx512_pd_instruction_er-instruction_handler db 'vscalefps',2Ch dw avx512_ps_instruction_er-instruction_handler db 'vscalefsd',2Dh dw avx512_sd_instruction_er-instruction_handler db 'vscalefss',2Dh dw avx512_ss_instruction_er-instruction_handler db 'vunpckhpd',15h dw avx_pd_instruction-instruction_handler db 'vunpckhps',15h dw avx_ps_instruction-instruction_handler db 'vunpcklpd',14h dw avx_pd_instruction-instruction_handler db 'vunpcklps',14h dw avx_ps_instruction-instruction_handler db 'xrstors64',3 dw xsaves_instruction_64bit-instruction_handler instructions_10: db 'aesdeclast',0DFh dw sse4_instruction_66_38-instruction_handler db 'aesenclast',0DDh dw sse4_instruction_66_38-instruction_handler db 'clflushopt',7 dw clflushopt_instruction-instruction_handler db 'cmpunordpd',3 dw cmp_pd_instruction-instruction_handler db 'cmpunordps',3 dw cmp_ps_instruction-instruction_handler db 'cmpunordsd',3 dw cmp_sd_instruction-instruction_handler db 'cmpunordss',3 dw cmp_ss_instruction-instruction_handler db 'cmpxchg16b',16 dw cmpxchgx_instruction-instruction_handler db 'loadall286',5 dw simple_extended_instruction-instruction_handler db 'loadall386',7 dw simple_extended_instruction-instruction_handler db 'maskmovdqu',0 dw maskmovdqu_instruction-instruction_handler db 'phminposuw',41h dw sse4_instruction_66_38-instruction_handler db 'prefetcht0',1 dw prefetch_instruction-instruction_handler db 'prefetcht1',2 dw prefetch_instruction-instruction_handler db 'prefetcht2',3 dw prefetch_instruction-instruction_handler db 'punpckhqdq',6Dh dw sse_pd_instruction-instruction_handler db 'punpcklqdq',6Ch dw sse_pd_instruction-instruction_handler db 'sha256msg1',0CCh dw sse4_instruction_38-instruction_handler db 'sha256msg2',0CDh dw sse4_instruction_38-instruction_handler db 'vcmptruepd',0Fh dw avx_cmp_pd_instruction-instruction_handler db 'vcmptrueps',0Fh dw avx_cmp_ps_instruction-instruction_handler db 'vcmptruesd',0Fh dw avx_cmp_sd_instruction-instruction_handler db 'vcmptruess',0Fh dw avx_cmp_ss_instruction-instruction_handler db 'vcvtpd2udq',79h dw avx_cvtpd2udq_instruction-instruction_handler db 'vcvtpd2uqq',79h dw avx_single_source_pd_instruction_er_evex-instruction_handler db 'vcvtps2udq',79h dw avx_single_source_ps_instruction_er_evex-instruction_handler db 'vcvtps2uqq',79h dw avx_cvtps2qq_instruction-instruction_handler db 'vcvtsd2usi',79h dw avx_cvtsd2usi_instruction-instruction_handler db 'vcvtss2usi',79h dw avx_cvtss2usi_instruction-instruction_handler db 'vcvttpd2dq',0E6h dw avx_cvttpd2dq_instruction-instruction_handler db 'vcvttpd2qq',7Ah dw avx_single_source_pd_instruction_sae_evex-instruction_handler db 'vcvttps2dq',5Bh dw avx_cvttps2dq_instruction-instruction_handler db 'vcvttps2qq',7Ah dw avx_cvttps2qq_instruction-instruction_handler db 'vcvttsd2si',2Ch dw avx_cvttsd2si_instruction-instruction_handler db 'vcvttss2si',2Ch dw avx_cvttss2si_instruction-instruction_handler db 'vcvtudq2pd',7Ah dw avx_cvtudq2pd_instruction-instruction_handler db 'vcvtudq2ps',7Ah dw avx_cvtudq2ps_instruction-instruction_handler db 'vcvtuqq2pd',7Ah dw avx_cvtqq2pd_instruction-instruction_handler db 'vcvtuqq2ps',7Ah dw avx_cvtuqq2ps_instruction-instruction_handler db 'vcvtusi2sd',7Bh dw avx_cvtusi2sd_instruction-instruction_handler db 'vcvtusi2ss',7Bh dw avx_cvtusi2ss_instruction-instruction_handler db 'vextractps',17h dw avx_extract_d_instruction-instruction_handler db 'vfpclasspd',66h dw avx512_fpclasspd_instruction-instruction_handler db 'vfpclassps',66h dw avx512_fpclassps_instruction-instruction_handler db 'vfpclasssd',67h dw avx512_fpclasssd_instruction-instruction_handler db 'vfpclassss',67h dw avx512_fpclassss_instruction-instruction_handler db 'vgatherdpd',92h dw gather_pd_instruction-instruction_handler db 'vgatherdps',92h dw gather_ps_instruction-instruction_handler db 'vgatherqpd',93h dw gather_pd_instruction-instruction_handler db 'vgatherqps',93h dw gather_ps_instruction-instruction_handler db 'vgetmantpd',26h dw avx512_single_source_pd_instruction_sae_imm8-instruction_handler db 'vgetmantps',26h dw avx512_single_source_ps_instruction_sae_imm8-instruction_handler db 'vgetmantsd',27h dw avx512_sd_instruction_sae_imm8-instruction_handler db 'vgetmantss',27h dw avx512_ss_instruction_sae_imm8-instruction_handler db 'vgf2p8mulb',0CFh dw avx_bw_instruction_38-instruction_handler db 'vmaskmovpd',2Dh dw avx_maskmov_instruction-instruction_handler db 'vmaskmovps',2Ch dw avx_maskmov_instruction-instruction_handler db 'vp4dpwssds',53h dw avx512_4vnniw_instruction-instruction_handler db 'vpclmulqdq',-1 dw avx_pclmulqdq_instruction-instruction_handler db 'vpcmpestri',61h dw avx_single_source_128bit_instruction_3a_imm8_noevex-instruction_handler db 'vpcmpestrm',60h dw avx_single_source_128bit_instruction_3a_imm8_noevex-instruction_handler db 'vpcmpistri',63h dw avx_single_source_128bit_instruction_3a_imm8_noevex-instruction_handler db 'vpcmpistrm',62h dw avx_single_source_128bit_instruction_3a_imm8_noevex-instruction_handler db 'vpcmpnequb',4 dw avx512_cmp_ub_instruction-instruction_handler db 'vpcmpnequd',4 dw avx512_cmp_ud_instruction-instruction_handler db 'vpcmpnequq',4 dw avx512_cmp_uq_instruction-instruction_handler db 'vpcmpnequw',4 dw avx512_cmp_uw_instruction-instruction_handler db 'vpcmpnleub',6 dw avx512_cmp_ub_instruction-instruction_handler db 'vpcmpnleud',6 dw avx512_cmp_ud_instruction-instruction_handler db 'vpcmpnleuq',6 dw avx512_cmp_uq_instruction-instruction_handler db 'vpcmpnleuw',6 dw avx512_cmp_uw_instruction-instruction_handler db 'vpcmpnltub',5 dw avx512_cmp_ub_instruction-instruction_handler db 'vpcmpnltud',5 dw avx512_cmp_ud_instruction-instruction_handler db 'vpcmpnltuq',5 dw avx512_cmp_uq_instruction-instruction_handler db 'vpcmpnltuw',5 dw avx512_cmp_uw_instruction-instruction_handler db 'vpcomnequb',5 dw xop_pcom_ub_instruction-instruction_handler db 'vpcomnequd',5 dw xop_pcom_ud_instruction-instruction_handler db 'vpcomnequq',5 dw xop_pcom_uq_instruction-instruction_handler db 'vpcomnequw',5 dw xop_pcom_uw_instruction-instruction_handler db 'vpcomtrueb',7 dw xop_pcom_b_instruction-instruction_handler db 'vpcomtrued',7 dw xop_pcom_d_instruction-instruction_handler db 'vpcomtrueq',7 dw xop_pcom_q_instruction-instruction_handler db 'vpcomtruew',7 dw xop_pcom_w_instruction-instruction_handler db 'vperm2f128',6 dw avx_perm2f128_instruction-instruction_handler db 'vperm2i128',46h dw avx_perm2f128_instruction-instruction_handler db 'vpermil2pd',49h dw vpermil2_instruction-instruction_handler db 'vpermil2ps',48h dw vpermil2_instruction-instruction_handler db 'vpgatherdd',90h dw gather_ps_instruction-instruction_handler db 'vpgatherdq',90h dw gather_pd_instruction-instruction_handler db 'vpgatherqd',91h dw gather_ps_instruction-instruction_handler db 'vpgatherqq',91h dw gather_pd_instruction-instruction_handler db 'vpmacssdqh',8Fh dw xop_triple_source_128bit_instruction-instruction_handler db 'vpmacssdql',87h dw xop_triple_source_128bit_instruction-instruction_handler db 'vpmadcsswd',0A6h dw xop_triple_source_128bit_instruction-instruction_handler db 'vpmaddubsw',4 dw avx_bw_instruction_38-instruction_handler db 'vpmaskmovd',8Ch dw avx_maskmov_instruction-instruction_handler db 'vpmaskmovq',8Ch dw avx_maskmov_w1_instruction-instruction_handler db 'vpternlogd',25h dw avx_d_instruction_3a_imm8_evex-instruction_handler db 'vpternlogq',25h dw avx_q_instruction_3a_imm8_evex-instruction_handler db 'vpunpckhbw',68h dw avx_bw_instruction-instruction_handler db 'vpunpckhdq',6Ah dw avx_d_instruction-instruction_handler db 'vpunpckhwd',69h dw avx_bw_instruction-instruction_handler db 'vpunpcklbw',60h dw avx_bw_instruction-instruction_handler db 'vpunpckldq',62h dw avx_d_instruction-instruction_handler db 'vpunpcklwd',61h dw avx_bw_instruction-instruction_handler db 'vrsqrt14pd',4Eh dw avx512_single_source_pd_instruction-instruction_handler db 'vrsqrt14ps',4Eh dw avx512_single_source_ps_instruction-instruction_handler db 'vrsqrt14sd',4Fh dw avx512_sd_instruction-instruction_handler db 'vrsqrt14ss',4Fh dw avx512_ss_instruction-instruction_handler db 'vrsqrt28pd',0CCh dw avx512_exp2pd_instruction-instruction_handler db 'vrsqrt28ps',0CCh dw avx512_exp2ps_instruction-instruction_handler db 'vrsqrt28sd',0CDh dw avx512_sd_instruction_sae-instruction_handler db 'vrsqrt28ss',0CDh dw avx512_ss_instruction_sae-instruction_handler db 'vshuff32x4',23h dw avx512_shuf_d_instruction-instruction_handler db 'vshuff64x2',23h dw avx512_shuf_q_instruction-instruction_handler db 'vshufi32x4',43h dw avx512_shuf_d_instruction-instruction_handler db 'vshufi64x2',43h dw avx512_shuf_q_instruction-instruction_handler db 'vzeroupper',77h dw vzeroupper_instruction-instruction_handler db 'xsaveopt64',110b dw fxsave_instruction_64bit-instruction_handler instructions_11: db 'pclmulhqhdq',10001b dw pclmulqdq_instruction-instruction_handler db 'pclmullqhdq',10000b dw pclmulqdq_instruction-instruction_handler db 'prefetchnta',0 dw prefetch_instruction-instruction_handler db 'prefetchwt1',2 dw amd_prefetch_instruction-instruction_handler db 'saveprevssp',0EAh dw setssbsy_instruction-instruction_handler db 'sha256rnds2',0CBh dw sse4_instruction_38_xmm0-instruction_handler db 'vaesdeclast',0DFh dw avx_instruction_38_nomask-instruction_handler db 'vaesenclast',0DDh dw avx_instruction_38_nomask-instruction_handler db 'vcmpeq_ospd',10h dw avx_cmp_pd_instruction-instruction_handler db 'vcmpeq_osps',10h dw avx_cmp_ps_instruction-instruction_handler db 'vcmpeq_ossd',10h dw avx_cmp_sd_instruction-instruction_handler db 'vcmpeq_osss',10h dw avx_cmp_ss_instruction-instruction_handler db 'vcmpeq_uqpd',8 dw avx_cmp_pd_instruction-instruction_handler db 'vcmpeq_uqps',8 dw avx_cmp_ps_instruction-instruction_handler db 'vcmpeq_uqsd',8 dw avx_cmp_sd_instruction-instruction_handler db 'vcmpeq_uqss',8 dw avx_cmp_ss_instruction-instruction_handler db 'vcmpeq_uspd',18h dw avx_cmp_pd_instruction-instruction_handler db 'vcmpeq_usps',18h dw avx_cmp_ps_instruction-instruction_handler db 'vcmpeq_ussd',18h dw avx_cmp_sd_instruction-instruction_handler db 'vcmpeq_usss',18h dw avx_cmp_ss_instruction-instruction_handler db 'vcmpfalsepd',0Bh dw avx_cmp_pd_instruction-instruction_handler db 'vcmpfalseps',0Bh dw avx_cmp_ps_instruction-instruction_handler db 'vcmpfalsesd',0Bh dw avx_cmp_sd_instruction-instruction_handler db 'vcmpfalsess',0Bh dw avx_cmp_ss_instruction-instruction_handler db 'vcmpge_oqpd',1Dh dw avx_cmp_pd_instruction-instruction_handler db 'vcmpge_oqps',1Dh dw avx_cmp_ps_instruction-instruction_handler db 'vcmpge_oqsd',1Dh dw avx_cmp_sd_instruction-instruction_handler db 'vcmpge_oqss',1Dh dw avx_cmp_ss_instruction-instruction_handler db 'vcmpgt_oqpd',1Eh dw avx_cmp_pd_instruction-instruction_handler db 'vcmpgt_oqps',1Eh dw avx_cmp_ps_instruction-instruction_handler db 'vcmpgt_oqsd',1Eh dw avx_cmp_sd_instruction-instruction_handler db 'vcmpgt_oqss',1Eh dw avx_cmp_ss_instruction-instruction_handler db 'vcmple_oqpd',12h dw avx_cmp_pd_instruction-instruction_handler db 'vcmple_oqps',12h dw avx_cmp_ps_instruction-instruction_handler db 'vcmple_oqsd',12h dw avx_cmp_sd_instruction-instruction_handler db 'vcmple_oqss',12h dw avx_cmp_ss_instruction-instruction_handler db 'vcmplt_oqpd',11h dw avx_cmp_pd_instruction-instruction_handler db 'vcmplt_oqps',11h dw avx_cmp_ps_instruction-instruction_handler db 'vcmplt_oqsd',11h dw avx_cmp_sd_instruction-instruction_handler db 'vcmplt_oqss',11h dw avx_cmp_ss_instruction-instruction_handler db 'vcmpord_spd',17h dw avx_cmp_pd_instruction-instruction_handler db 'vcmpord_sps',17h dw avx_cmp_ps_instruction-instruction_handler db 'vcmpord_ssd',17h dw avx_cmp_sd_instruction-instruction_handler db 'vcmpord_sss',17h dw avx_cmp_ss_instruction-instruction_handler db 'vcmpunordpd',3 dw avx_cmp_pd_instruction-instruction_handler db 'vcmpunordps',3 dw avx_cmp_ps_instruction-instruction_handler db 'vcmpunordsd',3 dw avx_cmp_sd_instruction-instruction_handler db 'vcmpunordss',3 dw avx_cmp_ss_instruction-instruction_handler db 'vcompresspd',8Ah dw avx_compress_q_instruction-instruction_handler db 'vcompressps',8Ah dw avx_compress_d_instruction-instruction_handler db 'vcvttpd2udq',78h dw avx_cvttpd2udq_instruction-instruction_handler db 'vcvttpd2uqq',78h dw avx_single_source_pd_instruction_sae_evex-instruction_handler db 'vcvttps2udq',78h dw avx_cvttps2udq_instruction-instruction_handler db 'vcvttps2uqq',78h dw avx_cvttps2qq_instruction-instruction_handler db 'vcvttsd2usi',78h dw avx_cvttsd2usi_instruction-instruction_handler db 'vcvttss2usi',78h dw avx_cvttss2usi_instruction-instruction_handler db 'vfixupimmpd',54h dw avx512_pd_instruction_sae_imm8-instruction_handler db 'vfixupimmps',54h dw avx512_ps_instruction_sae_imm8-instruction_handler db 'vfixupimmsd',55h dw avx512_sd_instruction_sae_imm8-instruction_handler db 'vfixupimmss',55h dw avx512_ss_instruction_sae_imm8-instruction_handler db 'vfmadd132pd',98h dw fma_instruction_pd-instruction_handler db 'vfmadd132ps',98h dw fma_instruction_ps-instruction_handler db 'vfmadd132sd',99h dw fma_instruction_sd-instruction_handler db 'vfmadd132ss',99h dw fma_instruction_ss-instruction_handler db 'vfmadd213pd',0A8h dw fma_instruction_pd-instruction_handler db 'vfmadd213ps',0A8h dw fma_instruction_ps-instruction_handler db 'vfmadd213sd',0A9h dw fma_instruction_sd-instruction_handler db 'vfmadd213ss',0A9h dw fma_instruction_ss-instruction_handler db 'vfmadd231pd',0B8h dw fma_instruction_pd-instruction_handler db 'vfmadd231ps',0B8h dw fma_instruction_ps-instruction_handler db 'vfmadd231sd',0B9h dw fma_instruction_sd-instruction_handler db 'vfmadd231ss',0B9h dw fma_instruction_ss-instruction_handler db 'vfmaddsubpd',5Dh dw fma4_instruction_p-instruction_handler db 'vfmaddsubps',5Ch dw fma4_instruction_p-instruction_handler db 'vfmsub132pd',9Ah dw fma_instruction_pd-instruction_handler db 'vfmsub132ps',9Ah dw fma_instruction_ps-instruction_handler db 'vfmsub132sd',9Bh dw fma_instruction_sd-instruction_handler db 'vfmsub132ss',9Bh dw fma_instruction_ss-instruction_handler db 'vfmsub213pd',0AAh dw fma_instruction_pd-instruction_handler db 'vfmsub213ps',0AAh dw fma_instruction_ps-instruction_handler db 'vfmsub213sd',0ABh dw fma_instruction_sd-instruction_handler db 'vfmsub213ss',0ABh dw fma_instruction_ss-instruction_handler db 'vfmsub231pd',0BAh dw fma_instruction_pd-instruction_handler db 'vfmsub231ps',0BAh dw fma_instruction_ps-instruction_handler db 'vfmsub231sd',0BBh dw fma_instruction_sd-instruction_handler db 'vfmsub231ss',0BBh dw fma_instruction_ss-instruction_handler db 'vfmsubaddpd',5Fh dw fma4_instruction_p-instruction_handler db 'vfmsubaddps',5Eh dw fma4_instruction_p-instruction_handler db 'vinsertf128',18h dw avx_insertf128_instruction-instruction_handler db 'vinserti128',38h dw avx_insertf128_instruction-instruction_handler db 'vmaskmovdqu',0 dw avx_maskmovdqu_instruction-instruction_handler db 'vpcomfalseb',6 dw xop_pcom_b_instruction-instruction_handler db 'vpcomfalsed',6 dw xop_pcom_d_instruction-instruction_handler db 'vpcomfalseq',6 dw xop_pcom_q_instruction-instruction_handler db 'vpcomfalsew',6 dw xop_pcom_w_instruction-instruction_handler db 'vpcompressb',63h dw avx_compress_d_instruction-instruction_handler db 'vpcompressd',8Bh dw avx_compress_d_instruction-instruction_handler db 'vpcompressq',8Bh dw avx_compress_q_instruction-instruction_handler db 'vpcompressw',63h dw avx_compress_q_instruction-instruction_handler db 'vpcomtrueub',7 dw xop_pcom_ub_instruction-instruction_handler db 'vpcomtrueud',7 dw xop_pcom_ud_instruction-instruction_handler db 'vpcomtrueuq',7 dw xop_pcom_uq_instruction-instruction_handler db 'vpcomtrueuw',7 dw xop_pcom_uw_instruction-instruction_handler db 'vpconflictd',0C4h dw avx_single_source_d_instruction_38_evex-instruction_handler db 'vpconflictq',0C4h dw avx_single_source_q_instruction_38_evex-instruction_handler db 'vphminposuw',41h dw avx_single_source_instruction_38_noevex-instruction_handler db 'vpmadd52huq',0B5h dw avx_q_instruction_38_evex-instruction_handler db 'vpmadd52luq',0B4h dw avx_q_instruction_38_evex-instruction_handler db 'vpscatterdd',0A0h dw scatter_ps_instruction-instruction_handler db 'vpscatterdq',0A0h dw scatter_pd_instruction-instruction_handler db 'vpscatterqd',0A1h dw scatter_ps_instruction-instruction_handler db 'vpscatterqq',0A1h dw scatter_pd_instruction-instruction_handler db 'vpunpckhqdq',6Dh dw avx_q_instruction-instruction_handler db 'vpunpcklqdq',6Ch dw avx_q_instruction-instruction_handler db 'vrndscalepd',9 dw avx512_single_source_pd_instruction_sae_imm8-instruction_handler db 'vrndscaleps',8 dw avx512_single_source_ps_instruction_sae_imm8-instruction_handler db 'vrndscalesd',0Bh dw avx512_sd_instruction_sae_imm8-instruction_handler db 'vrndscaless',0Ah dw avx512_ss_instruction_sae_imm8-instruction_handler db 'vscatterdpd',0A2h dw scatter_pd_instruction-instruction_handler db 'vscatterdps',0A2h dw scatter_ps_instruction-instruction_handler db 'vscatterqpd',0A3h dw scatter_pd_instruction-instruction_handler db 'vscatterqps',0A3h dw scatter_ps_instruction-instruction_handler instructions_12: db 'pclmulhqhqdq',10001b dw pclmulqdq_instruction-instruction_handler db 'pclmulhqlqdq',1 dw pclmulqdq_instruction-instruction_handler db 'pclmullqhqdq',10000b dw pclmulqdq_instruction-instruction_handler db 'pclmullqlqdq',0 dw pclmulqdq_instruction-instruction_handler db 'vbroadcastsd',19h dw avx_broadcastsd_instruction-instruction_handler db 'vbroadcastss',18h dw avx_broadcastss_instruction-instruction_handler db 'vcmpneq_oqpd',0Ch dw avx_cmp_pd_instruction-instruction_handler db 'vcmpneq_oqps',0Ch dw avx_cmp_ps_instruction-instruction_handler db 'vcmpneq_oqsd',0Ch dw avx_cmp_sd_instruction-instruction_handler db 'vcmpneq_oqss',0Ch dw avx_cmp_ss_instruction-instruction_handler db 'vcmpneq_ospd',1Ch dw avx_cmp_pd_instruction-instruction_handler db 'vcmpneq_osps',1Ch dw avx_cmp_ps_instruction-instruction_handler db 'vcmpneq_ossd',1Ch dw avx_cmp_sd_instruction-instruction_handler db 'vcmpneq_osss',1Ch dw avx_cmp_ss_instruction-instruction_handler db 'vcmpneq_uspd',14h dw avx_cmp_pd_instruction-instruction_handler db 'vcmpneq_usps',14h dw avx_cmp_ps_instruction-instruction_handler db 'vcmpneq_ussd',14h dw avx_cmp_sd_instruction-instruction_handler db 'vcmpneq_usss',14h dw avx_cmp_ss_instruction-instruction_handler db 'vcmpnge_uqpd',19h dw avx_cmp_pd_instruction-instruction_handler db 'vcmpnge_uqps',19h dw avx_cmp_ps_instruction-instruction_handler db 'vcmpnge_uqsd',19h dw avx_cmp_sd_instruction-instruction_handler db 'vcmpnge_uqss',19h dw avx_cmp_ss_instruction-instruction_handler db 'vcmpngt_uqpd',1Ah dw avx_cmp_pd_instruction-instruction_handler db 'vcmpngt_uqps',1Ah dw avx_cmp_ps_instruction-instruction_handler db 'vcmpngt_uqsd',1Ah dw avx_cmp_sd_instruction-instruction_handler db 'vcmpngt_uqss',1Ah dw avx_cmp_ss_instruction-instruction_handler db 'vcmpnle_uqpd',16h dw avx_cmp_pd_instruction-instruction_handler db 'vcmpnle_uqps',16h dw avx_cmp_ps_instruction-instruction_handler db 'vcmpnle_uqsd',16h dw avx_cmp_sd_instruction-instruction_handler db 'vcmpnle_uqss',16h dw avx_cmp_ss_instruction-instruction_handler db 'vcmpnlt_uqpd',15h dw avx_cmp_pd_instruction-instruction_handler db 'vcmpnlt_uqps',15h dw avx_cmp_ps_instruction-instruction_handler db 'vcmpnlt_uqsd',15h dw avx_cmp_sd_instruction-instruction_handler db 'vcmpnlt_uqss',15h dw avx_cmp_ss_instruction-instruction_handler db 'vextractf128',19h dw avx_extractf128_instruction-instruction_handler db 'vextracti128',39h dw avx_extractf128_instruction-instruction_handler db 'vfnmadd132pd',9Ch dw fma_instruction_pd-instruction_handler db 'vfnmadd132ps',9Ch dw fma_instruction_ps-instruction_handler db 'vfnmadd132sd',9Dh dw fma_instruction_sd-instruction_handler db 'vfnmadd132ss',9Dh dw fma_instruction_ss-instruction_handler db 'vfnmadd213pd',0ACh dw fma_instruction_pd-instruction_handler db 'vfnmadd213ps',0ACh dw fma_instruction_ps-instruction_handler db 'vfnmadd213sd',0ADh dw fma_instruction_sd-instruction_handler db 'vfnmadd213ss',0ADh dw fma_instruction_ss-instruction_handler db 'vfnmadd231pd',0BCh dw fma_instruction_pd-instruction_handler db 'vfnmadd231ps',0BCh dw fma_instruction_ps-instruction_handler db 'vfnmadd231sd',0BDh dw fma_instruction_sd-instruction_handler db 'vfnmadd231ss',0BDh dw fma_instruction_ss-instruction_handler db 'vfnmsub132pd',9Eh dw fma_instruction_pd-instruction_handler db 'vfnmsub132ps',9Eh dw fma_instruction_ps-instruction_handler db 'vfnmsub132sd',9Fh dw fma_instruction_sd-instruction_handler db 'vfnmsub132ss',9Fh dw fma_instruction_ss-instruction_handler db 'vfnmsub213pd',0AEh dw fma_instruction_pd-instruction_handler db 'vfnmsub213ps',0AEh dw fma_instruction_ps-instruction_handler db 'vfnmsub213sd',0AFh dw fma_instruction_sd-instruction_handler db 'vfnmsub213ss',0AFh dw fma_instruction_ss-instruction_handler db 'vfnmsub231pd',0BEh dw fma_instruction_pd-instruction_handler db 'vfnmsub231ps',0BEh dw fma_instruction_ps-instruction_handler db 'vfnmsub231sd',0BFh dw fma_instruction_sd-instruction_handler db 'vfnmsub231ss',0BFh dw fma_instruction_ss-instruction_handler db 'vinsertf32x4',18h dw avx512_insert_32x4_instruction-instruction_handler db 'vinsertf32x8',1Ah dw avx512_insert_32x8_instruction-instruction_handler db 'vinsertf64x2',18h dw avx512_insert_64x2_instruction-instruction_handler db 'vinsertf64x4',1Ah dw avx512_insert_64x4_instruction-instruction_handler db 'vinserti32x4',38h dw avx512_insert_32x4_instruction-instruction_handler db 'vinserti32x8',3Ah dw avx512_insert_32x8_instruction-instruction_handler db 'vinserti64x2',38h dw avx512_insert_64x2_instruction-instruction_handler db 'vinserti64x4',3Ah dw avx512_insert_64x4_instruction-instruction_handler db 'vpbroadcastb',78h dw avx_pbroadcastb_instruction-instruction_handler db 'vpbroadcastd',58h dw avx_pbroadcastd_instruction-instruction_handler db 'vpbroadcastq',59h dw avx_pbroadcastq_instruction-instruction_handler db 'vpbroadcastw',79h dw avx_pbroadcastw_instruction-instruction_handler db 'vpclmulhqhdq',10001b dw avx_pclmulqdq_instruction-instruction_handler db 'vpclmullqhdq',10000b dw avx_pclmulqdq_instruction-instruction_handler db 'vpcomfalseub',6 dw xop_pcom_ub_instruction-instruction_handler db 'vpcomfalseud',6 dw xop_pcom_ud_instruction-instruction_handler db 'vpcomfalseuq',6 dw xop_pcom_uq_instruction-instruction_handler db 'vpcomfalseuw',6 dw xop_pcom_uw_instruction-instruction_handler db 'vpermilmo2pd',10b dw vpermil_2pd_instruction-instruction_handler db 'vpermilmo2ps',10b dw vpermil_2ps_instruction-instruction_handler db 'vpermilmz2pd',11b dw vpermil_2pd_instruction-instruction_handler db 'vpermilmz2ps',11b dw vpermil_2ps_instruction-instruction_handler db 'vpermiltd2pd',0 dw vpermil_2pd_instruction-instruction_handler db 'vpermiltd2ps',0 dw vpermil_2ps_instruction-instruction_handler db 'vpshufbitqmb',8Fh dw avx512_ptestmb_instruction-instruction_handler instructions_13: db 'gf2p8affineqb',0CEh dw sse4_instruction_66_3a_imm8-instruction_handler db 'vcmptrue_uspd',1Fh dw avx_cmp_pd_instruction-instruction_handler db 'vcmptrue_usps',1Fh dw avx_cmp_ps_instruction-instruction_handler db 'vcmptrue_ussd',1Fh dw avx_cmp_sd_instruction-instruction_handler db 'vcmptrue_usss',1Fh dw avx_cmp_ss_instruction-instruction_handler db 'vcmpunord_spd',13h dw avx_cmp_pd_instruction-instruction_handler db 'vcmpunord_sps',13h dw avx_cmp_ps_instruction-instruction_handler db 'vcmpunord_ssd',13h dw avx_cmp_sd_instruction-instruction_handler db 'vcmpunord_sss',13h dw avx_cmp_ss_instruction-instruction_handler db 'vextractf32x4',19h dw avx512_extract_32x4_instruction-instruction_handler db 'vextractf32x8',1Bh dw avx512_extract_32x8_instruction-instruction_handler db 'vextractf64x2',19h dw avx512_extract_64x2_instruction-instruction_handler db 'vextractf64x4',1Bh dw avx512_extract_64x4_instruction-instruction_handler db 'vextracti32x4',39h dw avx512_extract_32x4_instruction-instruction_handler db 'vextracti32x8',3Bh dw avx512_extract_32x8_instruction-instruction_handler db 'vextracti64x2',39h dw avx512_extract_64x2_instruction-instruction_handler db 'vextracti64x4',3Bh dw avx512_extract_64x4_instruction-instruction_handler db 'vgatherpf0dpd',1 dw gatherpf_dpd_instruction-instruction_handler db 'vgatherpf0dps',1 dw gatherpf_dps_instruction-instruction_handler db 'vgatherpf0qpd',1 dw gatherpf_qpd_instruction-instruction_handler db 'vgatherpf0qps',1 dw gatherpf_qps_instruction-instruction_handler db 'vgatherpf1dpd',2 dw gatherpf_dpd_instruction-instruction_handler db 'vgatherpf1dps',2 dw gatherpf_dps_instruction-instruction_handler db 'vgatherpf1qpd',2 dw gatherpf_qpd_instruction-instruction_handler db 'vgatherpf1qps',2 dw gatherpf_qps_instruction-instruction_handler db 'vpclmulhqlqdq',1 dw avx_pclmulqdq_instruction-instruction_handler db 'vpclmullqlqdq',0 dw avx_pclmulqdq_instruction-instruction_handler instructions_14: db 'vbroadcastf128',1Ah dw avx_broadcast_128_instruction_noevex-instruction_handler db 'vbroadcasti128',5Ah dw avx_broadcast_128_instruction_noevex-instruction_handler db 'vcmpfalse_ospd',1Bh dw avx_cmp_pd_instruction-instruction_handler db 'vcmpfalse_osps',1Bh dw avx_cmp_ps_instruction-instruction_handler db 'vcmpfalse_ossd',1Bh dw avx_cmp_sd_instruction-instruction_handler db 'vcmpfalse_osss',1Bh dw avx_cmp_ss_instruction-instruction_handler db 'vfmaddsub132pd',96h dw fma_instruction_pd-instruction_handler db 'vfmaddsub132ps',96h dw fma_instruction_ps-instruction_handler db 'vfmaddsub213pd',0A6h dw fma_instruction_pd-instruction_handler db 'vfmaddsub213ps',0A6h dw fma_instruction_ps-instruction_handler db 'vfmaddsub231pd',0B6h dw fma_instruction_pd-instruction_handler db 'vfmaddsub231ps',0B6h dw fma_instruction_ps-instruction_handler db 'vfmsubadd132pd',97h dw fma_instruction_pd-instruction_handler db 'vfmsubadd132ps',97h dw fma_instruction_ps-instruction_handler db 'vfmsubadd213pd',0A7h dw fma_instruction_pd-instruction_handler db 'vfmsubadd213ps',0A7h dw fma_instruction_ps-instruction_handler db 'vfmsubadd231pd',0B7h dw fma_instruction_pd-instruction_handler db 'vfmsubadd231ps',0B7h dw fma_instruction_ps-instruction_handler db 'vgf2p8affineqb',0CEh dw avx_q_instruction_3a_imm8_w1-instruction_handler db 'vpmultishiftqb',83h dw avx_q_instruction_38_evex-instruction_handler db 'vscatterpf0dpd',5 dw gatherpf_dpd_instruction-instruction_handler db 'vscatterpf0dps',5 dw gatherpf_dps_instruction-instruction_handler db 'vscatterpf0qpd',5 dw gatherpf_qpd_instruction-instruction_handler db 'vscatterpf0qps',5 dw gatherpf_qps_instruction-instruction_handler db 'vscatterpf1dpd',6 dw gatherpf_dpd_instruction-instruction_handler db 'vscatterpf1dps',6 dw gatherpf_dps_instruction-instruction_handler db 'vscatterpf1qpd',6 dw gatherpf_qpd_instruction-instruction_handler db 'vscatterpf1qps',6 dw gatherpf_qps_instruction-instruction_handler instructions_15: db 'aeskeygenassist',0DFh dw sse4_instruction_66_3a_imm8-instruction_handler db 'vbroadcastf32x2',19h dw avx512_broadcast_32x2_instruction-instruction_handler db 'vbroadcastf32x4',1Ah dw avx512_broadcast_32x4_instruction-instruction_handler db 'vbroadcastf32x8',1Bh dw avx512_broadcast_32x8_instruction-instruction_handler db 'vbroadcastf64x2',1Ah dw avx512_broadcast_64x2_instruction-instruction_handler db 'vbroadcastf64x4',1Bh dw avx512_broadcast_64x4_instruction-instruction_handler db 'vbroadcasti32x2',59h dw avx512_broadcast_32x2_instruction-instruction_handler db 'vbroadcasti32x4',5Ah dw avx512_broadcast_32x4_instruction-instruction_handler db 'vbroadcasti32x8',5Bh dw avx512_broadcast_32x8_instruction-instruction_handler db 'vbroadcasti64x2',5Ah dw avx512_broadcast_64x2_instruction-instruction_handler db 'vbroadcasti64x4',5Bh dw avx512_broadcast_64x4_instruction-instruction_handler db 'vpbroadcastmb2q',2Ah dw avx512_pmov_m2_instruction_w1-instruction_handler db 'vpbroadcastmw2d',3Ah dw avx512_pmov_m2_instruction-instruction_handler instructions_16: db 'gf2p8affineinvqb',0CFh dw sse4_instruction_66_3a_imm8-instruction_handler db 'vaeskeygenassist',0DFh dw avx_single_source_128bit_instruction_3a_imm8_noevex-instruction_handler instructions_17: db 'vgf2p8affineinvqb',0CFh dw avx_q_instruction_3a_imm8_w1-instruction_handler instructions_end: data_directives: dw data_directives_2-data_directives,(data_directives_3-data_directives_2)/(2+3) dw data_directives_3-data_directives,(data_directives_4-data_directives_3)/(3+3) dw data_directives_4-data_directives,(data_directives_end-data_directives_4)/(4+3) data_directives_2: db 'db',1 dw data_bytes-instruction_handler db 'dd',4 dw data_dwords-instruction_handler db 'df',6 dw data_pwords-instruction_handler db 'dp',6 dw data_pwords-instruction_handler db 'dq',8 dw data_qwords-instruction_handler db 'dt',10 dw data_twords-instruction_handler db 'du',2 dw data_unicode-instruction_handler db 'dw',2 dw data_words-instruction_handler db 'rb',1 dw reserve_bytes-instruction_handler db 'rd',4 dw reserve_dwords-instruction_handler db 'rf',6 dw reserve_pwords-instruction_handler db 'rp',6 dw reserve_pwords-instruction_handler db 'rq',8 dw reserve_qwords-instruction_handler db 'rt',10 dw reserve_twords-instruction_handler db 'rw',2 dw reserve_words-instruction_handler data_directives_3: data_directives_4: db 'file',1 dw data_file-instruction_handler data_directives_end: fasm/source/variable.inc0000644000175000017500000000540114533376740016066 0ustar privalovprivalov ; flat assembler core variables ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. ; Variables which have to be set up by interface: memory_start dd ? memory_end dd ? additional_memory dd ? additional_memory_end dd ? stack_limit dd ? initial_definitions dd ? input_file dd ? output_file dd ? symbols_file dd ? passes_limit dw ? ; Internal core variables: current_pass dw ? include_paths dd ? free_additional_memory dd ? source_start dd ? code_start dd ? code_size dd ? real_code_size dd ? written_size dd ? headers_size dd ? current_line dd ? macro_line dd ? macro_block dd ? macro_block_line dd ? macro_block_line_number dd ? macro_symbols dd ? struc_name dd ? struc_label dd ? instant_macro_start dd ? parameters_end dd ? default_argument_value dd ? locals_counter rb 8 current_locals_prefix dd ? anonymous_reverse dd ? anonymous_forward dd ? labels_list dd ? label_hash dd ? label_leaf dd ? hash_tree dd ? addressing_space dd ? undefined_data_start dd ? undefined_data_end dd ? counter dd ? counter_limit dd ? error_info dd ? error_line dd ? error dd ? tagged_blocks dd ? structures_buffer dd ? number_start dd ? current_offset dd ? value dq ? fp_value rd 8 adjustment dq ? symbol_identifier dd ? address_symbol dd ? address_high dd ? uncompressed_displacement dd ? format_flags dd ? resolver_flags dd ? symbols_stream dd ? number_of_relocations dd ? number_of_sections dd ? stub_size dd ? stub_file dd ? current_section dd ? machine dw ? subsystem dw ? subsystem_version dd ? image_base dd ? image_base_high dd ? merge_segment dd ? resource_data dd ? resource_size dd ? actual_fixups_size dd ? reserved_fixups dd ? reserved_fixups_size dd ? last_fixup_base dd ? last_fixup_header dd ? parenthesis_stack dd ? blocks_stack dd ? parsed_lines dd ? logical_value_parentheses dd ? file_extension dd ? operand_size db ? operand_flags db ? operand_prefix db ? rex_prefix db ? opcode_prefix db ? vex_required db ? vex_register db ? immediate_size db ? mask_register db ? broadcast_size db ? rounding_mode db ? base_code db ? extended_code db ? supplemental_code db ? postbyte_register db ? segment_register db ? xop_opcode_map db ? mmx_size db ? jump_type db ? push_size db ? value_size db ? address_size db ? label_size db ? size_declared db ? address_size_declared db ? displacement_compression db ? value_undefined db ? value_constant db ? value_type db ? value_sign db ? fp_sign db ? fp_format db ? address_sign db ? address_register db ? compare_type db ? logical_value_wrapping db ? next_pass_needed db ? output_format db ? code_type db ? adjustment_sign db ? evex_mode db ? macro_status db ? skip_default_argument_value db ? prefix_flags db ? formatter_symbols_allowed db ? decorator_symbols_allowed db ? free_address_range db ? characters rb 100h converted rb 100h message rb 180h fasm/source/version.inc0000644000175000017500000000342014533376740015765 0ustar privalovprivalov ; flat assembler version 1.73 ; Copyright (c) 1999-2023, Tomasz Grysztar. ; All rights reserved. ; ; This programs is free for commercial and non-commercial use as long as ; the following conditions are adhered to. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions are ; met: ; ; 1. Redistributions of source code must retain the above copyright notice, ; this list of conditions and the following disclaimer. ; 2. Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in the ; documentation and/or other materials provided with the distribution. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ; TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A ; PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR ; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; ; The licence and distribution terms for any publically available ; version or derivative of this code cannot be changed. i.e. this code ; cannot simply be copied and put under another distribution licence ; (including the GNU Public Licence). VERSION_STRING equ "1.73.32" VERSION_MAJOR = 1 VERSION_MINOR = 73 fasm/source/x86_64.inc0000644000175000017500000043412614533376740015251 0ustar privalovprivalov ; flat assembler core ; Copyright (c) 1999-2022, Tomasz Grysztar. ; All rights reserved. simple_instruction_except64: cmp [code_type],64 je illegal_instruction simple_instruction: stos byte [edi] jmp instruction_assembled simple_instruction_only64: cmp [code_type],64 jne illegal_instruction jmp simple_instruction simple_instruction_16bit_except64: cmp [code_type],64 je illegal_instruction simple_instruction_16bit: cmp [code_type],16 jne size_prefix stos byte [edi] jmp instruction_assembled size_prefix: mov ah,al mov al,66h stos word [edi] jmp instruction_assembled simple_instruction_32bit_except64: cmp [code_type],64 je illegal_instruction simple_instruction_32bit: cmp [code_type],16 je size_prefix stos byte [edi] jmp instruction_assembled iret_instruction: cmp [code_type],64 jne simple_instruction simple_instruction_64bit: cmp [code_type],64 jne illegal_instruction mov ah,al mov al,48h stos word [edi] jmp instruction_assembled simple_extended_instruction_64bit: cmp [code_type],64 jne illegal_instruction mov byte [edi],48h inc edi simple_extended_instruction: mov ah,al mov al,0Fh stos word [edi] jmp instruction_assembled simple_extended_instruction_f3: mov byte [edi],0F3h inc edi jmp simple_extended_instruction prefix_instruction: stos byte [edi] or [prefix_flags],1 jmp continue_line segment_prefix: mov ah,al shr ah,4 cmp ah,3 jne illegal_instruction and al,1111b mov [segment_register],al call store_segment_prefix or [prefix_flags],1 jmp continue_line bnd_prefix_instruction: stos byte [edi] or [prefix_flags],1 + 10h jmp continue_line int_instruction: lods byte [esi] call get_size_operator cmp ah,1 ja invalid_operand_size cmp al,'(' jne invalid_operand call get_byte_value test eax,eax jns int_imm_ok call recoverable_overflow int_imm_ok: mov ah,al mov al,0CDh stos word [edi] jmp instruction_assembled aa_instruction: cmp [code_type],64 je illegal_instruction push eax mov bl,10 cmp byte [esi],'(' jne aa_store inc esi xor al,al xchg al,[operand_size] cmp al,1 ja invalid_operand_size call get_byte_value mov bl,al aa_store: cmp [operand_size],0 jne invalid_operand pop eax mov ah,bl stos word [edi] jmp instruction_assembled basic_instruction: mov [base_code],al lods byte [esi] call get_size_operator cmp al,10h je basic_reg cmp al,'[' jne invalid_operand basic_mem: call get_address push edx ebx ecx lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'(' je basic_mem_imm cmp al,10h jne invalid_operand basic_mem_reg: lods byte [esi] call convert_register mov [postbyte_register],al pop ecx ebx edx mov al,ah cmp al,1 je instruction_ready call operand_autodetect inc [base_code] instruction_ready: call store_instruction jmp instruction_assembled basic_mem_imm: mov al,[operand_size] cmp al,1 jb basic_mem_imm_nosize je basic_mem_imm_8bit cmp al,2 je basic_mem_imm_16bit cmp al,4 je basic_mem_imm_32bit cmp al,8 jne invalid_operand_size basic_mem_imm_64bit: cmp [size_declared],0 jne long_immediate_not_encodable call operand_64bit call get_simm32 cmp [value_type],4 jae long_immediate_not_encodable jmp basic_mem_imm_32bit_ok basic_mem_imm_nosize: call recoverable_unknown_size basic_mem_imm_8bit: call get_byte_value mov byte [value],al mov al,[base_code] shr al,3 mov [postbyte_register],al pop ecx ebx edx mov [base_code],80h call store_instruction_with_imm8 jmp instruction_assembled basic_mem_imm_16bit: call operand_16bit call get_word_value mov word [value],ax mov al,[base_code] shr al,3 mov [postbyte_register],al pop ecx ebx edx cmp [value_type],0 jne basic_mem_imm_16bit_store cmp [size_declared],0 jne basic_mem_imm_16bit_store cmp word [value],80h jb basic_mem_simm_8bit cmp word [value],-80h jae basic_mem_simm_8bit basic_mem_imm_16bit_store: mov [base_code],81h call store_instruction_with_imm16 jmp instruction_assembled basic_mem_simm_8bit: mov [base_code],83h call store_instruction_with_imm8 jmp instruction_assembled basic_mem_imm_32bit: call operand_32bit call get_dword_value basic_mem_imm_32bit_ok: mov dword [value],eax mov al,[base_code] shr al,3 mov [postbyte_register],al pop ecx ebx edx cmp [value_type],0 jne basic_mem_imm_32bit_store cmp [size_declared],0 jne basic_mem_imm_32bit_store cmp dword [value],80h jb basic_mem_simm_8bit cmp dword [value],-80h jae basic_mem_simm_8bit basic_mem_imm_32bit_store: mov [base_code],81h call store_instruction_with_imm32 jmp instruction_assembled get_simm32: call get_qword_value mov ecx,edx cdq cmp ecx,edx je simm32_range_ok call recoverable_overflow simm32_range_ok: cmp [value_type],4 jne get_simm32_ok mov [value_type],2 get_simm32_ok: ret basic_reg: lods byte [esi] call convert_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je basic_reg_reg cmp al,'(' je basic_reg_imm cmp al,'[' jne invalid_operand basic_reg_mem: call get_address mov al,[operand_size] cmp al,1 je basic_reg_mem_8bit call operand_autodetect add [base_code],3 jmp instruction_ready basic_reg_mem_8bit: add [base_code],2 jmp instruction_ready basic_reg_reg: lods byte [esi] call convert_register mov bl,[postbyte_register] mov [postbyte_register],al mov al,ah cmp al,1 je nomem_instruction_ready call operand_autodetect inc [base_code] nomem_instruction_ready: call store_nomem_instruction jmp instruction_assembled basic_reg_imm: mov al,[operand_size] cmp al,1 je basic_reg_imm_8bit cmp al,2 je basic_reg_imm_16bit cmp al,4 je basic_reg_imm_32bit cmp al,8 jne invalid_operand_size basic_reg_imm_64bit: cmp [size_declared],0 jne long_immediate_not_encodable call operand_64bit call get_simm32 cmp [value_type],4 jae long_immediate_not_encodable jmp basic_reg_imm_32bit_ok basic_reg_imm_8bit: call get_byte_value mov dl,al mov bl,[base_code] shr bl,3 xchg bl,[postbyte_register] or bl,bl jz basic_al_imm mov [base_code],80h call store_nomem_instruction mov al,dl stos byte [edi] jmp instruction_assembled basic_al_imm: mov al,[base_code] add al,4 stos byte [edi] mov al,dl stos byte [edi] jmp instruction_assembled basic_reg_imm_16bit: call operand_16bit call get_word_value mov dx,ax mov bl,[base_code] shr bl,3 xchg bl,[postbyte_register] cmp [value_type],0 jne basic_reg_imm_16bit_store cmp [size_declared],0 jne basic_reg_imm_16bit_store cmp dx,80h jb basic_reg_simm_8bit cmp dx,-80h jae basic_reg_simm_8bit basic_reg_imm_16bit_store: or bl,bl jz basic_ax_imm mov [base_code],81h call store_nomem_instruction basic_store_imm_16bit: mov ax,dx call mark_relocation stos word [edi] jmp instruction_assembled basic_reg_simm_8bit: mov [base_code],83h call store_nomem_instruction mov al,dl stos byte [edi] jmp instruction_assembled basic_ax_imm: add [base_code],5 call store_classic_instruction_code jmp basic_store_imm_16bit basic_reg_imm_32bit: call operand_32bit call get_dword_value basic_reg_imm_32bit_ok: mov edx,eax mov bl,[base_code] shr bl,3 xchg bl,[postbyte_register] cmp [value_type],0 jne basic_reg_imm_32bit_store cmp [size_declared],0 jne basic_reg_imm_32bit_store cmp edx,80h jb basic_reg_simm_8bit cmp edx,-80h jae basic_reg_simm_8bit basic_reg_imm_32bit_store: or bl,bl jz basic_eax_imm mov [base_code],81h call store_nomem_instruction basic_store_imm_32bit: mov eax,edx call mark_relocation stos dword [edi] jmp instruction_assembled basic_eax_imm: add [base_code],5 call store_classic_instruction_code jmp basic_store_imm_32bit recoverable_unknown_size: cmp [error_line],0 jne ignore_unknown_size push [current_line] pop [error_line] mov [error],operand_size_not_specified ignore_unknown_size: ret single_operand_instruction: mov [base_code],0F6h mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,10h je single_reg cmp al,'[' jne invalid_operand single_mem: call get_address mov al,[operand_size] cmp al,1 je single_mem_8bit jb single_mem_nosize call operand_autodetect inc [base_code] jmp instruction_ready single_mem_nosize: call recoverable_unknown_size single_mem_8bit: jmp instruction_ready single_reg: lods byte [esi] call convert_register mov bl,al mov al,ah cmp al,1 je single_reg_8bit call operand_autodetect inc [base_code] single_reg_8bit: jmp nomem_instruction_ready mov_instruction: mov [base_code],88h lods byte [esi] call get_size_operator cmp al,10h je mov_reg cmp al,14h je mov_creg cmp al,'[' jne invalid_operand mov_mem: call get_address push edx ebx ecx lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'(' je mov_mem_imm cmp al,10h jne invalid_operand mov_mem_reg: lods byte [esi] cmp al,30h jb mov_mem_general_reg cmp al,40h jb mov_mem_sreg mov_mem_general_reg: call convert_register mov [postbyte_register],al pop ecx ebx edx cmp ah,1 je mov_mem_reg_8bit inc [base_code] mov al,ah call operand_autodetect mov al,[postbyte_register] or al,bl or al,bh jz mov_mem_ax jmp instruction_ready mov_mem_reg_8bit: or al,bl or al,bh jnz instruction_ready mov_mem_al: test ch,22h jnz mov_mem_address16_al test ch,44h jnz mov_mem_address32_al test ch,not 88h jnz invalid_address_size call check_mov_address64 cmp al,0 jg mov_mem_address64_al jl instruction_ready cmp [code_type],16 jne mov_mem_address32_al cmp edx,10000h jb mov_mem_address16_al mov_mem_address32_al: call store_segment_prefix_if_necessary call address_32bit_prefix mov [base_code],0A2h store_mov_address32: call store_classic_instruction_code call store_address_32bit_value jmp instruction_assembled mov_mem_address16_al: call store_segment_prefix_if_necessary call address_16bit_prefix mov [base_code],0A2h store_mov_address16: cmp [code_type],64 je invalid_address call store_classic_instruction_code mov eax,edx stos word [edi] cmp edx,10000h jge value_out_of_range jmp instruction_assembled check_mov_address64: cmp [code_type],64 jne no_address64 test ch,88h jnz address64_required mov eax,[address_high] or eax,eax jz no_address64 bt edx,31 adc eax,0 jz address64_simm32 address64_required: mov al,1 ret address64_simm32: mov al,-1 ret no_address64: test ch,08h jnz invalid_address_size xor al,al ret mov_mem_address64_al: call store_segment_prefix_if_necessary mov [base_code],0A2h store_mov_address64: call store_classic_instruction_code call store_address_64bit_value jmp instruction_assembled mov_mem_ax: test ch,22h jnz mov_mem_address16_ax test ch,44h jnz mov_mem_address32_ax test ch,not 88h jnz invalid_address_size call check_mov_address64 cmp al,0 jg mov_mem_address64_ax jl instruction_ready cmp [code_type],16 jne mov_mem_address32_ax cmp edx,10000h jb mov_mem_address16_ax mov_mem_address32_ax: call store_segment_prefix_if_necessary call address_32bit_prefix mov [base_code],0A3h jmp store_mov_address32 mov_mem_address16_ax: call store_segment_prefix_if_necessary call address_16bit_prefix mov [base_code],0A3h jmp store_mov_address16 mov_mem_address64_ax: call store_segment_prefix_if_necessary mov [base_code],0A3h jmp store_mov_address64 mov_mem_sreg: sub al,31h mov [postbyte_register],al pop ecx ebx edx mov ah,[operand_size] or ah,ah jz mov_mem_sreg_store cmp ah,2 jne invalid_operand_size mov_mem_sreg_store: mov [base_code],8Ch jmp instruction_ready mov_mem_imm: mov al,[operand_size] cmp al,1 jb mov_mem_imm_nosize je mov_mem_imm_8bit cmp al,2 je mov_mem_imm_16bit cmp al,4 je mov_mem_imm_32bit cmp al,8 jne invalid_operand_size mov_mem_imm_64bit: cmp [size_declared],0 jne long_immediate_not_encodable call operand_64bit call get_simm32 cmp [value_type],4 jae long_immediate_not_encodable jmp mov_mem_imm_32bit_store mov_mem_imm_nosize: call recoverable_unknown_size mov_mem_imm_8bit: call get_byte_value mov byte [value],al mov [postbyte_register],0 mov [base_code],0C6h pop ecx ebx edx call store_instruction_with_imm8 jmp instruction_assembled mov_mem_imm_16bit: call operand_16bit call get_word_value mov word [value],ax mov [postbyte_register],0 mov [base_code],0C7h pop ecx ebx edx call store_instruction_with_imm16 jmp instruction_assembled mov_mem_imm_32bit: call operand_32bit call get_dword_value mov_mem_imm_32bit_store: mov dword [value],eax mov [postbyte_register],0 mov [base_code],0C7h pop ecx ebx edx call store_instruction_with_imm32 jmp instruction_assembled mov_reg: lods byte [esi] mov ah,al sub ah,10h and ah,al test ah,0F0h jnz mov_sreg call convert_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' je mov_reg_mem cmp al,'(' je mov_reg_imm cmp al,14h je mov_reg_creg cmp al,10h jne invalid_operand mov_reg_reg: lods byte [esi] mov ah,al sub ah,10h and ah,al test ah,0F0h jnz mov_reg_sreg call convert_register mov bl,[postbyte_register] mov [postbyte_register],al mov al,ah cmp al,1 je mov_reg_reg_8bit call operand_autodetect inc [base_code] mov_reg_reg_8bit: jmp nomem_instruction_ready mov_reg_sreg: mov bl,[postbyte_register] mov ah,al and al,1111b mov [postbyte_register],al shr ah,4 cmp ah,3 jne invalid_operand dec [postbyte_register] cmp [operand_size],8 je mov_reg_sreg64 cmp [operand_size],4 je mov_reg_sreg32 cmp [operand_size],2 jne invalid_operand_size call operand_16bit jmp mov_reg_sreg_store mov_reg_sreg64: call operand_64bit jmp mov_reg_sreg_store mov_reg_sreg32: call operand_32bit mov_reg_sreg_store: mov [base_code],8Ch jmp nomem_instruction_ready mov_reg_creg: lods byte [esi] mov bl,al shr al,4 cmp al,4 ja invalid_operand add al,20h mov [extended_code],al and bl,1111b xchg bl,[postbyte_register] mov [base_code],0Fh cmp [code_type],64 je mov_reg_creg_64bit cmp [operand_size],4 jne invalid_operand_size cmp [postbyte_register],8 jne mov_reg_creg_store cmp [extended_code],20h jne mov_reg_creg_store mov al,0F0h stos byte [edi] mov [postbyte_register],0 mov_reg_creg_store: jmp nomem_instruction_ready mov_reg_creg_64bit: cmp [operand_size],8 jne invalid_operand_size jmp nomem_instruction_ready mov_reg_mem: add [base_code],2 call get_address mov al,[operand_size] cmp al,1 je mov_reg_mem_8bit inc [base_code] call operand_autodetect mov al,[postbyte_register] or al,bl or al,bh jz mov_ax_mem jmp instruction_ready mov_reg_mem_8bit: mov al,[postbyte_register] or al,bl or al,bh jz mov_al_mem jmp instruction_ready mov_al_mem: test ch,22h jnz mov_al_mem_address16 test ch,44h jnz mov_al_mem_address32 test ch,not 88h jnz invalid_address_size call check_mov_address64 cmp al,0 jg mov_al_mem_address64 jl instruction_ready cmp [code_type],16 jne mov_al_mem_address32 cmp edx,10000h jb mov_al_mem_address16 mov_al_mem_address32: call store_segment_prefix_if_necessary call address_32bit_prefix mov [base_code],0A0h jmp store_mov_address32 mov_al_mem_address16: call store_segment_prefix_if_necessary call address_16bit_prefix mov [base_code],0A0h jmp store_mov_address16 mov_al_mem_address64: call store_segment_prefix_if_necessary mov [base_code],0A0h jmp store_mov_address64 mov_ax_mem: test ch,22h jnz mov_ax_mem_address16 test ch,44h jnz mov_ax_mem_address32 test ch,not 88h jnz invalid_address_size call check_mov_address64 cmp al,0 jg mov_ax_mem_address64 jl instruction_ready cmp [code_type],16 jne mov_ax_mem_address32 cmp edx,10000h jb mov_ax_mem_address16 mov_ax_mem_address32: call store_segment_prefix_if_necessary call address_32bit_prefix mov [base_code],0A1h jmp store_mov_address32 mov_ax_mem_address16: call store_segment_prefix_if_necessary call address_16bit_prefix mov [base_code],0A1h jmp store_mov_address16 mov_ax_mem_address64: call store_segment_prefix_if_necessary mov [base_code],0A1h jmp store_mov_address64 mov_reg_imm: mov al,[operand_size] cmp al,1 je mov_reg_imm_8bit cmp al,2 je mov_reg_imm_16bit cmp al,4 je mov_reg_imm_32bit cmp al,8 jne invalid_operand_size mov_reg_imm_64bit: call operand_64bit call get_qword_value mov ecx,edx cmp [size_declared],0 jne mov_reg_imm_64bit_store cmp [value_type],4 jae mov_reg_imm_64bit_store cdq cmp ecx,edx je mov_reg_64bit_imm_32bit mov_reg_imm_64bit_store: push eax ecx mov al,0B8h call store_mov_reg_imm_code pop edx eax call mark_relocation stos dword [edi] mov eax,edx stos dword [edi] jmp instruction_assembled mov_reg_imm_8bit: call get_byte_value mov dl,al mov al,0B0h call store_mov_reg_imm_code mov al,dl stos byte [edi] jmp instruction_assembled mov_reg_imm_16bit: call get_word_value mov dx,ax call operand_16bit mov al,0B8h call store_mov_reg_imm_code mov ax,dx call mark_relocation stos word [edi] jmp instruction_assembled mov_reg_imm_32bit: call operand_32bit call get_dword_value mov edx,eax mov al,0B8h call store_mov_reg_imm_code mov_store_imm_32bit: mov eax,edx call mark_relocation stos dword [edi] jmp instruction_assembled store_mov_reg_imm_code: mov ah,[postbyte_register] test ah,1000b jz mov_reg_imm_prefix_ok or [rex_prefix],41h mov_reg_imm_prefix_ok: and ah,111b add al,ah mov [base_code],al call store_classic_instruction_code ret mov_reg_64bit_imm_32bit: mov edx,eax mov bl,[postbyte_register] mov [postbyte_register],0 mov [base_code],0C7h call store_nomem_instruction jmp mov_store_imm_32bit mov_sreg: mov ah,al and al,1111b mov [postbyte_register],al shr ah,4 cmp ah,3 jne invalid_operand cmp al,2 je illegal_instruction dec [postbyte_register] lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' je mov_sreg_mem cmp al,10h jne invalid_operand mov_sreg_reg: lods byte [esi] call convert_register or ah,ah jz mov_sreg_reg_size_ok cmp ah,2 jne invalid_operand_size mov bl,al mov_sreg_reg_size_ok: mov [base_code],8Eh jmp nomem_instruction_ready mov_sreg_mem: call get_address mov al,[operand_size] or al,al jz mov_sreg_mem_size_ok cmp al,2 jne invalid_operand_size mov_sreg_mem_size_ok: mov [base_code],8Eh jmp instruction_ready mov_creg: lods byte [esi] mov ah,al shr ah,4 cmp ah,4 ja invalid_operand add ah,22h mov [extended_code],ah and al,1111b mov [postbyte_register],al mov [base_code],0Fh lods byte [esi] cmp al,',' jne invalid_operand call take_register mov bl,al cmp [code_type],64 je mov_creg_64bit cmp ah,4 jne invalid_operand_size cmp [postbyte_register],8 jne mov_creg_store cmp [extended_code],22h jne mov_creg_store mov al,0F0h stos byte [edi] mov [postbyte_register],0 mov_creg_store: jmp nomem_instruction_ready mov_creg_64bit: cmp ah,8 je mov_creg_store jmp invalid_operand_size test_instruction: mov [base_code],84h lods byte [esi] call get_size_operator cmp al,10h je test_reg cmp al,'[' jne invalid_operand test_mem: call get_address push edx ebx ecx lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'(' je test_mem_imm cmp al,10h jne invalid_operand test_mem_reg: lods byte [esi] call convert_register mov [postbyte_register],al pop ecx ebx edx mov al,ah cmp al,1 je test_mem_reg_8bit call operand_autodetect inc [base_code] test_mem_reg_8bit: jmp instruction_ready test_mem_imm: mov al,[operand_size] cmp al,1 jb test_mem_imm_nosize je test_mem_imm_8bit cmp al,2 je test_mem_imm_16bit cmp al,4 je test_mem_imm_32bit cmp al,8 jne invalid_operand_size test_mem_imm_64bit: cmp [size_declared],0 jne long_immediate_not_encodable call operand_64bit call get_simm32 cmp [value_type],4 jae long_immediate_not_encodable jmp test_mem_imm_32bit_store test_mem_imm_nosize: call recoverable_unknown_size test_mem_imm_8bit: call get_byte_value mov byte [value],al mov [postbyte_register],0 mov [base_code],0F6h pop ecx ebx edx call store_instruction_with_imm8 jmp instruction_assembled test_mem_imm_16bit: call operand_16bit call get_word_value mov word [value],ax mov [postbyte_register],0 mov [base_code],0F7h pop ecx ebx edx call store_instruction_with_imm16 jmp instruction_assembled test_mem_imm_32bit: call operand_32bit call get_dword_value test_mem_imm_32bit_store: mov dword [value],eax mov [postbyte_register],0 mov [base_code],0F7h pop ecx ebx edx call store_instruction_with_imm32 jmp instruction_assembled test_reg: lods byte [esi] call convert_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' je test_reg_mem cmp al,'(' je test_reg_imm cmp al,10h jne invalid_operand test_reg_reg: lods byte [esi] call convert_register mov bl,[postbyte_register] mov [postbyte_register],al mov al,ah cmp al,1 je test_reg_reg_8bit call operand_autodetect inc [base_code] test_reg_reg_8bit: jmp nomem_instruction_ready test_reg_imm: mov al,[operand_size] cmp al,1 je test_reg_imm_8bit cmp al,2 je test_reg_imm_16bit cmp al,4 je test_reg_imm_32bit cmp al,8 jne invalid_operand_size test_reg_imm_64bit: cmp [size_declared],0 jne long_immediate_not_encodable call operand_64bit call get_simm32 cmp [value_type],4 jae long_immediate_not_encodable jmp test_reg_imm_32bit_store test_reg_imm_8bit: call get_byte_value mov dl,al mov bl,[postbyte_register] mov [postbyte_register],0 mov [base_code],0F6h or bl,bl jz test_al_imm call store_nomem_instruction mov al,dl stos byte [edi] jmp instruction_assembled test_al_imm: mov [base_code],0A8h call store_classic_instruction_code mov al,dl stos byte [edi] jmp instruction_assembled test_reg_imm_16bit: call operand_16bit call get_word_value mov dx,ax mov bl,[postbyte_register] mov [postbyte_register],0 mov [base_code],0F7h or bl,bl jz test_ax_imm call store_nomem_instruction mov ax,dx call mark_relocation stos word [edi] jmp instruction_assembled test_ax_imm: mov [base_code],0A9h call store_classic_instruction_code mov ax,dx stos word [edi] jmp instruction_assembled test_reg_imm_32bit: call operand_32bit call get_dword_value test_reg_imm_32bit_store: mov edx,eax mov bl,[postbyte_register] mov [postbyte_register],0 mov [base_code],0F7h or bl,bl jz test_eax_imm call store_nomem_instruction mov eax,edx call mark_relocation stos dword [edi] jmp instruction_assembled test_eax_imm: mov [base_code],0A9h call store_classic_instruction_code mov eax,edx stos dword [edi] jmp instruction_assembled test_reg_mem: call get_address mov al,[operand_size] cmp al,1 je test_reg_mem_8bit call operand_autodetect inc [base_code] test_reg_mem_8bit: jmp instruction_ready xchg_instruction: mov [base_code],86h lods byte [esi] call get_size_operator cmp al,10h je xchg_reg cmp al,'[' jne invalid_operand xchg_mem: call get_address push edx ebx ecx lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je test_mem_reg jmp invalid_operand xchg_reg: lods byte [esi] call convert_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' je test_reg_mem cmp al,10h jne invalid_operand xchg_reg_reg: lods byte [esi] call convert_register mov bl,al mov al,ah cmp al,1 je xchg_reg_reg_8bit call operand_autodetect cmp [postbyte_register],0 je xchg_ax_reg or bl,bl jnz xchg_reg_reg_store mov bl,[postbyte_register] xchg_ax_reg: cmp [code_type],64 jne xchg_ax_reg_ok cmp ah,4 jne xchg_ax_reg_ok or bl,bl jz xchg_reg_reg_store xchg_ax_reg_ok: test bl,1000b jz xchg_ax_reg_store or [rex_prefix],41h and bl,111b xchg_ax_reg_store: add bl,90h mov [base_code],bl call store_classic_instruction_code jmp instruction_assembled xchg_reg_reg_store: inc [base_code] xchg_reg_reg_8bit: jmp nomem_instruction_ready push_instruction: mov [push_size],al push_next: lods byte [esi] call get_size_operator cmp al,10h je push_reg cmp al,'(' je push_imm cmp al,'[' jne invalid_operand push_mem: call get_address mov al,[operand_size] mov ah,[push_size] cmp al,2 je push_mem_16bit cmp al,4 je push_mem_32bit cmp al,8 je push_mem_64bit or al,al jnz invalid_operand_size cmp ah,2 je push_mem_16bit cmp ah,4 je push_mem_32bit cmp ah,8 je push_mem_64bit call recoverable_unknown_size jmp push_mem_store push_mem_16bit: test ah,not 2 jnz invalid_operand_size call operand_16bit jmp push_mem_store push_mem_32bit: test ah,not 4 jnz invalid_operand_size cmp [code_type],64 je illegal_instruction call operand_32bit jmp push_mem_store push_mem_64bit: test ah,not 8 jnz invalid_operand_size cmp [code_type],64 jne illegal_instruction push_mem_store: mov [base_code],0FFh mov [postbyte_register],110b call store_instruction jmp push_done push_reg: lods byte [esi] mov ah,al sub ah,10h and ah,al test ah,0F0h jnz push_sreg call convert_register test al,1000b jz push_reg_ok or [rex_prefix],41h and al,111b push_reg_ok: add al,50h mov [base_code],al mov al,ah mov ah,[push_size] cmp al,2 je push_reg_16bit cmp al,4 je push_reg_32bit cmp al,8 jne invalid_operand_size push_reg_64bit: test ah,not 8 jnz invalid_operand_size cmp [code_type],64 jne illegal_instruction jmp push_reg_store push_reg_32bit: test ah,not 4 jnz invalid_operand_size cmp [code_type],64 je illegal_instruction call operand_32bit jmp push_reg_store push_reg_16bit: test ah,not 2 jnz invalid_operand_size call operand_16bit push_reg_store: call store_classic_instruction_code jmp push_done push_sreg: mov bl,al mov dl,[operand_size] mov dh,[push_size] cmp dl,2 je push_sreg16 cmp dl,4 je push_sreg32 cmp dl,8 je push_sreg64 or dl,dl jnz invalid_operand_size cmp dh,2 je push_sreg16 cmp dh,4 je push_sreg32 cmp dh,8 je push_sreg64 jmp push_sreg_store push_sreg16: test dh,not 2 jnz invalid_operand_size call operand_16bit jmp push_sreg_store push_sreg32: test dh,not 4 jnz invalid_operand_size cmp [code_type],64 je illegal_instruction call operand_32bit jmp push_sreg_store push_sreg64: test dh,not 8 jnz invalid_operand_size cmp [code_type],64 jne illegal_instruction push_sreg_store: mov al,bl cmp al,40h jae invalid_operand sub al,31h jc invalid_operand cmp al,4 jae push_sreg_386 shl al,3 add al,6 mov [base_code],al cmp [code_type],64 je illegal_instruction jmp push_reg_store push_sreg_386: sub al,4 shl al,3 add al,0A0h mov [extended_code],al mov [base_code],0Fh jmp push_reg_store push_imm: mov al,[operand_size] mov ah,[push_size] or al,al je push_imm_size_ok or ah,ah je push_imm_size_ok cmp al,ah jne invalid_operand_size push_imm_size_ok: cmp al,2 je push_imm_16bit cmp al,4 je push_imm_32bit cmp al,8 je push_imm_64bit cmp ah,2 je push_imm_optimized_16bit cmp ah,4 je push_imm_optimized_32bit cmp ah,8 je push_imm_optimized_64bit or al,al jnz invalid_operand_size cmp [code_type],16 je push_imm_optimized_16bit cmp [code_type],32 je push_imm_optimized_32bit push_imm_optimized_64bit: cmp [code_type],64 jne illegal_instruction call get_simm32 mov edx,eax cmp [value_type],0 jne push_imm_32bit_store cmp eax,-80h jl push_imm_32bit_store cmp eax,80h jge push_imm_32bit_store jmp push_imm_8bit push_imm_optimized_32bit: cmp [code_type],64 je illegal_instruction call get_dword_value mov edx,eax call operand_32bit cmp [value_type],0 jne push_imm_32bit_store cmp eax,-80h jl push_imm_32bit_store cmp eax,80h jge push_imm_32bit_store jmp push_imm_8bit push_imm_optimized_16bit: call get_word_value mov dx,ax call operand_16bit cmp [value_type],0 jne push_imm_16bit_store cmp ax,-80h jl push_imm_16bit_store cmp ax,80h jge push_imm_16bit_store push_imm_8bit: mov ah,al mov [base_code],6Ah call store_classic_instruction_code mov al,ah stos byte [edi] jmp push_done push_imm_16bit: call get_word_value mov dx,ax call operand_16bit push_imm_16bit_store: mov [base_code],68h call store_classic_instruction_code mov ax,dx call mark_relocation stos word [edi] jmp push_done push_imm_64bit: cmp [code_type],64 jne illegal_instruction call get_simm32 mov edx,eax jmp push_imm_32bit_store push_imm_32bit: cmp [code_type],64 je illegal_instruction call get_dword_value mov edx,eax call operand_32bit push_imm_32bit_store: mov [base_code],68h call store_classic_instruction_code mov eax,edx call mark_relocation stos dword [edi] push_done: lods byte [esi] dec esi cmp al,0Fh je instruction_assembled or al,al jz instruction_assembled ; mov [operand_size],0 ; mov [operand_flags],0 ; mov [operand_prefix],0 ; mov [rex_prefix],0 and dword [operand_size],0 jmp push_next pop_instruction: mov [push_size],al pop_next: lods byte [esi] call get_size_operator cmp al,10h je pop_reg cmp al,'[' jne invalid_operand pop_mem: call get_address mov al,[operand_size] mov ah,[push_size] cmp al,2 je pop_mem_16bit cmp al,4 je pop_mem_32bit cmp al,8 je pop_mem_64bit or al,al jnz invalid_operand_size cmp ah,2 je pop_mem_16bit cmp ah,4 je pop_mem_32bit cmp ah,8 je pop_mem_64bit call recoverable_unknown_size jmp pop_mem_store pop_mem_16bit: test ah,not 2 jnz invalid_operand_size call operand_16bit jmp pop_mem_store pop_mem_32bit: test ah,not 4 jnz invalid_operand_size cmp [code_type],64 je illegal_instruction call operand_32bit jmp pop_mem_store pop_mem_64bit: test ah,not 8 jnz invalid_operand_size cmp [code_type],64 jne illegal_instruction pop_mem_store: mov [base_code],08Fh mov [postbyte_register],0 call store_instruction jmp pop_done pop_reg: lods byte [esi] mov ah,al sub ah,10h and ah,al test ah,0F0h jnz pop_sreg call convert_register test al,1000b jz pop_reg_ok or [rex_prefix],41h and al,111b pop_reg_ok: add al,58h mov [base_code],al mov al,ah mov ah,[push_size] cmp al,2 je pop_reg_16bit cmp al,4 je pop_reg_32bit cmp al,8 je pop_reg_64bit jmp invalid_operand_size pop_reg_64bit: test ah,not 8 jnz invalid_operand_size cmp [code_type],64 jne illegal_instruction jmp pop_reg_store pop_reg_32bit: test ah,not 4 jnz invalid_operand_size cmp [code_type],64 je illegal_instruction call operand_32bit jmp pop_reg_store pop_reg_16bit: test ah,not 2 jnz invalid_operand_size call operand_16bit pop_reg_store: call store_classic_instruction_code pop_done: lods byte [esi] dec esi cmp al,0Fh je instruction_assembled or al,al jz instruction_assembled ; mov [operand_size],0 ; mov [operand_flags],0 ; mov [operand_prefix],0 ; mov [rex_prefix],0 and dword [operand_size],0 jmp pop_next pop_sreg: mov dl,[operand_size] mov dh,[push_size] cmp al,32h je pop_cs mov bl,al cmp dl,2 je pop_sreg16 cmp dl,4 je pop_sreg32 cmp dl,8 je pop_sreg64 or dl,dl jnz invalid_operand_size cmp dh,2 je pop_sreg16 cmp dh,4 je pop_sreg32 cmp dh,8 je pop_sreg64 jmp pop_sreg_store pop_sreg16: test dh,not 2 jnz invalid_operand_size call operand_16bit jmp pop_sreg_store pop_sreg32: test dh,not 4 jnz invalid_operand_size cmp [code_type],64 je illegal_instruction call operand_32bit jmp pop_sreg_store pop_sreg64: test dh,not 8 jnz invalid_operand_size cmp [code_type],64 jne illegal_instruction pop_sreg_store: mov al,bl cmp al,40h jae invalid_operand sub al,31h jc invalid_operand cmp al,4 jae pop_sreg_386 shl al,3 add al,7 mov [base_code],al cmp [code_type],64 je illegal_instruction jmp pop_reg_store pop_cs: cmp [code_type],16 jne illegal_instruction cmp dl,2 je pop_cs_store or dl,dl jnz invalid_operand_size cmp dh,2 je pop_cs_store or dh,dh jnz illegal_instruction pop_cs_store: test dh,not 2 jnz invalid_operand_size mov al,0Fh stos byte [edi] jmp pop_done pop_sreg_386: sub al,4 shl al,3 add al,0A1h mov [extended_code],al mov [base_code],0Fh jmp pop_reg_store inc_instruction: mov [base_code],al lods byte [esi] call get_size_operator cmp al,10h je inc_reg cmp al,'[' je inc_mem jne invalid_operand inc_mem: call get_address mov al,[operand_size] cmp al,1 je inc_mem_8bit jb inc_mem_nosize call operand_autodetect mov al,0FFh xchg al,[base_code] mov [postbyte_register],al jmp instruction_ready inc_mem_nosize: call recoverable_unknown_size inc_mem_8bit: mov al,0FEh xchg al,[base_code] mov [postbyte_register],al jmp instruction_ready inc_reg: lods byte [esi] call convert_register mov bl,al mov al,0FEh xchg al,[base_code] mov [postbyte_register],al mov al,ah cmp al,1 je inc_reg_8bit call operand_autodetect cmp [code_type],64 je inc_reg_long_form mov al,[postbyte_register] shl al,3 add al,bl add al,40h mov [base_code],al call store_classic_instruction_code jmp instruction_assembled inc_reg_long_form: inc [base_code] inc_reg_8bit: jmp nomem_instruction_ready set_instruction: mov [base_code],0Fh mov [extended_code],al lods byte [esi] call get_size_operator cmp al,10h je set_reg cmp al,'[' jne invalid_operand set_mem: call get_address cmp [operand_size],1 ja invalid_operand_size mov [postbyte_register],0 jmp instruction_ready set_reg: lods byte [esi] call convert_register cmp ah,1 jne invalid_operand_size mov bl,al mov [postbyte_register],0 jmp nomem_instruction_ready arpl_instruction: cmp [code_type],64 je illegal_instruction mov [base_code],63h lods byte [esi] call get_size_operator cmp al,10h je arpl_reg cmp al,'[' jne invalid_operand call get_address lods byte [esi] cmp al,',' jne invalid_operand call take_register mov [postbyte_register],al cmp ah,2 jne invalid_operand_size jmp instruction_ready arpl_reg: lods byte [esi] call convert_register cmp ah,2 jne invalid_operand_size mov bl,al lods byte [esi] cmp al,',' jne invalid_operand call take_register mov [postbyte_register],al jmp nomem_instruction_ready bound_instruction: cmp [code_type],64 je illegal_instruction call take_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] cmp al,2 je bound_store cmp al,4 jne invalid_operand_size bound_store: call operand_autodetect mov [base_code],62h jmp instruction_ready enter_instruction: lods byte [esi] call get_size_operator cmp ah,2 je enter_imm16_size_ok or ah,ah jnz invalid_operand_size enter_imm16_size_ok: cmp al,'(' jne invalid_operand call get_word_value cmp [next_pass_needed],0 jne enter_imm16_ok cmp [value_type],0 jne invalid_use_of_symbol test eax,eax js value_out_of_range enter_imm16_ok: push eax mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp ah,1 je enter_imm8_size_ok or ah,ah jnz invalid_operand_size enter_imm8_size_ok: cmp al,'(' jne invalid_operand call get_byte_value cmp [next_pass_needed],0 jne enter_imm8_ok test eax,eax js value_out_of_range enter_imm8_ok: mov dl,al pop ebx mov al,0C8h stos byte [edi] mov ax,bx stos word [edi] mov al,dl stos byte [edi] jmp instruction_assembled ret_instruction_only64: cmp [code_type],64 jne illegal_instruction jmp ret_instruction ret_instruction_32bit_except64: cmp [code_type],64 je illegal_instruction ret_instruction_32bit: call operand_32bit jmp ret_instruction ret_instruction_16bit: call operand_16bit jmp ret_instruction ret_instruction_64bit: call operand_64bit ret_instruction: and [prefix_flags],not 10h ret_common: mov [base_code],al lods byte [esi] dec esi or al,al jz simple_ret cmp al,0Fh je simple_ret lods byte [esi] call get_size_operator or ah,ah jz ret_imm cmp ah,2 je ret_imm jmp invalid_operand_size ret_imm: cmp al,'(' jne invalid_operand call get_word_value cmp [next_pass_needed],0 jne ret_imm_ok cmp [value_type],0 jne invalid_use_of_symbol test eax,eax js value_out_of_range ret_imm_ok: cmp [size_declared],0 jne ret_imm_store or ax,ax jz simple_ret ret_imm_store: mov dx,ax call store_classic_instruction_code mov ax,dx stos word [edi] jmp instruction_assembled simple_ret: inc [base_code] call store_classic_instruction_code jmp instruction_assembled retf_instruction: cmp [code_type],64 jne ret_common retf_instruction_64bit: call operand_64bit jmp ret_common retf_instruction_32bit: call operand_32bit jmp ret_common retf_instruction_16bit: call operand_16bit jmp ret_common lea_instruction: mov [base_code],8Dh call take_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand xor al,al xchg al,[operand_size] push eax lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand or [operand_flags],1 call get_address pop eax mov [operand_size],al call operand_autodetect jmp instruction_ready ls_instruction: or al,al jz les_instruction cmp al,3 jz lds_instruction add al,0B0h mov [extended_code],al mov [base_code],0Fh jmp ls_code_ok les_instruction: mov [base_code],0C4h jmp ls_short_code lds_instruction: mov [base_code],0C5h ls_short_code: cmp [code_type],64 je illegal_instruction ls_code_ok: call take_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand add [operand_size],2 lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] cmp al,4 je ls_16bit cmp al,6 je ls_32bit cmp al,10 je ls_64bit jmp invalid_operand_size ls_16bit: call operand_16bit jmp instruction_ready ls_32bit: call operand_32bit jmp instruction_ready ls_64bit: call operand_64bit jmp instruction_ready sh_instruction: mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,10h je sh_reg cmp al,'[' jne invalid_operand sh_mem: call get_address push edx ebx ecx mov al,[operand_size] push eax mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'(' je sh_mem_imm cmp al,10h jne invalid_operand sh_mem_reg: lods byte [esi] cmp al,11h jne invalid_operand pop eax ecx ebx edx cmp al,1 je sh_mem_cl_8bit jb sh_mem_cl_nosize call operand_autodetect mov [base_code],0D3h jmp instruction_ready sh_mem_cl_nosize: call recoverable_unknown_size sh_mem_cl_8bit: mov [base_code],0D2h jmp instruction_ready sh_mem_imm: mov al,[operand_size] or al,al jz sh_mem_imm_size_ok cmp al,1 jne invalid_operand_size sh_mem_imm_size_ok: call get_byte_value mov byte [value],al pop eax ecx ebx edx cmp al,1 je sh_mem_imm_8bit jb sh_mem_imm_nosize call operand_autodetect cmp byte [value],1 je sh_mem_1 mov [base_code],0C1h call store_instruction_with_imm8 jmp instruction_assembled sh_mem_1: mov [base_code],0D1h jmp instruction_ready sh_mem_imm_nosize: call recoverable_unknown_size sh_mem_imm_8bit: cmp byte [value],1 je sh_mem_1_8bit mov [base_code],0C0h call store_instruction_with_imm8 jmp instruction_assembled sh_mem_1_8bit: mov [base_code],0D0h jmp instruction_ready sh_reg: lods byte [esi] call convert_register mov bx,ax mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'(' je sh_reg_imm cmp al,10h jne invalid_operand sh_reg_reg: lods byte [esi] cmp al,11h jne invalid_operand mov al,bh cmp al,1 je sh_reg_cl_8bit call operand_autodetect mov [base_code],0D3h jmp nomem_instruction_ready sh_reg_cl_8bit: mov [base_code],0D2h jmp nomem_instruction_ready sh_reg_imm: mov al,[operand_size] or al,al jz sh_reg_imm_size_ok cmp al,1 jne invalid_operand_size sh_reg_imm_size_ok: push ebx call get_byte_value mov dl,al pop ebx mov al,bh cmp al,1 je sh_reg_imm_8bit call operand_autodetect cmp dl,1 je sh_reg_1 mov [base_code],0C1h call store_nomem_instruction mov al,dl stos byte [edi] jmp instruction_assembled sh_reg_1: mov [base_code],0D1h jmp nomem_instruction_ready sh_reg_imm_8bit: cmp dl,1 je sh_reg_1_8bit mov [base_code],0C0h call store_nomem_instruction mov al,dl stos byte [edi] jmp instruction_assembled sh_reg_1_8bit: mov [base_code],0D0h jmp nomem_instruction_ready shd_instruction: mov [base_code],0Fh mov [extended_code],al lods byte [esi] call get_size_operator cmp al,10h je shd_reg cmp al,'[' jne invalid_operand shd_mem: call get_address push edx ebx ecx lods byte [esi] cmp al,',' jne invalid_operand call take_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand mov al,ah mov [operand_size],0 push eax lods byte [esi] call get_size_operator cmp al,'(' je shd_mem_reg_imm cmp al,10h jne invalid_operand lods byte [esi] cmp al,11h jne invalid_operand pop eax ecx ebx edx call operand_autodetect inc [extended_code] jmp instruction_ready shd_mem_reg_imm: mov al,[operand_size] or al,al jz shd_mem_reg_imm_size_ok cmp al,1 jne invalid_operand_size shd_mem_reg_imm_size_ok: call get_byte_value mov byte [value],al pop eax ecx ebx edx call operand_autodetect call store_instruction_with_imm8 jmp instruction_assembled shd_reg: lods byte [esi] call convert_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_register mov bl,[postbyte_register] mov [postbyte_register],al mov al,ah push eax ebx lods byte [esi] cmp al,',' jne invalid_operand mov [operand_size],0 lods byte [esi] call get_size_operator cmp al,'(' je shd_reg_reg_imm cmp al,10h jne invalid_operand lods byte [esi] cmp al,11h jne invalid_operand pop ebx eax call operand_autodetect inc [extended_code] jmp nomem_instruction_ready shd_reg_reg_imm: mov al,[operand_size] or al,al jz shd_reg_reg_imm_size_ok cmp al,1 jne invalid_operand_size shd_reg_reg_imm_size_ok: call get_byte_value mov dl,al pop ebx eax call operand_autodetect call store_nomem_instruction mov al,dl stos byte [edi] jmp instruction_assembled movx_instruction: mov [base_code],0Fh mov [extended_code],al call take_register mov [postbyte_register],al mov al,ah push eax lods byte [esi] cmp al,',' jne invalid_operand mov [operand_size],0 lods byte [esi] call get_size_operator cmp al,10h je movx_reg cmp al,'[' jne invalid_operand call get_address pop eax mov ah,[operand_size] or ah,ah jz movx_unknown_size cmp ah,al jae invalid_operand_size cmp ah,1 je movx_mem_store cmp ah,2 jne invalid_operand_size inc [extended_code] movx_mem_store: call operand_autodetect jmp instruction_ready movx_unknown_size: cmp al,2 je movx_mem_store call recoverable_unknown_size jmp movx_mem_store movx_reg: lods byte [esi] call convert_register pop ebx xchg bl,al cmp ah,al jae invalid_operand_size cmp ah,1 je movx_reg_8bit cmp ah,2 je movx_reg_16bit jmp invalid_operand_size movx_reg_8bit: call operand_autodetect jmp nomem_instruction_ready movx_reg_16bit: call operand_autodetect inc [extended_code] jmp nomem_instruction_ready movsxd_instruction: mov [base_code],al call take_register mov [postbyte_register],al cmp ah,8 jne invalid_operand_size lods byte [esi] cmp al,',' jne invalid_operand mov [operand_size],0 lods byte [esi] call get_size_operator cmp al,10h je movsxd_reg cmp al,'[' jne invalid_operand call get_address cmp [operand_size],4 je movsxd_mem_store cmp [operand_size],0 jne invalid_operand_size movsxd_mem_store: call operand_64bit jmp instruction_ready movsxd_reg: lods byte [esi] call convert_register cmp ah,4 jne invalid_operand_size mov bl,al call operand_64bit jmp nomem_instruction_ready bt_instruction: mov [postbyte_register],al shl al,3 add al,83h mov [extended_code],al mov [base_code],0Fh lods byte [esi] call get_size_operator cmp al,10h je bt_reg cmp al,'[' jne invalid_operand call get_address push eax ebx ecx lods byte [esi] cmp al,',' jne invalid_operand cmp byte [esi],'(' je bt_mem_imm cmp byte [esi],11h jne bt_mem_reg cmp byte [esi+2],'(' je bt_mem_imm bt_mem_reg: call take_register mov [postbyte_register],al pop ecx ebx edx mov al,ah call operand_autodetect jmp instruction_ready bt_mem_imm: xor al,al xchg al,[operand_size] push eax lods byte [esi] call get_size_operator cmp al,'(' jne invalid_operand mov al,[operand_size] or al,al jz bt_mem_imm_size_ok cmp al,1 jne invalid_operand_size bt_mem_imm_size_ok: call get_byte_value mov byte [value],al pop eax or al,al jz bt_mem_imm_nosize call operand_autodetect bt_mem_imm_store: pop ecx ebx edx mov [extended_code],0BAh call store_instruction_with_imm8 jmp instruction_assembled bt_mem_imm_nosize: call recoverable_unknown_size jmp bt_mem_imm_store bt_reg: lods byte [esi] call convert_register mov bl,al lods byte [esi] cmp al,',' jne invalid_operand cmp byte [esi],'(' je bt_reg_imm cmp byte [esi],11h jne bt_reg_reg cmp byte [esi+2],'(' je bt_reg_imm bt_reg_reg: call take_register mov [postbyte_register],al mov al,ah call operand_autodetect jmp nomem_instruction_ready bt_reg_imm: xor al,al xchg al,[operand_size] push eax ebx lods byte [esi] call get_size_operator cmp al,'(' jne invalid_operand mov al,[operand_size] or al,al jz bt_reg_imm_size_ok cmp al,1 jne invalid_operand_size bt_reg_imm_size_ok: call get_byte_value mov byte [value],al pop ebx eax call operand_autodetect bt_reg_imm_store: mov [extended_code],0BAh call store_nomem_instruction mov al,byte [value] stos byte [edi] jmp instruction_assembled bs_instruction: mov [extended_code],al mov [base_code],0Fh call get_reg_mem jc bs_reg_reg mov al,[operand_size] call operand_autodetect jmp instruction_ready bs_reg_reg: mov al,ah call operand_autodetect jmp nomem_instruction_ready get_reg_mem: call take_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je get_reg_reg cmp al,'[' jne invalid_argument call get_address clc ret get_reg_reg: lods byte [esi] call convert_register mov bl,al stc ret ud_instruction: mov [extended_code],al mov [base_code],0Fh call get_reg_mem jc ud_reg_reg cmp [operand_size],4 jne invalid_operand_size jmp instruction_ready ud_reg_reg: cmp ah,4 jne invalid_operand_size jmp nomem_instruction_ready imul_instruction: mov [base_code],0F6h mov [postbyte_register],5 lods byte [esi] call get_size_operator cmp al,10h je imul_reg cmp al,'[' jne invalid_operand imul_mem: call get_address mov al,[operand_size] cmp al,1 je imul_mem_8bit jb imul_mem_nosize call operand_autodetect inc [base_code] jmp instruction_ready imul_mem_nosize: call recoverable_unknown_size imul_mem_8bit: jmp instruction_ready imul_reg: lods byte [esi] call convert_register cmp byte [esi],',' je imul_reg_ mov bl,al mov al,ah cmp al,1 je imul_reg_8bit call operand_autodetect inc [base_code] imul_reg_8bit: jmp nomem_instruction_ready imul_reg_: mov [postbyte_register],al inc esi cmp byte [esi],'(' je imul_reg_imm cmp byte [esi],11h jne imul_reg_noimm cmp byte [esi+2],'(' je imul_reg_imm imul_reg_noimm: lods byte [esi] call get_size_operator cmp al,10h je imul_reg_reg cmp al,'[' jne invalid_operand imul_reg_mem: call get_address push edx ebx ecx cmp byte [esi],',' je imul_reg_mem_imm mov al,[operand_size] call operand_autodetect pop ecx ebx edx mov [base_code],0Fh mov [extended_code],0AFh jmp instruction_ready imul_reg_mem_imm: inc esi lods byte [esi] call get_size_operator cmp al,'(' jne invalid_operand mov al,[operand_size] cmp al,2 je imul_reg_mem_imm_16bit cmp al,4 je imul_reg_mem_imm_32bit cmp al,8 jne invalid_operand_size imul_reg_mem_imm_64bit: cmp [size_declared],0 jne long_immediate_not_encodable call operand_64bit call get_simm32 cmp [value_type],4 jae long_immediate_not_encodable jmp imul_reg_mem_imm_32bit_ok imul_reg_mem_imm_16bit: call operand_16bit call get_word_value mov word [value],ax cmp [value_type],0 jne imul_reg_mem_imm_16bit_store cmp [size_declared],0 jne imul_reg_mem_imm_16bit_store cmp ax,-80h jl imul_reg_mem_imm_16bit_store cmp ax,80h jl imul_reg_mem_imm_8bit_store imul_reg_mem_imm_16bit_store: pop ecx ebx edx mov [base_code],69h call store_instruction_with_imm16 jmp instruction_assembled imul_reg_mem_imm_32bit: call operand_32bit call get_dword_value imul_reg_mem_imm_32bit_ok: mov dword [value],eax cmp [value_type],0 jne imul_reg_mem_imm_32bit_store cmp [size_declared],0 jne imul_reg_mem_imm_32bit_store cmp eax,-80h jl imul_reg_mem_imm_32bit_store cmp eax,80h jl imul_reg_mem_imm_8bit_store imul_reg_mem_imm_32bit_store: pop ecx ebx edx mov [base_code],69h call store_instruction_with_imm32 jmp instruction_assembled imul_reg_mem_imm_8bit_store: pop ecx ebx edx mov [base_code],6Bh call store_instruction_with_imm8 jmp instruction_assembled imul_reg_imm: mov bl,[postbyte_register] dec esi jmp imul_reg_reg_imm imul_reg_reg: lods byte [esi] call convert_register mov bl,al cmp byte [esi],',' je imul_reg_reg_imm mov al,ah call operand_autodetect mov [base_code],0Fh mov [extended_code],0AFh jmp nomem_instruction_ready imul_reg_reg_imm: inc esi lods byte [esi] call get_size_operator cmp al,'(' jne invalid_operand mov al,[operand_size] cmp al,2 je imul_reg_reg_imm_16bit cmp al,4 je imul_reg_reg_imm_32bit cmp al,8 jne invalid_operand_size imul_reg_reg_imm_64bit: cmp [size_declared],0 jne long_immediate_not_encodable call operand_64bit push ebx call get_simm32 cmp [value_type],4 jae long_immediate_not_encodable jmp imul_reg_reg_imm_32bit_ok imul_reg_reg_imm_16bit: call operand_16bit push ebx call get_word_value pop ebx mov dx,ax cmp [value_type],0 jne imul_reg_reg_imm_16bit_store cmp [size_declared],0 jne imul_reg_reg_imm_16bit_store cmp ax,-80h jl imul_reg_reg_imm_16bit_store cmp ax,80h jl imul_reg_reg_imm_8bit_store imul_reg_reg_imm_16bit_store: mov [base_code],69h call store_nomem_instruction mov ax,dx call mark_relocation stos word [edi] jmp instruction_assembled imul_reg_reg_imm_32bit: call operand_32bit push ebx call get_dword_value imul_reg_reg_imm_32bit_ok: pop ebx mov edx,eax cmp [value_type],0 jne imul_reg_reg_imm_32bit_store cmp [size_declared],0 jne imul_reg_reg_imm_32bit_store cmp eax,-80h jl imul_reg_reg_imm_32bit_store cmp eax,80h jl imul_reg_reg_imm_8bit_store imul_reg_reg_imm_32bit_store: mov [base_code],69h call store_nomem_instruction mov eax,edx call mark_relocation stos dword [edi] jmp instruction_assembled imul_reg_reg_imm_8bit_store: mov [base_code],6Bh call store_nomem_instruction mov al,dl stos byte [edi] jmp instruction_assembled in_instruction: call take_register or al,al jnz invalid_operand lods byte [esi] cmp al,',' jne invalid_operand mov al,ah push eax mov [operand_size],0 lods byte [esi] call get_size_operator cmp al,'(' je in_imm cmp al,10h je in_reg jmp invalid_operand in_reg: lods byte [esi] cmp al,22h jne invalid_operand pop eax cmp al,1 je in_al_dx cmp al,2 je in_ax_dx cmp al,4 jne invalid_operand_size in_ax_dx: call operand_autodetect mov [base_code],0EDh call store_classic_instruction_code jmp instruction_assembled in_al_dx: mov al,0ECh stos byte [edi] jmp instruction_assembled in_imm: mov al,[operand_size] or al,al jz in_imm_size_ok cmp al,1 jne invalid_operand_size in_imm_size_ok: call get_byte_value mov dl,al pop eax cmp al,1 je in_al_imm cmp al,2 je in_ax_imm cmp al,4 jne invalid_operand_size in_ax_imm: call operand_autodetect mov [base_code],0E5h call store_classic_instruction_code mov al,dl stos byte [edi] jmp instruction_assembled in_al_imm: mov al,0E4h stos byte [edi] mov al,dl stos byte [edi] jmp instruction_assembled out_instruction: lods byte [esi] call get_size_operator cmp al,'(' je out_imm cmp al,10h jne invalid_operand lods byte [esi] cmp al,22h jne invalid_operand lods byte [esi] cmp al,',' jne invalid_operand mov [operand_size],0 call take_register or al,al jnz invalid_operand mov al,ah cmp al,1 je out_dx_al cmp al,2 je out_dx_ax cmp al,4 jne invalid_operand_size out_dx_ax: call operand_autodetect mov [base_code],0EFh call store_classic_instruction_code jmp instruction_assembled out_dx_al: mov al,0EEh stos byte [edi] jmp instruction_assembled out_imm: mov al,[operand_size] or al,al jz out_imm_size_ok cmp al,1 jne invalid_operand_size out_imm_size_ok: call get_byte_value mov dl,al lods byte [esi] cmp al,',' jne invalid_operand mov [operand_size],0 call take_register or al,al jnz invalid_operand mov al,ah cmp al,1 je out_imm_al cmp al,2 je out_imm_ax cmp al,4 jne invalid_operand_size out_imm_ax: call operand_autodetect mov [base_code],0E7h call store_classic_instruction_code mov al,dl stos byte [edi] jmp instruction_assembled out_imm_al: mov al,0E6h stos byte [edi] mov al,dl stos byte [edi] jmp instruction_assembled call_instruction: mov [postbyte_register],10b mov [base_code],0E8h mov [extended_code],9Ah jmp process_jmp jmp_instruction: mov [postbyte_register],100b mov [base_code],0E9h mov [extended_code],0EAh process_jmp: lods byte [esi] call get_jump_operator test [prefix_flags],10h jz jmp_type_ok test [jump_type],not 2 jnz illegal_instruction mov [jump_type],2 and [prefix_flags],not 10h jmp_type_ok: call get_size_operator cmp al,'(' je jmp_imm mov [base_code],0FFh cmp al,10h je jmp_reg cmp al,'[' jne invalid_operand jmp_mem: cmp [jump_type],1 je illegal_instruction call get_address mov edx,eax mov al,[operand_size] or al,al jz jmp_mem_size_not_specified cmp al,2 je jmp_mem_16bit cmp al,4 je jmp_mem_32bit cmp al,6 je jmp_mem_48bit cmp al,8 je jmp_mem_64bit cmp al,10 je jmp_mem_80bit jmp invalid_operand_size jmp_mem_size_not_specified: cmp [jump_type],3 je jmp_mem_far cmp [jump_type],2 je jmp_mem_near call recoverable_unknown_size jmp_mem_near: cmp [code_type],16 je jmp_mem_16bit cmp [code_type],32 je jmp_mem_near_32bit jmp_mem_64bit: cmp [jump_type],3 je invalid_operand_size cmp [code_type],64 jne illegal_instruction jmp instruction_ready jmp_mem_far: cmp [code_type],16 je jmp_mem_far_32bit jmp_mem_48bit: call operand_32bit jmp_mem_far_store: cmp [jump_type],2 je invalid_operand_size inc [postbyte_register] jmp instruction_ready jmp_mem_80bit: call operand_64bit jmp jmp_mem_far_store jmp_mem_far_32bit: call operand_16bit jmp jmp_mem_far_store jmp_mem_32bit: cmp [jump_type],3 je jmp_mem_far_32bit cmp [jump_type],2 je jmp_mem_near_32bit cmp [code_type],16 je jmp_mem_far_32bit jmp_mem_near_32bit: cmp [code_type],64 je illegal_instruction call operand_32bit jmp instruction_ready jmp_mem_16bit: cmp [jump_type],3 je invalid_operand_size call operand_16bit jmp instruction_ready jmp_reg: test [jump_type],1 jnz invalid_operand lods byte [esi] call convert_register mov bl,al mov al,ah cmp al,2 je jmp_reg_16bit cmp al,4 je jmp_reg_32bit cmp al,8 jne invalid_operand_size jmp_reg_64bit: cmp [code_type],64 jne illegal_instruction jmp nomem_instruction_ready jmp_reg_32bit: cmp [code_type],64 je illegal_instruction call operand_32bit jmp nomem_instruction_ready jmp_reg_16bit: call operand_16bit jmp nomem_instruction_ready jmp_imm: cmp byte [esi],'.' je invalid_value mov ebx,esi dec esi call skip_symbol xchg esi,ebx cmp byte [ebx],':' je jmp_far cmp [jump_type],3 je invalid_operand jmp_near: mov al,[operand_size] cmp al,2 je jmp_imm_16bit cmp al,4 je jmp_imm_32bit cmp al,8 je jmp_imm_64bit or al,al jnz invalid_operand_size cmp [code_type],16 je jmp_imm_16bit cmp [code_type],64 je jmp_imm_64bit jmp_imm_32bit: cmp [code_type],64 je invalid_operand_size call get_address_dword_value cmp [code_type],16 jne jmp_imm_32bit_prefix_ok mov byte [edi],66h inc edi jmp_imm_32bit_prefix_ok: call calculate_jump_offset cdq call check_for_short_jump jc jmp_short jmp_imm_32bit_store: mov edx,eax sub edx,3 jno jmp_imm_32bit_ok cmp [code_type],64 je jump_out_of_range jmp_imm_32bit_ok: mov al,[base_code] stos byte [edi] mov eax,edx call mark_relocation stos dword [edi] jmp instruction_assembled jmp_imm_64bit: cmp [code_type],64 jne invalid_operand_size call get_address_qword_value call calculate_jump_offset mov ecx,edx cdq cmp edx,ecx jne jump_out_of_range call check_for_short_jump jnc jmp_imm_32bit_store jmp_short: mov ah,al mov al,0EBh stos word [edi] jmp instruction_assembled jmp_imm_16bit: call get_address_word_value cmp [code_type],16 je jmp_imm_16bit_prefix_ok mov byte [edi],66h inc edi jmp_imm_16bit_prefix_ok: call calculate_jump_offset cwde cdq call check_for_short_jump jc jmp_short cmp [value_type],0 jne invalid_use_of_symbol mov edx,eax dec edx mov al,[base_code] stos byte [edi] mov eax,edx stos word [edi] jmp instruction_assembled calculate_jump_offset: add edi,2 mov ebp,[addressing_space] call calculate_relative_offset sub edi,2 ret check_for_short_jump: cmp [jump_type],1 je forced_short ja no_short_jump cmp [base_code],0E8h je no_short_jump cmp [value_type],0 jne no_short_jump cmp eax,80h jb short_jump cmp eax,-80h jae short_jump no_short_jump: clc ret forced_short: cmp [base_code],0E8h je illegal_instruction cmp [next_pass_needed],0 jne jmp_short_value_type_ok cmp [value_type],0 jne invalid_use_of_symbol jmp_short_value_type_ok: cmp eax,-80h jae short_jump cmp eax,80h jae jump_out_of_range short_jump: stc ret jump_out_of_range: cmp [error_line],0 jne instruction_assembled mov eax,[current_line] mov [error_line],eax mov [error],relative_jump_out_of_range jmp instruction_assembled jmp_far: cmp [jump_type],2 je invalid_operand cmp [code_type],64 je illegal_instruction mov al,[extended_code] mov [base_code],al call get_word_value push eax inc esi lods byte [esi] cmp al,'(' jne invalid_operand mov al,[value_type] push eax push [symbol_identifier] cmp byte [esi],'.' je invalid_value mov al,[operand_size] cmp al,4 je jmp_far_16bit cmp al,6 je jmp_far_32bit or al,al jnz invalid_operand_size cmp [code_type],16 jne jmp_far_32bit jmp_far_16bit: call get_word_value mov ebx,eax call operand_16bit call store_classic_instruction_code mov ax,bx call mark_relocation stos word [edi] jmp_far_segment: pop [symbol_identifier] pop eax mov [value_type],al pop eax call mark_relocation stos word [edi] jmp instruction_assembled jmp_far_32bit: call get_dword_value mov ebx,eax call operand_32bit call store_classic_instruction_code mov eax,ebx call mark_relocation stos dword [edi] jmp jmp_far_segment conditional_jump: mov [base_code],al and [prefix_flags],not 10h lods byte [esi] call get_jump_operator cmp [jump_type],3 je invalid_operand call get_size_operator cmp al,'(' jne invalid_operand cmp byte [esi],'.' je invalid_value mov al,[operand_size] cmp al,2 je conditional_jump_16bit cmp al,4 je conditional_jump_32bit cmp al,8 je conditional_jump_64bit or al,al jnz invalid_operand_size cmp [code_type],16 je conditional_jump_16bit cmp [code_type],64 je conditional_jump_64bit conditional_jump_32bit: cmp [code_type],64 je invalid_operand_size call get_address_dword_value cmp [code_type],16 jne conditional_jump_32bit_prefix_ok mov byte [edi],66h inc edi conditional_jump_32bit_prefix_ok: call calculate_jump_offset cdq call check_for_short_jump jc conditional_jump_short conditional_jump_32bit_store: mov edx,eax sub edx,4 jno conditional_jump_32bit_range_ok cmp [code_type],64 je jump_out_of_range conditional_jump_32bit_range_ok: mov ah,[base_code] add ah,10h mov al,0Fh stos word [edi] mov eax,edx call mark_relocation stos dword [edi] jmp instruction_assembled conditional_jump_64bit: cmp [code_type],64 jne invalid_operand_size call get_address_qword_value call calculate_jump_offset mov ecx,edx cdq cmp edx,ecx jne jump_out_of_range call check_for_short_jump jnc conditional_jump_32bit_store conditional_jump_short: mov ah,al mov al,[base_code] stos word [edi] jmp instruction_assembled conditional_jump_16bit: call get_address_word_value cmp [code_type],16 je conditional_jump_16bit_prefix_ok mov byte [edi],66h inc edi conditional_jump_16bit_prefix_ok: call calculate_jump_offset cwde cdq call check_for_short_jump jc conditional_jump_short cmp [value_type],0 jne invalid_use_of_symbol mov edx,eax sub dx,2 mov ah,[base_code] add ah,10h mov al,0Fh stos word [edi] mov eax,edx stos word [edi] jmp instruction_assembled loop_instruction_16bit: cmp [code_type],64 je illegal_instruction cmp [code_type],16 je loop_instruction mov [operand_prefix],67h jmp loop_instruction loop_instruction_32bit: cmp [code_type],32 je loop_instruction mov [operand_prefix],67h jmp loop_instruction loop_instruction_64bit: cmp [code_type],64 jne illegal_instruction loop_instruction: mov [base_code],al lods byte [esi] call get_jump_operator cmp [jump_type],1 ja invalid_operand call get_size_operator cmp al,'(' jne invalid_operand cmp byte [esi],'.' je invalid_value mov al,[operand_size] cmp al,2 je loop_jump_16bit cmp al,4 je loop_jump_32bit cmp al,8 je loop_jump_64bit or al,al jnz invalid_operand_size cmp [code_type],16 je loop_jump_16bit cmp [code_type],64 je loop_jump_64bit loop_jump_32bit: cmp [code_type],64 je invalid_operand_size call get_address_dword_value cmp [code_type],16 jne loop_jump_32bit_prefix_ok mov byte [edi],66h inc edi loop_jump_32bit_prefix_ok: call loop_counter_size call calculate_jump_offset cdq make_loop_jump: call check_for_short_jump jc conditional_jump_short scas word [edi] jmp jump_out_of_range loop_counter_size: cmp [operand_prefix],0 je loop_counter_size_ok push eax mov al,[operand_prefix] stos byte [edi] pop eax loop_counter_size_ok: ret loop_jump_64bit: cmp [code_type],64 jne invalid_operand_size call get_address_qword_value call loop_counter_size call calculate_jump_offset mov ecx,edx cdq cmp edx,ecx jne jump_out_of_range jmp make_loop_jump loop_jump_16bit: call get_address_word_value cmp [code_type],16 je loop_jump_16bit_prefix_ok mov byte [edi],66h inc edi loop_jump_16bit_prefix_ok: call loop_counter_size call calculate_jump_offset cwde cdq jmp make_loop_jump movs_instruction: lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address or eax,eax jnz invalid_address or bl,ch jnz invalid_address cmp [segment_register],1 ja invalid_address push ebx lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address pop edx or eax,eax jnz invalid_address or bl,ch jnz invalid_address mov al,dh mov ah,bh shr al,4 shr ah,4 cmp al,ah jne address_sizes_do_not_agree and bh,111b and dh,111b cmp bh,6 jne invalid_address cmp dh,7 jne invalid_address cmp al,2 je movs_address_16bit cmp al,4 je movs_address_32bit cmp [code_type],64 jne invalid_address_size jmp movs_store movs_address_32bit: call address_32bit_prefix jmp movs_store movs_address_16bit: cmp [code_type],64 je invalid_address_size call address_16bit_prefix movs_store: xor ebx,ebx call store_segment_prefix_if_necessary mov al,0A4h movs_check_size: mov bl,[operand_size] cmp bl,1 je simple_instruction inc al cmp bl,2 je simple_instruction_16bit cmp bl,4 je simple_instruction_32bit cmp bl,8 je simple_instruction_64bit or bl,bl jnz invalid_operand_size call recoverable_unknown_size jmp simple_instruction lods_instruction: lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address or eax,eax jnz invalid_address or bl,ch jnz invalid_address cmp bh,26h je lods_address_16bit cmp bh,46h je lods_address_32bit cmp bh,86h jne invalid_address cmp [code_type],64 jne invalid_address_size jmp lods_store lods_address_32bit: call address_32bit_prefix jmp lods_store lods_address_16bit: cmp [code_type],64 je invalid_address_size call address_16bit_prefix lods_store: xor ebx,ebx call store_segment_prefix_if_necessary mov al,0ACh jmp movs_check_size stos_instruction: mov [base_code],al lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address or eax,eax jnz invalid_address or bl,ch jnz invalid_address cmp bh,27h je stos_address_16bit cmp bh,47h je stos_address_32bit cmp bh,87h jne invalid_address cmp [code_type],64 jne invalid_address_size jmp stos_store stos_address_32bit: call address_32bit_prefix jmp stos_store stos_address_16bit: cmp [code_type],64 je invalid_address_size call address_16bit_prefix stos_store: cmp [segment_register],1 ja invalid_address mov al,[base_code] jmp movs_check_size cmps_instruction: lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address or eax,eax jnz invalid_address or bl,ch jnz invalid_address mov al,[segment_register] push eax ebx lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address or eax,eax jnz invalid_address or bl,ch jnz invalid_address pop edx eax cmp [segment_register],1 ja invalid_address mov [segment_register],al mov al,dh mov ah,bh shr al,4 shr ah,4 cmp al,ah jne address_sizes_do_not_agree and bh,111b and dh,111b cmp bh,7 jne invalid_address cmp dh,6 jne invalid_address cmp al,2 je cmps_address_16bit cmp al,4 je cmps_address_32bit cmp [code_type],64 jne invalid_address_size jmp cmps_store cmps_address_32bit: call address_32bit_prefix jmp cmps_store cmps_address_16bit: cmp [code_type],64 je invalid_address_size call address_16bit_prefix cmps_store: xor ebx,ebx call store_segment_prefix_if_necessary mov al,0A6h jmp movs_check_size ins_instruction: lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address or eax,eax jnz invalid_address or bl,ch jnz invalid_address cmp bh,27h je ins_address_16bit cmp bh,47h je ins_address_32bit cmp bh,87h jne invalid_address cmp [code_type],64 jne invalid_address_size jmp ins_store ins_address_32bit: call address_32bit_prefix jmp ins_store ins_address_16bit: cmp [code_type],64 je invalid_address_size call address_16bit_prefix ins_store: cmp [segment_register],1 ja invalid_address lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] cmp al,10h jne invalid_operand lods byte [esi] cmp al,22h jne invalid_operand mov al,6Ch ins_check_size: cmp [operand_size],8 jne movs_check_size jmp invalid_operand_size outs_instruction: lods byte [esi] cmp al,10h jne invalid_operand lods byte [esi] cmp al,22h jne invalid_operand lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address or eax,eax jnz invalid_address or bl,ch jnz invalid_address cmp bh,26h je outs_address_16bit cmp bh,46h je outs_address_32bit cmp bh,86h jne invalid_address cmp [code_type],64 jne invalid_address_size jmp outs_store outs_address_32bit: call address_32bit_prefix jmp outs_store outs_address_16bit: cmp [code_type],64 je invalid_address_size call address_16bit_prefix outs_store: xor ebx,ebx call store_segment_prefix_if_necessary mov al,6Eh jmp ins_check_size xlat_instruction: lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address or eax,eax jnz invalid_address or bl,ch jnz invalid_address cmp bh,23h je xlat_address_16bit cmp bh,43h je xlat_address_32bit cmp bh,83h jne invalid_address cmp [code_type],64 jne invalid_address_size jmp xlat_store xlat_address_32bit: call address_32bit_prefix jmp xlat_store xlat_address_16bit: cmp [code_type],64 je invalid_address_size call address_16bit_prefix xlat_store: call store_segment_prefix_if_necessary mov al,0D7h cmp [operand_size],1 jbe simple_instruction jmp invalid_operand_size pm_word_instruction: mov ah,al shr ah,4 and al,111b mov [base_code],0Fh mov [extended_code],ah mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,10h je pm_reg pm_mem: cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] cmp al,2 je pm_mem_store or al,al jnz invalid_operand_size pm_mem_store: jmp instruction_ready pm_reg: lods byte [esi] call convert_register mov bl,al cmp ah,2 jne invalid_operand_size jmp nomem_instruction_ready pm_store_word_instruction: mov ah,al shr ah,4 and al,111b mov [base_code],0Fh mov [extended_code],ah mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,10h jne pm_mem lods byte [esi] call convert_register mov bl,al mov al,ah call operand_autodetect jmp nomem_instruction_ready lgdt_instruction: mov [base_code],0Fh mov [extended_code],1 mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] cmp al,6 je lgdt_mem_48bit cmp al,10 je lgdt_mem_80bit or al,al jnz invalid_operand_size jmp lgdt_mem_store lgdt_mem_80bit: cmp [code_type],64 jne illegal_instruction jmp lgdt_mem_store lgdt_mem_48bit: cmp [code_type],64 je illegal_instruction cmp [postbyte_register],2 jb lgdt_mem_store call operand_32bit lgdt_mem_store: jmp instruction_ready lar_instruction: mov [extended_code],al mov [base_code],0Fh call take_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand xor al,al xchg al,[operand_size] call operand_autodetect lods byte [esi] call get_size_operator cmp al,10h je lar_reg_reg cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] or al,al jz lar_reg_mem cmp al,2 jne invalid_operand_size lar_reg_mem: jmp instruction_ready lar_reg_reg: lods byte [esi] call convert_register cmp ah,2 jne invalid_operand_size mov bl,al jmp nomem_instruction_ready invlpg_instruction: mov [base_code],0Fh mov [extended_code],1 mov [postbyte_register],7 lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address jmp instruction_ready simple_instruction_f2_0f_01: mov byte [edi],0F2h inc edi jmp simple_instruction_0f_01 simple_instruction_f3_0f_01: mov byte [edi],0F3h inc edi jmp simple_instruction_0f_01 swapgs_instruction: cmp [code_type],64 jne illegal_instruction simple_instruction_0f_01: mov ah,al mov al,0Fh stos byte [edi] mov al,1 stos word [edi] jmp instruction_assembled basic_486_instruction: mov [base_code],0Fh mov [extended_code],al lods byte [esi] call get_size_operator cmp al,10h je basic_486_reg cmp al,'[' jne invalid_operand call get_address push edx ebx ecx lods byte [esi] cmp al,',' jne invalid_operand call take_register mov [postbyte_register],al pop ecx ebx edx mov al,ah cmp al,1 je basic_486_mem_reg_8bit call operand_autodetect inc [extended_code] basic_486_mem_reg_8bit: jmp instruction_ready basic_486_reg: lods byte [esi] call convert_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_register mov bl,al xchg bl,[postbyte_register] mov al,ah cmp al,1 je basic_486_reg_reg_8bit call operand_autodetect inc [extended_code] basic_486_reg_reg_8bit: jmp nomem_instruction_ready bswap_instruction: call take_register test al,1000b jz bswap_reg_code_ok or [rex_prefix],41h and al,111b bswap_reg_code_ok: add al,0C8h mov [extended_code],al mov [base_code],0Fh cmp ah,8 je bswap_reg64 cmp ah,4 jne invalid_operand_size call operand_32bit call store_classic_instruction_code jmp instruction_assembled bswap_reg64: call operand_64bit call store_classic_instruction_code jmp instruction_assembled cmpxchgx_instruction: mov [base_code],0Fh mov [extended_code],0C7h mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov ah,1 xchg [postbyte_register],ah mov al,[operand_size] or al,al jz cmpxchgx_size_ok cmp al,ah jne invalid_operand_size cmpxchgx_size_ok: cmp ah,16 jne cmpxchgx_store call operand_64bit cmpxchgx_store: jmp instruction_ready nop_instruction: mov ah,[esi] cmp ah,10h je extended_nop cmp ah,11h je extended_nop cmp ah,'[' je extended_nop stos byte [edi] jmp instruction_assembled extended_nop: mov [base_code],0Fh mov [extended_code],1Fh mov [postbyte_register],0 lods byte [esi] call get_size_operator cmp al,10h je extended_nop_reg cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] or al,al jz extended_nop_store call operand_autodetect extended_nop_store: jmp instruction_ready extended_nop_reg: lods byte [esi] call convert_register mov bl,al mov al,ah call operand_autodetect jmp nomem_instruction_ready basic_fpu_instruction: mov [postbyte_register],al mov [base_code],0D8h lods byte [esi] call get_size_operator cmp al,10h je basic_fpu_streg cmp al,'[' je basic_fpu_mem dec esi mov ah,[postbyte_register] cmp ah,2 jb invalid_operand cmp ah,3 ja invalid_operand mov bl,1 jmp nomem_instruction_ready basic_fpu_mem: call get_address mov al,[operand_size] cmp al,4 je basic_fpu_mem_32bit cmp al,8 je basic_fpu_mem_64bit or al,al jnz invalid_operand_size call recoverable_unknown_size basic_fpu_mem_32bit: jmp instruction_ready basic_fpu_mem_64bit: mov [base_code],0DCh jmp instruction_ready basic_fpu_streg: lods byte [esi] call convert_fpu_register mov bl,al mov ah,[postbyte_register] cmp ah,2 je basic_fpu_single_streg cmp ah,3 je basic_fpu_single_streg or al,al jz basic_fpu_st0 test ah,110b jz basic_fpu_streg_st0 xor [postbyte_register],1 basic_fpu_streg_st0: lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_fpu_register or al,al jnz invalid_operand mov [base_code],0DCh jmp nomem_instruction_ready basic_fpu_st0: lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_fpu_register mov bl,al basic_fpu_single_streg: mov [base_code],0D8h jmp nomem_instruction_ready simple_fpu_instruction: mov ah,al or ah,11000000b mov al,0D9h stos word [edi] jmp instruction_assembled fi_instruction: mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] cmp al,2 je fi_mem_16bit cmp al,4 je fi_mem_32bit or al,al jnz invalid_operand_size call recoverable_unknown_size fi_mem_32bit: mov [base_code],0DAh jmp instruction_ready fi_mem_16bit: mov [base_code],0DEh jmp instruction_ready fld_instruction: mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,10h je fld_streg cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] cmp al,4 je fld_mem_32bit cmp al,8 je fld_mem_64bit cmp al,10 je fld_mem_80bit or al,al jnz invalid_operand_size call recoverable_unknown_size fld_mem_32bit: mov [base_code],0D9h jmp instruction_ready fld_mem_64bit: mov [base_code],0DDh jmp instruction_ready fld_mem_80bit: mov al,[postbyte_register] cmp al,0 je fld_mem_80bit_store dec [postbyte_register] cmp al,3 je fld_mem_80bit_store jmp invalid_operand_size fld_mem_80bit_store: add [postbyte_register],5 mov [base_code],0DBh jmp instruction_ready fld_streg: lods byte [esi] call convert_fpu_register mov bl,al cmp [postbyte_register],2 jae fst_streg mov [base_code],0D9h jmp nomem_instruction_ready fst_streg: mov [base_code],0DDh jmp nomem_instruction_ready fild_instruction: mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] cmp al,2 je fild_mem_16bit cmp al,4 je fild_mem_32bit cmp al,8 je fild_mem_64bit or al,al jnz invalid_operand_size call recoverable_unknown_size fild_mem_32bit: mov [base_code],0DBh jmp instruction_ready fild_mem_16bit: mov [base_code],0DFh jmp instruction_ready fild_mem_64bit: mov al,[postbyte_register] cmp al,1 je fisttp_64bit_store jb fild_mem_64bit_store dec [postbyte_register] cmp al,3 je fild_mem_64bit_store jmp invalid_operand_size fild_mem_64bit_store: add [postbyte_register],5 mov [base_code],0DFh jmp instruction_ready fisttp_64bit_store: mov [base_code],0DDh jmp instruction_ready fbld_instruction: mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] or al,al jz fbld_mem_80bit cmp al,10 je fbld_mem_80bit jmp invalid_operand_size fbld_mem_80bit: mov [base_code],0DFh jmp instruction_ready faddp_instruction: mov [postbyte_register],al mov [base_code],0DEh mov edx,esi lods byte [esi] call get_size_operator cmp al,10h je faddp_streg mov esi,edx mov bl,1 jmp nomem_instruction_ready faddp_streg: lods byte [esi] call convert_fpu_register mov bl,al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_fpu_register or al,al jnz invalid_operand jmp nomem_instruction_ready fcompp_instruction: mov ax,0D9DEh stos word [edi] jmp instruction_assembled fucompp_instruction: mov ax,0E9DAh stos word [edi] jmp instruction_assembled fxch_instruction: mov dx,01D9h jmp fpu_single_operand ffreep_instruction: mov dx,00DFh jmp fpu_single_operand ffree_instruction: mov dl,0DDh mov dh,al fpu_single_operand: mov ebx,esi lods byte [esi] call get_size_operator cmp al,10h je fpu_streg or dh,dh jz invalid_operand mov esi,ebx shl dh,3 or dh,11000001b mov ax,dx stos word [edi] jmp instruction_assembled fpu_streg: lods byte [esi] call convert_fpu_register shl dh,3 or dh,al or dh,11000000b mov ax,dx stos word [edi] jmp instruction_assembled fstenv_instruction: mov byte [edi],9Bh inc edi fldenv_instruction: mov [base_code],0D9h jmp fpu_mem fstenv_instruction_16bit: mov byte [edi],9Bh inc edi fldenv_instruction_16bit: call operand_16bit jmp fldenv_instruction fstenv_instruction_32bit: mov byte [edi],9Bh inc edi fldenv_instruction_32bit: call operand_32bit jmp fldenv_instruction fsave_instruction_32bit: mov byte [edi],9Bh inc edi fnsave_instruction_32bit: call operand_32bit jmp fnsave_instruction fsave_instruction_16bit: mov byte [edi],9Bh inc edi fnsave_instruction_16bit: call operand_16bit jmp fnsave_instruction fsave_instruction: mov byte [edi],9Bh inc edi fnsave_instruction: mov [base_code],0DDh fpu_mem: mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address cmp [operand_size],0 jne invalid_operand_size jmp instruction_ready fstcw_instruction: mov byte [edi],9Bh inc edi fldcw_instruction: mov [postbyte_register],al mov [base_code],0D9h lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] or al,al jz fldcw_mem_16bit cmp al,2 je fldcw_mem_16bit jmp invalid_operand_size fldcw_mem_16bit: jmp instruction_ready fstsw_instruction: mov al,9Bh stos byte [edi] fnstsw_instruction: mov [base_code],0DDh mov [postbyte_register],7 lods byte [esi] call get_size_operator cmp al,10h je fstsw_reg cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] or al,al jz fstsw_mem_16bit cmp al,2 je fstsw_mem_16bit jmp invalid_operand_size fstsw_mem_16bit: jmp instruction_ready fstsw_reg: lods byte [esi] call convert_register cmp ax,0200h jne invalid_operand mov ax,0E0DFh stos word [edi] jmp instruction_assembled finit_instruction: mov byte [edi],9Bh inc edi fninit_instruction: mov ah,al mov al,0DBh stos word [edi] jmp instruction_assembled fcmov_instruction: mov dh,0DAh jmp fcomi_streg fcomi_instruction: mov dh,0DBh jmp fcomi_streg fcomip_instruction: mov dh,0DFh fcomi_streg: mov dl,al lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_fpu_register mov ah,al cmp byte [esi],',' je fcomi_st0_streg add ah,dl mov al,dh stos word [edi] jmp instruction_assembled fcomi_st0_streg: or ah,ah jnz invalid_operand inc esi lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_fpu_register mov ah,al add ah,dl mov al,dh stos word [edi] jmp instruction_assembled basic_mmx_instruction: mov [base_code],0Fh mov [extended_code],al mmx_instruction: lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register call make_mmx_prefix mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je mmx_mmreg_mmreg cmp al,'[' jne invalid_operand mmx_mmreg_mem: call get_address jmp instruction_ready mmx_mmreg_mmreg: lods byte [esi] call convert_mmx_register mov bl,al jmp nomem_instruction_ready mmx_bit_shift_instruction: mov [base_code],0Fh mov [extended_code],al lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register call make_mmx_prefix mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand mov [operand_size],0 lods byte [esi] call get_size_operator cmp al,10h je mmx_mmreg_mmreg cmp al,'(' je mmx_ps_mmreg_imm8 cmp al,'[' je mmx_mmreg_mem jmp invalid_operand mmx_ps_mmreg_imm8: call get_byte_value mov byte [value],al test [operand_size],not 1 jnz invalid_value mov bl,[extended_code] mov al,bl shr bl,4 and al,1111b add al,70h mov [extended_code],al sub bl,0Ch shl bl,1 xchg bl,[postbyte_register] call store_nomem_instruction mov al,byte [value] stos byte [edi] jmp instruction_assembled pmovmskb_instruction: mov [base_code],0Fh mov [extended_code],al call take_register cmp ah,4 je pmovmskb_reg_size_ok cmp [code_type],64 jne invalid_operand_size cmp ah,8 jnz invalid_operand_size pmovmskb_reg_size_ok: mov [postbyte_register],al mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register mov bl,al call make_mmx_prefix cmp [extended_code],0C5h je mmx_nomem_imm8 jmp nomem_instruction_ready mmx_imm8: push ebx ecx edx xor cl,cl xchg cl,[operand_size] lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator test ah,not 1 jnz invalid_operand_size mov [operand_size],cl cmp al,'(' jne invalid_operand call get_byte_value mov byte [value],al pop edx ecx ebx call store_instruction_with_imm8 jmp instruction_assembled mmx_nomem_imm8: call store_nomem_instruction call append_imm8 jmp instruction_assembled append_imm8: mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator test ah,not 1 jnz invalid_operand_size cmp al,'(' jne invalid_operand call get_byte_value stosb ret pinsrw_instruction: mov [extended_code],al mov [base_code],0Fh lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register call make_mmx_prefix mov [postbyte_register],al mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je pinsrw_mmreg_reg cmp al,'[' jne invalid_operand call get_address cmp [operand_size],0 je mmx_imm8 cmp [operand_size],2 jne invalid_operand_size jmp mmx_imm8 pinsrw_mmreg_reg: lods byte [esi] call convert_register cmp ah,4 jne invalid_operand_size mov bl,al jmp mmx_nomem_imm8 pshufw_instruction: mov [mmx_size],8 mov [opcode_prefix],al jmp pshuf_instruction pshufd_instruction: mov [mmx_size],16 mov [opcode_prefix],al pshuf_instruction: mov [base_code],0Fh mov [extended_code],70h lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register cmp ah,[mmx_size] jne invalid_operand_size mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je pshuf_mmreg_mmreg cmp al,'[' jne invalid_operand call get_address jmp mmx_imm8 pshuf_mmreg_mmreg: lods byte [esi] call convert_mmx_register mov bl,al jmp mmx_nomem_imm8 movd_instruction: mov [base_code],0Fh mov [extended_code],7Eh lods byte [esi] call get_size_operator cmp al,10h je movd_reg cmp al,'[' jne invalid_operand call get_address test [operand_size],not 4 jnz invalid_operand_size call get_mmx_source_register jmp instruction_ready movd_reg: lods byte [esi] cmp al,0B0h jae movd_mmreg call convert_register cmp ah,4 jne invalid_operand_size mov bl,al call get_mmx_source_register jmp nomem_instruction_ready movd_mmreg: mov [extended_code],6Eh call convert_mmx_register mov [postbyte_register],al call make_mmx_prefix mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je movd_mmreg_reg cmp al,'[' jne invalid_operand call get_address test [operand_size],not 4 jnz invalid_operand_size jmp instruction_ready movd_mmreg_reg: lods byte [esi] call convert_register cmp ah,4 jne invalid_operand_size mov bl,al jmp nomem_instruction_ready get_mmx_source_register: mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register mov [postbyte_register],al make_mmx_prefix: cmp [operand_size],16 jne no_mmx_prefix mov [operand_prefix],66h no_mmx_prefix: ret movq_instruction: mov [base_code],0Fh lods byte [esi] call get_size_operator cmp al,10h je movq_reg cmp al,'[' jne invalid_operand call get_address test [operand_size],not 8 jnz invalid_operand_size call get_mmx_source_register mov al,7Fh cmp ah,8 je movq_mem_ready mov al,0D6h movq_mem_ready: mov [extended_code],al jmp instruction_ready movq_reg: lods byte [esi] cmp al,0B0h jae movq_mmreg call convert_register cmp ah,8 jne invalid_operand_size mov bl,al mov [extended_code],7Eh call operand_64bit call get_mmx_source_register jmp nomem_instruction_ready movq_mmreg: call convert_mmx_register mov [postbyte_register],al mov [extended_code],6Fh mov [mmx_size],ah cmp ah,16 jne movq_mmreg_ mov [extended_code],7Eh mov [opcode_prefix],0F3h movq_mmreg_: lods byte [esi] cmp al,',' jne invalid_operand mov [operand_size],0 lods byte [esi] call get_size_operator cmp al,10h je movq_mmreg_reg cmp al,'[' jne invalid_operand call get_address test [operand_size],not 8 jnz invalid_operand_size jmp instruction_ready movq_mmreg_reg: lods byte [esi] cmp al,0B0h jae movq_mmreg_mmreg mov [operand_size],0 call convert_register cmp ah,8 jne invalid_operand_size mov [extended_code],6Eh mov [opcode_prefix],0 mov bl,al cmp [mmx_size],16 jne movq_mmreg_reg_store mov [opcode_prefix],66h movq_mmreg_reg_store: call operand_64bit jmp nomem_instruction_ready movq_mmreg_mmreg: call convert_mmx_register cmp ah,[mmx_size] jne invalid_operand_size mov bl,al jmp nomem_instruction_ready movdq_instruction: mov [opcode_prefix],al mov [base_code],0Fh mov [extended_code],6Fh lods byte [esi] call get_size_operator cmp al,10h je movdq_mmreg cmp al,'[' jne invalid_operand call get_address lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al mov [extended_code],7Fh jmp instruction_ready movdq_mmreg: lods byte [esi] call convert_xmm_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je movdq_mmreg_mmreg cmp al,'[' jne invalid_operand call get_address jmp instruction_ready movdq_mmreg_mmreg: lods byte [esi] call convert_xmm_register mov bl,al jmp nomem_instruction_ready lddqu_instruction: lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register push eax lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address pop eax mov [postbyte_register],al mov [opcode_prefix],0F2h mov [base_code],0Fh mov [extended_code],0F0h jmp instruction_ready movdq2q_instruction: mov [opcode_prefix],0F2h mov [mmx_size],8 jmp movq2dq_ movq2dq_instruction: mov [opcode_prefix],0F3h mov [mmx_size],16 movq2dq_: lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register cmp ah,[mmx_size] jne invalid_operand_size mov [postbyte_register],al mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register xor [mmx_size],8+16 cmp ah,[mmx_size] jne invalid_operand_size mov bl,al mov [base_code],0Fh mov [extended_code],0D6h jmp nomem_instruction_ready sse_ps_instruction_imm8: mov [immediate_size],1 sse_ps_instruction: mov [mmx_size],16 jmp sse_instruction sse_pd_instruction_imm8: mov [immediate_size],1 sse_pd_instruction: mov [mmx_size],16 mov [opcode_prefix],66h jmp sse_instruction sse_ss_instruction: mov [mmx_size],4 mov [opcode_prefix],0F3h jmp sse_instruction sse_sd_instruction: mov [mmx_size],8 mov [opcode_prefix],0F2h jmp sse_instruction cmp_pd_instruction: mov [opcode_prefix],66h cmp_ps_instruction: mov [mmx_size],16 mov byte [value],al mov al,0C2h jmp sse_instruction cmp_ss_instruction: mov [mmx_size],4 mov [opcode_prefix],0F3h jmp cmp_sx_instruction cmpsd_instruction: mov al,0A7h mov ah,[esi] or ah,ah jz simple_instruction_32bit cmp ah,0Fh je simple_instruction_32bit mov al,-1 cmp_sd_instruction: mov [mmx_size],8 mov [opcode_prefix],0F2h cmp_sx_instruction: mov byte [value],al mov al,0C2h jmp sse_instruction comiss_instruction: mov [mmx_size],4 jmp sse_instruction comisd_instruction: mov [mmx_size],8 mov [opcode_prefix],66h jmp sse_instruction cvtdq2pd_instruction: mov [opcode_prefix],0F3h cvtps2pd_instruction: mov [mmx_size],8 jmp sse_instruction cvtpd2dq_instruction: mov [mmx_size],16 mov [opcode_prefix],0F2h jmp sse_instruction movshdup_instruction: mov [mmx_size],16 mov [opcode_prefix],0F3h sse_instruction: mov [base_code],0Fh mov [extended_code],al lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand sse_xmmreg: lods byte [esi] call convert_xmm_register sse_reg: mov [postbyte_register],al mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je sse_xmmreg_xmmreg sse_reg_mem: cmp al,'[' jne invalid_operand call get_address cmp [operand_size],0 je sse_mem_size_ok mov al,[mmx_size] cmp [operand_size],al jne invalid_operand_size sse_mem_size_ok: mov al,[extended_code] mov ah,[supplemental_code] cmp al,0C2h je sse_cmp_mem_ok cmp ax,443Ah je sse_cmp_mem_ok cmp [immediate_size],1 je mmx_imm8 cmp [immediate_size],-1 jne sse_ok call take_additional_xmm0 mov [immediate_size],0 sse_ok: jmp instruction_ready sse_cmp_mem_ok: cmp byte [value],-1 je mmx_imm8 call store_instruction_with_imm8 jmp instruction_assembled sse_xmmreg_xmmreg: cmp [operand_prefix],66h jne sse_xmmreg_xmmreg_ok cmp [extended_code],12h je invalid_operand cmp [extended_code],16h je invalid_operand sse_xmmreg_xmmreg_ok: lods byte [esi] call convert_xmm_register mov bl,al mov al,[extended_code] mov ah,[supplemental_code] cmp al,0C2h je sse_cmp_nomem_ok cmp ax,443Ah je sse_cmp_nomem_ok cmp [immediate_size],1 je mmx_nomem_imm8 cmp [immediate_size],-1 jne sse_nomem_ok call take_additional_xmm0 mov [immediate_size],0 sse_nomem_ok: jmp nomem_instruction_ready sse_cmp_nomem_ok: cmp byte [value],-1 je mmx_nomem_imm8 call store_nomem_instruction mov al,byte [value] stosb jmp instruction_assembled take_additional_xmm0: cmp byte [esi],',' jne additional_xmm0_ok inc esi lods byte [esi] cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register test al,al jnz invalid_operand additional_xmm0_ok: ret pslldq_instruction: mov [postbyte_register],al mov [opcode_prefix],66h mov [base_code],0Fh mov [extended_code],73h lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov bl,al jmp mmx_nomem_imm8 movpd_instruction: mov [opcode_prefix],66h movps_instruction: mov [base_code],0Fh mov [extended_code],al mov [mmx_size],16 jmp sse_mov_instruction movss_instruction: mov [mmx_size],4 mov [opcode_prefix],0F3h jmp sse_movs movsd_instruction: mov al,0A5h mov ah,[esi] or ah,ah jz simple_instruction_32bit cmp ah,0Fh je simple_instruction_32bit mov [mmx_size],8 mov [opcode_prefix],0F2h sse_movs: mov [base_code],0Fh mov [extended_code],10h jmp sse_mov_instruction sse_mov_instruction: lods byte [esi] call get_size_operator cmp al,10h je sse_xmmreg sse_mem: cmp al,'[' jne invalid_operand inc [extended_code] call get_address cmp [operand_size],0 je sse_mem_xmmreg mov al,[mmx_size] cmp [operand_size],al jne invalid_operand_size mov [operand_size],0 sse_mem_xmmreg: lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al jmp instruction_ready movlpd_instruction: mov [opcode_prefix],66h movlps_instruction: mov [base_code],0Fh mov [extended_code],al mov [mmx_size],8 lods byte [esi] call get_size_operator cmp al,10h jne sse_mem lods byte [esi] call convert_xmm_register mov [postbyte_register],al mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator jmp sse_reg_mem movhlps_instruction: mov [base_code],0Fh mov [extended_code],al mov [mmx_size],0 lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je sse_xmmreg_xmmreg_ok jmp invalid_operand maskmovq_instruction: mov cl,8 jmp maskmov_instruction maskmovdqu_instruction: mov cl,16 mov [opcode_prefix],66h maskmov_instruction: mov [base_code],0Fh mov [extended_code],0F7h lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register cmp ah,cl jne invalid_operand_size mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register mov bl,al jmp nomem_instruction_ready movmskpd_instruction: mov [opcode_prefix],66h movmskps_instruction: mov [base_code],0Fh mov [extended_code],50h call take_register mov [postbyte_register],al cmp ah,4 je movmskps_reg_ok cmp ah,8 jne invalid_operand_size cmp [code_type],64 jne invalid_operand movmskps_reg_ok: mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je sse_xmmreg_xmmreg_ok jmp invalid_operand cvtpi2pd_instruction: mov [opcode_prefix],66h cvtpi2ps_instruction: mov [base_code],0Fh mov [extended_code],al lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je cvtpi_xmmreg_xmmreg cmp al,'[' jne invalid_operand call get_address cmp [operand_size],0 je cvtpi_size_ok cmp [operand_size],8 jne invalid_operand_size cvtpi_size_ok: jmp instruction_ready cvtpi_xmmreg_xmmreg: lods byte [esi] call convert_mmx_register cmp ah,8 jne invalid_operand_size mov bl,al jmp nomem_instruction_ready cvtsi2ss_instruction: mov [opcode_prefix],0F3h jmp cvtsi_instruction cvtsi2sd_instruction: mov [opcode_prefix],0F2h cvtsi_instruction: mov [base_code],0Fh mov [extended_code],al lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al cvtsi_xmmreg: mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je cvtsi_xmmreg_reg cmp al,'[' jne invalid_operand call get_address cmp [operand_size],0 je cvtsi_size_ok cmp [operand_size],4 je cvtsi_size_ok cmp [operand_size],8 jne invalid_operand_size call operand_64bit cvtsi_size_ok: jmp instruction_ready cvtsi_xmmreg_reg: lods byte [esi] call convert_register cmp ah,4 je cvtsi_xmmreg_reg_store cmp ah,8 jne invalid_operand_size call operand_64bit cvtsi_xmmreg_reg_store: mov bl,al jmp nomem_instruction_ready cvtps2pi_instruction: mov [mmx_size],8 jmp cvtpd_instruction cvtpd2pi_instruction: mov [opcode_prefix],66h mov [mmx_size],16 cvtpd_instruction: mov [base_code],0Fh mov [extended_code],al lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register cmp ah,8 jne invalid_operand_size mov [operand_size],0 jmp sse_reg cvtss2si_instruction: mov [opcode_prefix],0F3h mov [mmx_size],4 jmp cvt2si_instruction cvtsd2si_instruction: mov [opcode_prefix],0F2h mov [mmx_size],8 cvt2si_instruction: mov [extended_code],al mov [base_code],0Fh call take_register mov [operand_size],0 cmp ah,4 je sse_reg cmp ah,8 jne invalid_operand_size call operand_64bit jmp sse_reg ssse3_instruction: mov [base_code],0Fh mov [extended_code],38h mov [supplemental_code],al jmp mmx_instruction palignr_instruction: mov [base_code],0Fh mov [extended_code],3Ah mov [supplemental_code],0Fh lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register call make_mmx_prefix mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je palignr_mmreg_mmreg cmp al,'[' jne invalid_operand call get_address jmp mmx_imm8 palignr_mmreg_mmreg: lods byte [esi] call convert_mmx_register mov bl,al jmp mmx_nomem_imm8 amd3dnow_instruction: mov [base_code],0Fh mov [extended_code],0Fh mov byte [value],al lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register cmp ah,8 jne invalid_operand_size mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je amd3dnow_mmreg_mmreg cmp al,'[' jne invalid_operand call get_address call store_instruction_with_imm8 jmp instruction_assembled amd3dnow_mmreg_mmreg: lods byte [esi] call convert_mmx_register cmp ah,8 jne invalid_operand_size mov bl,al call store_nomem_instruction mov al,byte [value] stos byte [edi] jmp instruction_assembled sse4_instruction_38_xmm0: mov [immediate_size],-1 jmp sse4_instruction_38 sse4_instruction_66_38_xmm0: mov [immediate_size],-1 sse4_instruction_66_38: mov [opcode_prefix],66h sse4_instruction_38: mov [mmx_size],16 mov [supplemental_code],al mov al,38h jmp sse_instruction sse4_ss_instruction_66_3a_imm8: mov [immediate_size],1 mov cl,4 jmp sse4_instruction_66_3a_setup sse4_sd_instruction_66_3a_imm8: mov [immediate_size],1 mov cl,8 jmp sse4_instruction_66_3a_setup sse4_instruction_66_3a_imm8: mov [immediate_size],1 mov cl,16 sse4_instruction_66_3a_setup: mov [opcode_prefix],66h sse4_instruction_3a_setup: mov [supplemental_code],al mov al,3Ah mov [mmx_size],cl jmp sse_instruction sse4_instruction_3a_imm8: mov [immediate_size],1 mov cl,16 jmp sse4_instruction_3a_setup pclmulqdq_instruction: mov byte [value],al mov al,44h mov cl,16 jmp sse4_instruction_66_3a_setup extractps_instruction: call setup_66_0f_3a lods byte [esi] call get_size_operator cmp al,10h je extractps_reg cmp al,'[' jne invalid_operand call get_address cmp [operand_size],4 je extractps_size_ok cmp [operand_size],0 jne invalid_operand_size extractps_size_ok: push edx ebx ecx mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al pop ecx ebx edx jmp mmx_imm8 extractps_reg: lods byte [esi] call convert_register push eax mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al pop ebx mov al,bh cmp al,4 je mmx_nomem_imm8 cmp al,8 jne invalid_operand_size cmp [code_type],64 jne illegal_instruction jmp mmx_nomem_imm8 setup_66_0f_3a: mov [extended_code],3Ah mov [supplemental_code],al mov [base_code],0Fh mov [opcode_prefix],66h ret insertps_instruction: call setup_66_0f_3a lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je insertps_xmmreg_reg cmp al,'[' jne invalid_operand call get_address cmp [operand_size],4 je insertps_size_ok cmp [operand_size],0 jne invalid_operand_size insertps_size_ok: jmp mmx_imm8 insertps_xmmreg_reg: lods byte [esi] call convert_mmx_register mov bl,al jmp mmx_nomem_imm8 pextrq_instruction: mov [mmx_size],8 jmp pextr_instruction pextrd_instruction: mov [mmx_size],4 jmp pextr_instruction pextrw_instruction: mov [mmx_size],2 jmp pextr_instruction pextrb_instruction: mov [mmx_size],1 pextr_instruction: call setup_66_0f_3a lods byte [esi] call get_size_operator cmp al,10h je pextr_reg cmp al,'[' jne invalid_operand call get_address mov al,[mmx_size] cmp al,[operand_size] je pextr_size_ok cmp [operand_size],0 jne invalid_operand_size pextr_size_ok: cmp al,8 jne pextr_prefix_ok call operand_64bit pextr_prefix_ok: push edx ebx ecx mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al pop ecx ebx edx jmp mmx_imm8 pextr_reg: lods byte [esi] call convert_register cmp [mmx_size],4 ja pextrq_reg cmp ah,4 je pextr_reg_size_ok cmp [code_type],64 jne pextr_invalid_size cmp ah,8 je pextr_reg_size_ok pextr_invalid_size: jmp invalid_operand_size pextrq_reg: cmp ah,8 jne pextr_invalid_size call operand_64bit pextr_reg_size_ok: mov [operand_size],0 push eax lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register mov ebx,eax pop eax mov [postbyte_register],al mov al,ah cmp [mmx_size],2 jne pextr_reg_store mov [opcode_prefix],0 mov [extended_code],0C5h call make_mmx_prefix jmp mmx_nomem_imm8 pextr_reg_store: cmp bh,16 jne invalid_operand_size xchg bl,[postbyte_register] jmp mmx_nomem_imm8 pinsrb_instruction: mov [mmx_size],1 jmp pinsr_instruction pinsrd_instruction: mov [mmx_size],4 jmp pinsr_instruction pinsrq_instruction: mov [mmx_size],8 call operand_64bit pinsr_instruction: call setup_66_0f_3a lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al pinsr_xmmreg: mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je pinsr_xmmreg_reg cmp al,'[' jne invalid_operand call get_address cmp [operand_size],0 je mmx_imm8 mov al,[mmx_size] cmp al,[operand_size] je mmx_imm8 jmp invalid_operand_size pinsr_xmmreg_reg: lods byte [esi] call convert_register mov bl,al cmp [mmx_size],8 je pinsrq_xmmreg_reg cmp ah,4 je mmx_nomem_imm8 jmp invalid_operand_size pinsrq_xmmreg_reg: cmp ah,8 je mmx_nomem_imm8 jmp invalid_operand_size pmovsxbw_instruction: mov [mmx_size],8 jmp pmovsx_instruction pmovsxbd_instruction: mov [mmx_size],4 jmp pmovsx_instruction pmovsxbq_instruction: mov [mmx_size],2 jmp pmovsx_instruction pmovsxwd_instruction: mov [mmx_size],8 jmp pmovsx_instruction pmovsxwq_instruction: mov [mmx_size],4 jmp pmovsx_instruction pmovsxdq_instruction: mov [mmx_size],8 pmovsx_instruction: call setup_66_0f_38 lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand mov [operand_size],0 lods byte [esi] call get_size_operator cmp al,10h je pmovsx_xmmreg_reg cmp al,'[' jne invalid_operand call get_address cmp [operand_size],0 je instruction_ready mov al,[mmx_size] cmp al,[operand_size] jne invalid_operand_size jmp instruction_ready pmovsx_xmmreg_reg: lods byte [esi] call convert_xmm_register mov bl,al jmp nomem_instruction_ready setup_66_0f_38: mov [extended_code],38h mov [supplemental_code],al mov [base_code],0Fh mov [opcode_prefix],66h ret xsaves_instruction_64bit: call operand_64bit xsaves_instruction: mov ah,0C7h jmp xsave_common fxsave_instruction_64bit: call operand_64bit fxsave_instruction: mov ah,0AEh xor cl,cl xsave_common: mov [base_code],0Fh mov [extended_code],ah mov [postbyte_register],al mov [mmx_size],cl lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov ah,[operand_size] or ah,ah jz xsave_size_ok cmp ah,[mmx_size] jne invalid_operand_size xsave_size_ok: jmp instruction_ready clflush_instruction: mov ah,0AEh mov cl,1 jmp xsave_common cldemote_instruction: mov ah,1Ch mov cl,1 jmp xsave_common stmxcsr_instruction: mov ah,0AEh mov cl,4 jmp xsave_common prefetch_instruction: mov [extended_code],18h prefetch_mem_8bit: mov [base_code],0Fh mov [postbyte_register],al lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand or ah,ah jz prefetch_size_ok cmp ah,1 jne invalid_operand_size prefetch_size_ok: call get_address jmp instruction_ready amd_prefetch_instruction: mov [extended_code],0Dh jmp prefetch_mem_8bit clflushopt_instruction: mov [extended_code],0AEh mov [opcode_prefix],66h jmp prefetch_mem_8bit pcommit_instruction: mov byte [edi],66h inc edi fence_instruction: mov bl,al mov ax,0AE0Fh stos word [edi] mov al,bl stos byte [edi] jmp instruction_assembled pause_instruction: mov ax,90F3h stos word [edi] jmp instruction_assembled movntq_instruction: mov [mmx_size],8 jmp movnt_instruction movntpd_instruction: mov [opcode_prefix],66h movntps_instruction: mov [mmx_size],16 movnt_instruction: mov [extended_code],al mov [base_code],0Fh lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_mmx_register cmp ah,[mmx_size] jne invalid_operand_size mov [postbyte_register],al jmp instruction_ready movntsd_instruction: mov [opcode_prefix],0F2h mov [mmx_size],8 jmp movnts_instruction movntss_instruction: mov [opcode_prefix],0F3h mov [mmx_size],4 movnts_instruction: mov [extended_code],al mov [base_code],0Fh lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] cmp al,[mmx_size] je movnts_size_ok test al,al jnz invalid_operand_size movnts_size_ok: lods byte [esi] cmp al,',' jne invalid_operand mov [operand_size],0 lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al jmp instruction_ready movdiri_instruction: mov [supplemental_code],al mov al,38h movnti_instruction: mov [base_code],0Fh mov [extended_code],al lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address lods byte [esi] cmp al,',' jne invalid_operand call take_register cmp ah,4 je movnti_store cmp ah,8 jne invalid_operand_size call operand_64bit movnti_store: mov [postbyte_register],al jmp instruction_ready monitor_instruction: mov [postbyte_register],al cmp byte [esi],0 je monitor_instruction_store cmp byte [esi],0Fh je monitor_instruction_store call take_register cmp ax,0400h jne invalid_operand lods byte [esi] cmp al,',' jne invalid_operand call take_register cmp ax,0401h jne invalid_operand cmp [postbyte_register],0C8h jne monitor_instruction_store lods byte [esi] cmp al,',' jne invalid_operand call take_register cmp ax,0402h jne invalid_operand monitor_instruction_store: mov ax,010Fh stos word [edi] mov al,[postbyte_register] stos byte [edi] jmp instruction_assembled pconfig_instruction: mov [postbyte_register],al jmp monitor_instruction_store movntdqa_instruction: call setup_66_0f_38 lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address jmp instruction_ready extrq_instruction: mov [opcode_prefix],66h mov [base_code],0Fh mov [extended_code],78h lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je extrq_xmmreg_xmmreg test ah,not 1 jnz invalid_operand_size cmp al,'(' jne invalid_operand xor bl,bl xchg bl,[postbyte_register] call store_nomem_instruction call get_byte_value stosb call append_imm8 jmp instruction_assembled extrq_xmmreg_xmmreg: inc [extended_code] lods byte [esi] call convert_xmm_register mov bl,al jmp nomem_instruction_ready insertq_instruction: mov [opcode_prefix],0F2h mov [base_code],0Fh mov [extended_code],78h lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov [postbyte_register],al mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_xmm_register mov bl,al cmp byte [esi],',' je insertq_with_imm inc [extended_code] jmp nomem_instruction_ready insertq_with_imm: call store_nomem_instruction call append_imm8 call append_imm8 jmp instruction_assembled crc32_instruction: mov [opcode_prefix],0F2h mov [base_code],0Fh mov [extended_code],38h mov [supplemental_code],0F0h call take_register mov [postbyte_register],al cmp ah,4 je crc32_reg_size_ok cmp ah,8 jne invalid_operand cmp [code_type],64 jne illegal_instruction crc32_reg_size_ok: lods byte [esi] cmp al,',' jne invalid_operand mov [operand_size],0 lods byte [esi] call get_size_operator cmp al,10h je crc32_reg_reg cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] test al,al jz crc32_unknown_size cmp al,1 je crc32_reg_mem_store inc [supplemental_code] call operand_autodetect crc32_reg_mem_store: jmp instruction_ready crc32_unknown_size: call recoverable_unknown_size jmp crc32_reg_mem_store crc32_reg_reg: lods byte [esi] call convert_register mov bl,al mov al,ah cmp al,1 je crc32_reg_reg_store inc [supplemental_code] call operand_autodetect crc32_reg_reg_store: jmp nomem_instruction_ready popcnt_instruction: mov [opcode_prefix],0F3h jmp bs_instruction movbe_instruction: mov [supplemental_code],al mov [extended_code],38h mov [base_code],0Fh lods byte [esi] call get_size_operator cmp al,'[' je movbe_mem cmp al,10h jne invalid_operand lods byte [esi] call convert_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' jne invalid_argument call get_address mov al,[operand_size] call operand_autodetect jmp instruction_ready movbe_mem: inc [supplemental_code] call get_address push edx ebx ecx lods byte [esi] cmp al,',' jne invalid_operand call take_register mov [postbyte_register],al pop ecx ebx edx mov al,[operand_size] call operand_autodetect jmp instruction_ready adx_instruction: mov [base_code],0Fh mov [extended_code],38h mov [supplemental_code],0F6h mov [operand_prefix],al call get_reg_mem jc adx_reg_reg mov al,[operand_size] cmp al,4 je instruction_ready cmp al,8 jne invalid_operand_size call operand_64bit jmp instruction_ready adx_reg_reg: cmp ah,4 je nomem_instruction_ready cmp ah,8 jne invalid_operand_size call operand_64bit jmp nomem_instruction_ready rdpid_instruction: mov [postbyte_register],al mov [extended_code],0C7h mov [base_code],0Fh mov [opcode_prefix],0F3h call take_register mov bl,al cmp [code_type],64 je rdpid_64bit cmp ah,4 jne invalid_operand_size jmp nomem_instruction_ready rdpid_64bit: cmp ah,8 jne invalid_operand_size jmp nomem_instruction_ready ptwrite_instruction: mov [base_code],0Fh mov [extended_code],0AEh mov [postbyte_register],al mov [opcode_prefix],0F3h lods byte [esi] call get_size_operator cmp al,10h je ptwrite_reg ptwrite_mem: cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] cmp al,4 je ptwrite_mem_store cmp al,8 je ptwrite_mem_64bit or al,al jnz invalid_operand_size call recoverable_unknown_size jmp ptwrite_mem_store ptwrite_mem_64bit: call operand_64bit ptwrite_mem_store: mov al,[operand_size] call operand_autodetect jmp instruction_ready ptwrite_reg: lods byte [esi] call convert_register mov bl,al mov al,ah cmp al,4 je nomem_instruction_ready cmp al,8 jne invalid_operand_size call operand_64bit jmp nomem_instruction_ready vmclear_instruction: mov [opcode_prefix],66h jmp vmx_instruction vmxon_instruction: mov [opcode_prefix],0F3h vmx_instruction: mov [postbyte_register],al mov [extended_code],0C7h lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] or al,al jz vmx_size_ok cmp al,8 jne invalid_operand_size vmx_size_ok: mov [base_code],0Fh jmp instruction_ready vmread_instruction: mov [extended_code],78h lods byte [esi] call get_size_operator cmp al,10h je vmread_nomem cmp al,'[' jne invalid_operand call get_address lods byte [esi] cmp al,',' jne invalid_operand call take_register mov [postbyte_register],al call vmread_check_size jmp vmx_size_ok vmread_nomem: lods byte [esi] call convert_register push eax call vmread_check_size lods byte [esi] cmp al,',' jne invalid_operand call take_register mov [postbyte_register],al call vmread_check_size pop ebx mov [base_code],0Fh jmp nomem_instruction_ready vmread_check_size: cmp [code_type],64 je vmread_long cmp [operand_size],4 jne invalid_operand_size ret vmread_long: cmp [operand_size],8 jne invalid_operand_size ret vmwrite_instruction: mov [extended_code],79h call take_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,10h je vmwrite_nomem cmp al,'[' jne invalid_operand call get_address call vmread_check_size jmp vmx_size_ok vmwrite_nomem: lods byte [esi] call convert_register mov bl,al mov [base_code],0Fh jmp nomem_instruction_ready vmx_inv_instruction: call setup_66_0f_38 call take_register mov [postbyte_register],al call vmread_check_size mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] or al,al jz vmx_size_ok cmp al,16 jne invalid_operand_size jmp vmx_size_ok simple_svm_instruction: push eax mov [base_code],0Fh mov [extended_code],1 call take_register or al,al jnz invalid_operand simple_svm_detect_size: cmp ah,2 je simple_svm_16bit cmp ah,4 je simple_svm_32bit cmp [code_type],64 jne invalid_operand_size jmp simple_svm_store simple_svm_16bit: cmp [code_type],16 je simple_svm_store cmp [code_type],64 je invalid_operand_size jmp prefixed_svm_store simple_svm_32bit: cmp [code_type],32 je simple_svm_store prefixed_svm_store: mov al,67h stos byte [edi] simple_svm_store: call store_classic_instruction_code pop eax stos byte [edi] jmp instruction_assembled skinit_instruction: call take_register cmp ax,0400h jne invalid_operand mov al,0DEh jmp simple_instruction_0f_01 clzero_instruction: call take_register or al,al jnz invalid_operand mov al,0FCh cmp [code_type],64 je clzero_64bit cmp ah,4 jne invalid_operand jmp simple_instruction_0f_01 clzero_64bit: cmp ah,8 jne invalid_operand jmp simple_instruction_0f_01 invlpga_instruction: push eax mov [base_code],0Fh mov [extended_code],1 call take_register or al,al jnz invalid_operand mov bl,ah mov [operand_size],0 lods byte [esi] cmp al,',' jne invalid_operand call take_register cmp ax,0401h jne invalid_operand mov ah,bl jmp simple_svm_detect_size rdrand_instruction: mov [base_code],0Fh mov [extended_code],0C7h mov [postbyte_register],al call take_register mov bl,al mov al,ah call operand_autodetect jmp nomem_instruction_ready rdfsbase_instruction: cmp [code_type],64 jne illegal_instruction mov [opcode_prefix],0F3h mov [base_code],0Fh mov [extended_code],0AEh mov [postbyte_register],al call take_register mov bl,al mov al,ah cmp ah,2 je invalid_operand_size call operand_autodetect jmp nomem_instruction_ready xabort_instruction: lods byte [esi] call get_size_operator cmp ah,1 ja invalid_operand_size cmp al,'(' jne invalid_operand call get_byte_value mov dl,al mov ax,0F8C6h stos word [edi] mov al,dl stos byte [edi] jmp instruction_assembled xbegin_instruction: lods byte [esi] cmp al,'(' jne invalid_operand mov al,[code_type] cmp al,64 je xbegin_64bit cmp al,32 je xbegin_32bit xbegin_16bit: call get_address_word_value add edi,4 mov ebp,[addressing_space] call calculate_relative_offset sub edi,4 shl eax,16 mov ax,0F8C7h stos dword [edi] jmp instruction_assembled xbegin_32bit: call get_address_dword_value jmp xbegin_address_ok xbegin_64bit: call get_address_qword_value xbegin_address_ok: add edi,5 mov ebp,[addressing_space] call calculate_relative_offset sub edi,5 mov edx,eax cwde cmp eax,edx jne xbegin_rel32 mov al,66h stos byte [edi] mov eax,edx shl eax,16 mov ax,0F8C7h stos dword [edi] jmp instruction_assembled xbegin_rel32: sub edx,1 jno xbegin_rel32_ok cmp [code_type],64 je jump_out_of_range xbegin_rel32_ok: mov ax,0F8C7h stos word [edi] mov eax,edx stos dword [edi] jmp instruction_assembled bndcl_instruction: mov ah,0F3h jmp bndc_instruction bndcu_instruction: mov ah,0F2h bndc_instruction: mov [opcode_prefix],ah mov [base_code],0Fh mov [extended_code],al call take_bnd_register mov [postbyte_register],al call get_bnd_size mov [operand_size],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' je bndc_mem cmp al,10h jne invalid_operand lods byte [esi] call convert_register mov bl,al jmp nomem_instruction_ready bndc_mem: call get_address_of_required_size jmp instruction_ready bndmov_instruction: mov [opcode_prefix],66h mov [base_code],0Fh mov [extended_code],al call get_bnd_size shl al,1 mov [operand_size],al lods byte [esi] cmp al,14h je bndmov_reg call get_size_operator cmp al,'[' jne invalid_operand inc [extended_code] call get_address_of_required_size lods byte [esi] cmp al,',' jne invalid_operand call take_bnd_register mov [postbyte_register],al jmp instruction_ready bndmov_reg: lods byte [esi] call convert_bnd_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] cmp al,14h je bndmov_reg_reg call get_size_operator cmp al,'[' jne invalid_operand call get_address_of_required_size jmp instruction_ready bndmov_reg_reg: lods byte [esi] call convert_bnd_register mov bl,al jmp nomem_instruction_ready take_bnd_register: lods byte [esi] cmp al,14h jne invalid_operand lods byte [esi] convert_bnd_register: mov ah,al shr ah,4 cmp ah,6 jne invalid_operand and al,1111b ret bndmk_instruction: mov [opcode_prefix],0F3h mov [base_code],0Fh mov [extended_code],al call take_bnd_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_bnd_size call get_address_prefixes call get_address_component cmp byte [esi-1],']' je bndmk_ready lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] cmp al,'(' jne invalid_operand or dl,bl or dl,[address_sign] or edx,[address_high] jnz invalid_address mov [address_register],bh call get_address_component lods byte [esi] cmp al,']' jne invalid_operand or bh,bh jz bndmk_selected_base cmp bl,bh je bndmk_to_index or bl,bl jnz invalid_address mov bl,bh bndmk_to_index: inc cl bndmk_selected_base: mov bh,[address_register] bndmk_ready: or bx,bx jz instruction_ready cmp [address_size_declared],0 jne instruction_ready and ch,not 0Fh jmp instruction_ready get_bnd_size: mov al,4 cmp [code_type],64 jne bnd_size_ok add al,4 bnd_size_ok: mov [address_size],al ret get_address_component: mov [free_address_range],0 call calculate_address mov [address_high],edx mov edx,eax or bx,bx jz address_component_ok mov al,bl or al,bh shr al,4 cmp al,[address_size] jne invalid_address address_component_ok: ret bndldx_instruction: mov [base_code],0Fh mov [extended_code],al call take_bnd_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_bnd_mib jmp bndmk_ready bndstx_instruction: mov [base_code],0Fh mov [extended_code],al call take_bnd_mib lods byte [esi] cmp al,',' jne invalid_operand call take_bnd_register mov [postbyte_register],al jmp bndmk_ready take_bnd_mib: lods byte [esi] cmp al,'[' jne invalid_operand call get_bnd_size call get_address_prefixes call get_address_component cmp byte [esi-1],']' je bnd_mib_ok lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] cmp al,'(' jne invalid_operand mov al,[address_sign] push eax ebx ecx edx push [address_symbol] call get_address_component lods byte [esi] cmp al,']' jne invalid_operand or dl,bl or dl,[address_sign] or edx,[address_high] jnz invalid_address mov [address_register],bh pop [address_symbol] pop edx ecx ebx eax mov [address_sign],al or bl,bl jz mib_place_index or bh,bh jnz invalid_address cmp cl,1 jne invalid_address mov bh,bl mib_place_index: mov bl,[address_register] xor cl,cl or bl,bl jz bnd_mib_ok inc cl bnd_mib_ok: ret tpause_instruction: mov [postbyte_register],6 mov [extended_code],0AEh mov [base_code],0Fh mov [opcode_prefix],al call take_register cmp ah,4 jne invalid_operand_size mov bl,al cmp byte [esi],',' jne nomem_instruction_ready inc esi call take_register cmp ax,0402h jne invalid_operand lods byte [esi] cmp al,',' jne invalid_operand call take_register cmp ax,0400h jne invalid_operand jmp nomem_instruction_ready umonitor_instruction: mov [postbyte_register],6 mov [extended_code],0AEh mov [base_code],0Fh mov [opcode_prefix],0F3h call take_register mov bl,al mov al,ah call operand_autodetect jmp nomem_instruction_ready movdir64b_instruction: call setup_66_0f_38 call take_register mov [postbyte_register],al xor al,al xchg al,[operand_size] push eax lods byte [esi] cmp al,',' jne invalid_operand lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address mov al,[operand_size] or al,al jz movdir64b_ready cmp al,64 jne invalid_operand_size movdir64b_ready: push edi call store_instruction pop ebx eax mov cl,[code_type] cmp byte [ebx],67h jne movdir64b_size_check shr cl,1 cmp cl,16 jae movdir64b_size_check mov cl,32 movdir64b_size_check: shl al,3 cmp al,cl jne invalid_operand_size jmp instruction_assembled setssbsy_instruction: shl eax,24 or eax,010FF3h stos dword [edi] jmp instruction_assembled rstorssp_instruction: mov ah,1 jmp setup_clrssbsy clrssbsy_instruction: mov ah,0AEh setup_clrssbsy: mov [base_code],0Fh mov [extended_code],ah mov [postbyte_register],al mov [opcode_prefix],0F3h lods byte [esi] call get_size_operator cmp al,'[' jne invalid_operand call get_address test [operand_size],not 8 jnz invalid_operand_size jmp instruction_ready rdsspq_instruction: mov [rex_prefix],48h rdsspd_instruction: mov ah,1Eh jmp setup_incssp incsspq_instruction: mov [rex_prefix],48h incsspd_instruction: mov ah,0AEh setup_incssp: mov [base_code],0Fh mov [extended_code],ah mov [postbyte_register],al mov [opcode_prefix],0F3h lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] call convert_register mov bl,al call cet_size_check jmp nomem_instruction_ready cet_size_check: cmp [rex_prefix],0 je cet_dword cmp [code_type],64 jne illegal_instruction shr ah,1 cet_dword: cmp ah,4 jne invalid_operand_size ret wrussq_instruction: mov [opcode_prefix],66h wrssq_instruction: mov [rex_prefix],48h jmp wrssd_instruction wrussd_instruction: mov [opcode_prefix],66h wrssd_instruction: mov [base_code],0Fh mov [extended_code],38h mov [supplemental_code],al lods byte [esi] call get_size_operator cmp al,10h je wrss_reg cmp al,'[' jne invalid_operand call get_address push edx ebx ecx lods byte [esi] cmp al,',' jne invalid_operand call take_register mov [postbyte_register],al pop ecx ebx edx call cet_size_check jmp instruction_ready wrss_reg: lods byte [esi] call convert_register mov [postbyte_register],al lods byte [esi] cmp al,',' jne invalid_operand call take_register mov bl,al xchg bl,[postbyte_register] call cet_size_check jmp nomem_instruction_ready endbr_instruction: shl eax,24 or eax,1E0FF3h stos dword [edi] jmp instruction_assembled take_register: lods byte [esi] call get_size_operator cmp al,10h jne invalid_operand lods byte [esi] convert_register: mov ah,al shr ah,4 and al,0Fh cmp ah,8 je match_register_size cmp ah,4 ja invalid_operand cmp ah,1 ja match_register_size cmp al,4 jb match_register_size or ah,ah jz high_byte_register or [rex_prefix],40h match_register_size: cmp ah,[operand_size] je register_size_ok cmp [operand_size],0 jne operand_sizes_do_not_match mov [operand_size],ah register_size_ok: ret high_byte_register: mov ah,1 or [rex_prefix],10h jmp match_register_size convert_fpu_register: mov ah,al shr ah,4 and al,111b cmp ah,10 jne invalid_operand jmp match_register_size convert_mmx_register: mov ah,al shr ah,4 cmp ah,0Ch je xmm_register ja invalid_operand and al,111b cmp ah,0Bh jne invalid_operand mov ah,8 jmp match_register_size xmm_register: and al,0Fh mov ah,16 cmp al,8 jb match_register_size cmp [code_type],64 jne invalid_operand jmp match_register_size convert_xmm_register: mov ah,al shr ah,4 cmp ah,0Ch je xmm_register jmp invalid_operand get_size_operator: xor ah,ah cmp al,11h jne no_size_operator mov [size_declared],1 lods word [esi] xchg al,ah or [operand_flags],1 cmp ah,[operand_size] je size_operator_ok cmp [operand_size],0 jne operand_sizes_do_not_match mov [operand_size],ah size_operator_ok: ret no_size_operator: mov [size_declared],0 cmp al,'[' jne size_operator_ok and [operand_flags],not 1 ret get_jump_operator: mov [jump_type],0 cmp al,12h jne jump_operator_ok lods word [esi] mov [jump_type],al mov al,ah jump_operator_ok: ret get_address: and [address_size],0 get_address_of_required_size: call get_address_prefixes and [free_address_range],0 call calculate_address cmp byte [esi-1],']' jne invalid_address mov [address_high],edx mov edx,eax cmp [address_size_declared],0 jne address_ok cmp [segment_register],4 ja address_ok or bx,bx jnz clear_address_size cmp [code_type],64 jne address_ok calculate_relative_address: mov edx,[address_symbol] mov [symbol_identifier],edx mov edx,[address_high] mov ebp,[addressing_space] call calculate_relative_offset mov [address_high],edx cdq cmp edx,[address_high] je address_high_ok call recoverable_overflow address_high_ok: mov edx,eax ror ecx,16 mov cl,[value_type] rol ecx,16 mov bx,9900h clear_address_size: and ch,not 0Fh address_ok: ret get_address_prefixes: and [segment_register],0 and [address_size_declared],0 mov al,[code_type] shr al,3 mov [value_size],al mov al,[esi] and al,11110000b cmp al,60h jne get_address_size_prefix lods byte [esi] sub al,60h mov [segment_register],al mov al,[esi] and al,11110000b get_address_size_prefix: cmp al,70h jne address_size_prefix_ok lods byte [esi] sub al,70h cmp al,2 jb invalid_address_size cmp al,8 ja invalid_address_size mov [value_size],al or [address_size_declared],1 or [address_size],al cmp al,[address_size] jne invalid_address_size address_size_prefix_ok: ret operand_16bit: cmp [code_type],16 je size_prefix_ok mov [operand_prefix],66h ret operand_32bit: cmp [code_type],16 jne size_prefix_ok mov [operand_prefix],66h size_prefix_ok: ret operand_64bit: cmp [code_type],64 jne illegal_instruction or [rex_prefix],48h ret operand_autodetect: cmp al,2 je operand_16bit cmp al,4 je operand_32bit cmp al,8 je operand_64bit jmp invalid_operand_size store_segment_prefix_if_necessary: mov al,[segment_register] or al,al jz segment_prefix_ok cmp al,4 ja segment_prefix_386 cmp [code_type],64 je segment_prefix_ok cmp al,3 je ss_prefix jb segment_prefix_86 cmp bl,25h je segment_prefix_86 cmp bh,25h je segment_prefix_86 cmp bh,45h je segment_prefix_86 cmp bh,44h je segment_prefix_86 ret ss_prefix: cmp bl,25h je segment_prefix_ok cmp bh,25h je segment_prefix_ok cmp bh,45h je segment_prefix_ok cmp bh,44h je segment_prefix_ok jmp segment_prefix_86 store_segment_prefix: mov al,[segment_register] or al,al jz segment_prefix_ok cmp al,5 jae segment_prefix_386 segment_prefix_86: dec al shl al,3 add al,26h stos byte [edi] jmp segment_prefix_ok segment_prefix_386: add al,64h-5 stos byte [edi] segment_prefix_ok: ret store_instruction_code: cmp [vex_required],0 jne store_vex_instruction_code store_classic_instruction_code: mov al,[operand_prefix] or al,al jz operand_prefix_ok stos byte [edi] operand_prefix_ok: mov al,[opcode_prefix] or al,al jz opcode_prefix_ok stos byte [edi] opcode_prefix_ok: mov al,[rex_prefix] test al,40h jz rex_prefix_ok cmp [code_type],64 jne invalid_operand test al,0B0h jnz disallowed_combination_of_registers stos byte [edi] rex_prefix_ok: mov al,[base_code] stos byte [edi] cmp al,0Fh jne instruction_code_ok store_extended_code: mov al,[extended_code] stos byte [edi] cmp al,38h je store_supplemental_code cmp al,3Ah je store_supplemental_code instruction_code_ok: ret store_supplemental_code: mov al,[supplemental_code] stos byte [edi] ret store_nomem_instruction: test [postbyte_register],10000b jz nomem_reg_high_code_ok or [vex_required],10h and [postbyte_register],1111b nomem_reg_high_code_ok: test [postbyte_register],1000b jz nomem_reg_code_ok or [rex_prefix],44h and [postbyte_register],111b nomem_reg_code_ok: test bl,10000b jz nomem_rm_high_code_ok or [rex_prefix],42h or [vex_required],8 and bl,1111b nomem_rm_high_code_ok: test bl,1000b jz nomem_rm_code_ok or [rex_prefix],41h and bl,111b nomem_rm_code_ok: and [displacement_compression],0 call store_instruction_code mov al,[postbyte_register] shl al,3 or al,bl or al,11000000b stos byte [edi] ret store_instruction: mov [current_offset],edi and [displacement_compression],0 test [postbyte_register],10000b jz reg_high_code_ok or [vex_required],10h and [postbyte_register],1111b reg_high_code_ok: test [postbyte_register],1000b jz reg_code_ok or [rex_prefix],44h and [postbyte_register],111b reg_code_ok: cmp [code_type],64 jne address_value_ok xor eax,eax bt edx,31 sbb eax,[address_high] jz address_value_ok cmp [address_high],0 jne address_value_out_of_range test ch,44h jnz address_value_ok test bx,8080h jz address_value_ok address_value_out_of_range: call recoverable_overflow address_value_ok: call store_segment_prefix_if_necessary test [vex_required],4 jnz address_vsib or bx,bx jz address_immediate cmp bx,9800h je address_rip_based cmp bx,9400h je address_eip_based cmp bx,9900h je address_relative mov al,bl or al,bh and al,11110000b cmp al,80h je postbyte_64bit cmp al,40h je postbyte_32bit cmp al,20h jne invalid_address cmp [code_type],64 je invalid_address_size call address_16bit_prefix test ch,22h setz [displacement_compression] call store_instruction_code cmp bl,bh jbe determine_16bit_address xchg bl,bh determine_16bit_address: cmp bx,2600h je address_si cmp bx,2700h je address_di cmp bx,2300h je address_bx cmp bx,2500h je address_bp cmp bx,2625h je address_bp_si cmp bx,2725h je address_bp_di cmp bx,2723h je address_bx_di cmp bx,2623h jne invalid_address address_bx_si: xor al,al jmp postbyte_16bit address_bx_di: mov al,1 jmp postbyte_16bit address_bp_si: mov al,10b jmp postbyte_16bit address_bp_di: mov al,11b jmp postbyte_16bit address_si: mov al,100b jmp postbyte_16bit address_di: mov al,101b jmp postbyte_16bit address_bx: mov al,111b jmp postbyte_16bit address_bp: mov al,110b postbyte_16bit: test ch,22h jnz address_16bit_value or ch,ch jnz address_sizes_do_not_agree cmp edx,10000h jge value_out_of_range cmp edx,-8000h jl value_out_of_range or dx,dx jz address cmp [displacement_compression],2 ja address_8bit_value je address_16bit_value cmp dx,80h jb address_8bit_value cmp dx,-80h jae address_8bit_value address_16bit_value: or al,10000000b mov cl,[postbyte_register] shl cl,3 or al,cl stos byte [edi] mov eax,edx stos word [edi] ret address_8bit_value: or al,01000000b mov cl,[postbyte_register] shl cl,3 or al,cl stos byte [edi] mov al,dl stos byte [edi] ret address: cmp al,110b je address_8bit_value mov cl,[postbyte_register] shl cl,3 or al,cl stos byte [edi] ret address_vsib: mov al,bl shr al,4 test al,1 jz vsib_high_code_ok or [vex_register],10000b or [vex_required],8 xor al,1 vsib_high_code_ok: cmp al,6 je vsib_index_ok cmp al,0Ch jb invalid_address vsib_index_ok: mov al,bh shr al,4 cmp al,4 je postbyte_32bit cmp [code_type],64 je address_prefix_ok test al,al jnz invalid_address postbyte_32bit: call address_32bit_prefix jmp address_prefix_ok postbyte_64bit: cmp [code_type],64 jne invalid_address_size address_prefix_ok: cmp bl,44h je invalid_address cmp bl,84h je invalid_address test bh,1000b jz base_code_ok or [rex_prefix],41h base_code_ok: test bl,1000b jz index_code_ok or [rex_prefix],42h index_code_ok: test ch,44h or 88h setz [displacement_compression] call store_instruction_code or cl,cl jz only_base_register base_and_index: mov al,100b xor ah,ah cmp cl,1 je scale_ok cmp cl,2 je scale_1 cmp cl,4 je scale_2 or ah,11000000b jmp scale_ok scale_2: or ah,10000000b jmp scale_ok scale_1: or ah,01000000b scale_ok: or bh,bh jz only_index_register and bl,111b shl bl,3 or ah,bl and bh,111b or ah,bh sib_ready: test ch,44h or 88h jnz sib_address_32bit_value or ch,ch jnz address_sizes_do_not_agree cmp bh,5 je address_value or edx,edx jz sib_address address_value: cmp [displacement_compression],2 ja sib_address_8bit_value je sib_address_32bit_value cmp edx,80h jb sib_address_8bit_value cmp edx,-80h jnb sib_address_8bit_value sib_address_32bit_value: or al,10000000b mov cl,[postbyte_register] shl cl,3 or al,cl stos word [edi] jmp store_address_32bit_value sib_address_8bit_value: or al,01000000b mov cl,[postbyte_register] shl cl,3 or al,cl stos word [edi] mov al,dl stos byte [edi] ret sib_address: mov cl,[postbyte_register] shl cl,3 or al,cl stos word [edi] ret only_index_register: or ah,101b and bl,111b shl bl,3 or ah,bl mov cl,[postbyte_register] shl cl,3 or al,cl stos word [edi] test ch,44h or 88h jnz store_address_32bit_value or ch,ch jnz invalid_address_size cmp [displacement_compression],2 jbe store_address_32bit_value mov edx,[uncompressed_displacement] jmp store_address_32bit_value zero_index_register: mov bl,4 mov cl,1 jmp base_and_index only_base_register: mov al,bh and al,111b cmp al,4 je zero_index_register test ch,44h or 88h jnz simple_address_32bit_value or ch,ch jnz address_sizes_do_not_agree or edx,edx jz simple_address cmp [displacement_compression],2 ja simple_address_8bit_value je simple_address_32bit_value cmp edx,80h jb simple_address_8bit_value cmp edx,-80h jnb simple_address_8bit_value simple_address_32bit_value: or al,10000000b mov cl,[postbyte_register] shl cl,3 or al,cl stos byte [edi] jmp store_address_32bit_value simple_address_8bit_value: or al,01000000b mov cl,[postbyte_register] shl cl,3 or al,cl stos byte [edi] mov al,dl stos byte [edi] ret simple_address: cmp al,5 je simple_address_8bit_value mov cl,[postbyte_register] shl cl,3 or al,cl stos byte [edi] ret address_immediate: cmp [code_type],64 je address_immediate_sib test ch,44h or 88h jnz address_immediate_32bit test ch,22h jnz address_immediate_16bit or ch,ch jnz invalid_address_size cmp [code_type],16 je addressing_16bit address_immediate_32bit: call address_32bit_prefix call store_instruction_code store_immediate_address: mov al,101b mov cl,[postbyte_register] shl cl,3 or al,cl stos byte [edi] store_address_32bit_value: test ch,0F0h jz address_32bit_relocation_ok mov eax,ecx shr eax,16 cmp al,4 jne address_32bit_relocation mov al,2 address_32bit_relocation: xchg [value_type],al mov ebx,[address_symbol] xchg ebx,[symbol_identifier] call mark_relocation mov [value_type],al mov [symbol_identifier],ebx address_32bit_relocation_ok: mov eax,edx stos dword [edi] ret store_address_64bit_value: test ch,0F0h jz address_64bit_relocation_ok mov eax,ecx shr eax,16 xchg [value_type],al mov ebx,[address_symbol] xchg ebx,[symbol_identifier] call mark_relocation mov [value_type],al mov [symbol_identifier],ebx address_64bit_relocation_ok: mov eax,edx stos dword [edi] mov eax,[address_high] stos dword [edi] ret address_immediate_sib: test ch,44h jnz address_immediate_sib_32bit test ch,not 88h jnz invalid_address_size test edx,80000000h jz address_immediate_sib_store cmp [address_high],0 je address_immediate_sib_nosignextend address_immediate_sib_store: call store_instruction_code mov al,100b mov ah,100101b mov cl,[postbyte_register] shl cl,3 or al,cl stos word [edi] jmp store_address_32bit_value address_immediate_sib_32bit: test ecx,0FF0000h jnz address_immediate_sib_nosignextend test edx,80000000h jz address_immediate_sib_store address_immediate_sib_nosignextend: call address_32bit_prefix jmp address_immediate_sib_store address_eip_based: mov al,67h stos byte [edi] address_rip_based: cmp [code_type],64 jne invalid_address call store_instruction_code jmp store_immediate_address address_relative: call store_instruction_code movzx eax,[immediate_size] add eax,edi sub eax,[current_offset] add eax,5 sub edx,eax jno address_relative_ok call recoverable_overflow address_relative_ok: mov al,101b mov cl,[postbyte_register] shl cl,3 or al,cl stos byte [edi] shr ecx,16 xchg [value_type],cl mov ebx,[address_symbol] xchg ebx,[symbol_identifier] mov eax,edx call mark_relocation mov [value_type],cl mov [symbol_identifier],ebx stos dword [edi] ret addressing_16bit: cmp edx,10000h jge address_immediate_32bit cmp edx,-8000h jl address_immediate_32bit movzx edx,dx address_immediate_16bit: call address_16bit_prefix call store_instruction_code mov al,110b mov cl,[postbyte_register] shl cl,3 or al,cl stos byte [edi] mov eax,edx stos word [edi] cmp edx,10000h jge value_out_of_range cmp edx,-8000h jl value_out_of_range ret address_16bit_prefix: cmp [code_type],16 je instruction_prefix_ok mov al,67h stos byte [edi] ret address_32bit_prefix: cmp [code_type],32 je instruction_prefix_ok mov al,67h stos byte [edi] instruction_prefix_ok: ret store_instruction_with_imm8: mov [immediate_size],1 call store_instruction mov al,byte [value] stos byte [edi] ret store_instruction_with_imm16: mov [immediate_size],2 call store_instruction mov ax,word [value] call mark_relocation stos word [edi] ret store_instruction_with_imm32: mov [immediate_size],4 call store_instruction mov eax,dword [value] call mark_relocation stos dword [edi] ret fasm/tools/0000755000175000017500000000000014533376740013446 5ustar privalovprivalovfasm/tools/dos/0000755000175000017500000000000014533376740014233 5ustar privalovprivalovfasm/tools/dos/listing.asm0000644000175000017500000000703514533376740016413 0ustar privalovprivalov format MZ heap 0 stack 8000h entry loader:init include 'loader.inc' segment main use32 start: call get_params jnc make_listing mov esi,_usage call display_string mov ax,4C02h int 21h make_listing: call listing mov ax,4C00h int 21h error: mov esi,_error_prefix call display_string pop esi call display_string mov esi,_error_suffix call display_string mov ax,4C00h int 21h get_params: push ds mov ds,[psp_selector] mov esi,81h mov edi,params find_param: lodsb cmp al,20h je find_param cmp al,'-' je option_param cmp al,0Dh je all_params or al,al jz all_params cmp [es:input_file],0 jne get_output_file mov [es:input_file],edi jmp process_param get_output_file: cmp [es:output_file],0 jne bad_params mov [es:output_file],edi process_param: cmp al,22h je string_param copy_param: stosb lodsb cmp al,20h je param_end cmp al,0Dh je param_end or al,al jz param_end jmp copy_param string_param: lodsb cmp al,22h je string_param_end cmp al,0Dh je param_end or al,al jz param_end stosb jmp string_param option_param: lodsb cmp al,'a' je addresses_option cmp al,'A' je addresses_option cmp al,'b' je bytes_per_line_option cmp al,'B' je bytes_per_line_option invalid_option: pop ds stc ret get_option_value: xor eax,eax mov edx,eax get_option_digit: lodsb cmp al,20h je option_value_ok cmp al,0Dh je option_value_ok or al,al jz option_value_ok sub al,30h jc bad_params_value cmp al,9 ja bad_params_value imul edx,10 jo bad_params_value add edx,eax jc bad_params_value jmp get_option_digit option_value_ok: dec esi clc ret bad_params_value: stc ret bytes_per_line_option: lodsb cmp al,20h je bytes_per_line_option cmp al,0Dh je invalid_option or al,al jz invalid_option dec esi call get_option_value jc bad_params or edx,edx jz invalid_option cmp edx,1000 ja invalid_option mov [es:code_bytes_per_line],edx jmp find_param addresses_option: lodsb cmp al,20h je set_addresses_option cmp al,0Dh je set_addresses_option or al,al jnz bad_params set_addresses_option: dec esi mov [es:show_addresses],1 jmp find_param param_end: dec esi string_param_end: xor al,al stosb jmp find_param all_params: xor al,al stosb pop ds cmp [input_file],0 je bad_params cmp [output_file],0 je bad_params clc ret bad_params: stc ret include 'system.inc' include '..\listing.inc' _usage db 'listing generator for flat assembler',0Dh,0Ah db 'usage: listing ',0Dh,0Ah db 'optional settings:',0Dh,0Ah db ' -a show target addresses for assembled code',0Dh,0Ah db ' -b set the amount of bytes listed per line',0Dh,0Ah db 0 _error_prefix db 'error: ',0 _error_suffix db '.',0Dh,0Ah,0 input_file dd 0 output_file dd 0 code_bytes_per_line dd 16 show_addresses db 0 line_break db 0Dh,0Ah input dd ? assembled_code dd ? assembled_code_length dd ? code_end dd ? code_offset dd ? code_length dd ? output_handle dd ? output_buffer dd ? current_source_file dd ? current_source_line dd ? source dd ? source_length dd ? maximum_address_length dd ? address_start dd ? last_listed_address dd ? psp_selector dw ? environment_selector dw ? memory_handles_count dd ? memory_handles rd 400h params rb 1000h characters rb 100h segment buffer_segment buffer = (buffer_segment-main) shl 4 db 1000h dup ? segment stack_segment stack_bottom = (stack_segment-main) shl 4 db 4000h dup ? stack_top = stack_bottom + $ fasm/tools/dos/loader.inc0000644000175000017500000000336714533376740016205 0ustar privalovprivalov segment loader use16 init: mov ax,1687h int 2Fh or ax,ax ; DPMI installed? jnz short no_dpmi test bl,1 ; 32-bit programs supported? jz short no_dpmi mov word [cs:mode_switch],di mov word [cs:mode_switch+2],es mov bx,si ; allocate memory for DPMI data mov ah,48h int 21h jnc init_protected_mode init_failed: call init_error db 'error: DPMI initialization failed.',0Dh,0Ah,0 no_dpmi: call init_error db 'error: 32-bit DPMI services are not available.',0Dh,0Ah,0 init_error: pop si push cs pop ds display_error: lodsb test al,al jz short error_finish mov dl,al mov ah,2 int 21h jmp short display_error error_finish: mov ax,4CFFh int 21h init_protected_mode: mov es,ax mov ds,[ds:2Ch] mov ax,1 call far [cs:mode_switch] ; switch to protected mode jc init_failed mov cx,1 xor ax,ax int 31h ; allocate descriptor for code jc init_failed mov si,ax xor ax,ax int 31h ; allocate descriptor for data jc init_failed mov di,ax mov dx,cs lar cx,dx shr cx,8 or cx,0C000h mov bx,si mov ax,9 int 31h ; set code descriptor access rights jc init_failed mov dx,ds lar cx,dx shr cx,8 or cx,0C000h mov bx,di int 31h ; set data descriptor access rights jc init_failed mov ecx,main shl ecx,4 mov dx,cx shr ecx,16 mov ax,7 int 31h ; set data descriptor base address jc init_failed mov bx,si int 31h ; set code descriptor base address jc init_failed mov cx,0FFFFh mov dx,0FFFFh mov ax,8 ; set segment limit to 4 GB int 31h jc init_failed mov bx,di int 31h jc init_failed mov ax,ds mov ds,di mov [psp_selector],es mov [environment_selector],ax cli mov ss,di mov esp,stack_top sti mov es,di xor eax,eax mov [memory_handles_count],eax push si push start retf mode_switch dd ? fasm/tools/dos/prepsrc.asm0000644000175000017500000000361214533376740016415 0ustar privalovprivalov format MZ heap 0 stack 8000h entry loader:init include 'loader.inc' segment main use32 start: call get_params jnc make_dump mov esi,_usage call display_string mov ax,4C02h int 21h make_dump: call preprocessed_source mov ax,4C00h int 21h error: mov esi,_error_prefix call display_string pop esi call display_string mov esi,_error_suffix call display_string mov ax,4C00h int 21h get_params: push ds mov ds,[psp_selector] mov esi,81h mov edi,params find_param: lodsb cmp al,20h je find_param cmp al,0Dh je all_params or al,al jz all_params cmp [es:input_file],0 jne get_output_file mov [es:input_file],edi jmp process_param get_output_file: cmp [es:output_file],0 jne bad_params mov [es:output_file],edi process_param: cmp al,22h je string_param copy_param: stosb lodsb cmp al,20h je param_end cmp al,0Dh je param_end or al,al jz param_end jmp copy_param string_param: lodsb cmp al,22h je string_param_end cmp al,0Dh je param_end or al,al jz param_end stosb jmp string_param bad_params_value: stc ret param_end: dec esi string_param_end: xor al,al stosb jmp find_param all_params: xor al,al stosb pop ds cmp [input_file],0 je bad_params cmp [output_file],0 je bad_params clc ret bad_params: stc ret include 'system.inc' include '..\prepsrc.inc' _usage db 'preprocessed source dumper for flat assembler',0Dh,0Ah db 'usage: prepsrc ',0Dh,0Ah db 0 _error_prefix db 'error: ',0 _error_suffix db '.',0Dh,0Ah,0 input_file dd 0 output_file dd 0 psp_selector dw ? environment_selector dw ? memory_handles_count dd ? memory_handles rd 400h params rb 1000h segment buffer_segment buffer = (buffer_segment-main) shl 4 db 1000h dup ? segment stack_segment stack_bottom = (stack_segment-main) shl 4 db 4000h dup ? stack_top = stack_bottom + $ fasm/tools/dos/symbols.asm0000644000175000017500000000365214533376740016433 0ustar privalovprivalov format MZ heap 0 stack 8000h entry loader:init include 'loader.inc' segment main use32 start: call get_params jnc make_dump mov esi,_usage call display_string mov ax,4C02h int 21h make_dump: call symbols mov ax,4C00h int 21h error: mov esi,_error_prefix call display_string pop esi call display_string mov esi,_error_suffix call display_string mov ax,4C00h int 21h get_params: push ds mov ds,[psp_selector] mov esi,81h mov edi,params find_param: lodsb cmp al,20h je find_param cmp al,0Dh je all_params or al,al jz all_params cmp [es:input_file],0 jne get_output_file mov [es:input_file],edi jmp process_param get_output_file: cmp [es:output_file],0 jne bad_params mov [es:output_file],edi process_param: cmp al,22h je string_param copy_param: stosb lodsb cmp al,20h je param_end cmp al,0Dh je param_end or al,al jz param_end jmp copy_param string_param: lodsb cmp al,22h je string_param_end cmp al,0Dh je param_end or al,al jz param_end stosb jmp string_param bad_params_value: stc ret param_end: dec esi string_param_end: xor al,al stosb jmp find_param all_params: xor al,al stosb pop ds cmp [input_file],0 je bad_params cmp [output_file],0 je bad_params clc ret bad_params: stc ret include 'system.inc' include '..\symbols.inc' _usage db 'symbols dumper for flat assembler',0Dh,0Ah db 'usage: symbols ',0Dh,0Ah db 0 _error_prefix db 'error: ',0 _error_suffix db '.',0Dh,0Ah,0 input_file dd 0 output_file dd 0 input dd ? output_buffer dd ? output_handle dd ? psp_selector dw ? environment_selector dw ? memory_handles_count dd ? memory_handles rd 400h params rb 1000h segment buffer_segment buffer = (buffer_segment-main) shl 4 db 1000h dup ? segment stack_segment stack_bottom = (stack_segment-main) shl 4 db 4000h dup ? stack_top = stack_bottom + $ fasm/tools/dos/system.inc0000644000175000017500000000616514533376740016262 0ustar privalovprivalov display_string: lods byte [esi] or al,al jz string_end mov dl,al mov ah,2 int 21h jmp display_string string_end: ret alloc: push ebx esi edi mov cx,ax shr eax,16 mov bx,ax mov ax,501h int 31h jc dpmi_allocation_failed mov ax,bx shl eax,16 mov ax,cx mov edx,main shl edx,4 sub eax,edx mov bx,si shl ebx,16 mov bx,di mov ecx,[memory_handles_count] inc [memory_handles_count] shl ecx,3 add ecx,memory_handles mov [ecx],eax mov [ecx+4],ebx pop edi esi ebx clc ret dpmi_allocation_failed: pop edi esi ebx stc ret free: push ebx esi edi mov esi,memory_handles mov ecx,[memory_handles_count] find_memory_handle: cmp eax,[esi] je memory_handle_found add esi,8 loop find_memory_handle pop edi esi ret memory_handle_found: mov ebx,[esi+4] dec [memory_handles_count] dec ecx jz free_memory remove_memory_handle: mov edx,[esi+8] mov edi,[esi+8+4] mov [esi],edx mov [esi+4],edi add esi,8 loop remove_memory_handle free_memory: mov esi,ebx shr esi,16 mov di,bx mov ax,502h int 31h pop edi esi ebx ret open: push esi edi ebp call adapt_path mov ax,716Ch mov bx,100000b mov dx,1 xor cx,cx xor si,si call dos_int jnc open_done cmp ax,7100h je old_open stc jmp open_done old_open: mov ax,3D00h xor dx,dx call dos_int open_done: mov bx,ax pop ebp edi esi ret adapt_path: mov esi,edx mov edi,buffer copy_path: lodsb cmp al,'/' jne path_char_ok mov al,'\' path_char_ok: stosb or al,al jnz copy_path ret dos_int: push 0 0 0 pushw buffer_segment buffer_segment stc pushfw push eax push ecx push edx push ebx push 0 push ebp push esi push edi mov ax,300h mov bx,21h xor cx,cx mov edi,esp push es ss pop es int 31h pop es mov edi,[esp] mov esi,[esp+4] mov ebp,[esp+8] mov ebx,[esp+10h] mov edx,[esp+14h] mov ecx,[esp+18h] mov ah,[esp+20h] add esp,32h sahf mov eax,[esp-32h+1Ch] ret create: push esi edi ebp call adapt_path mov ax,716Ch mov bx,100001b mov dx,10010b xor cx,cx xor si,si xor di,di call dos_int jnc create_done cmp ax,7100h je old_create stc jmp create_done old_create: mov ah,3Ch xor cx,cx xor dx,dx call dos_int create_done: mov bx,ax pop ebp edi esi ret write: push edx esi edi ebp mov ebp,ecx mov esi,edx write_loop: mov ecx,1000h sub ebp,1000h jnc do_write add ebp,1000h mov ecx,ebp xor ebp,ebp do_write: push ecx mov edi,buffer shr ecx,2 rep movsd mov ecx,[esp] and ecx,11b rep movsb pop ecx mov ah,40h xor dx,dx call dos_int or ebp,ebp jnz write_loop pop ebp edi esi edx ret read: push edx esi edi ebp mov ebp,ecx mov edi,edx read_loop: mov ecx,1000h sub ebp,1000h jnc do_read add ebp,1000h mov ecx,ebp xor ebp,ebp do_read: push ecx mov ah,3Fh xor dx,dx call dos_int cmp ax,cx jne eof mov esi,buffer mov ecx,[esp] shr ecx,2 rep movsd pop ecx and ecx,11b rep movsb or ebp,ebp jnz read_loop read_done: pop ebp edi esi edx ret eof: pop ecx stc jmp read_done close: mov ah,3Eh int 21h ret lseek: mov ah,42h mov ecx,edx shr ecx,16 int 21h pushf shl edx,16 popf mov dx,ax mov eax,edx ret fasm/tools/fas.txt0000644000175000017500000005571014533376740014770 0ustar privalovprivalov flat assembler Symbolic information file format Table 1 Header /-------------------------------------------------------------------------\ | Offset | Size | Description | |========|=========|======================================================| | +0 | dword | Signature 1A736166h (little-endian). | |--------|---------|------------------------------------------------------| | +4 | byte | Major version of flat assembler. | |--------|---------|------------------------------------------------------| | +5 | byte | Minor version of flat assembler. | |--------|---------|------------------------------------------------------| | +6 | word | Length of header. | |--------|---------|------------------------------------------------------| | +8 | dword | Offset of input file name in the strings table. | |--------|---------|------------------------------------------------------| | +12 | dword | Offset of output file name in the strings table. | |--------|---------|------------------------------------------------------| | +16 | dword | Offset of strings table. | |--------|---------|------------------------------------------------------| | +20 | dword | Length of strings table. | |--------|---------|------------------------------------------------------| | +24 | dword | Offset of symbols table. | |--------|---------|------------------------------------------------------| | +28 | dword | Length of symbols table. | |--------|---------|------------------------------------------------------| | +32 | dword | Offset of preprocessed source. | |--------|---------|------------------------------------------------------| | +36 | dword | Length of preprocessed source. | |--------|---------|------------------------------------------------------| | +40 | dword | Offset of assembly dump. | |--------|---------|------------------------------------------------------| | +44 | dword | Length of assembly dump. | |--------|---------|------------------------------------------------------| | +48 | dword | Offset of section names table. | |--------|---------|------------------------------------------------------| | +52 | dword | Length of section names table. | |--------|---------|------------------------------------------------------| | +56 | dword | Offset of symbol references dump. | |--------|---------|------------------------------------------------------| | +60 | dword | Length of symbol references dump. | \-------------------------------------------------------------------------/ Notes: If header is shorter than 64 bytes, it comes from a version that does not support dumping some of the structures. It should then be interpreted that the data for missing structures could not be provided, not that the size of that data is zero. Offsets given in header generally mean positions in the file, however input and output file names are specified by offsets in the strings table, so you have to add their offset to the offset of strings table to obtain the positions of those strings in the file. The strings table contains just a sequence of ASCIIZ strings, which may be referred to by other parts of the file. It contains the names of main input file, the output file, and the names of the sections and external symbols if there were any. The symbols table is an array of 32-byte structures, each one in format specified by table 2. The preprocessed source is a sequence of preprocessed lines, each one in format as defined in table 3. The assembly dump contains an array of 28-byte structures, each one in format specified by table 4, and at the end of this array an additional double word containing the offset in output file at which the assembly was ended. It is possible that file does not contain assembly dump at all - this happens when some error occured and only the preprocessed source was dumped. If error occured during the preprocessing, only the source up to the point of error is provided. In such case (and only then) the field at offset 44 contains zero. The section names table exists only when the output format was an object file (ELF or COFF), and it is an array of 4-byte entries, each being an offset of the name of the section in the strings table. The index of section in this table is the same, as the index of section in the generated object file. The symbol references dump contains an array of 8-byte structures, each one describes an event of some symbol being used. The first double word of such structure contains an offset of symbol in the symbols table, and the second double word is an offset of structure in assembly dump, which specifies at what moment the symbol was referenced. Table 2 Symbol structure /-------------------------------------------------------------------------\ | Offset | Size | Description | |========|=======|========================================================| | +0 | qword | Value of symbol. | |--------|-------|--------------------------------------------------------| | +8 | word | Flags (table 2.1). | |--------|-------|--------------------------------------------------------| | +10 | byte | Size of data labelled by this symbol (zero means plain | | | | label without size attached). | |--------|-------|--------------------------------------------------------| | +11 | byte | Type of value (table 2.2). Any value other than zero | | | | means some kind of relocatable symbol. | |--------|-------|--------------------------------------------------------| | +12 | dword | Extended SIB, the first two bytes are register codes | | | | and the second two bytes are corresponding scales. | |--------|-------|--------------------------------------------------------| | +16 | word | Number of pass in which symbol was defined last time. | |--------|-------|--------------------------------------------------------| | +18 | word | Number of pass in which symbol was used last time. | |--------|-------|--------------------------------------------------------| | +20 | dword | If the symbol is relocatable, this field contains | | | | information about section or external symbol, to which | | | | it is relative - otherwise this field has no meaning. | | | | When the highest bit is cleared, the symbol is | | | | relative to a section, and the bits 0-30 contain | | | | the index (starting from 1) in the table of sections. | | | | When the highest bit is set, the symbol is relative to | | | | an external symbol, and the bits 0-30 contain the | | | | the offset of the name of this symbol in the strings | | | | table. | |--------|-------|--------------------------------------------------------| | +24 | dword | If the highest bit is cleared, the bits 0-30 contain | | | | the offset of symbol name in the preprocessed source. | | | | This name is a pascal-style string (byte length | | | | followed by string data). | | | | Zero in this field means an anonymous symbol. | | | | If the highest bit is set, the bits 0-30 contain the | | | | offset of the symbol name in the strings table, and | | | | this name is a zero-ended string in this case (as are | | | | all the strings there). | |--------|-------|--------------------------------------------------------| | +28 | dword | Offset in the preprocessed source of line that defined | | | | this symbol (see table 3). | \-------------------------------------------------------------------------/ Table 2.1 Symbol flags /-----------------------------------------------------------------\ | Bit | Value | Description | |=====|=======|===================================================| | 0 | 1 | Symbol was defined. | |-----|-------|---------------------------------------------------| | 1 | 2 | Symbol is an assembly-time variable. | |-----|-------|---------------------------------------------------| | 2 | 4 | Symbol cannot be forward-referenced. | |-----|-------|---------------------------------------------------| | 3 | 8 | Symbol was used. | |-----|-------|---------------------------------------------------| | 4 | 10h | The prediction was needed when checking | | | | whether the symbol was used. | |-----|-------|---------------------------------------------------| | 5 | 20h | Result of last predicted check for being used. | |-----|-------|---------------------------------------------------| | 6 | 40h | The prediction was needed when checking | | | | whether the symbol was defined. | |-----|-------|---------------------------------------------------| | 7 | 80h | Result of last predicted check for being defined. | |-----|-------|---------------------------------------------------| | 8 | 100h | The optimization adjustment is applied to | | | | the value of this symbol. | |-----|-------|---------------------------------------------------| | 9 | 200h | The value of symbol is negative number encoded | | | | as two's complement. | |-----|-------|---------------------------------------------------| | 10 | 400h | Symbol is a special marker and has no value. | \-----------------------------------------------------------------/ Notes: Some of those flags are listed here just for completness, as they have little use outside of the flat assembler. However the bit 0 is important, because the symbols table contains all the labels that occured in source, even if some of them were in the conditional blocks that did not get assembled. Table 2.2 Symbol value types /-------------------------------------------------------------------\ | Value | Description | |=======|===========================================================| | 0 | Absolute value. | |-------|-----------------------------------------------------------| | 1 | Relocatable segment address (only with MZ output). | |-------|-----------------------------------------------------------| | 2 | Relocatable 32-bit address. | |-------|-----------------------------------------------------------| | 3 | Relocatable relative 32-bit address (value valid only for | | | symbol used in the same place where it was calculated, | | | it should not occur in the symbol structure). | |-------|-----------------------------------------------------------| | 4 | Relocatable 64-bit address. | |-------|-----------------------------------------------------------| | 5 | [ELF only] GOT-relative 32-bit address. | |-------|-----------------------------------------------------------| | 6 | [ELF only] 32-bit address of PLT entry. | |-------|-----------------------------------------------------------| | 7 | [ELF only] Relative 32-bit address of PLT entry (value | | | valid only for symbol used in the same place where it | | | was calculated, it should not occur in the symbol | | | structure). | \-------------------------------------------------------------------/ Notes: The types 3 and 7 should never be encountered in the symbols dump, they are only used internally by the flat assembler. If type value is a negative number, it is an opposite of a value from this table and it means that the symbol of a given type has been negated. Table 2.3 Register codes for extended SIB /------------------\ | Value | Register | |=======|==========| | 23h | BX | |-------|----------| | 25h | BP | |-------|----------| | 26h | SI | |-------|----------| | 27h | DI | |-------|----------| | 40h | EAX | |-------|----------| | 41h | ECX | |-------|----------| | 42h | EDX | |-------|----------| | 43h | EBX | |-------|----------| | 44h | ESP | |-------|----------| | 45h | EBP | |-------|----------| | 46h | ESI | |-------|----------| | 47h | EDI | |-------|----------| | 48h | R8D | |-------|----------| | 49h | R9D | |-------|----------| | 4Ah | R10D | |-------|----------| | 4Bh | R11D | |-------|----------| | 4Ch | R12D | |-------|----------| | 4Dh | R13D | |-------|----------| | 4Eh | R14D | |-------|----------| | 4Fh | R15D | |-------|----------| | 80h | RAX | |-------|----------| | 81h | RCX | |-------|----------| | 82h | RDX | |-------|----------| | 83h | RBX | |-------|----------| | 84h | RSP | |-------|----------| | 85h | RBP | |-------|----------| | 86h | RSI | |-------|----------| | 87h | RDI | |-------|----------| | 88h | R8 | |-------|----------| | 89h | R9 | |-------|----------| | 8Ah | R10 | |-------|----------| | 8Bh | R11 | |-------|----------| | 8Ch | R12 | |-------|----------| | 8Dh | R13 | |-------|----------| | 8Eh | R14 | |-------|----------| | 8Fh | R15 | |-------|----------| | 94h | EIP | |-------|----------| | 98h | RIP | \------------------/ Table 3 Preprocessed line /--------------------------------------------------------------------------\ | Offset | Size | Value | |========|=================================================================| | +0 | dword | When the line was loaded from source, this field | | | | contains either zero (if it is the line from the main | | | | input file), or an offset inside the preprocessed | | | | source to the name of file, from which this line was | | | | loaded (the name of file is zero-ended string). | | | | When the line was generated by macroinstruction, this | | | | field contains offset inside the preprocessed source to | | | | the pascal-style string specifying the name of | | | | macroinstruction, which generated this line. | |--------|-------|---------------------------------------------------------| | +4 | dword | Bits 0-30 contain the number of this line. | | | | If the highest bit is zeroed, this line was loaded from | | | | source. | | | | If the highest bit is set, this line was generated by | | | | macroinstruction. | |--------|-------|---------------------------------------------------------| | +8 | dword | If the line was loaded from source, this field contains | | | | the position of the line inside the source file, from | | | | which it was loaded. | | | | If line was generated by macroinstruction, this field | | | | contains the offset of preprocessed line, which invoked | | | | the macroinstruction. | | | | If line was generated by instantaneous macro, this | | | | field is equal to the next one. | |--------|-------|---------------------------------------------------------| | +12 | dword | If the line was generated by macroinstruction, this | | | | field contains offset of the preprocessed line inside | | | | the definition of macro, from which this one was | | | | generated. | |--------|-------|---------------------------------------------------------| | +16 | ? | The tokenized contents of line. | \--------------------------------------------------------------------------/ Notes: To determine, whether this is the line loaded from source, or generated by macroinstruction, you need to check the highest bit of the second double word. The contents of line is no longer a text, which it was in source file, but a sequence of tokens, ended with a zero byte. Any chain of characters that aren't special ones, separated from other similar chains with spaces or some other special characters, is converted into symbol token. The first byte of this element has the value of 1Ah, the second byte is the count of characters, followed by this amount of bytes, which build the symbol. Some characters have a special meaning, and cannot occur inside the symbol, they split the symbols and are converted into separate tokens. For example, if source contains this line of text: mov ax,4 preprocessor converts it into the chain of bytes, shown here with their hexadecimal values (characters corresponding to some of those values are placed below the hexadecimal codes): 1A 03 6D 6F 76 1A 02 61 78 2C 1A 01 34 00 m o v a x , 4 The third type of token that can be found in preprocessed line is the quoted text. This element is created from chain of any bytes other than line breaks that are placed between the single or double quotes in the original text. First byte of such element is always 22h, it is followed by double word which specifies the number of bytes that follow, and the value of quoted text comes next. For example, this line from source: mov eax,'ABCD' is converted into (the notation used is the same as in previous sample): 1A 03 6D 6F 76 1A 03 65 61 78 2C 22 04 00 00 00 41 42 43 44 00 m o v e a x , A B C D This data defines two symbols followed by symbol character, quoted text and zero byte that marks end of line. There is also a special case of symbol token with first byte having the value 3Bh instead of 1Ah, such symbol means that all the line elements that follow, including this one, have already been interpreted by preprocessor and are ignored by assembler. Table 4 Row of the assembly dump /-------------------------------------------------------------------------\ | Offset | Size | Description | |========|=======|========================================================| | +0 | dword | Offset in output file. | |--------|-------|--------------------------------------------------------| | +4 | dword | Offset of line in preprocessed source. | |--------|-------|--------------------------------------------------------| | +8 | qword | Value of $ address. | |--------|-------|--------------------------------------------------------| | +16 | dword | Extended SIB for the $ address, the first two bytes | | | | are register codes and the second two bytes are | | | | corresponding scales. | |--------|-------|--------------------------------------------------------| | +20 | dword | If the $ address is relocatable, this field contains | | | | information about section or external symbol, to which | | | | it is relative - otherwise this field is zero. | | | | When the highest bit is cleared, the address is | | | | relative to a section, and the bits 0-30 contain | | | | the index (starting from 1) in the table of sections. | | | | When the highest bit is set, the address is relative | | | | to an external symbol, and the bits 0-30 contain the | | | | the offset of the name of this symbol in the strings | | | | table. | |--------|-------|--------------------------------------------------------| | +24 | byte | Type of $ address value (as in table 2.2). | |--------|-------|--------------------------------------------------------| | +25 | byte | Type of code - possible values are 16, 32, and 64. | |--------|-------|--------------------------------------------------------| | +26 | byte | If the bit 0 is set, then at this point the assembly | | | | was taking place inside the virtual block, and the | | | | offset in output file has no meaning here. | | | | If the bit 1 is set, the line was assembled at the | | | | point, which was not included in the output file for | | | | some other reasons (like inside the reserved data at | | | | the end of section). | |--------|-------|--------------------------------------------------------| | +27 | byte | The higher bits of value of $ address. | \-------------------------------------------------------------------------/ Notes: Each row of the assembly dump informs, that the given line of preprocessed source was assembled at the specified address (defined by its type, value and the extended SIB) and at the specified position in output file. fasm/tools/libc/0000755000175000017500000000000014533376740014357 5ustar privalovprivalovfasm/tools/libc/ccall.inc0000644000175000017500000000047614533376740016137 0ustar privalovprivalov macro ccall proc,[arg] { common push ebp mov ebp,esp local size size = 0 if ~ arg eq forward size = size + 4 common sub esp,size end if and esp,-16 if ~ arg eq add esp,size reverse pushd arg common end if call proc leave } fasm/tools/libc/listing.asm0000644000175000017500000000565614533376740016546 0ustar privalovprivalov format ELF public main include 'ccall.inc' section '.text' executable align 16 main: mov ecx,[esp+4] mov [argc],ecx mov ebx,[esp+8] mov [argv],ebx mov [display_handle],1 call get_params jnc make_listing mov esi,_usage call display_string ccall exit,2 make_listing: call listing ccall exit,0 error: mov [display_handle],2 mov esi,_error_prefix call display_string pop esi call display_string mov esi,_error_suffix call display_string ccall exit,0 get_params: mov ecx,[argc] mov ebx,[argv] add ebx,4 dec ecx jz bad_params get_param: mov esi,[ebx] mov al,[esi] cmp al,'-' je option_param cmp [input_file],0 jne get_output_file mov [input_file],esi jmp next_param get_output_file: cmp [output_file],0 jne bad_params mov [output_file],esi jmp next_param option_param: inc esi lodsb cmp al,'a' je addresses_option cmp al,'A' je addresses_option cmp al,'b' je bytes_per_line_option cmp al,'B' je bytes_per_line_option bad_params: stc ret addresses_option: cmp byte [esi],0 jne bad_params mov [show_addresses],1 jmp next_param bytes_per_line_option: cmp byte [esi],0 jne get_bytes_per_line_setting dec ecx jz bad_params add ebx,4 mov esi,[ebx] get_bytes_per_line_setting: call get_option_value or edx,edx jz bad_params cmp edx,1000 ja bad_params mov [code_bytes_per_line],edx next_param: add ebx,4 dec ecx jnz get_param cmp [input_file],0 je bad_params cmp [output_file],0 je bad_params clc ret get_option_value: xor eax,eax mov edx,eax get_option_digit: lodsb cmp al,20h je option_value_ok cmp al,0Dh je option_value_ok or al,al jz option_value_ok sub al,30h jc invalid_option_value cmp al,9 ja invalid_option_value imul edx,10 jo invalid_option_value add edx,eax jc invalid_option_value jmp get_option_digit option_value_ok: dec esi clc ret invalid_option_value: stc ret include 'system.inc' include '..\listing.inc' section '.data' writeable align 4 input_file dd 0 output_file dd 0 code_bytes_per_line dd 16 show_addresses db 0 line_break db 0Dh,0Ah _usage db 'listing generator for flat assembler',0Dh,0Ah db 'usage: listing ',0Dh,0Ah db 'optional settings:',0Dh,0Ah db ' -a show target addresses for assembled code',0Dh,0Ah db ' -b set the amount of bytes listed per line',0Dh,0Ah db 0 _error_prefix db 'error: ',0 _error_suffix db '.',0Dh,0Ah,0 section '.bss' writeable align 4 argc dd ? argv dd ? input dd ? assembled_code dd ? assembled_code_length dd ? code_end dd ? code_offset dd ? code_length dd ? output_handle dd ? output_buffer dd ? current_source_file dd ? current_source_line dd ? source dd ? source_length dd ? maximum_address_length dd ? address_start dd ? last_listed_address dd ? display_handle dd ? character db ? params rb 1000h characters rb 100h buffer rb 1000h fasm/tools/libc/prepsrc.asm0000644000175000017500000000257514533376740016550 0ustar privalovprivalov format ELF public main include 'ccall.inc' section '.text' executable align 16 main: mov ecx,[esp+4] mov [argc],ecx mov ebx,[esp+8] mov [argv],ebx mov [display_handle],1 call get_params jnc make_dump mov esi,_usage call display_string ccall exit,2 make_dump: call preprocessed_source ccall exit,0 error: mov [display_handle],2 mov esi,_error_prefix call display_string pop esi call display_string mov esi,_error_suffix call display_string ccall exit,0 get_params: mov ecx,[argc] mov ebx,[argv] add ebx,4 dec ecx jz bad_params get_param: mov esi,[ebx] mov al,[esi] cmp [input_file],0 jne get_output_file mov [input_file],esi jmp next_param get_output_file: cmp [output_file],0 jne bad_params mov [output_file],esi jmp next_param bad_params: stc ret next_param: add ebx,4 dec ecx jnz get_param cmp [input_file],0 je bad_params cmp [output_file],0 je bad_params clc ret include 'system.inc' include '..\prepsrc.inc' section '.data' writeable align 4 input_file dd 0 output_file dd 0 _usage db 'preprocessed source dumper for flat assembler',0Dh,0Ah db 'usage: prepsrc ',0Dh,0Ah db 0 _error_prefix db 'error: ',0 _error_suffix db '.',0Dh,0Ah,0 section '.bss' writeable align 4 argc dd ? argv dd ? display_handle dd ? character db ? params rb 1000h buffer rb 1000h fasm/tools/libc/symbols.asm0000644000175000017500000000263514533376740016557 0ustar privalovprivalov format ELF public main include 'ccall.inc' section '.text' executable align 16 main: mov ecx,[esp+4] mov [argc],ecx mov ebx,[esp+8] mov [argv],ebx mov [display_handle],1 call get_params jnc make_dump mov esi,_usage call display_string ccall exit,2 make_dump: call symbols ccall exit,0 error: mov [display_handle],2 mov esi,_error_prefix call display_string pop esi call display_string mov esi,_error_suffix call display_string ccall exit,0 get_params: mov ecx,[argc] mov ebx,[argv] add ebx,4 dec ecx jz bad_params get_param: mov esi,[ebx] mov al,[esi] cmp [input_file],0 jne get_output_file mov [input_file],esi jmp next_param get_output_file: cmp [output_file],0 jne bad_params mov [output_file],esi jmp next_param bad_params: stc ret next_param: add ebx,4 dec ecx jnz get_param cmp [input_file],0 je bad_params cmp [output_file],0 je bad_params clc ret include 'system.inc' include '..\symbols.inc' section '.data' writeable align 4 input_file dd 0 output_file dd 0 _usage db 'symbols dumper for flat assembler',0Dh,0Ah db 'usage: symbols ',0Dh,0Ah db 0 _error_prefix db 'error: ',0 _error_suffix db '.',0Dh,0Ah,0 section '.bss' writeable align 4 input dd ? output_buffer dd ? output_handle dd ? argc dd ? argv dd ? display_handle dd ? character db ? params rb 1000h buffer rb 1000h fasm/tools/libc/system.inc0000644000175000017500000000274414533376740016405 0ustar privalovprivalov extrn malloc extrn getenv extrn fopen extrn fclose extrn fread extrn fwrite extrn fseek extrn ftell extrn time extrn exit extrn 'free' as libc_free extrn 'write' as libc_write alloc: ccall malloc,eax test eax,eax jz allocation_failed clc ret allocation_failed: stc ret free: ccall libc_free,eax ret display_string: lodsb or al,al jz string_displayed mov dl,al call display_character jmp display_string string_displayed: ret display_character: mov [character],dl ccall libc_write,[display_handle],character,1 ret open: push esi edi ebp call adapt_path ccall fopen,buffer,open_mode pop ebp edi esi or eax,eax jz file_error mov ebx,eax clc ret adapt_path: mov esi,edx mov edi,buffer copy_path: lods byte [esi] cmp al,'\' jne path_char_ok mov al,'/' path_char_ok: stos byte [edi] or al,al jnz copy_path cmp edi,buffer+1000h ja not_enough_memory ret create: push esi edi ebp call adapt_path ccall fopen,buffer,create_mode pop ebp edi esi or eax,eax jz file_error mov ebx,eax clc ret close: ccall fclose,ebx ret read: push ebx ecx edx esi edi ccall fread,edx,1,ecx,ebx pop edi esi edx ecx ebx cmp eax,ecx jne file_error clc ret file_error: stc ret write: push ebx ecx edx esi edi ccall fwrite,edx,1,ecx,ebx pop edi esi edx ecx ebx cmp eax,ecx jne file_error clc ret lseek: push ebx movzx eax,al ccall fseek,ebx,edx,eax mov ebx,[esp] ccall ftell,ebx pop ebx ret open_mode db 'r',0 create_mode db 'w',0 fasm/tools/listing.inc0000644000175000017500000003016514533376740015617 0ustar privalovprivalov listing: mov edx,[input_file] call open jc input_not_found call load_file mov [input],eax cmp ecx,38h jb invalid_input cmp dword [eax],1A736166h jne invalid_input cmp dword [eax+44],0 je incomplete_input add [eax+16],eax add [eax+24],eax add [eax+32],eax add [eax+40],eax add [eax+48],eax mov edx,[eax+16] add [eax+8],edx add [eax+12],edx mov edx,[eax+12] call open jc code_not_found call load_file mov [assembled_code],eax mov [assembled_code_length],ecx call close mov [maximum_address_length],0 mov ebx,[input] mov esi,[ebx+40] lea ebp,[esi-4] add ebp,[ebx+44] get_offsets_for_lines: cmp esi,ebp je offsets_prepared mov edx,[esi+4] add edx,[ebx+32] find_line_loaded_from_source: test byte [edx+7],1 shl 7 jz store_offset_in_line mov edx,[edx+8] add edx,[ebx+32] jmp find_line_loaded_from_source store_offset_in_line: cmp dword [edx+12],0 jne get_next_offset mov [edx+12],esi movzx ecx,byte [esi+27] and cl,1 mov edi,[esi+20] test edi,edi jz base_name_length_ok xor ecx,ecx btr edi,31 jc count_base_name_characters dec edi shl edi,2 add edi,[ebx+48] mov edi,[edi] count_base_name_characters: mov ecx,[ebx+20] sub ecx,edi add edi,[ebx+16] mov edx,edi xor al,al repne scasb mov ecx,edi sub ecx,edx base_name_length_ok: cmp byte [esi+18],1 jb first_register_length_ok ja first_register_with_scale add ecx,5 jmp first_register_length_ok first_register_with_scale: add ecx,5+3 first_register_length_ok: cmp byte [esi+19],1 jb second_register_length_ok ja second_register_with_scale add ecx,5 jmp second_register_length_ok second_register_with_scale: add ecx,5+3 second_register_length_ok: cmp ecx,[maximum_address_length] jb get_next_offset mov [maximum_address_length],ecx get_next_offset: add esi,28 jmp get_offsets_for_lines offsets_prepared: mov eax,[esi] mov [code_end],eax add [maximum_address_length],19 mov edi,characters xor al,al make_characters_table: stosb inc al jnz make_characters_table mov edi,characters mov esi,symbol_characters+1 movzx ecx,byte [esi-1] xor eax,eax mark_symbol_characters: lodsb mov byte [edi+eax],0 loop mark_symbol_characters mov eax,[code_bytes_per_line] imul eax,3 add eax,[maximum_address_length] add eax,18 call alloc jc not_enough_memory mov [output_buffer],eax mov esi,[ebx+32] mov ebp,esi add ebp,[ebx+36] mov edx,[output_file] call create jc writing_error mov [output_handle],ebx xor eax,eax mov [current_source_file],eax mov [last_listed_address],eax mov [code_length],eax generate_listing: cmp esi,ebp jae listing_done mov edi,[output_buffer] test byte [esi+7],1 shl 7 jnz next_line mov ebx,[esi+12] test ebx,ebx jz no_code_listing test byte [ebx+26],11b jnz no_code_listing push esi mov edx,[esi] mov ecx,[esi+4] find_next_code_point: add esi,16 call skip_preprocessed_line cmp esi,ebp je last_code_point cmp edx,[esi] jne next_line_ok cmp ecx,[esi+4] je find_next_code_point next_line_ok: test byte [esi+7],1 shl 7 jnz find_next_code_point mov eax,[esi+12] test eax,eax jz find_next_code_point test byte [eax+26],11b jnz find_next_code_point mov eax,[eax] jmp calculate_code_length last_code_point: mov eax,[code_end] calculate_code_length: pop esi mov edx,[ebx] sub eax,edx jz no_code_listing mov [code_length],eax mov [code_offset],edx add eax,edx cmp eax,[assembled_code_length] jbe write_file_offset mov [code_length],0 write_file_offset: call write_hex_dword mov ax,': ' stosw call list_address call list_code jmp code_listing_ok no_code_listing: mov al,20h mov ecx,8+2 rep stosb call list_address mov ecx,[code_bytes_per_line] imul ecx,3 mov al,20h rep stosb code_listing_ok: call write_listing_data mov eax,[input] mov edx,[esi] test edx,edx jz main_source_file add edx,[eax+32] jmp source_name_ok main_source_file: mov edx,[eax+8] source_name_ok: cmp edx,[current_source_file] je source_loaded push ebx push edx call open jc source_not_found pop eax xchg eax,[current_source_file] test eax,eax jz load_source mov eax,[source] call free load_source: call load_file mov [source],eax mov [source_length],ecx call close pop ebx source_loaded: mov eax,[source] add eax,[esi+8] mov [current_source_line],eax push esi ebp call write_source_line pop ebp esi write_supplemental_rows: mov eax,[code_length] or eax,[current_source_line] jz next_line mov edi,[output_buffer] mov ecx,8+2 movzx eax,[show_addresses] imul eax,[maximum_address_length] add ecx,eax mov al,20h rep stosb call list_code call write_listing_data push esi ebp call write_source_line pop ebp esi jmp write_supplemental_rows next_line: mov edx,[esi] mov ecx,[esi+4] find_next_line: add esi,16 call skip_preprocessed_line cmp edx,[esi] jne generate_listing cmp ecx,[esi+4] jne generate_listing jmp find_next_line list_address: cmp [show_addresses],0 je address_ok mov [address_start],edi mov eax,[esi+12] test eax,eax jz address_finished cmp [last_listed_address],0 je make_address push esi edi lea esi,[eax+8] mov edi,[last_listed_address] mov ecx,17 repe cmpsb pop edi esi je address_finished make_address: mov ebx,[esi+12] lea eax,[ebx+8] mov [last_listed_address],eax mov al,'[' stosb mov edx,[ebx+20] test edx,edx jz write_main_address push esi mov esi,edx mov eax,[input] btr esi,31 jc base_name_ready dec esi shl esi,2 add esi,[eax+48] mov esi,[esi] base_name_ready: add esi,[eax+16] copy_section_name: lodsb test al,al jz section_name_ok stosb jmp copy_section_name section_name_ok: pop esi mov al,':' test edx,80000000h jz address_separator_ok cmp byte [ebx+27],0 jne address_separator_ok mov al,'+' address_separator_ok: stosb write_main_address: cmp byte [ebx+27],0 jne write_negative_address mov edx,[ebx+8+4] call write_hex_dword mov edx,[ebx+8] call write_hex_dword jmp write_address_registers write_negative_address: mov al,'-' stosb mov eax,[ebx+8] mov edx,[ebx+8+4] not eax not edx add eax,1 adc edx,0 push eax call write_hex_dword pop edx call write_hex_dword write_address_registers: mov dl,[ebx+16] mov dh,[ebx+18] call address_register mov dl,[ebx+17] mov dh,[ebx+19] call address_register mov ax,']' stosb address_finished: mov ecx,[maximum_address_length] sub ecx,edi add ecx,[address_start] mov al,20h rep stosb address_ok: ret address_register: cmp dh,0 je register_ok jl negative_register mov al,'+' jmp register_sign_ok negative_register: mov al,'-' register_sign_ok: stosb push esi mov esi,address_registers find_register: lodsb test al,al jz register_found cmp al,dl je register_found cmp dl,[esi] je register_found lodsb movzx eax,al add esi,eax jmp find_register register_found: lodsb movzx ecx,al rep movsb pop esi cmp dh,1 je register_ok mov al,'*' stosb test dh,0F0h jz first_scale_digit_ok mov al,dh shr al,4 cmp al,10 sbb al,69h das stosb first_scale_digit_ok: mov al,dh and al,1111b cmp al,10 sbb al,69h das stosb register_ok: ret list_code: mov ecx,[code_length] cmp ecx,[code_bytes_per_line] jb code_bytes_count_ready mov ecx,[code_bytes_per_line] code_bytes_count_ready: sub [code_length],ecx mov edx,[code_offset] add [code_offset],ecx jecxz code_bytes_ok push ecx add edx,[assembled_code] list_code_bytes: mov al,[edx] and al,1111b cmp al,10 sbb al,69h das mov ah,al mov al,[edx] shr al,4 cmp al,10 sbb al,69h das stosw mov al,20h stosb inc edx loop list_code_bytes pop ecx code_bytes_ok: neg ecx add ecx,[code_bytes_per_line] imul ecx,3 mov al,20h rep stosb ret write_listing_data: mov ecx,[output_buffer] sub ecx,edi and ecx,111b mov al,20h rep stosb mov edx,[output_buffer] mov ecx,edi sub ecx,edx mov ebx,[output_handle] call write jc writing_error ret write_source_line: mov esi,[current_source_line] test esi,esi je write_line_break mov ebp,[source_length] add ebp,[source] mov ebx,characters xor cl,cl start_cutting: xor dl,dl cut_source_line: cmp esi,ebp je end_of_file lodsb cmp al,0Dh je cr_character cmp al,0Ah je lf_character cmp al,1Ah je end_of_line or al,al jz end_of_line cmp dl,3Bh je cut_source_line cmp al,3Bh je start_special_block cmp dl,22h je inside_string cmp dl,27h je inside_string cmp al,'\' je check_for_line_continuation xlatb test al,al jz start_cutting cmp dl,0FFh je cut_source_line cmp al,22h je start_special_block cmp al,27h je start_special_block mov dl,0FFh jmp cut_source_line start_special_block: mov dl,al jmp cut_source_line inside_string: cmp al,dl jne cut_source_line jmp start_cutting check_for_line_continuation: or cl,0FFh cmp esi,ebp je end_of_file mov al,[esi] cmp al,20h je start_cutting cmp al,0Dh je start_cutting cmp al,0Ah je start_cutting cmp al,3Bh je start_cutting xor cl,cl jmp start_cutting cr_character: mov edx,esi mov word [line_break],0Dh cmp esi,ebp je line_with_break mov al,[esi] cmp al,0Ah jne line_with_break inc edx mov [line_break+1],al jmp line_with_break lf_character: mov edx,esi mov word [line_break],0Ah cmp esi,ebp je line_with_break mov al,[esi] cmp al,0Dh jne line_with_break inc edx mov [line_break+1],al line_with_break: dec esi jmp write_line end_of_line: dec esi end_of_file: mov edx,esi write_line: cmp cl,0FFh je continued_line xor edx,edx continued_line: xchg edx,[current_source_line] mov ecx,esi sub ecx,edx mov ebx,[output_handle] call write jc writing_error write_line_break: mov edx,line_break mov ecx,2 cmp [line_break+1],0 jne line_break_size_ok dec ecx line_break_size_ok: call write jc writing_error ret listing_done: mov ebx,[output_handle] call close ret load_file: push ebx mov al,2 xor edx,edx call lseek test eax,eax jz empty_file push eax call alloc jc not_enough_memory push eax xor al,al xor edx,edx call lseek mov ecx,[esp+4] mov edx,[esp] call read jc reading_error pop eax ecx pop ebx ret empty_file: pop ebx mov ecx,eax ret write_hex_dword: mov ecx,8 write_hex_digits: xor al,al shld eax,edx,4 cmp al,10 sbb al,69h das stosb shl edx,4 loop write_hex_digits ret skip_preprocessed_line: lods byte [esi] cmp al,1Ah je skip_preprocessed_symbol cmp al,3Bh je skip_preprocessed_symbol cmp al,22h je skip_preprocessed_string or al,al jnz skip_preprocessed_line ret skip_preprocessed_symbol: lods byte [esi] movzx eax,al add esi,eax jmp skip_preprocessed_line skip_preprocessed_string: lods dword [esi] add esi,eax jmp skip_preprocessed_line not_enough_memory: call error db 'not enough memory to load the required data',0 input_not_found: call error db 'the input file was not found',0 code_not_found: call error db 'the assembled file was not found',0 source_not_found: call error db 'could not find some of the source files',0 reading_error: call error db 'some error occured while trying to read file',0 writing_error: call error db 'some error occured while trying to write file',0 invalid_input: call error db 'input file is not a recognized assembly information format',0 incomplete_input: call error db 'input file does not contain an assembly dump',0 symbol_characters db 27, 9,0Ah,0Dh,1Ah,20h,'+-/*=<>()[]{}:,|&~#`;\' address_registers db 23h,2,'bx' db 25h,2,'bp' db 26h,2,'si' db 27h,2,'di' db 40h,3,'eax' db 41h,3,'ecx' db 42h,3,'edx' db 43h,3,'ebx' db 44h,3,'esp' db 45h,3,'ebp' db 46h,3,'esi' db 47h,3,'edi' db 48h,3,'r8d' db 49h,3,'r9d' db 4Ah,4,'r10d' db 4Bh,4,'r11d' db 4Ch,4,'r12d' db 4Dh,4,'r13d' db 4Eh,4,'r14d' db 4Fh,4,'r15d' db 80h,3,'rax' db 81h,3,'rcx' db 82h,3,'rdx' db 83h,3,'rbx' db 84h,3,'rsp' db 85h,3,'rbp' db 86h,3,'rsi' db 87h,3,'rdi' db 88h,2,'r8' db 89h,2,'r9' db 8Ah,3,'r10' db 8Bh,3,'r11' db 8Ch,3,'r12' db 8Dh,3,'r13' db 8Eh,3,'r14' db 8Fh,3,'r15' db 0F4h,3,'eip' db 0F8h,3,'rip' db 0,1,'?' fasm/tools/prepsrc.inc0000644000175000017500000000351314533376740015621 0ustar privalovprivalov preprocessed_source: mov edx,[input_file] call open jc input_not_found mov al,2 xor edx,edx call lseek cmp eax,30h jb invalid_input push eax call alloc jc not_enough_memory push eax xor al,al xor edx,edx call lseek mov ecx,[esp+4] mov edx,[esp] call read jc reading_error pop eax ecx cmp dword [eax],1A736166h jne invalid_input mov esi,[eax+32] add esi,eax mov ebp,[eax+36] add ebp,esi mov edi,eax push eax preprocessed_to_text: cmp esi,ebp jae conversion_done add esi,16 xor dl,dl convert_preprocessed_line: lodsb cmp al,1Ah je copy_symbol cmp al,22h je copy_symbol cmp al,3Bh je preprocessor_symbols or al,al jz line_converted stosb xor dl,dl jmp convert_preprocessed_line copy_symbol: or dl,dl jz space_ok mov byte [edi],20h inc edi space_ok: cmp al,22h je quoted lodsb movzx ecx,al rep movsb or dl,-1 jmp convert_preprocessed_line quoted: mov al,27h stosb lodsd mov ecx,eax jecxz quoted_copied copy_quoted: lodsb stosb cmp al,27h jne quote_ok stosb quote_ok: loop copy_quoted quoted_copied: mov al,27h stosb or dl,-1 jmp convert_preprocessed_line preprocessor_symbols: mov al,3Bh stosb jmp copy_symbol line_converted: mov ax,0A0Dh stosw jmp preprocessed_to_text conversion_done: mov edx,[output_file] call create jc writing_error pop edx mov ecx,edi sub ecx,edx call write jc writing_error call close ret not_enough_memory: call error db 'not enough memory to load the required data',0 input_not_found: call error db 'the input file was not found',0 reading_error: call error db 'some error occured while trying to read file',0 writing_error: call error db 'some error occured while trying to write file',0 invalid_input: call error db 'input file is not a recognized assembly information format',0 fasm/tools/readme.txt0000644000175000017500000000217614533376740015452 0ustar privalovprivalov This directory contains some tools, which extract various types of information from the symbolic information file generated by flat assembler, and present them in a human-readable form. The listing tool creates a listing of assembled code - this tool needs to be executed in the exact configuration, in which the assembly was taking place. All the source files and the output file aswell must not have been moved or modified - if any of them was altered before generating the listing, it is going to contain garbage instead of useful information. For example, if you assembled the file with the command like: fasm example.asm example.exe -s example.fas you should generate listing by immediately running this command from the same directory: listing example.fas example.lst In addition, the "-a" switch is recommended to use in the case of executable formats, as it allows to get the run-time addresses for all the assembled code and data. The preprocessed source and symbols dump tools are simpler ones - they only need the symbolic information file as input and generate proper output text regardless of the availability of other files. fasm/tools/symbols.inc0000644000175000017500000001702414533376740015635 0ustar privalovprivalov symbols: mov edx,[input_file] call open jc input_not_found mov al,2 xor edx,edx call lseek cmp eax,30h jb invalid_input push eax call alloc jc not_enough_memory push eax xor al,al xor edx,edx call lseek mov ecx,[esp+4] mov edx,[esp] call read jc reading_error pop eax ecx cmp dword [eax],1A736166h jne invalid_input mov [input],eax add [eax+16],eax add [eax+24],eax add [eax+32],eax add [eax+48],eax mov edx,[eax+16] add [eax+8],edx mov ebx,eax mov eax,[ebx+20] add eax,[ebx+36] cmp eax,1000h ja allocate_output_buffer mov eax,1000h allocate_output_buffer: call alloc jc not_enough_memory mov [output_buffer],eax mov edx,[output_file] call create jc writing_error mov [output_handle],ebx mov ebx,[input] mov edx,[ebx+24] mov ebp,[ebx+28] add ebp,edx dump_symbols: cmp edx,ebp je dump_done test byte [edx+8],1 jz next_symbol test byte [edx+9],4 jnz next_symbol mov edi,[output_buffer] mov esi,[edx+24] test esi,esi jz anonymous_symbol mov ebx,[input] btr esi,31 jc symbol_name_in_strings_table add esi,[ebx+32] lodsb movzx ecx,al rep movsb jmp symbol_name_ok symbol_name_in_strings_table: add esi,[ebx+16] call write_string jmp symbol_name_ok anonymous_symbol: mov al,'@' stosb stosb symbol_name_ok: test byte [edx+9],2 jnz negative_value mov eax,': 0x' stosd mov eax,[edx+4] call write_hex_dword mov eax,[edx] call write_hex_dword jmp write_address_registers negative_value: mov eax,': -0' stosd mov al,'x' stosb mov ecx,[edx] mov eax,[edx+4] not ecx not eax add ecx,1 adc eax,0 push ecx or ecx,eax jnz negative_value_ok mov byte [edi],'1' inc edi negative_value_ok: call write_hex_dword pop eax call write_hex_dword write_address_registers: mov bl,[edx+12] mov bh,[edx+14] call write_address_register mov bl,[edx+13] mov bh,[edx+15] call write_address_register mov bl,[edx+11] cmp bl,0 je symbol_type_ok jl negated_symbol mov ax,', ' stosw jmp write_symbol_type negated_symbol: mov ax,', ' stosw mov esi,_negated call write_string neg bl write_symbol_type: cmp bl,1 je segment_type cmp bl,5 je rva_type cmp bl,6 je plt_type test byte [edx+20+3],80h jnz external mov esi,_relocatable call write_string cmp dword [edx+20],0 je symbol_type_ok mov esi,_in_section call write_string jmp write_symbol_base simple_relocatable: mov esi,_relocatable call write_string jmp symbol_type_ok external: mov esi,_relative_to_external call write_string jmp write_symbol_base segment_type: mov esi,_relocatable_segment call write_string jmp symbol_type_ok rva_type: mov esi,_rva call write_string jmp write_symbol_base plt_type: mov esi,_plt call write_string write_symbol_base: mov esi,[edx+20] btr esi,31 jc write_external_name dec esi shl esi,2 mov ebx,[input] add esi,[ebx+48] mov esi,[esi] add esi,[ebx+16] call write_string mov al,'(' stosb mov eax,[edx+20] call write_dec_number mov al,')' stosb jmp symbol_type_ok write_external_name: mov ebx,[input] add esi,[ebx+16] call write_string jmp symbol_type_ok symbol_type_ok: mov esi,_defined call write_string mov ebx,[edx+28] mov eax,[input] add ebx,[eax+32] call write_line_identifier mov ax,0A0Dh stosw push edx mov ebx,[output_handle] mov ecx,edi mov edx,[output_buffer] sub ecx,edx call write pop edx next_symbol: add edx,32 jmp dump_symbols dump_done: mov ebx,[output_handle] call close ret write_string: lodsb test al,al jz string_ok stosb jmp write_string string_ok: ret write_hex_dword: mov ebx,eax mov ecx,8 write_hex_digits: xor al,al shld eax,ebx,4 cmp al,10 sbb al,69h das stosb shl ebx,4 loop write_hex_digits ret write_dec_number: push ebx edx mov ecx,1000000000 xor edx,edx xor bl,bl dec_number_loop: div ecx push edx cmp ecx,1 je write_dec_digit or bl,bl jnz write_dec_digit or al,al jz dec_digit_ok not bl write_dec_digit: add al,30h stosb dec_digit_ok: mov eax,ecx xor edx,edx mov ecx,10 div ecx mov ecx,eax pop eax or ecx,ecx jnz dec_number_loop pop edx ebx ret write_address_register: cmp bh,0 je register_ok jl negative_register mov al,'+' jmp register_sign_ok negative_register: mov al,'-' register_sign_ok: stosb push esi mov esi,address_registers find_register: lodsb test al,al jz register_not_found cmp al,bl je register_found cmp bl,[esi] je register_found lodsb movzx eax,al add esi,eax jmp find_register register_not_found: mov al,bl shr al,5 cmp al,0Ch shr 1 je xmm_register cmp al,0Eh shr 1 je ymm_register cmp al,6 shr 1 je zmm_register register_found: lodsb movzx ecx,al rep movsb write_register_scale: pop esi cmp bh,1 je register_ok mov al,'*' stosb movzx eax,bh call write_dec_number register_ok: ret zmm_register: mov al,'z' jmp vector_address_register ymm_register: mov al,'y' jmp vector_address_register xmm_register: mov al,'x' vector_address_register: stosb mov ax,'mm' stosw mov al,bl and eax,11111b call write_dec_number jmp write_register_scale write_line_identifier: test dword [ebx+4],80000000h jnz identify_macro_generated_line mov esi,[ebx] mov eax,[input] test esi,esi jz main_file add esi,[eax+32] jmp file_name_ok main_file: mov esi,[eax+8] file_name_ok: call write_string mov al,'[' stosb mov eax,[ebx+4] call write_dec_number mov al,']' stosb ret identify_macro_generated_line: mov al,'{' stosb mov esi,_generated_by call write_string push ebx mov ebx,[ebx+8] mov eax,[input] add ebx,[eax+32] call write_line_identifier pop ebx mov eax,[ebx+8] cmp eax,[ebx+12] je macro_generated_line_identifier_ok mov esi,_from call write_string push ebx mov ebx,[ebx+12] mov eax,[input] add ebx,[eax+32] call write_line_identifier pop ebx macro_generated_line_identifier_ok: mov al,'}' stosb ret not_enough_memory: call error db 'not enough memory to load the required data',0 input_not_found: call error db 'the input file was not found',0 code_not_found: call error db 'the assembled file was not found',0 source_not_found: call error db 'could not find some of the source files',0 reading_error: call error db 'some error occured while trying to read file',0 writing_error: call error db 'some error occured while trying to write file',0 invalid_input: call error db 'input file is not a recognized assembly information format',0 address_registers db 23h,2,'bx' db 25h,2,'bp' db 26h,2,'si' db 27h,2,'di' db 40h,3,'eax' db 41h,3,'ecx' db 42h,3,'edx' db 43h,3,'ebx' db 44h,3,'esp' db 45h,3,'ebp' db 46h,3,'esi' db 47h,3,'edi' db 48h,3,'r8d' db 49h,3,'r9d' db 4Ah,4,'r10d' db 4Bh,4,'r11d' db 4Ch,4,'r12d' db 4Dh,4,'r13d' db 4Eh,4,'r14d' db 4Fh,4,'r15d' db 80h,3,'rax' db 81h,3,'rcx' db 82h,3,'rdx' db 83h,3,'rbx' db 84h,3,'rsp' db 85h,3,'rbp' db 86h,3,'rsi' db 87h,3,'rdi' db 88h,2,'r8' db 89h,2,'r9' db 8Ah,3,'r10' db 8Bh,3,'r11' db 8Ch,3,'r12' db 8Dh,3,'r13' db 8Eh,3,'r14' db 8Fh,3,'r15' db 94h,3,'eip' db 98h,3,'rip' db 0,1,'?' _negated db 'negated ',0 _relocatable_segment db 'relocatable segment',0 _relocatable db 'relocatable',0 _in_section db ' in section ',0 _relative_to_external db 'relative to external ',0 _rva db 'relative to RVA or GOT-based offset of ',0 _plt db 'relative to address of PLT entry for ',0 _defined db ', defined in ',0 _generated_by db 'line generated by ',0 _from db ' from ',0 fasm/tools/win32/0000755000175000017500000000000014533376740014410 5ustar privalovprivalovfasm/tools/win32/listing.asm0000644000175000017500000000730214533376740016565 0ustar privalovprivalov format PE console 4.0 entry start include 'win32a.inc' section '.data' data readable writeable _usage db 'listing generator for flat assembler',0Dh,0Ah db 'usage: listing ',0Dh,0Ah db 'optional settings:',0Dh,0Ah db ' -a show target addresses for assembled code',0Dh,0Ah db ' -b set the amount of bytes listed per line',0Dh,0Ah db 0 _error_prefix db 'error: ',0 _error_suffix db '.',0Dh,0Ah,0 line_break db 0Dh,0Ah input_file dd 0 output_file dd 0 code_bytes_per_line dd 16 show_addresses db 0 input dd ? assembled_code dd ? assembled_code_length dd ? code_end dd ? code_offset dd ? code_length dd ? output_handle dd ? output_buffer dd ? current_source_file dd ? current_source_line dd ? source dd ? source_length dd ? maximum_address_length dd ? address_start dd ? last_listed_address dd ? display_handle dd ? bytes_count dd ? params rb 1000h characters rb 100h section '.text' code readable executable start: mov [display_handle],STD_OUTPUT_HANDLE call get_params jnc make_listing mov esi,_usage call display_string invoke ExitProcess,2 make_listing: call listing invoke ExitProcess,0 error: mov [display_handle],STD_ERROR_HANDLE mov esi,_error_prefix call display_string pop esi call display_string mov esi,_error_suffix call display_string invoke ExitProcess,1 get_params: invoke GetCommandLine mov esi,eax mov edi,params find_command_start: lodsb cmp al,20h je find_command_start cmp al,22h je skip_quoted_name skip_name: lodsb cmp al,20h je find_param or al,al jz all_params jmp skip_name skip_quoted_name: lodsb cmp al,22h je find_param or al,al jz all_params jmp skip_quoted_name find_param: lodsb cmp al,20h je find_param cmp al,'-' je option_param cmp al,0Dh je all_params or al,al jz all_params cmp [input_file],0 jne get_output_file mov [input_file],edi jmp process_param get_output_file: cmp [output_file],0 jne bad_params mov [output_file],edi process_param: cmp al,22h je string_param copy_param: stosb lodsb cmp al,20h je param_end cmp al,0Dh je param_end or al,al jz param_end jmp copy_param string_param: lodsb cmp al,22h je string_param_end cmp al,0Dh je param_end or al,al jz param_end stosb jmp string_param option_param: lodsb cmp al,'a' je addresses_option cmp al,'A' je addresses_option cmp al,'b' je bytes_per_line_option cmp al,'B' je bytes_per_line_option bad_params: stc ret get_option_value: xor eax,eax mov edx,eax get_option_digit: lodsb cmp al,20h je option_value_ok cmp al,0Dh je option_value_ok or al,al jz option_value_ok sub al,30h jc invalid_option_value cmp al,9 ja invalid_option_value imul edx,10 jo invalid_option_value add edx,eax jc invalid_option_value jmp get_option_digit option_value_ok: dec esi clc ret invalid_option_value: stc ret bytes_per_line_option: lodsb cmp al,20h je bytes_per_line_option cmp al,0Dh je bad_params or al,al jz bad_params dec esi call get_option_value or edx,edx jz bad_params cmp edx,1000 ja bad_params mov [code_bytes_per_line],edx jmp find_param addresses_option: lodsb cmp al,20h je set_addresses_option cmp al,0Dh je set_addresses_option or al,al jnz bad_params set_addresses_option: dec esi mov [show_addresses],1 jmp find_param param_end: dec esi string_param_end: xor al,al stosb jmp find_param all_params: cmp [input_file],0 je bad_params cmp [output_file],0 je bad_params clc ret include 'system.inc' include '..\listing.inc' section '.idata' import data readable writeable library kernel32,'KERNEL32.DLL' include 'api\kernel32.inc' fasm/tools/win32/prepsrc.asm0000644000175000017500000000410614533376740016571 0ustar privalovprivalov format PE console 4.0 entry start include 'win32a.inc' section '.data' data readable writeable _usage db 'preprocessed source dumper for flat assembler',0Dh,0Ah db 'usage: prepsrc ',0Dh,0Ah db 0 _error_prefix db 'error: ',0 _error_suffix db '.',0Dh,0Ah,0 input_file dd 0 output_file dd 0 display_handle dd ? bytes_count dd ? params rb 1000h section '.text' code readable executable start: mov [display_handle],STD_OUTPUT_HANDLE call get_params jnc make_dump mov esi,_usage call display_string invoke ExitProcess,2 make_dump: call preprocessed_source invoke ExitProcess,0 error: mov [display_handle],STD_ERROR_HANDLE mov esi,_error_prefix call display_string pop esi call display_string mov esi,_error_suffix call display_string invoke ExitProcess,1 get_params: invoke GetCommandLine mov esi,eax mov edi,params find_command_start: lodsb cmp al,20h je find_command_start cmp al,22h je skip_quoted_name skip_name: lodsb cmp al,20h je find_param or al,al jz all_params jmp skip_name skip_quoted_name: lodsb cmp al,22h je find_param or al,al jz all_params jmp skip_quoted_name find_param: lodsb cmp al,20h je find_param cmp al,0Dh je all_params or al,al jz all_params cmp [input_file],0 jne get_output_file mov [input_file],edi jmp process_param get_output_file: cmp [output_file],0 jne bad_params mov [output_file],edi process_param: cmp al,22h je string_param copy_param: stosb lodsb cmp al,20h je param_end cmp al,0Dh je param_end or al,al jz param_end jmp copy_param string_param: lodsb cmp al,22h je string_param_end cmp al,0Dh je param_end or al,al jz param_end stosb jmp string_param bad_params: stc ret param_end: dec esi string_param_end: xor al,al stosb jmp find_param all_params: cmp [input_file],0 je bad_params cmp [output_file],0 je bad_params clc ret include 'system.inc' include '..\prepsrc.inc' section '.idata' import data readable writeable library kernel32,'KERNEL32.DLL' include 'api\kernel32.inc' fasm/tools/win32/symbols.asm0000644000175000017500000000414614533376740016607 0ustar privalovprivalov format PE console 4.0 entry start include 'win32a.inc' section '.data' data readable writeable _usage db 'symbols dumper for flat assembler',0Dh,0Ah db 'usage: symbols ',0Dh,0Ah db 0 _error_prefix db 'error: ',0 _error_suffix db '.',0Dh,0Ah,0 input_file dd 0 output_file dd 0 input dd ? output_buffer dd ? output_handle dd ? display_handle dd ? bytes_count dd ? params rb 1000h section '.text' code readable executable start: mov [display_handle],STD_OUTPUT_HANDLE call get_params jnc make_dump mov esi,_usage call display_string invoke ExitProcess,2 make_dump: call symbols invoke ExitProcess,0 error: mov [display_handle],STD_ERROR_HANDLE mov esi,_error_prefix call display_string pop esi call display_string mov esi,_error_suffix call display_string invoke ExitProcess,1 get_params: invoke GetCommandLine mov esi,eax mov edi,params find_command_start: lodsb cmp al,20h je find_command_start cmp al,22h je skip_quoted_name skip_name: lodsb cmp al,20h je find_param or al,al jz all_params jmp skip_name skip_quoted_name: lodsb cmp al,22h je find_param or al,al jz all_params jmp skip_quoted_name find_param: lodsb cmp al,20h je find_param cmp al,0Dh je all_params or al,al jz all_params cmp [input_file],0 jne get_output_file mov [input_file],edi jmp process_param get_output_file: cmp [output_file],0 jne bad_params mov [output_file],edi process_param: cmp al,22h je string_param copy_param: stosb lodsb cmp al,20h je param_end cmp al,0Dh je param_end or al,al jz param_end jmp copy_param string_param: lodsb cmp al,22h je string_param_end cmp al,0Dh je param_end or al,al jz param_end stosb jmp string_param bad_params: stc ret param_end: dec esi string_param_end: xor al,al stosb jmp find_param all_params: cmp [input_file],0 je bad_params cmp [output_file],0 je bad_params clc ret include 'system.inc' include '..\symbols.inc' section '.idata' import data readable writeable library kernel32,'KERNEL32.DLL' include 'api\kernel32.inc' fasm/tools/win32/system.inc0000644000175000017500000000176214533376740016435 0ustar privalovprivalov display_string: invoke GetStdHandle,[display_handle] mov edx,eax mov edi,esi or ecx,-1 xor al,al repne scasb neg ecx sub ecx,2 invoke WriteFile,edx,esi,ecx,bytes_count,0 retn alloc: invoke VirtualAlloc,0,eax,MEM_COMMIT,PAGE_READWRITE or eax,eax jz allocation_error clc retn allocation_error: stc retn free: invoke VirtualFree,eax,0,MEM_RELEASE retn open: invoke CreateFile,edx,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0 cmp eax,-1 je file_error mov ebx,eax clc retn file_error: stc retn create: invoke CreateFile,edx,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0 cmp eax,-1 je file_error mov ebx,eax clc retn write: invoke WriteFile,ebx,edx,ecx,bytes_count,0 or eax,eax jz file_error clc retn read: push ecx invoke ReadFile,ebx,edx,ecx,bytes_count,0 pop edx or eax,eax jz file_error cmp edx,[bytes_count] jne file_error clc retn close: invoke CloseHandle,ebx retn lseek: movzx eax,al invoke SetFilePointer,ebx,edx,0,eax cmp eax,-1 je file_error retn fasm/whatsnew.txt0000644000175000017500000004061714533376740014717 0ustar privalovprivalov Visit http://flatassembler.net/ for more information. version 1.73.32 (Dec 04, 2023) [-] Corrected encoding of "rdpid" instruction operand. version 1.73.31 (Jul 12, 2023) [+] Handling multiple sign characters before a floating-point value. [-] Corrected an issue with negative offsets for some relocatable addresses. [-] Fixed a potential crash in external stub processor for PE. version 1.73.30 (Feb 21, 2022) [-] No longer signal an error when there is no line to concatenate with "\". version 1.73.29 (Dec 18, 2021) [-] Corrected an issue in external use of expression calculator. version 1.73.28 (Sep 16, 2021) [+] Added special preprocessing of symbols "__file__" and "__line__" (backported from flat assembler g). version 1.73.27 (Jan 27, 2021) [-] The assembler should no longer prematurely abort when sign-extended 32-bit value in 64-bit instruction overflows during intermediate passes. version 1.73.26 (Jan 26, 2021) [-] Corrected assembly of some "mov" variants when "use32" setting is used with 64-bit relocatable formats. version 1.73.25 (Aug 20, 2020) [-] Corrected operand size handling for "vldmxcsr"/"vstmxcsr" instructions. version 1.73.24 (Apr 29, 2020) [+] Added "invlpgb" and "tlbsync" instructions. [-] Upper bits of default entry point of ELF64 executable were not correctly stored in the header. version 1.73.23 (Apr 09, 2020) [+] Added "psmash", "pvalidate", "rmpadjust" and "rmpupdate" instructions. [-] No longer allowing "mov" to/from CR9-CR15 outside of long mode. version 1.73.22 (Feb 09, 2020) [-] Removed a trick from preprocessor's implementation that caused the x64 version to crash when replacing symbolic constant in a label. version 1.73.21 (Dec 05, 2019) [+] Added "$%" and "$%%" symbols, and output offset addressing with "load" and "store" directives (backported from flat assembler g). It can be used only with binary output format. [+] Added VAES and VPCMULQDQ instruction set extensions. [+] Added "pconfig" instruction. version 1.73.20 (Nov 29, 2019) [-] Fixed a bug in "cmpxchg" and "xadd" introduced by previous version. version 1.73.19 (Nov 27, 2019) [+] Added AVX512_BITALG, AVX512_VPOPCNTDQ, AVX512_VBMI2, AVX512_VNNI and AVX512_4VNNIW instruction sets. [+] Added CET_SS and CET_IBT instruction sets. [+] Added "ptwrite" instruction. version 1.73.18 (Nov 13, 2019) [-] Addresses prefixed with "fs:" or "gs:" are no longer RIP-relative by default. version 1.73.17 (Nov 10, 2019) [+] Added "mcommit" instruction. version 1.73.16 (Aug 04, 2019) [-] Corrected a mistake in AVX-512 mask parsing that led to "{k0}" mask being erroneously accepted. version 1.73.15 (Aug 01, 2019) [+] Added "movdiri", "movdir64b" instructions and GFNI instruction set. version 1.73.14 (Jul 30, 2019) [+] Added "rdpru" and "wbnoinvd" instructions. version 1.73.13 (Jul 14, 2019) [-] Corrections in 64-bit Linux interface. version 1.73.12 (May 19, 2019) [-] Implied memory size allowed for 16-bit "movzx"/"movsx". version 1.73.11 (Apr 19, 2019) [+] Added "definite" operator. version 1.73.10 (Apr 05, 2019) [+] Added "cldemote", "tpause", "umonitor" and "umwait" instructions. version 1.73.09 (Feb 17, 2019) [-] Fixed a bug in AVX-512 instruction encoding with "{sae}" modifier. version 1.73.08 (Jan 31, 2019) [-] Fixed a bug in "align" directive for "dynamic" variant of ELF executable. version 1.73.07 (Jan 30, 2019) [+] Added "dynamic" variant of ELF executable. [+] Added "gnurelro" segment type for ELF executable. version 1.73.06 (Jan 04, 2019) [+] Added "ud0" and "ud1" instruction. [-] Fixed a minor bug in ELF formatter. version 1.73.05 (Jan 03, 2019) [-] Segments in ELF executable format automatically expanded to cover headers and dynamic linking information. version 1.73.04 (Apr 30, 2018) [-] Fixed a bug in "bndstx"/"bndldx" special address syntax processing. version 1.73.03 (Apr 15, 2018) [+] Added "rdpid", "xsavec", "xsaves", "xrstors", "clzero", "monitorx" and "mwaitx" instructions. version 1.73.02 (Dec 16, 2017) [-] Fixed a bug in the storage of "virtual as" blocks. version 1.73.01 (Nov 25, 2017) [+] Added virtual block continuation syntax (backported from flat assembler g). [+] Documentation update. [-] Fixed a bug in addressing data of the "virtual as" block. version 1.73.00 (Nov 24, 2017) [+] Added "virtual as" syntax (backported from flat assembler g). version 1.72 (Oct 10, 2017) [+] Support for Intel AVX-512, SHA, CLFLUSHOPT, CLWB, PCOMMIT, ADX, RDSEED, SMAP and MPX instruction sets. [+] Added "irpv" and "postpone" directives. [+] Added ability to define a special kind of label identifying the addressing space. This label can the be used with "load" or "store" directives to allow operations on bytes in any addressing space, not just the current one. This special label is defined by following its name with double colon, and can only be used with "load" and "store" directive, where address can now be specified in two parts, first the adressing space label, then the colon and then the address inside that addressing space. [+] In the definition of macroinstruction the last argument can now be followed by "&" character to indicate that this argument can be filled with all the remaining contents of line that called the macro. This feature cannot be combined with a multi-value arguments. [+] Default value for macroinstruction parameter can now be defined with ":" character as an alternative to "=". [+] Added a 64-bit ELF executable version of flat assembler for Linux. It has no extended capabilities compared to regular versions, it just simulates the 32-bit environment to allow running the assembler on systems that support only 64-bit executables. [+] Added "gnustack" and "gnuehframe" segment types to ELF executable formatter. [+] Console versions now display preprocessed instruction that caused an error (previously only displayed by Windows GUI interface). [+] Brought back the "-d" switch for command line. [-] Removed dependence on size context for expression operators like NOT and XOR. [+] Added "bsf" and "bsr" operators to numerical expressions. [+] Allowed underscore character to be put inside a number value. [+] Allowed octal numbers ending with "q". [-] Removed the restriction that disallowed numerical constant to forward-reference its own value. version 1.70 (Apr 17, 2012) [+] Added support for AVX, AVX2, AES, CLMUL, FMA, RDRAND, FSGSBASE, F16C, FMA4, XOP, MOVBE, BMI, TBM, INVPCID, HLE and RTM instruction sets. [+] Added half-precision floating point values support. [+] Extended the syntax of "rept" directive to allow numerical expressions to be calculated by preprocessor in its arguments. [+] Added "large" and "NX" settings for PE format. [+] Allowed PE fixups to be resolved anywhere in the generated executable. [+] Allowed to specify branding value (use 3 for Linux) after the "format ELF executable" setting. [+] Added "intepreter", "dynamic" and "note" keywords for creation of special segments in ELF executables. [-] Fixed long mode opcode generator to allow absolute addresses to be generated with "qword" keyword inside square brackets. [-] Disallowed negative immediates with "int", "enter", "ret" instructions. [+] Allowed symbolic information dump file to be created even in case of error. In such case it contains only the preprocessed source that can be extracted with PREPSRC tool. If error occured during preprocessing, only the source up to the point of error is provided. [+] Added symbol references table to symbolic dump file. [-] Corrected the "defined" and "used" flags in the symbols dump to reflect the state from the final assembly pass. [+] Added "assert" directive. [-] Formatter symbols like "PE" or "readable" are now recognized only in the context of formatter directives, and thus are no longer disallowed as labels. [+] Macroinstruction argument now can have default value, defined with "=" symbol followed by value after the argument name in definition. [+] Added "relativeto" operator, which can be used in logical expressions to test whether two values differ only by a constant and not relocatable amount. [-] Revised the expression calculator, it now is able to correctly perform calculations in signed and unsigned ranges in full 64-bit. This fixes a number of issues - the overflow will now be correctly detected for 64-bit values in cases, where previous versions could not distinguish whether it was an overflow or not. The effect of these corrections is that "dq" directive will now behave consistently with behavior of the data directives for smaller sizes, and the same applies to all the places where "qword" size for value is used. version 1.68 (Jun 13, 2009) [+] Added SSSE3 (Supplemental SSE3), SSE4.1, SSE4.2 and SSE4a instructions. [+] Added the AMD SVM and Intel SMX instructions. [+] Added "rdmsrq", "wrmsrq", "sysexitq" and "sysretq" mnemonics for the 64-bit variants of respective instructions. [+] Added "fstenvw", "fstenvd", "fsavew", "fsaved", "frstorw" and "frstord" mnemonics to allow choosing between 16-bit and 32-bit variants of structures used by the "fstenv", "fsave" and "frstor" instructions. [+] Added "plt" operator for the ELF output format. [+] Allowed "rva" operator to be used in MS COFF object format, and also added "static" keyword for the "public" directive. [+] Added Intel-style aliases for the additional long mode 8-bit registers. [-] The PE formatter now automatically detects whether relocatable labels should be used, depending on whether the fixups directory is placed somewhere into executable by programer, or not. This makes possible the more flexible use of the addressing symbols in case of PE executable fixed at some position. [-] Added support for outputting the 32-bit address relocations in case of 64-bit object formats and PE executable. This makes some specific instructions compilable, but it also forces linker to put such generated code into the low 2 gigabytes of addressing space. [+] Added "EFI", "EFIboot" and "EFIruntime" subsystem keywords for PE format. [-] Corrected the precedence of operators of macroinstruction line maker. The symbol escaping now has always the higher priority than symbol conversion, and both have higher precedence than concatenation. [+] Allowed to check "@b" and "@f" symbols with "defined" operator. [+] Allowed "as" operator to specify the output file extension when placed at the end of the "format" directive line. [-] Definition of macro with the same name as one of the preprocessor's directives is no longer allowed. [+] Allowed single quote character to be put inside the number value, to help improve long numbers readability. [+] Added optional symbolic information output, and a set of tools that extract various kinds of information from it. [+] Added "err" directive that allows to signalize error from the source. version 1.66 (May 7, 2006) [+] Added "define" directive to preprocessor, which defines symbolic constants, the same kind as "equ" directive, however there's an important difference that "define" doesn't process symbolic constants in the value before assigning it. For example: a equ 1 a equ a+a define b 1 define b b+b defines the "a" constant with value "1+1", but the "b" is defined with value "b+b". This directive may be useful in some advanced macroinstructions. [-] Moved part of the conditional expression processing into parser, for slightly better performance and lesser memory usage by assembler. The logical values defined with "eq", "eqtype" and "in" operators are now evaluated by the parser and if they are enough to determine the condition, the whole block is processed accordingly. Thus this block: if eax eq EAX | 0/0 nop end if is parsed into just "nop" instruction, since parser is able to determine that the condition is true, even though one of the logical values makes no sense - but since this is none of the "eq", "eqtype" and "in" expressions, the parser doesn't investigate. [-] Also the assembler is now calculating only as many logical values as it needs to determine the condition. So this block: if defined alpha & alpha end if will not cause error when "alpha" is not defined, as it would with previous versions. This is because after checking that "defined alpha" is false condition it doesn't need to know the second logical value to determine the value of conjunction. [+] Added "short" keyword for specifying jump type, the "jmp byte" form is now obsolete and no longer correct - use "jmp short" instead. [-] The size operator applied to jump no longer applies to the size of relative displacement - now it applies to the size of target address. [-] The "ret" instruction with 0 parameter is now assembled into short form, unless you force using the 16-bit immediate with "word" operator. [+] Added missing extended registers for the 32-bit addressing in long mode. [+] Added "linkremove" and "linkinfo" section flags for MS COFF output. [+] Added support for GOT offsets in ELF object formatter, which can be useful when making position-independent code for shared libraries. For any label you can get its offset relative to GOT by preceding it with "rva" operator (the same keyword as for PE format is used, to avoid adding a new one, while this one has very similar meaning). [-] Changed ELF executable to use "segment" directive in place of "section", to make the distinction between the run-time segments and linkable sections. If you had a "section" directive in your ELF executables and they no longer assemble, replace it with "segment". [-] The PE formatter now always creates the fixups directory when told to - even when there are no fixups to be put there (in such case it creates the directory with one empty block). [-] Some of the internal structures have been extended to provide the possibility of making extensive symbol dumps. [-] Corrected "fix" directive to keep the value intact before assigning it to the prioritized constant. [+] The ` operator now works with any kind of symbol; when used with quoted string it simply does nothing. Thus the sequence of ` operators applied to one symbol work the same as if there was just one. In similar manner, the sequence of # operators now works as if it was a single one - using such a sequence instead of escaping, which was kept for some backward compatibility, is now deprecated. [-] Corrected order of identifying assembler directives ("if db eq db" was incorrectly interpreted as data definition). [-] Many other small bugs fixed. version 1.64 (Aug 8, 2005) [+] Output of PE executables for Win64 architecture (with "format PE64" setting). [+] Added "while" and "break" directives. [+] Added "irp" and "irps" directives. [+] The macro arguments can be marked as required with the "*" character. [-] Fixed checking for overflow when multiplying 64-bit values - the result must always fit in the range of signed 64 integer now. [-] Segment prefixes were generated incorrectly in 16-bit mode when BP was used as a second addressing register - fixed. [-] The "local" directive was not creating unique labels in some cases - fixed. [-] The "not encodable with long immediate" error in 64-bit mode was sometimes wrongly signaled - fixed. [-] Other minor fixes and corrections. version 1.62 (Jun 14, 2005) [+] Escaping of symbols inside macroinstructions with backslash. [+] Ability of outputting the COFF object files for Win64 architecture (with "format MS64 COFF" setting). [+] New preprocessor directives: "restruc", "rept" and "match" [+] VMX instructions support (not documented). [+] Extended data directives to allow use of the "dup" operator. [+] Extended "struc" features to allow custom definitions of main structure's label. [-] When building resources from the the .RES file that contained more than one resource of the same string name, the separate resource directories were created with the same names - fixed. [-] Several bugs in the ELF64 object output has been fixed. [-] Corrected behavior of "fix" directive to more straightforward. [-] Fixed bug in "include" directive, which caused files included from within macros to be processed the wrong way.