< 4096 ==PAGESIZE 16777216 ==STACKSIZE 128 ==STACKSTART # hex decoding { "(.)(.)" regex { } { "not a valid hex-string" die } ? * { { streq }_ [ "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F" ] -01 index } -20*10* 16 mul add } "%" defq # registers < [ /rax /rcx /rdx /rbx /rsp /rbp /rsi /rdi /r8 /r9 /r10 /r11 /r12 /r13 /r14 /r15 ] { 1 -01 defv }' each > ==bit64table { bit64table -01 . -- } /bit64assert deff < [ /eax /ecx /edx /ebx /esp /ebp /esi /edi /r8d /r9d /r10d /r11d /r12d /r13d /r14d /r15d ] { 1 -01 defv }' each > ==bit32table { bit32table -01 . -- } /bit32assert deff < [ /ax /cx /dx /bx /sp /bp /si /di /r8w /r9w /r10w /r11w /r12w /r13w /r14w /r15w ] { 1 -01 defv }' each > ==bit16table { bit16table -01 . -- } /bit16assert deff < [ /al /cl /dl /bl /spl /ah /bpl /ch /sil /dh /dil /bh /r8b /r9b /r10b /r11b /r12b /r13b /r14b /r15b ] { 1 -01 defv }' each > ==bit8table { bit8table -01 . -- } /bit8assert deff < [ /zero /al /ax /eax /rax /none ] { 0 -01 defv }' each [ /one /cl /cx /ecx /rcx ] { 1 -01 defv }' each [ /two /dl /dx /edx /rdx ] { 2 -01 defv }' each [ /three /bl /bx /ebx /rbx ] { 3 -01 defv }' each [ /four /sib /spl /ah /sp /esp /rsp ] { 4 -01 defv }' each [ /five /bpl /bp /ebp /rbp ] { 5 -01 defv }' each [ /six /sil /si /esi /rsi ] { 6 -01 defv }' each [ /seven /dil /di /edi /rdi ] { 7 -01 defv }' each [ /r8b /r8w /r8d /r8 ] { 8 -01 defv }' each [ /r9b /r9w /r9d /r9 ] { 9 -01 defv }' each [ /r10b /r10w /r10d /r10 ] { 10 -01 defv }' each [ /r11b /r11w /r11d /r11 ] { 11 -01 defv }' each [ /r12b /r12w /r12d /r12 ] { 12 -01 defv }' each [ /r13b /r13w /r13d /r13 ] { 13 -01 defv }' each [ /r14b /r14w /r14d /r14 ] { 14 -01 defv }' each [ /r15b /r15w /r15d /r15 ] { 15 -01 defv }' each > ==regnoTable { regnoTable -01 . } /regno deff < [ /al /cl /dl /bl ] { 0 -01 defv }' each [ /spl /bpl /sil /dil ] { 1 -01 defv }' each [ /r8b /r9b /r10b /r11b /r12b /r13b /r14b /r15b ] { 1 -01 defv }' each > ==rexreqbyteTable { rexreqbyteTable -01 . } /rexreqbyte deff # encoding a REX prefix { # ==b ==x ==r ==w %40 -01 regno %08 band 0 gt %01 mul add -01 regno %08 band 0 gt %02 mul add -01 regno %08 band 0 gt %04 mul add -01 0 gt %08 mul add } /rex deff { =mem =reg mem [ /spl /sp /esp /rsp /bpl /bp /ebp /rbp ] streq any not assert %00 mem regno %07 band add reg regno 8 mul %38 band add } /modrm00 deff { =mem =reg mem [ /spl /sp /esp /rsp ] streq any not assert %40 mem regno %07 band add reg regno 8 mul %38 band add } /modrm01 deff { =mem =reg mem [ /spl /sp /esp /rsp ] streq any not assert %80 mem regno %07 band add reg regno 8 mul %38 band add } /modrm10 deff { =mem =reg %C0 mem regno %07 band add reg regno 8 mul %38 band add } /modrm11 deff { ==base ==idx ==scale idx [ /spl /sp /esp /rsp ] streq any not assert base [ /bpl /bp /ebp /rbp ] streq any not assert scale _ 0 gt assert 8 le assert scale [ 1 %00 %40 1 %80 1 1 1 %C0 ] * _ 1 neq assert %C0 band %38 idx regno 8 mul band add %07 base regno band add } /sib deff { _ 0 ge assert 8 { _ 256 mod -01 256 div } rep -- } /imm64 deff { _ 0 lt { 4294967296 add } rep 4294967295 band 4 { _ 256 mod -01 256 div } rep -- } /imm32 deff { _ 0 lt { 65536 add } rep 65535 band 2 { _ 256 mod -01 256 div } rep -- } /imm16 deff { _ 0 lt { 256 add } rep 255 band } /imm8 deff # label handling < { defv }' /put deff > ==labels [ ] ==labelHoles { ==l ] _ len l labels .put [ -011 len dearray } /label deff { ==l ] _ len ==offset labelHoles [ { labels l . offset 1 add sub _ 128 lt assert _ 128 neg ge assert imm8 offset -102 =[] } ] cat =labelHoles [ -011 len dearray %00 } /labelRel8 deff { ==l ] _ len ==offset labelHoles [ { labels l . offset 2 add sub _ 32768 lt assert _ 32768 neg ge assert imm16 offset [ 0 1 ] add 2 dearray -204314 =[] =[] } ] cat =labelHoles [ -011 len dearray %00 %00 } /labelRel16 deff { ==l ] _ len ==offset labelHoles [ { labels l . offset 4 add sub _ 2147483648 lt assert _ 2147483648 neg ge assert imm32 offset [ 0 1 2 3 ] add 4 dearray -408518628738 =[] =[] =[] =[] } ] cat =labelHoles [ -011 len dearray %00 %00 %00 %00 } /labelRel32 deff { ==opcodes labelHoles { opcodes -01 * } each < { defv }' /put deff > =labels [ ] =labelHoles opcodes } /labelResolve deff { < ==name ==opcode { ==offset offset 128 neg ge assert offset 128 lt assert opcode offset imm8 } name "Rel8" cat { ==lbl opcode lbl labelRel8 _ 128 neg ge not { lbl " out of Lbl8 reach" cat die } rep _ 128 lt not { lbl " out of Lbl8 reach" cat die } rep } name "Lbl8" cat > -- 2 |deff rep }' /defJmpRel8 deff # instructions { ==reg ==mem reg bit32assert mem bit64assert reg regno %07 gt mem regno %07 gt or { 0 reg /none mem rex } rep %03 reg mem modrm00 } /addlMemReg deff { ==mem ==i mem bit64assert i 256 lt assert 1 /none /none mem rex %83 /zero mem modrm00 i imm8 } /addqImm8Mem deff { ==mem ==disp ==i mem bit64assert i 256 lt assert 1 /none /none mem rex %83 /zero mem modrm01 disp imm8 i imm8 } /addqImm8MemDisp8 deff { ==reg ==i reg bit64assert i 256 lt assert 1 /none /none reg rex %83 /zero reg modrm11 i imm8 } /addqImm8Reg deff { ==reg ==mem ==disp reg bit64assert mem bit64assert disp 128 lt assert 1 reg /none mem rex %03 reg mem modrm01 disp imm8 } /addqMemDisp8Reg deff { ==dst ==src dst bit64assert src bit64assert 1 src /none dst rex %01 src dst modrm11 } /addqRegReg deff { ==reg =i reg bit8assert i 256 lt assert reg regno %07 gt reg rexreqbyte or { 0 /none /none reg rex } rep %80 /four reg modrm11 i imm8 } /andbImmReg deff { ==dst ==src dst bit64assert src bit64assert 1 src /none dst rex %21 src dst modrm11 } /andqRegReg deff { ==lbl %E8 lbl labelRel32 } /callLbl32 deff { ==reg reg bit64assert reg regno %07 gt { 1 /none /none reg rex } rep %FF /two reg modrm11 } /callqReg deff { ==dst ==src src bit64assert dst bit64assert 1 dst /none src rex %0F %47 dst src modrm11 } /cmovaqRegReg deff { ==dst ==src src bit64assert dst bit64assert 1 dst /none src rex %0F %46 dst src modrm11 } /cmovnaqRegReg deff { ==dst ==src src bit64assert dst bit64assert 1 dst /none src rex %0F %43 dst src modrm11 } /cmovaeqRegReg deff { ==dst ==src src bit64assert dst bit64assert 1 dst /none src rex %0F %42 dst src modrm11 } /cmovaeqRegReg deff { ==dst ==src src bit64assert dst bit64assert 1 dst /none src rex %0F %4F dst src modrm11 } /cmovgqRegReg deff { ==dst ==src src bit64assert dst bit64assert 1 dst /none src rex %0F %4E dst src modrm11 } /cmovngqRegReg deff { ==dst ==src src bit64assert dst bit64assert 1 dst /none src rex %0F %4D dst src modrm11 } /cmovgeqRegReg deff { ==dst ==src src bit64assert dst bit64assert 1 dst /none src rex %0F %4C dst src modrm11 } /cmovngeqRegReg deff { ==dst ==src src bit64assert dst bit64assert 1 dst /none src rex %0F %45 dst src modrm11 } /cmovnzqRegReg deff { ==dst ==src src bit64assert dst bit64assert 1 dst /none src rex %0F %44 dst src modrm11 } /cmovzqRegReg deff { %A6 } /cmpsb deff { 1 /none /none /none rex %A7 } /cmpsq deff { ==reg =i reg bit8assert i 256 lt assert reg regno %07 gt reg rexreqbyte or { 0 /none /none reg rex } rep %80 /seven reg modrm11 i imm8 } /cmpbImmReg deff { ==dst ==src src bit8assert dst bit8assert src regno %07 gt dst regno %07 gt src rexreqbyte dst rexreqbyte or or or { 0 src /none dst rex } rep %38 src dst modrm11 } /cmpbRegReg deff { ==mem ==reg reg bit32assert mem bit64assert reg regno %07 gt mem regno %07 gt or { 0 reg /none mem rex } rep %39 reg mem modrm00 } /cmplRegMem deff { ==reg ==i reg bit64assert i 256 lt assert 1 /none /none reg rex %83 /seven reg modrm11 i imm8 } /cmpqImm8Reg deff { ==mem ==disp ==i mem bit64assert disp 128 lt assert i 256 lt assert 1 /none /none mem rex %83 /seven mem modrm01 disp imm8 i imm8 } /cmpqImm8MemDisp8 deff { ==reg ==mem ==idx reg bit64assert mem bit64assert idx bit64assert 1 reg idx mem rex %3B reg /sib modrm00 1 idx mem sib } /cmpqMemIndexReg deff { ==reg ==mem reg bit64assert mem bit64assert 1 reg /none mem rex %3B reg mem modrm00 } /cmpqMemReg deff { ==reg ==mem ==disp reg bit64assert mem bit64assert disp 128 lt assert 1 reg /none mem rex %3B reg mem modrm01 disp imm8 } /cmpqMemDisp8Reg deff { ==mem ==reg reg bit64assert mem bit64assert 1 reg /none mem rex %39 reg mem modrm00 } /cmpqRegMem deff { ==dst ==src dst bit64assert src bit64assert 1 src /none dst rex %39 src dst modrm11 } /cmpqRegReg deff { ==mem mem bit64assert 1 /none /none mem rex %FF /one mem modrm00 } /decqMem deff { ==reg reg bit64assert 1 /none /none reg rex %FF /one reg modrm11 } /decqReg deff { ==reg reg bit64assert 1 /none /none reg rex %F7 /six reg modrm11 } /divqReg deff { ==mem mem bit64assert 1 /none /none mem rex %FF /zero mem modrm00 } /incqMem deff { ==reg reg bit64assert 1 /none /none reg rex %FF /zero reg modrm11 } /incqReg deff %E2 /loop defJmpRel8 %EB /jmp defJmpRel8 { ==lbl %E9 lbl labelRel32 } /jmpLbl32 deff %77 /ja defJmpRel8 %72 /jb defJmpRel8 %76 /jbe defJmpRel8 %74 /je defJmpRel8 %7E /jle defJmpRel8 %73 /jnb defJmpRel8 %75 /jne defJmpRel8 %79 /jns defJmpRel8 %75 /jnz defJmpRel8 %78 /js defJmpRel8 %74 /jz defJmpRel8 { ==reg ==mem ==idx ==scale ==disp reg bit32assert mem bit64assert idx bit64assert disp 128 lt assert reg regno %07 gt mem regno %07 gt idx regno %07 gt or or { 0 reg idx mem rex } rep %8D reg /sib modrm01 scale idx mem sib disp imm8 } /lealMemIndexScaleDisp8Reg deff { ==reg ==mem ==disp reg bit64assert mem bit64assert disp 128 lt assert 1 reg /none mem rex %8D reg mem modrm01 disp imm8 } /leaqMemDisp8Reg deff { ==reg ==mem ==idx ==scale reg bit64assert mem bit64assert idx bit64assert 1 reg idx mem rex %8D reg /sib modrm00 scale idx mem sib } /leaqMemIndexScaleReg deff { ==reg ==mem ==idx ==scale ==disp reg bit64assert mem bit64assert idx bit64assert 1 reg idx mem rex %8D reg /sib modrm01 scale idx mem sib disp imm8 } /leaqMemIndexScaleDisp8Reg deff { ==mem ==i mem bit64assert i 256 lt assert mem regno %07 gt { 0 /none /none mem rex } rep %C6 /zero mem modrm00 i imm8 } /movbImmMem deff { ==mem ==disp ==i mem bit64assert disp 128 lt assert i 256 lt assert mem regno %07 gt { 0 /none /none mem rex } rep %C6 /zero mem modrm01 disp imm8 i imm8 } /movbImmMemDisp8 deff { ==reg ==mem ==disp reg bit8assert mem bit64assert disp 128 lt assert reg regno %07 gt reg rexreqbyte mem regno %07 gt or or { 0 reg /none mem rex } rep %8A reg mem modrm01 disp imm8 } /movbMemDisp8Reg deff { ==mem ==reg reg bit8assert mem bit64assert reg regno %07 gt reg rexreqbyte mem regno %07 gt or or { 0 reg /none mem rex } rep %88 reg mem modrm00 } /movbRegMem deff { ==mem ==i mem bit64assert i 65536 lt assert mem regno %07 gt { 0 /none /none mem rex } rep %66 %C7 /zero mem modrm00 i imm16 } /movwImmMem deff { ==mem ==i mem bit64assert i 65536 65536 mul lt assert mem regno %07 gt { 0 /none /none mem rex } rep %C7 /zero mem modrm00 i imm32 } /movlImmMem deff { ==mem ==disp ==i mem bit64assert disp 128 lt assert i 65536 65536 mul lt assert mem regno %07 gt { 0 /none /none mem rex } rep %C7 /zero mem modrm01 disp imm8 i imm32 } /movlImmMemDisp8 deff { ==reg ==mem reg bit32assert mem bit64assert reg regno %07 gt mem regno %07 gt or { 0 reg /none mem rex } rep %8B reg mem modrm00 } /movlMemReg deff { ==reg ==i reg bit64assert 1 /none /none reg rex %B8 reg regno %07 band add i imm64 } /movqImmReg deff { ==mem ==disp ==i mem bit64assert i 2147483648 lt assert i 2147483648 neg ge assert 1 /none /none mem rex %C7 /zero mem modrm01 disp imm8 i imm32 } /movqImm32MemDisp8 deff { ==reg reg bit64assert 1 /none /none reg rex %B8 reg regno %07 band add } /movqImmOOBReg deff { ==reg ==mem ==disp reg bit64assert mem bit64assert disp 128 lt assert 1 reg /none mem rex %8B reg mem modrm01 disp imm8 } /movqMemDisp8Reg deff { ==reg ==mem ==idx reg bit64assert mem bit64assert idx bit64assert 1 reg idx mem rex %8B reg /sib modrm00 1 idx mem sib } /movqMemIndexReg deff { ==reg ==mem reg bit64assert mem bit64assert 1 reg /none mem rex %8B reg mem modrm00 } /movqMemReg deff { ==mem ==reg reg bit64assert mem bit64assert 1 reg /none mem rex %89 reg mem modrm00 } /movqRegMem deff { ==mem ==disp ==reg reg bit64assert mem bit64assert disp 128 lt assert 1 reg /none mem rex %89 reg mem modrm01 disp imm8 } /movqRegMemDisp8 deff { ==mem ==idx ==reg reg bit64assert mem bit64assert idx bit64assert 1 reg idx mem rex %89 reg /sib modrm00 1 idx mem sib } /movqRegMemIndex deff { ==mem ==idx ==scale ==reg reg bit64assert mem bit64assert idx bit64assert 1 reg idx mem rex %89 reg /sib modrm00 scale idx mem sib } /movqRegMemIndexScale deff { ==dst ==src src bit64assert dst bit64assert 1 src /none dst rex %89 src dst modrm11 } /movqRegReg deff { %A4 } /movsb deff { 1 /none /none /none rex %A5 } /movsq deff { ==reg ==mem reg bit64assert mem bit64assert 1 reg /none mem rex %0F %B6 reg mem modrm00 } /movzxMem8Reg64 deff { ==reg ==mem ==disp reg bit64assert mem bit64assert disp 128 lt assert 1 reg /none mem rex %0F %B6 reg mem modrm01 disp imm8 } /movzxMem8Disp8Reg64 deff { ==reg ==mem ==idx ==scale ==disp reg bit64assert mem bit64assert idx bit64assert disp 128 lt assert 1 reg idx mem rex %0F %B6 reg /sib modrm01 scale idx mem sib disp imm8 } /movzxMem8IndexScaleDisp8Reg64 deff { ==reg reg bit64assert 1 /none /none reg rex %F7 /four reg modrm11 } /mulqReg deff { ==reg reg bit64assert 1 /none /none reg rex %F7 /three reg modrm11 } /negqReg deff { ==mem ==i mem bit64assert i 256 lt assert %80 /one mem modrm00 i imm8 } /orbImmMem deff { ==mem ==disp ==i mem bit64assert i 256 lt assert disp 128 lt assert %80 /one mem modrm01 disp imm8 i imm8 } /orbImmMemDisp8 deff { ==dst ==src dst bit64assert src bit64assert 1 src /none dst rex %09 src dst modrm11 } /orqRegReg deff { ==mem mem regno %07 gt { 1 /none /none mem rex } rep %8F /zero mem modrm00 } /popqMem deff { ==mem ==disp mem regno %07 gt { 1 /none /none mem rex } rep disp 128 lt assert %8F /zero mem modrm01 disp imm8 } /popqMemDisp8 deff { ==mem ==idx ==scale mem regno %07 gt idx regno %07 gt or { 1 /none idx mem rex } rep %8F /zero /sib modrm00 scale idx mem sib } /popqMemIndexScale deff { ==mem ==idx ==scale ==disp mem regno %07 gt idx regno %07 gt or { 1 /none idx mem rex } rep disp 128 lt assert %8F /zero /sib modrm01 scale idx mem sib disp imm8 } /popqMemIndexScaleDisp8 deff { ==reg reg regno %07 gt { 1 /none /none reg rex } rep %58 reg regno %07 band add } /popqReg deff { ==mem mem regno %07 gt { 1 /none /none mem rex } rep %FF /six mem modrm00 } /pushqMem deff { ==mem ==disp mem regno %07 gt { 1 /none /none mem rex } rep %FF /six mem modrm01 disp imm8 } /pushqMemDisp8 deff { ==mem ==idx ==scale mem regno %07 gt idx regno %07 gt or { 1 /none idx mem rex } rep %FF /six /sib modrm00 scale idx mem sib } /pushqMemIndexScale deff { ==mem ==idx ==scale ==disp mem regno %07 gt idx regno %07 gt or { 1 /none idx mem rex } rep disp 128 lt assert %FF /six /sib modrm01 scale idx mem sib disp imm8 } /pushqMemIndexScaleDisp8 deff { ==reg reg regno %07 gt { 1 /none /none reg rex } rep %50 reg regno %07 band add } /pushqReg deff { ==imm %68 imm imm32 } /pushqImm32 deff { %F3 } /reprcx deff { %F3 } /repz deff { %C3 } /retn deff { ==reg ==i reg bit64assert i 64 lt assert 1 /none /none reg rex %C1 /four reg modrm11 i imm8 } /shlqImm8Reg deff { ==reg reg bit64assert 1 /none /none reg rex %D1 /five reg modrm11 } /shrq1Reg deff { ==reg ==i reg bit64assert i 64 lt assert 1 /none /none reg rex %C1 /five reg modrm11 i imm8 } /shrqImm8Reg deff { ==reg ==i reg bit64assert i 256 lt assert 1 /none /none reg rex %83 /five reg modrm11 i imm8 } /subqImm8Reg deff { ==reg ==mem ==disp reg bit64assert mem bit64assert disp 128 lt assert 1 reg /none mem rex %2B reg mem modrm01 disp imm8 } /subqMemDisp8Reg deff { ==reg ==mem reg bit32assert mem bit64assert reg regno %07 gt mem regno %07 gt or { 0 reg /none mem rex } rep %2B reg mem modrm00 } /sublMemReg deff { ==reg ==mem reg bit64assert mem bit64assert 1 reg /none mem rex %2B reg mem modrm00 } /subqMemReg deff { ==dst ==src dst bit64assert src bit64assert 1 src /none dst rex %29 src dst modrm11 } /subqRegReg deff { %0F %05 } /syscall deff { ==reg =i reg bit8assert i 256 lt assert reg regno %07 gt { 0 /none /none reg rex } rep %F6 /zero reg modrm11 i imm8 } /testbImmReg deff { ==dst ==src dst bit64assert src bit64assert 1 src /none dst rex %85 src dst modrm11 } /testqRegReg deff { %0F %0B } /ud2 deff { ==mem ==reg reg bit64assert mem bit64assert 1 reg /none mem rex %87 reg mem modrm00 } /xchgqRegMem deff { ==dst ==src dst bit64assert src bit64assert 1 src /none dst rex %87 src dst modrm11 } /xchgqRegReg deff { ==reg ==mem reg bit64assert mem bit64assert 1 reg /none mem rex %33 reg mem modrm00 } /xorqMemReg deff { ==mem ==reg reg bit64assert mem bit64assert 1 reg /none mem rex %31 reg mem modrm00 } /xorqRegMem deff { ==dst ==src dst bit64assert src bit64assert 1 src /none dst rex %31 src dst modrm11 } /xorqRegReg deff # global stack layout # 0 - STACKSTART : global variables # %0 : current stack pointer # STACKSTART - ...: real stack [ /mainStack /mainCallStack ] { < STACKSIZE sys .asm .alloc ==stack stack .base ==i [ stack .base STACKSIZE add imm64 ] { i sys .asm .poke i 1 add =i } each stack > -12 == }' each STACKSIZE sys .asm .alloc .base ==quoteEncodingBuffer { ==opcodes opcodes len 1 sub PAGESIZE div 1 add PAGESIZE mul sys .asm .alloc /codearea defv sys .asm .|poke =*poke codearea .base opcodes { -101 poke 1 add } each -- codearea } /arrayToCode deff # take an array of instruction bytes and execute it on the given stack { ==callStack ==valueStack ==opcodes [ /rbx pushqReg /r15 pushqReg valueStack /rbx movqImmReg /rsp /rbx xchgqRegMem callStack /rbx movqImmReg /r15 /rbx xchgqRegMem opcodes _ len dearray callStack /rbx movqImmReg /r15 /rbx xchgqRegMem valueStack /rbx movqImmReg /rsp /rbx xchgqRegMem /r15 popqReg /rbx popqReg retn ] } /compileOn deff { compileOn arrayToCode _ .base sys .asm .execute .free } /executeOn deff { mainStack .base mainCallStack .base executeOn } /execute deff { mainStack .base mainCallStack .base compileOn } /compile deff > /assembler defv # vim: syn=elymas