├── .gitattributes ├── .gitignore ├── README.md ├── bin └── sasm.exe ├── examples ├── coff32.asm ├── coff64.asm ├── elf.inc ├── elf32.asm ├── elf32pic.asm ├── elf64.asm ├── elf64_printf.asm ├── elfx32.asm ├── mzexe.asm ├── pecoff.inc ├── peexe32.asm ├── peexe64.asm ├── tine.asm ├── tinype.asm ├── x86filter1.asm └── x86filter2.asm ├── license.txt ├── readme.txt └── src ├── SASM.inc ├── SASMCore.pas ├── SASMData.pas ├── SASMDataContent.inc ├── TRILinker.pas ├── sasm.dpr ├── sasm.lpi ├── x86conv.dpr ├── x86conv.lpi ├── x86format.dpr ├── x86format.lpi ├── x86ins.txt ├── x86keywords.txt ├── x86prefixes.txt └── x86regs.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | *.inc linguist-language=Pascal -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | #*.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | #*.ddp 15 | # 16 | # Visual LiveBindings file. Added in Delphi XE2. 17 | # Uncomment this if you are not using LiveBindings Designer. 18 | #*.vlb 19 | # 20 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 21 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 22 | #*.deployproj 23 | # 24 | # C++ object files produced when C/C++ Output file generation is configured. 25 | # Uncomment this if you are not using external objects (zlib library for example). 26 | #*.obj 27 | # 28 | 29 | # Delphi compiler-generated binaries (safe to delete) 30 | *.exe 31 | *.dll 32 | *.bpl 33 | *.bpi 34 | *.dcp 35 | *.so 36 | *.apk 37 | *.drc 38 | *.map 39 | *.dres 40 | *.rsm 41 | *.tds 42 | *.dcu 43 | *.lib 44 | *.a 45 | *.o 46 | *.ocx 47 | 48 | # Delphi autogenerated files (duplicated info) 49 | *.cfg 50 | *.hpp 51 | *Resource.rc 52 | 53 | # Delphi local files (user-specific info) 54 | *.local 55 | *.identcache 56 | *.projdata 57 | *.tvsconfig 58 | *.dsk 59 | 60 | # Delphi history and backups 61 | __history/ 62 | __recovery/ 63 | *.~* 64 | 65 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 66 | *.stat 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SASM 2 | 3 | SASM (Scriptable ASseMbler) is a x86 assembler with ECMAScript as (additional) macro language as an optional compile-in-option 4 | 5 | ## Features 6 | 7 | - Support for x86-16, x86-32 and x86-64 targets 8 | - since 2015, it's based on the opcode tables from the NASM project, before 2015, the whole x86 ISA code generation was hardcoded 9 | - Supported output formats: 10 | - BIN 11 | - COM 12 | - MZEXE 13 | - PE32 14 | - PE32+/PE64 15 | - ELF32 16 | - ELFX32 (untested) 17 | - ELF64 (works, but some small non-critical issues are still there) 18 | - COFF32 19 | - COFF64 20 | - OMF16 (Work in progress, non-existent/only-stub) 21 | - OMF32 (Work in progress, non-existent/only-stub) 22 | - TRI32 (TRI = Tiny Runtime Image, a simple object in-memory file format, designed for usage in just-in-time compilers and so on) 23 | - TRI64 (TRI = Tiny Runtime Image, a simple object in-memory file format, designed for usage in just-in-time compilers and so on) 24 | - and of course RUNTIME, where the assembled code can run directly after the assemblation, so it's also a runtime x86 assembler. 25 | - 1024-bit big integer parsing and arithmetics 26 | - Floating point number literal parsing up to inoffical 512 bit FP data formats. 27 | - And many more features . . . 28 | 29 | ## Requirements 30 | 31 | - Delphi or FreePascal as compiler for to compile SASM itself 32 | - PUCU.pas from https://github.com/BeRo1985/pucu for unicode handling stuff 33 | - Optional together with SASMBESEN as define: BESEN*.pas from https://github.com/BeRo1985/besen 34 | 35 | ## Support me 36 | 37 | [Support me at Patreon](https://www.patreon.com/bero) 38 | 39 | ## License 40 | 41 | zlib, otherwise see beginning comment of https://github.com/BeRo1985/sasm/blob/master/src/SASM.inc 42 | 43 | ## General guidelines for code contributors 44 | 45 | See beginning comment of https://github.com/BeRo1985/sasm/blob/master/src/SASM.inc 46 | -------------------------------------------------------------------------------- /bin/sasm.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BeRo1985/sasm/2ad5f94509e70533d47d5196a54a782cb5c0202a/bin/sasm.exe -------------------------------------------------------------------------------- /examples/coff32.asm: -------------------------------------------------------------------------------- 1 | .include("pecoff.inc") 2 | 3 | .cpu(all) 4 | 5 | .target(coff32) 6 | 7 | .section(".text", IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_ALIGN_16BYTES){ 8 | .entrypoint 9 | .public(main) 10 | main: 11 | invoke MessageBox, byte 0, dword Text, dword Title, byte 0 12 | invoke ExitProcess, byte 0 13 | } 14 | 15 | .section(".data", IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_16BYTES){ 16 | Title: db "Test", 0 17 | Text: db "Hello world!\0" 18 | } 19 | 20 | .section(".bss", IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_16BYTES){ 21 | TestData2: db 0, 0 22 | } 23 | 24 | .external(ExitProcess = "_ExitProcess@4") 25 | .external(MessageBox = "_MessageBoxA@16") 26 | -------------------------------------------------------------------------------- /examples/coff64.asm: -------------------------------------------------------------------------------- 1 | .include("pecoff.inc") 2 | 3 | .cpu(all) 4 | 5 | .target(coff64) 6 | 7 | .section(".text", IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_ALIGN_16BYTES){ 8 | .default(rel) 9 | .entrypoint 10 | .public(main) 11 | main: 12 | //sub rsp, 8*5 13 | sub rsp, 0x100 14 | mov rcx, 0xf 15 | not rcx 16 | and rsp, rcx 17 | xor rcx, rcx 18 | mov rdx, offset Text 19 | mov r8, offset Title 20 | xor r9, r9 21 | call MessageBox 22 | xor rcx, rcx 23 | call ExitProcess 24 | } 25 | 26 | .section(".data", IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_16BYTES){ 27 | Title: db "Test", 0 28 | Text: db "Hello world!\0" 29 | } 30 | 31 | .section(".bss", IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_16BYTES){ 32 | TestData2: db 0, 0 33 | } 34 | 35 | .external(ExitProcess = "ExitProcess") 36 | .external(MessageBox = "MessageBoxA") 37 | -------------------------------------------------------------------------------- /examples/elf.inc: -------------------------------------------------------------------------------- 1 | /* 2 | ** The include file for ELF32/ELF64 3 | */ 4 | 5 | ELFOSABI_NONE = 0 6 | ELFOSABI_HPUX = 1 7 | ELFOSABI_NETBSD = 2 8 | ELFOSABI_LINUX = 3 9 | ELFOSABI_HURD = 4 10 | ELFOSABI_SOLARIS = 6 11 | ELFOSABI_AIX = 7 12 | ELFOSABI_IRIX = 8 13 | ELFOSABI_FREEBSD = 9 14 | ELFOSABI_TRU64 = 10 15 | ELFOSABI_MODESTO = 11 16 | ELFOSABI_OPENBSD = 12 17 | ELFOSABI_OPENVMS = 13 18 | ELFOSABI_NSK = 14 19 | ELFOSABI_AROS = 15 20 | ELFOSABI_FENIXOS = 16 21 | ELFOSABI_C6000_ELFABI = 64 22 | ELFOSABI_C6000_LINUX = 65 23 | ELFOSABI_ARM = 97 24 | ELFOSABI_STANDALONE = 255 25 | 26 | ET_NONE = 0 // No file type 27 | ET_REL = 1 // Relocatable file 28 | ET_EXEC = 2 // Executable file 29 | ET_DYN = 3 // Shared object file 30 | ET_CORE = 4 // Core file 31 | ET_LOPROC = 0xff00 // Processor-specific 32 | ET_HIPROC = 0xffff // Processor-specific 33 | 34 | PT_NULL = 0 35 | PT_LOAD = 1 36 | PT_DYNAMIC = 2 37 | PT_INTERP = 3 38 | PT_NOTE = 4 39 | PT_SHLIB = 5 40 | PT_PHDR = 6 41 | PT_TLS = 7 42 | 43 | PF_X = 1 44 | PF_W = 2 45 | PF_W = 2 46 | PF_R = 4 47 | 48 | SHF_WRITE = 1 49 | SHF_ALLOC = 2 50 | SHF_EXECINSTR = 4 51 | SHF_MERGE = 16 52 | SHF_STRINGS = 32 53 | SHF_INFO_LINK = 64 54 | SHF_LINK_ORDER = 128 55 | SHF_OS_NONCONFORMING = 256 56 | SHF_GROUP = 512 57 | SHF_TLS = 1024 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /examples/elf32.asm: -------------------------------------------------------------------------------- 1 | .include("elf.inc") 2 | 3 | .cpu(all) 4 | 5 | .target(elf32) 6 | 7 | .section(".text", SHF_ALLOC | SHF_EXECINSTR){ 8 | .entrypoint 9 | .public(main) 10 | main: 11 | 12 | mov eax,4 13 | mov ebx,1 14 | mov ecx,offset TextString 15 | mov edx,TextLength 16 | int 0x80 17 | 18 | mov eax,1 19 | mov ebx,0 20 | int 0x80 21 | } 22 | 23 | .section(".data", SHF_ALLOC | SHF_WRITE){ 24 | TextString: db "Hello World!\n" 25 | TextLength = __here__ - offset TextString 26 | } 27 | 28 | -------------------------------------------------------------------------------- /examples/elf32pic.asm: -------------------------------------------------------------------------------- 1 | .include("elf.inc") 2 | 3 | .cpu(all) 4 | 5 | .target(elf32) 6 | 7 | //.external(_GLOBAL_OFFSET_TABLE_) 8 | //.external(printf = "printf") 9 | 10 | .section(".text", SHF_ALLOC | SHF_EXECINSTR){ 11 | .entrypoint 12 | .public(main) 13 | main: 14 | mov eax,4 15 | mov ebx,1 16 | mov ecx,offset TextString 17 | mov edx,TextLength 18 | int 0x80 19 | 20 | mov eax,1 21 | mov ebx,0 22 | int 0x80 23 | 24 | // PIC stuff 25 | // push ebx 26 | // call @getgot 27 | // @getgot: 28 | // pop ebx 29 | // add ebx, __gotpc__(_GLOBAL_OFFSET_TABLE_ + __no_relocation__(__here__ - @getgot)) 30 | } 31 | 32 | .section(".data", SHF_ALLOC | SHF_WRITE){ 33 | TextString: db "Hello World!\n" 34 | TextLength = _here_ - offset TextString 35 | } 36 | -------------------------------------------------------------------------------- /examples/elf64.asm: -------------------------------------------------------------------------------- 1 | .include("elf.inc") 2 | 3 | .cpu(all) 4 | 5 | .target(elf64) 6 | 7 | .section(".text", SHF_ALLOC | SHF_EXECINSTR){ 8 | .default(rel) 9 | .entrypoint 10 | .public(main) 11 | main: 12 | 13 | mov rax, 1 14 | mov rdi, 1 15 | mov rsi, offset TextString 16 | mov rdx, TextLength 17 | syscall 18 | 19 | mov rax, 60 20 | mov rdi, 0 21 | syscall 22 | 23 | ret 24 | } 25 | 26 | .section(".data", SHF_ALLOC | SHF_WRITE){ 27 | TextString: db "Hello World!\n" 28 | TextLength = __here__ - offset TextString 29 | } 30 | -------------------------------------------------------------------------------- /examples/elf64_printf.asm: -------------------------------------------------------------------------------- 1 | .include("elf.inc") 2 | 3 | .cpu(all) 4 | 5 | .target(elf64) 6 | 7 | .section(".text", SHF_ALLOC | SHF_EXECINSTR){ 8 | .default(rel) 9 | .entrypoint 10 | .public(main) 11 | main: 12 | push rbp 13 | mov rax, 0 14 | mov rsi, offset TextString 15 | mov rdi, offset FormatString 16 | call printf 17 | pop rbp 18 | mov rax,0 19 | ret 20 | } 21 | 22 | .section(".data", SHF_ALLOC | SHF_WRITE){ 23 | TextString: db "Hello World!\0" 24 | FormatString: db "%s\n\0" 25 | } 26 | 27 | .external(printf) -------------------------------------------------------------------------------- /examples/elfx32.asm: -------------------------------------------------------------------------------- 1 | .include("elf.inc") 2 | 3 | .cpu(all) 4 | 5 | .target(elfx32) 6 | 7 | .external(printf) 8 | 9 | .section(".text", SHF_ALLOC | SHF_EXECINSTR){ 10 | .default(rel) 11 | .entrypoint 12 | .public(main) 13 | main: 14 | push rbp 15 | mov rax, 0 16 | mov rsi, offset TextString 17 | mov rdi, offset FormatString 18 | call printf 19 | pop rbp 20 | mov rax,0 21 | ret 22 | } 23 | 24 | .section(".data", SHF_ALLOC | SHF_WRITE){ 25 | TextString: db "Hello World!\0" 26 | FormatString: db "%s\n\0" 27 | } 28 | 29 | 30 | -------------------------------------------------------------------------------- /examples/mzexe.asm: -------------------------------------------------------------------------------- 1 | .cpu(386) 2 | 3 | .target(mzexe){ 4 | stack = 0x8000 5 | heap = 0x0 6 | startoffset = 0x100 7 | } 8 | 9 | .segment(CodeSegment){ 10 | .entrypoint 11 | main: 12 | mov ax, seg16 DataSegment 13 | mov ds, ax 14 | mov ah, 0x9 15 | mov dx, ofs16 TextString 16 | int 0x21 17 | mov ah, 0x4c 18 | int 0x21 19 | } 20 | 21 | .segment(DataSegment){ 22 | TextString: db "Hello world!\r\n$" 23 | } -------------------------------------------------------------------------------- /examples/pecoff.inc: -------------------------------------------------------------------------------- 1 | /* 2 | ** The include file for PE32/PE32+/PE64 and COFF32/COFF64 3 | */ 4 | 5 | IMAGE_FILE_RELOCS_STRIPPED = 0x0001 6 | IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002 7 | IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004 8 | IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008 9 | IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010 10 | IMAGE_FILE_BYTES_REVERSED_LO = 0x0080 11 | IMAGE_FILE_32BIT_MACHINE = 0x0100 12 | IMAGE_FILE_DEBUG_STRIPPED = 0x0200 13 | IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400 14 | IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800 15 | IMAGE_FILE_SYSTEM = 0x1000 16 | IMAGE_FILE_DLL = 0x2000 17 | IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000 18 | IMAGE_FILE_BYTES_REVERSED_HI = 0x8000 19 | 20 | IMAGE_FILE_CHARACTERISTICS_EXE = IMAGE_FILE_RELOCS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_LOCAL_SYMS_STRIPPED | IMAGE_FILE_DEBUG_STRIPPED | IMAGE_FILE_32BIT_MACHINE 21 | IMAGE_FILE_CHARACTERISTICS_DLL = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_LOCAL_SYMS_STRIPPED | IMAGE_FILE_DEBUG_STRIPPED | IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_DLL 22 | 23 | IMAGE_SUBSYSTEM_UNKNOWN = 0 24 | IMAGE_SUBSYSTEM_NATIVE = 1 25 | IMAGE_SUBSYSTEM_WINDOWS_GUI = 2 26 | IMAGE_SUBSYSTEM_WINDOWS_CUI = 3 27 | IMAGE_SUBSYSTEM_OS2_CUI = 5 28 | IMAGE_SUBSYSTEM_POSIX_CUI = 7 29 | IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9 30 | IMAGE_SUBSYSTEM_EFI_APPLICATION = 10 31 | IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11 32 | IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12 33 | IMAGE_SUBSYSTEM_EFI_ROM = 13 34 | IMAGE_SUBSYSTEM_XBOX = 14 35 | IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16 36 | 37 | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040 38 | IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080 39 | IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100 40 | IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200 41 | IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400 42 | IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800 43 | IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000 44 | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 45 | 46 | IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 47 | 48 | IMAGE_DIRECTORY_ENTRY_EXPORT = 0 49 | IMAGE_DIRECTORY_ENTRY_IMPORT = 1 50 | IMAGE_DIRECTORY_ENTRY_RESOURCE = 2 51 | IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3 52 | IMAGE_DIRECTORY_ENTRY_SECURITY = 4 53 | IMAGE_DIRECTORY_ENTRY_BASERELOC = 5 54 | IMAGE_DIRECTORY_ENTRY_DEBUG = 6 55 | IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7 56 | IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8 57 | IMAGE_DIRECTORY_ENTRY_TLS = 9 58 | IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10 59 | IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11 60 | IMAGE_DIRECTORY_ENTRY_IAT = 12 61 | 62 | IMAGE_SIZEOF_SHORT_NAME = 8 63 | 64 | IMAGE_SCN_TYIMAGE_REG = 0x00000000 65 | IMAGE_SCN_TYIMAGE_DSECT = 0x00000001 66 | IMAGE_SCN_TYIMAGE_NOLOAD = 0x00000002 67 | IMAGE_SCN_TYIMAGE_GROUP = 0x00000004 68 | IMAGE_SCN_TYIMAGE_NO_PAD = 0x00000008 69 | IMAGE_SCN_TYIMAGE_COPY = 0x00000010 70 | IMAGE_SCN_CNT_CODE = 0x00000020 71 | IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 72 | IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 73 | IMAGE_SCN_LNK_OTHER = 0x00000100 74 | IMAGE_SCN_LNK_INFO = 0x00000200 75 | IMAGE_SCN_TYIMAGE_OVER = 0x0000400 76 | IMAGE_SCN_LNK_REMOVE = 0x00000800 77 | IMAGE_SCN_LNK_COMDAT = 0x00001000 78 | IMAGE_SCN_MEM_PROTECTED = 0x00004000 79 | IMAGE_SCN_MEM_FARDATA = 0x00008000 80 | IMAGE_SCN_MEM_SYSHEAP = 0x00010000 81 | IMAGE_SCN_MEM_PURGEABLE = 0x00020000 82 | IMAGE_SCN_MEM_16BIT = 0x00020000 83 | IMAGE_SCN_MEM_LOCKED = 0x00040000 84 | IMAGE_SCN_MEM_PRELOAD = 0x00080000 85 | IMAGE_SCN_ALIGN_1BYTES = 0x00100000 86 | IMAGE_SCN_ALIGN_2BYTES = 0x00200000 87 | IMAGE_SCN_ALIGN_4BYTES = 0x00300000 88 | IMAGE_SCN_ALIGN_8BYTES = 0x00400000 89 | IMAGE_SCN_ALIGN_16BYTES = 0x00500000 90 | IMAGE_SCN_ALIGN_32BYTES = 0x00600000 91 | IMAGE_SCN_ALIGN_64BYTES = 0x00700000 92 | IMAGE_SCN_ALIGN_128BYTES = 0x00800000 93 | IMAGE_SCN_ALIGN_256BYTES = 0x00900000 94 | IMAGE_SCN_ALIGN_512BYTES = 0x00a00000 95 | IMAGE_SCN_ALIGN_1024BYTES = 0x00b00000 96 | IMAGE_SCN_ALIGN_2048BYTES = 0x00c00000 97 | IMAGE_SCN_ALIGN_4096BYTES = 0x00d00000 98 | IMAGE_SCN_ALIGN_8192BYTES = 0x00e00000 99 | IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000 100 | IMAGE_SCN_MEM_DISCARDABLE = 0x02000000 101 | IMAGE_SCN_MEM_NOT_CACHED = 0x04000000 102 | IMAGE_SCN_MEM_NOT_PAGED = 0x08000000 103 | IMAGE_SCN_MEM_SHARED = 0x10000000 104 | IMAGE_SCN_MEM_EXECUTE = 0x20000000 105 | IMAGE_SCN_MEM_READ = 0x40000000 106 | IMAGE_SCN_MEM_WRITE = 0x80000000 107 | IMAGE_SCN_CNT_RESOURCE = 0x100000000 108 | 109 | IMAGE_REL_BASED_ABSOLUTE = 0 110 | IMAGE_REL_BASED_HIGH = 1 111 | IMAGE_REL_BASED_LOW = 2 112 | IMAGE_REL_BASED_HIGHLOW = 3 113 | IMAGE_REL_BASED_HIGHADJ = 4 114 | IMAGE_REL_BASED_MIPS_JMPADDR = 5 115 | IMAGE_REL_BASED_SECTION = 6 116 | IMAGE_REL_BASED_REL32 = 7 117 | 118 | IMAGE_REL_BASED_MIPS_JMPADDR16 = 9 119 | IMAGE_REL_BASED_IA64_IMM64 = 9 120 | IMAGE_REL_BASED_DIR64 = 10 121 | IMAGE_REL_BASED_HIGH3ADJ = 11 122 | 123 | !script { 124 | 125 | Assembler.defineMacro("invoke", function(){ 126 | var currentBits = Assembler.getCurrentBits(), currentTarget = Assembler.getCurrentTarget(); 127 | if(currentBits == 32){ 128 | // 32-bit x86 stdcall invoke 129 | var functionName = arguments[0]; 130 | for(var i = arguments.length - 1; i > 0; i--){ 131 | var functionParameter = arguments[i]; 132 | Assembler.parse("push "+functionParameter); 133 | } 134 | if(currentTarget == "coff32"){ 135 | // At least Microsoft's linker writes here redirected JMP sub-routines 136 | Assembler.parse("call "+functionName); 137 | }else if(currentTarget == "pe32"){ 138 | Assembler.parse("call dword ptr ["+functionName+"]"); 139 | }else{ 140 | Assembler.error("invoke isn't suppported on " + currentTarget + " target"); 141 | } 142 | }else{ 143 | Assembler.error("invoke isn't (yet) suppported on " + currentBits + " bits"); 144 | } 145 | }); 146 | 147 | } 148 | -------------------------------------------------------------------------------- /examples/peexe32.asm: -------------------------------------------------------------------------------- 1 | .include("pecoff.inc") 2 | 3 | .cpu(all) 4 | 5 | .target(pe32){ 6 | imagebase = 0x400000 7 | codebase = 0x1000 8 | subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI 9 | characteristics = IMAGE_FILE_CHARACTERISTICS_EXE 10 | } 11 | 12 | .section(".text", IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_ALIGN_16BYTES){ 13 | .entrypoint 14 | invoke MessageBox, byte 0, dword Text, dword Title, byte 0 15 | invoke ExitProcess, byte 0 16 | } 17 | 18 | .section(".data", IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_16BYTES){ 19 | Title: db "Test", 0 20 | Text: db "Hello world!\0" 21 | } 22 | 23 | .section(".bss", IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_16BYTES){ 24 | TestData2: db 0, 0 25 | } 26 | 27 | /* 28 | .section(".rsrc", IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_ALIGN_16BYTES){ 29 | .directoryentry(IMAGE_DIRECTORY_ENTRY_RESOURCE){ 30 | // your resource data stuff, but don't forget the RVA stuff 31 | } 32 | }*/ 33 | 34 | .library("kernel32.dll"){ 35 | ExitProcess = "ExitProcess" 36 | } 37 | 38 | .library("user32.dll"){ 39 | MessageBox = "MessageBoxA" 40 | } 41 | -------------------------------------------------------------------------------- /examples/peexe64.asm: -------------------------------------------------------------------------------- 1 | .include("pecoff.inc") 2 | 3 | .cpu(all) 4 | 5 | .target(pe64){ 6 | imagebase = 0x400000 7 | codebase = 0x1000 8 | subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI 9 | characteristics = IMAGE_FILE_CHARACTERISTICS_EXE 10 | } 11 | 12 | .section(".text", IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_ALIGN_16BYTES){ 13 | .entrypoint 14 | //sub rsp, 8*5 15 | sub rsp, 0x100 16 | mov rcx, 0xf 17 | not rcx 18 | and rsp, rcx 19 | xor rcx, rcx 20 | mov rdx, offset Text 21 | mov r8, offset Title 22 | xor r9, r9 23 | call qword ptr abs MessageBox 24 | xor rcx, rcx 25 | call qword ptr abs ExitProcess 26 | } 27 | 28 | .section(".data", IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_16BYTES){ 29 | Title: db "Test", 0 30 | Text: db "Hello world!\0" 31 | } 32 | 33 | .section(".bss", IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_16BYTES){ 34 | TestData2: db 0, 0 35 | } 36 | 37 | /* 38 | .section(".rsrc", IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_SHARED | IMAGE_SCN_ALIGN_16BYTES){ 39 | .directoryentry(IMAGE_DIRECTORY_ENTRY_RESOURCE){ 40 | // your resource data stuff, but don't forget the RVA stuff 41 | } 42 | }*/ 43 | 44 | .library("kernel32.dll"){ 45 | ExitProcess = "ExitProcess" 46 | } 47 | 48 | .library("user32.dll"){ 49 | MessageBox = "MessageBoxA" 50 | } 51 | -------------------------------------------------------------------------------- /examples/tine.asm: -------------------------------------------------------------------------------- 1 | /*************************************************************************************** 2 | ** 3 | ** TINE (This is not EFI) 4 | ** 5 | ** Version 1.00.2015.09.22.13.10.0000 6 | ** 7 | **************************************************************************************** 8 | ** 9 | ** A fake-(U)EFI boot loader, which loads a PE64 EFI application image on the 1 MB 10 | ** boundary, but this boot loader doesn't emulate the (U)EFI API interface, because 11 | ** it's designed for kernel images, which can differ from what they are loaded, whether 12 | ** from a real (U)EFI or fake (U)EFI image boot loader, for to have a single kernel 13 | ** image file for both BIOS/CSM and (U)EFI worlds, for to simplify the operating 14 | ** system development on x86-64 for to support both worlds. 15 | ** 16 | ** When a PE64 EFI application image is loaded from this fake-(U)EFI boot loader, then 17 | ** the RAX register contains 0xbabeface and the RBX register contains a pointer to a 18 | ** multiboot-based data info structure (with informations to memory map, boot drive, 19 | ** etc.) 20 | ** 21 | ** It supports FAT12, FAT16 and FAT32 file systems with auto-detection, where the VBR 22 | ** boot sector must be loaded at 0x07c0:0x0000 / 0x0000:0x7c00 since this boot loader 23 | ** parses the BPB data from this memory place. 24 | ** 25 | ** You do need my own assembler SASM for to build this source code. For to get the 26 | ** current stable SASM binary, write me a mail at benjamin[at]rosseaux[dot]de together 27 | ** with your used development operating system, so that I can compile my assembler for 28 | ** your OS. 29 | ** 30 | **************************************************************************************** 31 | ** 32 | ** Copyright (C) 2015, Benjamin 'BeRo' Rosseaux ( benjamin[at]rosseaux[dot]de ) 33 | ** All rights reserved. 34 | ** 35 | ** Redistribution and use in source and binary forms, with or without 36 | ** modification, are permitted provided that the following conditions are met: 37 | ** 38 | ** 1. Redistributions of source code must retain the above copyright notice, this 39 | ** list of conditions and the following disclaimer. 40 | ** 2. Redistributions in binary form must reproduce the above copyright notice, 41 | ** this list of conditions and the following disclaimer in the documentation 42 | ** and/or other materials provided with the distribution. 43 | ** 3. Neither the name of the copyright holders nor the names of its contributors 44 | ** may be used to endorse or promote products derived from this software without 45 | ** specific prior written permission. 46 | ** 47 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 48 | ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 49 | ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 50 | ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 51 | ** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 52 | ** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 53 | ** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 54 | ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 55 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 56 | ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | ** 58 | ** The views and conclusions contained in the software and documentation are those 59 | ** of the authors and should not be interpreted as representing official policies, 60 | ** either expressed or implied, of the author. 61 | ** 62 | **************************************************************************************/ 63 | 64 | .cpu(all) 65 | .target(bin) 66 | .bits(16) 67 | .startoffset(0x0700) // 0070:0000 (/ 0000:0700) where also the MS VBR boot sector would load us 68 | 69 | CodeSegment = 0x0000 // Maximal 29952 bytes code size for this code from 0x0000:0x0700 up to until 0x0000:07c00 70 | StackSegment = 0x2000 // 64k stack 71 | BufferSegment = 0x3000 // 64k buffer segment just right after the 64k stack 72 | FATBufferSegment = 0x4000 // FAT buffer segment just right after the 64k buffer 73 | 74 | PagingTableAddress = 0x8000 // 1024 bytes after the boot sector address 0x7c00 75 | 76 | MemoryMapAddress = 0x50000 // where the ax=0xe820 int 0x15 memory map will stored 77 | 78 | KernelLoadAddress = 0x1000000 // Load kernel raw data on the 16 MB boundary (after the possible ISA hole memory ranges) 79 | KernelUncompressedAddress = 0x2000000 // Unpacked kernel on the 32 MB boundary 80 | KernelBaseAddress = 0x100000 // Load parsed kernel on the 1 MB boundary (maximal 14MB raw data size => 16 MB - (1 MB lower memory + 1 MB possible ISA hole memory ranges) 81 | 82 | BootLoaderMagic = 0xbabeface // instead multiboot signature 0x2badb002, since we're a fake-(U)EFI boot loader and not a multiboot-compliant boot loader 83 | 84 | VBRAddress = 0x7c00 85 | 86 | vbsOemName = VBRAddress + 0x03 87 | vbpbBytesPerSector = VBRAddress + 0x0b 88 | vbpbSectorsPerCluster = VBRAddress + 0x0d 89 | vbpbReservedSectors = VBRAddress + 0x0e 90 | vbpbNumberOfFATs = VBRAddress + 0x10 91 | vbpbRootEntries = VBRAddress + 0x11 92 | vbpbTotalSectors = VBRAddress + 0x13 93 | vbpbMedia = VBRAddress + 0x15 94 | vbpbSectorsPerFAT = VBRAddress + 0x16 95 | vbpbSectorsPerTrack = VBRAddress + 0x18 96 | vbpbHeadsPerCylinder = VBRAddress + 0x1a 97 | vbpbHiddenSectors = VBRAddress + 0x1C 98 | vbpbTotalSectorsBig = VBRAddress + 0x20 99 | vOfsDriveNumber equ VBRAddress + 0x24 100 | vbpb32SectorsPerFAT = VBRAddress + 0x24 101 | vbpb32Flags = VBRAddress + 0x28 102 | vbpb32Version = VBRAddress + 0x2a 103 | vbpb32RootCluster = VBRAddress + 0x2c 104 | vbpb32InfoSector = VBRAddress + 0x30 105 | vbpb32BootBackupStart = VBRAddress + 0x32 106 | vbpb32Reserved = VBRAddress + 0x34 107 | vOfs32DriveNumber equ VBRAddress + 0x40 108 | 109 | FATWorkData = VBRAddress + 0x80 110 | FATWorkDataFATSize = FATWorkData + 0 111 | FATWorkDataSectorSizeBits = FATWorkData + 4 112 | FATWorkDataClusterSizeBits = FATWorkData + 8 113 | FATWorkDataNumSectors = FATWorkData + 12 114 | FATWorkDataHiddenSectors = FATWorkData + 16 115 | FATWorkDataFATOffset = FATWorkData + 20 116 | FATWorkDataFATLength = FATWorkData + 24 117 | FATWorkDataRootOffset = FATWorkData + 28 118 | FATWorkDataRootMax = FATWorkData + 32 119 | FATWorkDataDataOffset = FATWorkData + 36 120 | FATWorkDataNumClusters = FATWorkData + 40 121 | FATWorkDataFilePos = FATWorkData + 44 122 | FATWorkDataRootCluster = FATWorkData + 48 123 | FATWorkDataClusterEOFMarker = FATWorkData + 52 124 | FATWorkDriveNumber = FATWorkData + 56 125 | FATWorkFileCluster = FATWorkData + 60 126 | FATWorkDataSectorsPerCluster = FATWorkData + 64 127 | FATWorkDataBytesPerSector = FATWorkData + 68 128 | 129 | .macro(GDTEntry)(gdtLimit,gdtBase_00_15,gdtBase_16_23,gdtType,gdtMisc,gdtBase_24_31){ 130 | dw gdtLimit 131 | dw gdtBase_00_15 132 | db gdtBase_16_23 133 | db gdtType 134 | db gdtMisc 135 | db gdtBase_24_31 136 | } 137 | 138 | .macro(PrintMessage)(TextMessage){ 139 | .local SkipLabel, TextData 140 | jmp SkipLabel 141 | TextData: 142 | db TextMessage 143 | db 0 144 | SkipLabel: 145 | pushad 146 | mov si, offset TextData 147 | call PrintNullTerminatedString 148 | popad 149 | } 150 | 151 | .macro(PrintHeximal)(Bits, Value){ 152 | !if(Bits == 8){ 153 | pushad 154 | mov al, Value 155 | call PrintHexByte 156 | popad 157 | }else if(Bits == 16){ 158 | pushad 159 | mov ax, Value 160 | call PrintHexWord 161 | popad 162 | }else if(Bits == 32){ 163 | pushad 164 | mov eax, Value 165 | call PrintHexDWord 166 | popad 167 | } 168 | } 169 | 170 | .macro(PrintDecimal)(Bits, Value){ 171 | !if((Bits == 8) || (Bits == 16)){ 172 | pushad 173 | movzx eax, Value 174 | call PrintDWord 175 | popad 176 | }else if(Bits == 32){ 177 | pushad 178 | mov eax, Value 179 | call PrintDWord 180 | popad 181 | } 182 | } 183 | 184 | .struct(TFATDirectoryEntry){ 185 | FileName byte(11) 186 | Attributes byte(1) 187 | Reserved byte(1) 188 | CreationTimeMillisecondOrChecksum byte(1) 189 | CreationTimeHourMinute word(1) 190 | CreatedDate word(1) 191 | LastAccessedDate word(1) 192 | ClusterHi32 word(1) 193 | Time word(1) 194 | Date word(1) 195 | Cluster word(1) 196 | Size dword(1) 197 | } 198 | 199 | //////////////////////// 200 | 201 | PEEXEMAGIC = 0x00004550 202 | 203 | IMAGE_FILE_MACHINE_AMD64 = 0x8664 204 | 205 | .struct(TPE64Header){ 206 | Signature dword(1) 207 | CPUType word(1) 208 | NumberOfSections word(1) 209 | TimeStamp dword(1) 210 | PointerToSymbolTable dword(1) 211 | NumberOfSymbols dword(1) 212 | SizeOfOptionalHeader word(1) 213 | Characteristics word(1) 214 | Magic word(1) 215 | MajorLinkerVersion byte(1) 216 | MinorLinkerVersion byte(1) 217 | SizeOfCode dword(1) 218 | SizeOfInitializedData dword(1) 219 | SizeOfUninitializedData dword(1) 220 | AddressOfEntryPoint dword(1) 221 | BaseOfCode dword(1) 222 | BaseOfImage qword(1) 223 | SectionAlignment dword(1) 224 | FileAlignment dword(1) 225 | MajorOperatingSystemVersion word(1) 226 | MinorOperatingSystemVersion word(1) 227 | MajorImageVersion word(1) 228 | MinorImageVersion word(1) 229 | MajorSubsystemVersion word(1) 230 | MinorSubsystemVersion word(1) 231 | Win32VersionValue dword(1) 232 | ImageSize dword(1) 233 | HeaderSize dword(1) 234 | CheckSum dword(1) 235 | SubSystem word(1) 236 | DLLCharacteristics word(1) 237 | StackReserve qword(1) 238 | StackCommit qword(1) 239 | HeapReserve qword(1) 240 | HeapCommit qword(1) 241 | LoaderFlags dword(1) 242 | NumberOfRVAAndSizes dword(1) 243 | ExportRVA dword(1) 244 | ExportSize dword(1) 245 | ImportRVA dword(1) 246 | ImportSize dword(1) 247 | ResourceRVA dword(1) 248 | ResourceSize dword(1) 249 | ExceptionRVA dword(1) 250 | ExceptionSize dword(1) 251 | SecurityRVA dword(1) 252 | SecuritySize dword(1) 253 | RelocationRVA dword(1) 254 | RelocationSize dword(1) 255 | DebugRVA dword(1) 256 | DebugSize dword(1) 257 | ImageDescRVA dword(1) 258 | ImageDescSize dword(1) 259 | MachineRVA dword(1) 260 | MachineSize dword(1) 261 | TLSRVA dword(1) 262 | TLSSize dword(1) 263 | } 264 | 265 | .struct(TPE64SectionHeader){ 266 | Name byte(8) 267 | VirtualSize dword(1) 268 | RVA dword(1) 269 | PhysicalSize dword(1) 270 | PhysicalOfs dword(1) 271 | Reserved dword(3) 272 | Flags dword(1) 273 | } 274 | 275 | .struct(TPE64Relocation){ 276 | PageRVA dword(1) 277 | BlockSize dword(1) 278 | } 279 | 280 | //////////////////////// 281 | 282 | .code { 283 | 284 | // We're loaded at 0070:0000 285 | 286 | { 287 | LoaderEntryPoint: 288 | jmp short SkipSignature 289 | Signature: 290 | db "TINE\0" 291 | !script{ 292 | var MillisecondsElapsedSince1January1970_00_00_00_UTC = Date.now(); 293 | var TimeDateString = (new Date()).toUTCString(); 294 | Assembler.parse("dq " + MillisecondsElapsedSince1January1970_00_00_00_UTC); 295 | Assembler.parse("db \"" + TimeDateString + "\\0\""); 296 | } 297 | SkipSignature: 298 | 299 | // Jump from 0070:0000 into 0000:0700 space, so that CS and DS can be zero 300 | jmp word 0x0000:offset StartCode 301 | StartCode: 302 | 303 | // Setup stack 304 | mov ax, StackSegment 305 | mov ss, ax 306 | mov sp, 0xffff 307 | 308 | // Data segment = code segment 309 | push cs 310 | pop ds 311 | 312 | call ClearScreen 313 | 314 | PrintMessage "Loading system . . .\r\n" 315 | 316 | PrintMessage "Enabling A20 line . . . " 317 | call EnableA20 // Enable A20 line 318 | jz Hang 319 | PrintMessage "done!\r\n" 320 | 321 | PrintMessage "Enabling unreal mode . . . " 322 | call EnableUnrealMode // Enable unreal mode for FS segment register 323 | jz Hang 324 | PrintMessage "done!\r\n" 325 | 326 | PrintMessage "Checking for 64-bit capable processor . . . " 327 | call CheckLongMode 328 | jz Hang 329 | PrintMessage "done!\r\n" 330 | 331 | PrintMessage "Getting memory map . . . " 332 | call GetMemoryMap // Get memory map 333 | jz Hang 334 | mov ebx, 24 335 | mul ebx 336 | mov dword ptr [BootInfoMemoryMapLength], eax 337 | PrintMessage "done! " 338 | pushad 339 | mov eax, dword ptr [MemorySize] 340 | mov edx, dword ptr [MemorySize+4] 341 | shrd eax, edx, 20 342 | shr edx, 20 343 | call PrintDWord 344 | popad 345 | PrintMessage " MB RAM found . . .\r\n" 346 | 347 | PrintMessage "Initializing FAT file system . . . " 348 | call InitializeFATFileSystem // Detect and initialize FAT file system 349 | jz Hang 350 | PrintMessage "done! FAT" 351 | PrintDecimal 32, dword ptr cs:[FATWorkDataFATSize] 352 | PrintMessage " file system found . . .\r\n" 353 | 354 | PrintMessage "Searching kernel image file . . . " 355 | call FindFile 356 | jz Hang 357 | PrintMessage "done!\r\n" 358 | 359 | PrintMessage "Loading kernel image file . . . " 360 | call LoadKernel 361 | je Hang 362 | PrintMessage "done!\r\n" 363 | 364 | PrintMessage "Parsing kernel image and jumping to kernel image entry point . . .\r\n" 365 | 366 | EnterProtectedMode: 367 | cli 368 | 369 | push cs 370 | pop ds 371 | lgdt cs:[GDTDescriptor] // Load the GDT descriptor 372 | 373 | lidt cs:[IDTDescriptor] // Load the IDT descriptor 374 | 375 | mov eax, cr0 376 | or eax, 1 377 | mov cr0, eax 378 | 379 | jmp dword 0x0008:(CodeSegment << 4) + (offset Code32) 380 | 381 | KernelEntryPoint: 382 | dd 0 383 | 384 | .bits(32) 385 | Code32: 386 | mov ax, 0x10 387 | mov ds, ax 388 | mov es, ax 389 | mov fs, ax 390 | mov gs, ax 391 | mov ss, ax 392 | mov esp, 0x90000 393 | 394 | jmp dword 0x0008:(CodeSegment << 4) + (offset Code32ReloadSegments) 395 | Code32ReloadSegments: 396 | 397 | // Check for LZBRABIN signature 398 | mov ebx, KernelLoadAddress 399 | cmp dword ptr [ebx], 'RBZL' 400 | jne KernelUncompressed 401 | cmp dword ptr [ebx + 4], 'GMIA' 402 | jne KernelUncompressed 403 | 404 | KernelUncompress: 405 | mov edx, KernelUncompressedAddress 406 | push edx 407 | add ebx, 8 + 4 408 | call LZBRADepacker 409 | pop ebx 410 | 411 | KernelUncompressed: 412 | 413 | cmp dword ptr [ebx], 'FLE\x7F' 414 | je KernelLoadELF 415 | 416 | KernelLoadPE: 417 | mov eax, ebx 418 | cmp word ptr [eax], 'ZM' 419 | jne KernelLoadFlat 420 | add eax, dword ptr [eax + 0x3c] 421 | cmp word ptr [eax], 'EP' 422 | jne KernelLoadFlat 423 | mov edi, KernelBaseAddress 424 | call LoadPE64 425 | mov dword ptr [KernelEntryPoint], eax 426 | jmp KernelLoadFlatSkip 427 | 428 | KernelLoadELF: 429 | KernelLoadELFHang: 430 | jmp KernelLoadELFHang 431 | jmp KernelLoadFlatSkip 432 | 433 | KernelLoadFlat: 434 | 435 | mov esi, ebx 436 | mov edi, KernelBaseAddress 437 | mov dword ptr [KernelEntryPoint], edi 438 | mov ecx, 0xe00000 >> 2 439 | cld 440 | rep movsd 441 | 442 | KernelLoadFlatSkip: 443 | 444 | call BuildPagingTable 445 | 446 | // Entering long mode 447 | 448 | // Disabling paging 449 | mov eax, cr0 450 | and eax, 0x7fffffff 451 | mov cr0, eax 452 | 453 | // Build new page table directory 454 | 455 | // Set the paging table address into CR3 456 | mov eax, PagingTableAddress 457 | mov cr3, eax 458 | 459 | // Set the PAE enable bit in CR4 460 | mov eax, cr4 461 | or eax, 0x20 462 | mov cr4, eax 463 | 464 | // Enable long mode by setting the EFER.LME flag in MSR 0xC0000080 465 | mov ecx, 0x0c0000080 466 | rdmsr 467 | or eax, 0x100 468 | wrmsr 469 | 470 | // Enabling paging and protected mode 471 | mov eax, cr0 472 | or eax, 0x80000001 473 | mov cr0, eax 474 | 475 | lgdt [GDT64Descriptor] 476 | 477 | jmp dword 0x0008:(CodeSegment << 4) + (offset Code64) 478 | 479 | .bits(64) 480 | Code64: 481 | 482 | mov ax, 0x0010 483 | mov ds, ax 484 | mov es, ax 485 | mov fs, ax 486 | mov gs, ax 487 | mov ss, ax 488 | 489 | mov rax, BootLoaderMagic 490 | mov rbx, (CodeSegment << 4) + (offset BootInfo) 491 | 492 | // Calling kernel entry point 493 | xor rdx, rdx 494 | mov edx, dword ptr [KernelEntryPoint] 495 | call rdx 496 | 497 | Code64Hang: 498 | hlt 499 | jmp Code64Hang 500 | 501 | .bits(16) 502 | Hang: 503 | PrintMessage "ERROR ! ! !\r\n" 504 | HangLoop: 505 | hlt 506 | jmp HangLoop 507 | } 508 | 509 | { // Build a paging table for the first maximal 64 MB of memory 510 | PagingTablePML4T = PagingTableAddress 511 | PagingTablePDPT = PagingTableAddress + 0x1000 512 | PagingTablePDT = PagingTableAddress + 0x2000 513 | PagingTablePT = PagingTableAddress + 0x3000 514 | PagingTable16MB = 16777216 515 | PagingTableSize = 67108864 // must be dividable by 2 megabytes (because 1 PT = 2 megabytes) 516 | .bits(32) 517 | BuildPagingTable: 518 | 519 | // Truncating detected memory size down to 64 MB for our initial paging table 520 | mov edx, dword ptr [MemorySize + 4] 521 | test edx, edx 522 | jnz BuildPagingTableSizeTruncate 523 | mov edx, dword ptr MemorySize 524 | mov eax, PagingTable16MB 525 | cmp edx, eax 526 | cmovl edx, eax 527 | cmp edx, PagingTableSize 528 | jle BuildPagingTableSizeNoTruncate 529 | BuildPagingTableSizeTruncate: 530 | mov edx, PagingTableSize 531 | BuildPagingTableSizeNoTruncate: 532 | 533 | // Clear paging table memory range 534 | xor eax, eax 535 | mov ecx, ((PagingTablePT - PagingTablePML4T) + (PagingTableSize >> 10)) >> 2 // PML4T + PDPT + PDT + PT 536 | mov edi, PagingTableAddress 537 | rep stosd 538 | 539 | // Maps 256 TB 540 | mov dword ptr [PagingTablePML4T], PagingTablePDPT | 000000000011b // Present, R/W, Supervisor 541 | 542 | // Maps 512 GB 543 | mov dword ptr [PagingTablePDPT], PagingTablePDT | 000000000011b // Present, R/W, Supervisor 544 | 545 | // Maps 1 GB 546 | mov eax, PagingTablePT | 000000000011b // Present, R/W, Supervisor 547 | mov ebx, PagingTablePDT 548 | mov ecx, edx 549 | shr ecx, 21 // divide by 2 megabytes 550 | jecxz BuildPagingTablePDTLoopSkip 551 | BuildPagingTablePDTLoop: 552 | mov dword ptr [ebx], eax 553 | add eax, 0x1000 554 | add ebx, 0x08 555 | dec ecx 556 | jnz BuildPagingTablePDTLoop 557 | BuildPagingTablePDTLoopSkip: 558 | 559 | // Maps PagingTableSize in 2 megabytes PT blocks with 4 kilobytes per entry 560 | mov eax, 000000000011b // Present, R/W, Supervisor 561 | mov ecx, edx 562 | shr ecx, 12 // divide by 4 kilobytes 563 | mov edi, PagingTablePT 564 | BuildPagingTableLoop: 565 | mov dword ptr [edi], eax 566 | add edi, 8 567 | add eax, 0x1000 568 | dec ecx 569 | jnz BuildPagingTableLoop 570 | 571 | ret 572 | } 573 | 574 | { 575 | .bits(32) 576 | 577 | LZBRADepackerFlagModel = 0 578 | LZBRADepackerPrevMatchModel = 2 579 | LZBRADepackerMatchLowModel = 3 580 | LZBRADepackerLiteralModel = 35 581 | LZBRADepackerGamma0Model = 291 582 | LZBRADepackerGamma1Model = 547 583 | LZBRADepackerSizeModels = 803 584 | 585 | LZBRADepackerLocalSize = (LZBRADepackerSizeModels + 2) * 4 586 | LZBRADepackerModels = -LZBRADepackerLocalSize 587 | LZBRADepackerRange = LZBRADepackerModels + (LZBRADepackerSizeModels * 4) 588 | LZBRADepackerCode = LZBRADepackerRange + 4 589 | 590 | LZBRADepacker: 591 | push ebp 592 | mov ebp, esp 593 | sub esp, LZBRADepackerLocalSize 594 | 595 | push ebx 596 | push ecx 597 | push edx 598 | push esi 599 | push edi 600 | 601 | cld 602 | mov esi, ebx 603 | 604 | lodsd 605 | mov dword ptr [ebp + LZBRADepackerCode], eax 606 | 607 | xor eax,eax 608 | not eax 609 | mov dword ptr [ebp + LZBRADepackerRange], eax 610 | 611 | not eax 612 | mov ah, 0x08 // mov eax, 2048 613 | mov ecx, LZBRADepackerSizeModels 614 | lea edi, [ebp + LZBRADepackerModels] 615 | repe stosd 616 | 617 | mov edi, edx 618 | push edi 619 | 620 | jmp LZBRADepackerMain 621 | 622 | LZBRADepackerDecodeBit: // result = eax, Move = ecx, ModelIndex = eax 623 | push ebx 624 | push edx 625 | 626 | // Bound:=(Range shr 12)*Model[ModelIndex]; 627 | lea edx, [ebp + LZBRADepackerModels + eax * 4] 628 | mov eax, dword ptr [edx] 629 | mov ebx, dword ptr [ebp + LZBRADepackerRange] 630 | shr ebx, 12 631 | push edx 632 | imul eax, ebx 633 | pop edx 634 | 635 | // if Code0) then begin 749 | test dl, 2 750 | jnz LZBRADepackerNormalMatch 751 | xor eax, eax // PrevMatchModel 752 | mov al, LZBRADepackerPrevMatchModel 753 | mov cl, 5 754 | call LZBRADepackerDecodeBit 755 | jnc LZBRADepackerNormalMatch 756 | xor ecx, ecx // Len=0 757 | jmp LZBRADepackerDoMatch 758 | LZBRADepackerNormalMatch: 759 | 760 | // Offset:=DecodeGamma(Gamma0Model); 761 | push LZBRADepackerGamma0Model 762 | call LZBRADepackerDecodeGamma 763 | 764 | // if Offset=0 then exit; 765 | test eax, eax 766 | jz LZBRADepackerWeAreDone 767 | 768 | // dec(Offset,2); 769 | lea ebx, [eax - 2] 770 | 771 | // Offset:=((Offset shl 4)+DecodeTree(MatchLowModel+(ord(Offset<>0) shl 4),16,5))+1; 772 | push edx 773 | test ebx, ebx 774 | setnz dl 775 | movzx edx, dl 776 | shl edx, 4 777 | add edx, LZBRADepackerMatchLowModel 778 | mov cl, 5 779 | xor eax, eax 780 | mov al, 16 781 | call LZBRADepackerDecodeTree 782 | pop edx 783 | shl ebx, 4 784 | lea ebx, [eax + ebx + 1] 785 | 786 | // Len:=ord(Offset>=96)+ord(Offset>=2048); 787 | xor ecx, ecx 788 | xor eax, eax 789 | cmp ebx, 2048 790 | setge al 791 | add ecx, eax 792 | cmp ebx, 96 793 | setge al 794 | add ecx, eax 795 | 796 | LZBRADepackerDoMatch: 797 | 798 | or dl,2 // LastWasMatch = true 799 | 800 | // inc(Len,DecodeGamma(Gamma1Model)); 801 | push ecx 802 | push LZBRADepackerGamma1Model 803 | call LZBRADepackerDecodeGamma 804 | pop ecx 805 | add ecx, eax 806 | 807 | push esi 808 | mov esi, edi 809 | sub esi, ebx 810 | repe movsb 811 | pop esi 812 | 813 | jmp LZBRADepackerNextFlag 814 | 815 | LZBRADepackerLiteral: 816 | // byte(pointer(Destination)^):=DecodeTree(LiteralModel,256,4); 817 | push edx 818 | xor eax, eax // mov eax, 256 819 | inc ah 820 | mov cl, 4 821 | mov edx, LZBRADepackerLiteralModel 822 | call LZBRADepackerDecodeTree 823 | pop edx 824 | // inc(Destination); 825 | stosb 826 | // LastWasMatch:=false; 827 | and dl,0xfd 828 | 829 | LZBRADepackerNextFlag: 830 | // Flag:=boolean(byte(DecodeBit(FlagModel+byte(boolean(LastWasMatch)),5))); 831 | movzx eax, dl 832 | and al, 1 833 | mov cl, 5 834 | call LZBRADepackerDecodeBit 835 | and dl, 0xfe 836 | or dl, al 837 | 838 | jmp LZBRADepackerLoop 839 | 840 | LZBRADepackerWeAreDone: 841 | 842 | mov eax, edi 843 | pop edi 844 | sub eax, edi 845 | 846 | pop edi 847 | pop esi 848 | pop edx 849 | pop ecx 850 | pop ebx 851 | 852 | mov esp, ebp 853 | pop ebp 854 | ret 855 | 856 | } 857 | 858 | { 859 | .bits(32) 860 | LoadPE64: 861 | push ebx 862 | push ecx 863 | push esi 864 | 865 | // eax = PE Header 866 | // esi/ebx = MZ-EXE Header 867 | mov esi, ebx 868 | mov eax, ebx 869 | add eax, dword ptr [eax + 0x3c] 870 | 871 | // Clear memory 872 | push eax 873 | push edi 874 | mov ecx, dword ptr [eax + TPE64Header.ImageSize] 875 | xor eax, eax 876 | push ecx 877 | shr ecx, 2 878 | rep stosd 879 | pop ecx 880 | and ecx, 0x3 881 | rep stosb 882 | pop edi 883 | pop eax 884 | 885 | // Copy PE image header 886 | push esi 887 | push edi 888 | mov ecx, dword ptr [eax + TPE64Header.HeaderSize] 889 | push ecx 890 | shr ecx, 2 891 | rep movsd 892 | pop ecx 893 | and ecx, 0x3 894 | rep movsb 895 | pop edi 896 | pop esi 897 | 898 | movzx ecx, word ptr [eax + TPE64Header.NumberOfSections] 899 | movzx ebx, word ptr [eax + TPE64Header.SizeOfOptionalHeader] 900 | lea ebx, [ebx + eax + TPE64Header.Magic] 901 | 902 | // Copy sections 903 | LoadPEEXECopySectionLoop: 904 | push ecx 905 | push esi 906 | push edi 907 | add esi, dword ptr [ebx + TPE64SectionHeader.PhysicalOfs] 908 | add edi, dword ptr [ebx + TPE64SectionHeader.RVA] 909 | mov ecx, dword ptr [ebx + TPE64SectionHeader.PhysicalSize] 910 | push ecx 911 | shr ecx, 2 912 | rep movsd 913 | pop ecx 914 | and ecx, 0x3 915 | rep movsb 916 | pop edi 917 | pop esi 918 | pop ecx 919 | add ebx, TPE64SectionHeader 920 | dec ecx 921 | jnz LoadPEEXECopySectionLoop 922 | 923 | mov eax, dword ptr [eax + TPE64Header.AddressOfEntryPoint] 924 | 925 | pop esi 926 | pop ecx 927 | pop ebx 928 | 929 | push ebx 930 | mov ebx, edi 931 | call LoadPERelocate 932 | add eax, ebx 933 | pop ebx 934 | 935 | ret 936 | 937 | // --- Subroutine 938 | LoadPERelocate: 939 | pushad 940 | 941 | mov edi, ebx 942 | add edi, dword [edi + 0x3c] 943 | 944 | mov edx, ebx 945 | sub edx, dword ptr [edi + TPE64Header.BaseOfImage] 946 | mov dword ptr [edi + TPE64Header.BaseOfImage], ebx 947 | 948 | mov esi, dword ptr [edi + TPE64Header.RelocationRVA] 949 | test esi, esi 950 | jz LoadPERelocateDone 951 | 952 | mov ecx, dword ptr [edi + TPE64Header.RelocationSize] 953 | test ecx, ecx 954 | jz LoadPERelocateDone 955 | 956 | LoadPERelocateMore: 957 | mov ebp, dword ptr [ebx + esi + TPE64Relocation.PageRVA] 958 | mov ecx, dword ptr [ebx + esi + TPE64Relocation.BlockSize] 959 | test ecx, ecx 960 | jz LoadPERelocateDone 961 | 962 | sub ecx, TPE64Relocation 963 | add esi, TPE64Relocation 964 | 965 | LoadPERelocateNext: 966 | movzx eax, word ptr [ebx + esi] 967 | mov edi, eax 968 | and edi, 0xfff 969 | add edi, ebp 970 | shr eax, 12 971 | 972 | dec eax 973 | jz LoadPERelocateHIGH 974 | dec eax 975 | jz LoadPERelocateLOW 976 | dec eax 977 | jz LoadPERelocateHIGHLOW 978 | dec eax 979 | jz LoadPERelocateHIGHADJ 980 | sub eax, 6 981 | jz LoadPERelocateDIR64 982 | jmp LoadPERelocateSkip 983 | LoadPERelocateHIGH: 984 | push edx 985 | shr edx, 16 986 | add word ptr [ebx + edi], dx 987 | pop edx 988 | jmp LoadPERelocateSkip 989 | LoadPERelocateLOW: 990 | add word ptr [ebx + edi], dx 991 | jmp LoadPERelocateSkip 992 | LoadPERelocateHIGHLOW: 993 | add dword ptr [ebx + edi], edx 994 | jmp LoadPERelocateSkip 995 | LoadPERelocateHIGHADJ: 996 | add esi, 2 997 | sub ecx, 2 998 | mov eax,dword ptr [ebx + edi - 2] // Lo Hi (Little endian) 999 | // or to be absolute safe: 1000 | // mov ax, word ptr [ebx + edi] 1001 | // shl eax, 16 1002 | mov ax, word ptr [ebx + esi] 1003 | lea eax, [eax + edx + 0x8000] 1004 | shr eax, 16 1005 | mov word ptr [ebx + edi], dx 1006 | jmp LoadPERelocateSkip 1007 | LoadPERelocateDIR64: 1008 | add dword ptr [ebx + edi], edx 1009 | adc dword ptr [ebx + edi + 4], 0 1010 | jmp LoadPERelocateSkip 1011 | LoadPERelocateSkip: 1012 | 1013 | add esi, 2 1014 | sub ecx, 2 1015 | jnz LoadPERelocateNext 1016 | jmp LoadPERelocateMore 1017 | 1018 | LoadPERelocateDone: 1019 | clc 1020 | popad 1021 | ret 1022 | } 1023 | 1024 | { // Enable A20 line, if it's not enabled yet 1025 | .bits(16) 1026 | EnableA20: 1027 | pushad 1028 | 1029 | call CheckA20 1030 | jnz EnableA20Done 1031 | 1032 | EnableA20WithBIOS: 1033 | mov cx, 16 1034 | EnableA20WithBIOSLoop: 1035 | mov ax, 0x2401 1036 | int 0x15 1037 | call CheckA20 1038 | jnz EnableA20Done 1039 | dec cx 1040 | jnz EnableA20WithBIOSLoop 1041 | 1042 | EnableA20With8042Controller: 1043 | mov cx, 16 1044 | EnableA20With8042ControllerLoop: 1045 | cli 1046 | 1047 | // Disable keyboard 1048 | call EnableA20Wait 1049 | mov al, 0xad 1050 | out 0x64, al 1051 | 1052 | // Read from input 1053 | call EnableA20Wait 1054 | mov al, 0xd0 1055 | out 0x64, al 1056 | EnableA20WaitLoop: 1057 | in al, 0x64 1058 | test al, 1 1059 | jz EnableA20WaitLoop 1060 | in al, 0x60 1061 | 1062 | // Write to output 1063 | push eax 1064 | call EnableA20Wait 1065 | mov al, 0xd1 1066 | out 0x64, al 1067 | call EnableA20Wait 1068 | pop eax 1069 | or al, 2 1070 | out 0x60, al 1071 | 1072 | // Enable keyboard 1073 | call EnableA20Wait 1074 | mov al, 0xae 1075 | out 0x64, al 1076 | 1077 | call EnableA20Wait 1078 | 1079 | sti 1080 | 1081 | call CheckA20 1082 | jnz EnableA20Done 1083 | dec cx 1084 | jnz EnableA20With8042ControllerLoop 1085 | 1086 | FastEnableA20: 1087 | mov cx, 16 1088 | FastEnableA20Loop: 1089 | in al, 0x92 1090 | test al, 2 1091 | jnz FastEnableA20Done 1092 | or al, 2 1093 | and al, 0xfe 1094 | out 0x92, al 1095 | FastEnableA20Done: 1096 | call CheckA20 1097 | jnz EnableA20Done 1098 | dec cx 1099 | jnz FastEnableA20Loop 1100 | 1101 | EnableA20Hang: 1102 | jmp EnableA20Hang 1103 | 1104 | EnableA20Done: 1105 | popad 1106 | ret 1107 | } 1108 | 1109 | { 1110 | .bits(16) 1111 | EnableA20Wait: 1112 | in al, 0x64 1113 | test al, 2 1114 | jnz EnableA20Wait 1115 | ret 1116 | } 1117 | 1118 | { 1119 | .bits(16) 1120 | CheckA20: 1121 | pushf 1122 | push ds 1123 | push es 1124 | push di 1125 | push si 1126 | 1127 | cli 1128 | 1129 | xor ax, ax // ax = 0 1130 | mov es, ax 1131 | 1132 | not ax // ax = 0xFFFF 1133 | mov ds, ax 1134 | 1135 | mov di, 0x0500 1136 | mov si, 0x0510 1137 | 1138 | mov al, byte ptr es:[di] 1139 | push ax 1140 | 1141 | mov al, byte ptr ds:[si] 1142 | push ax 1143 | 1144 | mov byte ptr es:[di], 0x00 1145 | mov byte ptr ds:[si], 0xFF 1146 | 1147 | cmp byte ptr es:[di], 0xFF 1148 | 1149 | pop ax 1150 | mov byte ptr ds:[si], al 1151 | 1152 | pop ax 1153 | mov byte ptr es:[di], al 1154 | 1155 | mov ax, 0 1156 | je CheckA20Exit 1157 | 1158 | mov ax, 1 1159 | 1160 | CheckA20Exit: 1161 | pop si 1162 | pop di 1163 | pop es 1164 | pop ds 1165 | popf 1166 | test ax, ax 1167 | ret 1168 | } 1169 | 1170 | { 1171 | .bits(16) 1172 | CheckLongMode: 1173 | pushad 1174 | pushfd 1175 | 1176 | pop eax 1177 | mov ecx, eax 1178 | xor eax, 0x200000 1179 | push eax 1180 | popfd 1181 | 1182 | pushfd 1183 | pop eax 1184 | xor eax, ecx 1185 | shr eax, 21 1186 | and eax, 1 1187 | push ecx 1188 | popfd 1189 | 1190 | test eax, eax 1191 | jz CheckLongModeNoLongMode 1192 | 1193 | mov eax, 0x80000000 1194 | cpuid 1195 | 1196 | cmp eax, 0x80000001 1197 | jb CheckLongModeNoLongMode 1198 | 1199 | mov eax, 0x80000001 1200 | cpuid 1201 | test edx, 1 << 29 1202 | jz CheckLongModeNoLongMode 1203 | 1204 | xor eax, eax 1205 | not eax 1206 | 1207 | jmp CheckLongModeNoLongModeSkip 1208 | 1209 | CheckLongModeNoLongMode: 1210 | xor eax, eax 1211 | 1212 | CheckLongModeNoLongModeSkip: 1213 | 1214 | test eax, eax 1215 | popad 1216 | ret 1217 | } 1218 | 1219 | { // Enable unreal mode for FS segment Value 1220 | .bits(16) 1221 | EnableUnrealMode: 1222 | xor ax, ax 1223 | mov ds, ax // DS = 0 1224 | mov fs, ax // FS = 0 1225 | 1226 | pushad 1227 | 1228 | cli // no interrupts 1229 | 1230 | // Disable NMIs 1231 | mov dx, 0x70 1232 | in al, dx 1233 | or al, 0x80 1234 | out dx, al 1235 | 1236 | push ds // save real mode 1237 | push fs 1238 | 1239 | lgdt cs:[GDTDescriptor] // load GDT 1240 | 1241 | mov eax, cr0 // switch to pmode by 1242 | or al,1 // set pmode bit 1243 | mov cr0, eax 1244 | 1245 | jmp NoCrash // tell 386/486 to not crash 1246 | NoCrash: 1247 | 1248 | mov bx, 0x10 // select descriptor 2 1249 | mov fs, bx // 0x10 = 10000b 1250 | 1251 | and al, 0xfe // back to realmode 1252 | mov cr0, eax // by toggling bit again 1253 | 1254 | pop fs // get back old segment 1255 | pop ds 1256 | 1257 | // Enable NMIs 1258 | mov dx, 0x70 1259 | in al, dx 1260 | and al, 0x7f 1261 | out dx, al 1262 | 1263 | sti // re-enable interrupts 1264 | 1265 | popad 1266 | 1267 | xor ax,ax 1268 | not ax 1269 | test ax,ax 1270 | 1271 | ret 1272 | } 1273 | 1274 | { // Get memory map 1275 | .bits(16) 1276 | GetMemoryMap: 1277 | push bp 1278 | mov bp, sp 1279 | sub sp, 4 1280 | pushad 1281 | mov ax, MemoryMapAddress >> 4 1282 | mov es, ax 1283 | xor di, di 1284 | xor ebx, ebx // ebx must be 0 to start 1285 | mov dword ptr ss:[bp - 4], ebx // no entries yet 1286 | mov dword ptr cs:[MemorySize + 0], ebx 1287 | mov dword ptr cs:[MemorySize + 4], ebx 1288 | mov edx, 0x0534d4150 // Place "SMAP" into edx 1289 | mov eax, 0xe820 1290 | mov dword ptr es:[di + 20], 1 // force a valid ACPI 3.X entry 1291 | mov ecx, 24 // ask for 24 bytes 1292 | int 0x15 1293 | jc GetMemoryMapFailed // carry set on first call means "unsupported function" 1294 | mov edx, 0x0534d4150 // Some BIOSes apparently trash this Value? 1295 | cmp eax, edx // on success, eax must have been reset to "SMAP" 1296 | jne GetMemoryMapFailed 1297 | test ebx, ebx // ebx = 0 implies list is only 1 entry long (worthless) 1298 | je GetMemoryMapFailed 1299 | jmp GetMemoryMapJumpIn 1300 | GetMemoryMapLoop: 1301 | mov eax, 0xe820 // eax, ecx get trashed on every int 0x15 call 1302 | mov dword ptr es:[di + 20], 1 // force a valid ACPI 3.X entry 1303 | mov ecx, 24 // ask for 24 bytes again 1304 | int 0x15 1305 | jc GetMemoryMapSuccess // carry set means "end of list already reached" 1306 | mov edx, 0x0534d4150 // repair potentially trashed Value 1307 | GetMemoryMapJumpIn: 1308 | test cx, cx 1309 | jz GetMemoryMapSkip // skip any 0 length entries 1310 | cmp cl, 20 // got a 24 byte ACPI 3.X response? 1311 | jbe GetMemoryMapNotExtended 1312 | test byte es:[di + 20], 1 // if so: is the "ignore this data" bit clear? 1313 | je GetMemoryMapSkip 1314 | GetMemoryMapNotExtended: 1315 | mov ecx, dword ptr es:[di + 8] // get lower uint32_t of memory region length 1316 | or ecx, dword ptr es:[di + 12] // "or" it with upper uint32_t to test for zero 1317 | jz GetMemoryMapSkip // if length uint64_t is 0, skip entry 1318 | mov eax, dword ptr es:[di + 0] 1319 | mov ecx, dword ptr es:[di + 4] 1320 | add eax, dword ptr es:[di + 8] 1321 | adc ecx, dword ptr es:[di + 12] 1322 | cmp dword ptr cs:[MemorySize + 4], ecx 1323 | ja GetMemoryMapNotBigger 1324 | cmp dword ptr cs:[MemorySize + 0], eax 1325 | jae GetMemoryMapNotBigger 1326 | mov dword ptr cs:[MemorySize + 0], eax 1327 | mov dword ptr cs:[MemorySize + 4], ecx 1328 | GetMemoryMapNotBigger: 1329 | mov ecx, dword ptr ss:[bp - 4] 1330 | inc ecx // got a good entry: increment count, move to next storage spot 1331 | mov dword ptr ss:[bp - 4], ecx 1332 | add di, 24 1333 | GetMemoryMapSkip: 1334 | test ebx, ebx // if ebx resets to 0, list is complete 1335 | jne GetMemoryMapLoop 1336 | jmp GetMemoryMapSuccess 1337 | GetMemoryMapFailed: 1338 | xor eax, eax 1339 | mov dword ptr ss:[bp - 4], eax 1340 | GetMemoryMapSuccess: 1341 | popad 1342 | mov eax, dword ptr ss:[bp - 4] 1343 | mov sp, bp 1344 | pop bp 1345 | test eax, eax 1346 | ret 1347 | } 1348 | 1349 | { 1350 | .bits(16) 1351 | ClearScreen: 1352 | push bp 1353 | mov bp, sp 1354 | pushad 1355 | mov ax, 0x0003 // Text mode 1356 | int 0x10 1357 | mov ax, 0x0600 // Clear the screen 1358 | xor cx, cx // from (0,0) 1359 | mov dx, 0x184f // to (24,79) 1360 | mov bh, 0x07 // keep light grey display 1361 | int 0x10 1362 | mov ah, 0x02 // Set cursor position 1363 | xor dx, dx // at (0, 0) 1364 | mov bh, dh // page=0 1365 | int 0x10 1366 | popad 1367 | mov sp, bp 1368 | pop bp 1369 | ret 1370 | } 1371 | 1372 | { 1373 | .bits(16) 1374 | PrintChar: 1375 | pushad 1376 | mov ah, 0x0e // Write char and attributes at cursor pos 1377 | mov bx, 0x0700 // page=0, attributes is light grey and black 1378 | int 0x10 1379 | popad 1380 | ret 1381 | } 1382 | 1383 | { 1384 | PrintNullTerminatedString: 1385 | push bp 1386 | mov bp, sp 1387 | pushad 1388 | mov ax, 0x0e00 // Write char and attributes at cursor pos 1389 | mov bx, 0x0700 // page=0, attributes is light grey and black 1390 | PrintNullTerminatedStringLoop: 1391 | lodsb 1392 | or al, al 1393 | jz PrintNullTerminatedStringDone 1394 | int 0x10 1395 | jmp PrintNullTerminatedStringLoop 1396 | PrintNullTerminatedStringDone: 1397 | popad 1398 | mov sp, bp 1399 | pop bp 1400 | ret 1401 | } 1402 | 1403 | { 1404 | .bits(16) 1405 | PrintHexChar: 1406 | pushad 1407 | and al, 0x0f 1408 | mov ah, 0x0e // Write char and attributes at cursor pos 1409 | mov bx, 0x0700 // page=0, attributes is light grey and black 1410 | cmp al, 0xa 1411 | jae PrintHexCharOverTen 1412 | add al, '0' 1413 | jmp PrintHexCharOverTenSkip 1414 | PrintHexCharOverTen: 1415 | add al, 'a' - 0xa 1416 | PrintHexCharOverTenSkip: 1417 | int 0x10 1418 | popad 1419 | ret 1420 | } 1421 | 1422 | { 1423 | .bits(16) 1424 | PrintHexByte: 1425 | pushad 1426 | rol al, 4 1427 | call PrintHexChar 1428 | rol al, 4 1429 | call PrintHexChar 1430 | popad 1431 | ret 1432 | } 1433 | 1434 | { 1435 | .bits(16) 1436 | PrintHexWord: 1437 | pushad 1438 | rol ax, 8 1439 | call PrintHexByte 1440 | rol ax, 8 1441 | call PrintHexByte 1442 | popad 1443 | ret 1444 | } 1445 | 1446 | { 1447 | .bits(16) 1448 | PrintHexDWord: 1449 | pushad 1450 | rol eax, 16 1451 | call PrintHexWord 1452 | rol eax, 16 1453 | call PrintHexWord 1454 | popad 1455 | ret 1456 | } 1457 | 1458 | { 1459 | .bits(16) 1460 | PrintDWord: 1461 | pushad 1462 | test eax, eax 1463 | jz PrintDWordZero 1464 | xor ecx, ecx 1465 | mov ebx, 10 1466 | PrintDWordFillLoop: 1467 | xor edx, edx 1468 | div ebx 1469 | inc ecx 1470 | push dx 1471 | test eax, eax 1472 | jnz PrintDWordFillLoop 1473 | PrintDWordPrintLoop: 1474 | pop ax 1475 | call PrintHexChar 1476 | dec ecx 1477 | jnz PrintDWordPrintLoop 1478 | jmp PrintDWordZeroSkip 1479 | PrintDWordZero: 1480 | call PrintHexChar 1481 | PrintDWordZeroSkip: 1482 | popad 1483 | ret 1484 | } 1485 | 1486 | { 1487 | .bits(16) 1488 | InitializeFATFileSystem: 1489 | push bp 1490 | mov bp, sp 1491 | pushad 1492 | 1493 | // FATWorkData.SectorSizeBits:=log2(PBootSectorFAT1216(pointer(@BootSector))^.BytesPerSector); 1494 | movzx eax, word ptr cs:[vbpbBytesPerSector] 1495 | mov dword ptr cs:[FATWorkDataBytesPerSector], eax 1496 | bsf eax, eax 1497 | mov dword ptr cs:[FATWorkDataSectorSizeBits], eax 1498 | mov ebx, eax 1499 | 1500 | // FATWorkData.ClusterSizeBits:=FATWorkData.SectorSizeBits+integer(log2(PBootSectorFAT1216(pointer(@BootSector))^.SectorsPerCluster)); 1501 | movzx eax, byte ptr cs:[vbpbSectorsPerCluster] 1502 | mov dword ptr cs:[FATWorkDataSectorsPerCluster], eax 1503 | bsf eax, eax 1504 | add eax, ebx 1505 | mov dword ptr cs:[FATWorkDataClusterSizeBits], eax 1506 | 1507 | /* if PBootSectorFAT1216(pointer(@BootSector))^.TotalSectors<>0 then begin 1508 | ** FATWorkData.NumSectors:=PBootSectorFAT1216(pointer(@BootSector))^.TotalSectors; 1509 | ** end else begin 1510 | ** FATWorkData.NumSectors:=PBootSectorFAT1216(pointer(@BootSector))^.TotalSectorsBig; 1511 | ** end; 1512 | */ 1513 | movzx eax, word ptr cs:[vbpbTotalSectors] 1514 | test eax, eax 1515 | jnz InitializeFATFileSystemNoTotalSectorsBig 1516 | mov eax, dword ptr cs:[vbpbTotalSectorsBig] 1517 | InitializeFATFileSystemNoTotalSectorsBig: 1518 | mov dword ptr cs:[FATWorkDataNumSectors], eax 1519 | 1520 | // FATWorkData.HiddenSectors:=PBootSectorFAT1216(pointer(@BootSector))^.HiddenSectors; 1521 | mov eax, dword ptr cs:[vbpbHiddenSectors] 1522 | mov dword ptr cs:[FATWorkDataHiddenSectors], eax 1523 | 1524 | // FATWorkData.FATOffset:=PBootSectorFAT1216(pointer(@BootSector))^.ReservedSectors; 1525 | movzx eax, word ptr cs:[vbpbReservedSectors] 1526 | mov dword ptr cs:[FATWorkDataFATOffset], eax 1527 | 1528 | /* if PBootSectorFAT1216(pointer(@BootSector))^.SectorsPerFAT<>0 then begin 1529 | ** FATWorkData.FATLength:=PBootSectorFAT1216(pointer(@BootSector))^.SectorsPerFAT; 1530 | ** end else begin 1531 | ** FATWorkData.FATLength:=PBootSectorFAT32(pointer(@BootSector))^.FAT32SectorsPerFAT; 1532 | ** end; 1533 | */ 1534 | movzx eax, word ptr cs:[vbpbSectorsPerFAT] 1535 | test eax, eax 1536 | jnz InitializeFATFileSystemNoFAT32SectorsPerFAT 1537 | InitializeFATFileSystemFAT32SectorsPerFAT: 1538 | movzx eax, word ptr cs:[vbpb32SectorsPerFAT] 1539 | InitializeFATFileSystemNoFAT32SectorsPerFAT: 1540 | mov dword ptr cs:[FATWorkDataFATLength], eax 1541 | 1542 | // FATWorkData.RootOffset:=FATWorkData.FATOffset+(PBootSectorFAT1216(pointer(@BootSector))^.NumberOfFATs*FATWorkData.FATLength); 1543 | movzx eax, byte ptr cs:[vbpbNumberOfFATs] 1544 | mul dword ptr cs:[FATWorkDataFATLength] 1545 | add eax, dword ptr cs:[FATWorkDataFATOffset] 1546 | mov dword ptr cs:[FATWorkDataRootOffset], eax 1547 | 1548 | // FATWorkData.RootMax:=sizeof(TFATDirectoryEntry)*PBootSectorFAT1216(pointer(@BootSector))^.RootEntries; 1549 | movzx eax, word ptr cs:[vbpbRootEntries] 1550 | mov ebx, TFATDirectoryEntry 1551 | mul ebx 1552 | mov dword ptr cs:[FATWorkDataRootMax], eax 1553 | 1554 | // FATWorkData.DataOffset:=FATWorkData.RootOffset+((FATWorkData.RootMax-1) shr FATWorkData.SectorSizeBits)+1; 1555 | dec eax 1556 | mov ecx, dword ptr cs:[FATWorkDataSectorSizeBits] 1557 | shr eax, cl 1558 | add eax, dword ptr cs:[FATWorkDataRootOffset] 1559 | inc eax 1560 | mov dword ptr cs:[FATWorkDataDataOffset], eax 1561 | 1562 | // FATWorkData.NumClusters:=2+((FATWorkData.NumSectors-FATWorkData.DataOffset) div PBootSectorFAT1216(pointer(@BootSector))^.SectorsPerCluster); 1563 | mov eax, dword ptr cs:[FATWorkDataNumSectors] 1564 | sub eax, dword ptr cs:[FATWorkDataDataOffset] 1565 | xor edx, edx 1566 | div dword ptr cs:[FATWorkDataSectorsPerCluster] 1567 | add eax, 2 1568 | mov dword ptr cs:[FATWorkDataNumClusters], eax 1569 | 1570 | // FATWorkData.FilePos:=0; 1571 | xor eax, eax 1572 | mov dword ptr cs:[FATWorkDataFilePos], eax 1573 | 1574 | cmp word ptr cs:[vbpbSectorsPerFAT],0 1575 | je DetectFATFileSystemTypeFAT32 1576 | DetectFATFileSystemTypeFAT12orFAT16: 1577 | 1578 | /* if FATWorkData.RootMax=0 then begin 1579 | ** exit; 1580 | ** end; 1581 | */ 1582 | mov eax, dword ptr cs:[FATWorkDataRootMax] 1583 | test eax, eax 1584 | jz DetectFATFileSystemTypeUnknown 1585 | 1586 | // FATWorkData.RootCluster:=-1; 1587 | xor eax, eax 1588 | not eax 1589 | mov dword ptr cs:[FATWorkDataRootCluster], eax 1590 | 1591 | /* if FATWorkData.NumClusters>4087 then begin 1592 | ** FATWorkData.FATSize:=16; 1593 | ** FATWorkData.ClusterEOFMarker:=$fff8; 1594 | ** end else begin 1595 | ** FATWorkData.FATSize:=12; 1596 | ** FATWorkData.ClusterEOFMarker:=$ff8; 1597 | ** end; 1598 | */ 1599 | mov eax, dword ptr cs:[FATWorkDataNumClusters] 1600 | cmp eax, 4087 1601 | ja DetectFATFileSystemTypeFAT16 1602 | DetectFATFileSystemTypeFAT12: 1603 | mov eax, 12 1604 | mov ebx, 0x00000ff8 1605 | jmp DetectFATFileSystemTypeFAT16Skip 1606 | DetectFATFileSystemTypeFAT16: 1607 | mov eax, 16 1608 | mov ebx, 0x0000fff8 1609 | DetectFATFileSystemTypeFAT16Skip: 1610 | 1611 | movzx ecx, byte ptr cs:[vOfsDriveNumber] 1612 | jmp DetectFATFileSystemTypeDone 1613 | 1614 | DetectFATFileSystemTypeFAT32: 1615 | 1616 | mov ax, word ptr cs:[vbpbRootEntries] 1617 | test ax, ax 1618 | jnz DetectFATFileSystemTypeUnknown 1619 | 1620 | movzx eax, word ptr cs:[vbpb32Flags] 1621 | test eax, 0x0080 1622 | jnz DetectFATFileSystemTypeFAT32FATMirroringEnabled 1623 | DetectFATFileSystemTypeFAT32FATMirroringDisabled: 1624 | // FAT mirroring is disabled, get active FAT 1625 | 1626 | // ActiveFAT:=PBootSectorFAT32(pointer(@BootSector))^.FAT32Flags and $f; 1627 | and eax, 0xf 1628 | 1629 | // if ActiveFAT>=PBootSectorFAT32(pointer(@BootSector))^.NumberOfFATs then begin 1630 | // exit; 1631 | // end; 1632 | cmp al, byte ptr cs:[vbpbNumberOfFATs] 1633 | jae DetectFATFileSystemTypeUnknown 1634 | 1635 | // inc(FATWorkData.FATOffset,ActiveFAT*FATWorkData.FATLength); 1636 | mul dword ptr cs:[FATWorkDataFATLength] 1637 | add dword ptr cs:[FATWorkDataFATOffset], eax 1638 | 1639 | DetectFATFileSystemTypeFAT32FATMirroringEnabled: 1640 | 1641 | // FATWorkData.RootCluster:=PBootSectorFAT32(pointer(@BootSector))^.FAT32RootCluster; 1642 | mov eax, dword ptr cs:[vbpb32RootCluster] 1643 | mov dword ptr cs:[FATWorkDataRootCluster], eax 1644 | 1645 | mov eax, 32 1646 | mov ebx, 0xffffff8 1647 | movzx ecx, byte ptr cs:[vOfs32DriveNumber] 1648 | jmp DetectFATFileSystemTypeDone 1649 | 1650 | DetectFATFileSystemTypeUnknown: 1651 | xor eax, eax 1652 | xor ebx, ebx 1653 | xor ecx, ecx 1654 | 1655 | DetectFATFileSystemTypeDone: 1656 | mov dword ptr cs:[FATWorkDataFATSize], eax 1657 | mov dword ptr cs:[FATWorkDataClusterEOFMarker], ebx 1658 | mov dword ptr cs:[FATWorkDriveNumber], ecx 1659 | 1660 | test eax, eax 1661 | jz DetectFATFileSystemTypeCheckFail 1662 | 1663 | push eax 1664 | push ds 1665 | push es 1666 | mov ax, BufferSegment 1667 | mov es, ax 1668 | xor di, di 1669 | mov eax, dword ptr cs:[FATWorkDataFATOffset] 1670 | mov ecx, 1 1671 | call ReadSector 1672 | mov ecx, dword ptr es:[0] 1673 | pop es 1674 | pop ds 1675 | or ecx,0x08 1676 | pop eax 1677 | 1678 | cmp eax,12 1679 | je DetectFATFileSystemTypeCheckFAT12 1680 | cmp eax,16 1681 | je DetectFATFileSystemTypeCheckFAT16 1682 | cmp eax,32 1683 | je DetectFATFileSystemTypeCheckFAT32 1684 | jmp DetectFATFileSystemTypeCheckFail 1685 | DetectFATFileSystemTypeCheckFAT12: 1686 | movzx ebx, byte ptr cs:[vbpbMedia] 1687 | or ebx, 0x0f08 1688 | and ecx, 0x0fff 1689 | cmp ebx, ecx 1690 | jne DetectFATFileSystemTypeCheckFail 1691 | jmp DetectFATFileSystemTypeCheckDone 1692 | DetectFATFileSystemTypeCheckFAT16: 1693 | movzx ebx, byte ptr cs:[vbpbMedia] 1694 | or ebx, 0xff08 1695 | and ecx, 0xffff 1696 | cmp ebx, ecx 1697 | jne DetectFATFileSystemTypeCheckFail 1698 | jmp DetectFATFileSystemTypeCheckDone 1699 | DetectFATFileSystemTypeCheckFAT32: 1700 | movzx ebx, byte ptr cs:[vbpbMedia] 1701 | or ebx, 0x0fffff08 1702 | and ecx, 0x0fffffff 1703 | cmp ebx, ecx 1704 | jne DetectFATFileSystemTypeCheckFail 1705 | jmp DetectFATFileSystemTypeCheckDone 1706 | 1707 | DetectFATFileSystemTypeCheckFail: 1708 | xor eax, eax 1709 | mov dword ptr cs:[FATWorkDataFATSize], eax 1710 | mov dword ptr cs:[FATWorkDataClusterEOFMarker], eax 1711 | mov dword ptr cs:[FATWorkDriveNumber], eax 1712 | DetectFATFileSystemTypeCheckDone: 1713 | popad 1714 | mov sp, bp 1715 | pop bp 1716 | mov eax, dword ptr cs:[FATWorkDriveNumber] 1717 | mov dword ptr cs:[BootInfoBootDevice], eax 1718 | cmp dword ptr cs:[FATWorkDataFATSize], 12 1719 | jne DoNotReadFullFAT 1720 | ReadFullFAT: 1721 | // Load the entrie FAT (maximum 6 kilobytes for FAT12) 1722 | pushad 1723 | mov eax,dword ptr cs:[FATWorkDataFATOffset] 1724 | mov ecx,dword ptr cs:[FATWorkDataFATLength] 1725 | push word FATBufferSegment 1726 | pop es 1727 | call ReadSector 1728 | popad 1729 | DoNotReadFullFAT: 1730 | mov eax, dword ptr cs:[FATWorkDataFATSize] 1731 | test eax, eax 1732 | ret 1733 | 1734 | } 1735 | 1736 | { 1737 | .bits(16) 1738 | FindFile: 1739 | 1740 | pushad 1741 | 1742 | ReadFATRootDirectory: 1743 | cmp word ptr cs:[FATWorkDataFATSize], 32 1744 | je FindFileFAT32 1745 | ReadFATRootDirectoryFAT12FAT16: 1746 | 1747 | push word BufferSegment 1748 | pop es 1749 | 1750 | mov eax, dword ptr cs:[FATWorkDataRootMax] 1751 | mov ecx, dword ptr cs:[FATWorkDataBytesPerSector] 1752 | add eax, ecx 1753 | dec eax 1754 | xor edx, edx 1755 | div ecx 1756 | mov ecx, eax 1757 | 1758 | mov eax, dword ptr cs:[FATWorkDataRootOffset] 1759 | 1760 | call ReadSector 1761 | 1762 | push word BufferSegment 1763 | pop es 1764 | xor di, di 1765 | 1766 | push cs 1767 | pop ds 1768 | 1769 | cmp word ptr cs:[FATWorkDataFATSize], 32 1770 | je FindFileFAT32 1771 | 1772 | FindFileFAT12FAT16: 1773 | mov si, offset KernelFileName 1774 | mov dx, word ptr cs:[vbpbRootEntries] 1775 | FindNextFileFAT12FAT16: 1776 | 1777 | /*/ push di 1778 | mov al,byte ptr es:[di] 1779 | test al,al 1780 | jz FindNextFileFAT12FAT16PrintSkip 1781 | mov cx, 11 1782 | FindNextFileFAT12FAT16PrintLoop: 1783 | mov al,byte ptr es:[di] 1784 | inc di 1785 | call PrintChar 1786 | loop FindNextFileFAT12FAT16PrintLoop 1787 | FindNextFileFAT12FAT16PrintSkip: 1788 | pop di/**/ 1789 | 1790 | mov cx, 11 1791 | pusha 1792 | rep cmpsb 1793 | popa 1794 | je short FindFileFoundFAT1216 1795 | add di, TFATDirectoryEntry 1796 | dec dx 1797 | jnz short FindNextFileFAT12FAT16 1798 | jmp FindFileFail 1799 | FindFileFoundFAT1216: 1800 | push word ptr es:[di + TFATDirectoryEntry.ClusterHi32] 1801 | push word ptr es:[di + TFATDirectoryEntry.Cluster] 1802 | pop dword ptr cs:[FATWorkFileCluster] 1803 | jmp FindFileDone 1804 | 1805 | FindFileFAT32: 1806 | push word BufferSegment 1807 | pop es 1808 | mov esi, dword ptr cs:[FATWorkDataRootCluster] 1809 | FindFileMainFAT32: 1810 | call ReadCluster 1811 | shr ebx, 5 1812 | push esi 1813 | xor di, di 1814 | FindFileNextFAT32: 1815 | mov si, offset KernelFileName 1816 | mov cx, 11 1817 | pusha 1818 | rep cs: cmpsb 1819 | popa 1820 | je short FindFileFoundFAT32 1821 | add di, byte 32 1822 | dec bx 1823 | jnz short FindFileNextFAT32 1824 | pop esi 1825 | cmp esi, 0xffffff8 1826 | jb short FindFileMainFAT32 1827 | jmp FindFileFail 1828 | FindFileFoundFAT32: 1829 | push word ptr es:[di + TFATDirectoryEntry.ClusterHi32] 1830 | push word ptr es:[di + TFATDirectoryEntry.Cluster] 1831 | pop dword ptr cs:[FATWorkFileCluster] 1832 | jmp FindFileDone 1833 | 1834 | FindFileFail: 1835 | xor eax, eax 1836 | mov dword ptr cs:[FATWorkFileCluster], eax 1837 | 1838 | FindFileDone: 1839 | popad 1840 | mov eax, dword ptr cs:[FATWorkFileCluster] 1841 | test eax, eax 1842 | ret 1843 | 1844 | } 1845 | 1846 | { 1847 | .bits(16) 1848 | LoadKernel: 1849 | pushad 1850 | 1851 | mov ebp, KernelLoadAddress 1852 | 1853 | mov esi, dword ptr cs:[FATWorkFileCluster] 1854 | 1855 | push word BufferSegment 1856 | pop es 1857 | 1858 | LoadKernelLoop: 1859 | 1860 | push ebp 1861 | call ReadCluster 1862 | jc short LoadKernelNextIsDone 1863 | xor eax, eax 1864 | not eax 1865 | jmp LoadKernelNextIsNotDone 1866 | LoadKernelNextIsDone: 1867 | xor eax, eax 1868 | LoadKernelNextIsNotDone: 1869 | pop ebp 1870 | 1871 | xor edi, edi 1872 | LoadKernelCopyLoop: 1873 | mov dl, byte ptr es:[di] 1874 | mov byte ptr fs:[ebp], dl 1875 | inc edi 1876 | inc ebp 1877 | dec ebx 1878 | jnz LoadKernelCopyLoop 1879 | 1880 | test eax, eax 1881 | jnz short LoadKernelLoop 1882 | LoadKernelDone: 1883 | cmp ebp, KernelLoadAddress 1884 | popad 1885 | ret 1886 | } 1887 | 1888 | { 1889 | .bits(16) 1890 | ReadSector: 1891 | 1892 | pushad 1893 | 1894 | movzx dx, byte ptr cs:[FATWorkDriveNumber] 1895 | test dl, 0x80 1896 | jnz ReadSectorNoLBA 1897 | 1898 | ReadSectorTestLBA: 1899 | mov ax,0x4100 1900 | mov bx,0x55aa 1901 | int 0x13 1902 | jc ReadSectorNoLBA 1903 | 1904 | cmp bx,0xaa55 1905 | je ReadSectorLBA 1906 | 1907 | ReadSectorNoLBA: 1908 | popad 1909 | 1910 | push di 1911 | 1912 | xor bx, bx 1913 | mov edx, eax 1914 | shr edx, 16 1915 | 1916 | ReadSectorNoLBANext: 1917 | mov di, 5 1918 | 1919 | ReadSectorNoLBAMore: 1920 | pushad 1921 | 1922 | add ax, word ptr cs:[FATWorkDataHiddenSectors] 1923 | adc dx, word ptr cs:[FATWorkDataHiddenSectors + 2] 1924 | 1925 | xor cx, cx 1926 | 1927 | xchg ax, cx 1928 | xchg ax, dx 1929 | 1930 | div word ptr cs:[vbpbSectorsPerTrack] 1931 | 1932 | xchg ax, cx 1933 | 1934 | div word ptr cs:[vbpbSectorsPerTrack] 1935 | 1936 | xchg dx, cx 1937 | inc cx 1938 | 1939 | div word ptr cs:[vbpbHeadsPerCylinder] 1940 | 1941 | mov ch, al 1942 | shl ah, 6 1943 | or cl, ah 1944 | 1945 | mov dh, dl 1946 | 1947 | mov dl, byte ptr cs:[FATWorkDriveNumber] 1948 | 1949 | mov ax, 0x201 1950 | int 0x13 1951 | jnc ReadSectorNoLBADone 1952 | 1953 | mov ah, 0 1954 | int 0x13 1955 | 1956 | popad 1957 | 1958 | dec di 1959 | jnz ReadSectorNoLBAMore 1960 | jmp Hang 1961 | ReadSectorNoLBADone: 1962 | popad 1963 | 1964 | add bx, word ptr cs:[FATWorkDataBytesPerSector] 1965 | inc ax 1966 | jnz ReadSectorNoLBASkip 1967 | inc dx 1968 | ReadSectorNoLBASkip: 1969 | dec cx 1970 | jnz ReadSectorNoLBANext 1971 | 1972 | pop di 1973 | ret 1974 | 1975 | ReadSectorLBA: 1976 | popad 1977 | 1978 | push edx 1979 | push esi 1980 | push ds 1981 | 1982 | xor edx, edx 1983 | add eax, dword ptr cs:[FATWorkDataHiddenSectors] 1984 | adc edx, 0 1985 | 1986 | push edx // LBA Hi 1987 | push eax // LBA Lo 1988 | push es // Buffer Segment 1989 | push word 0 // Buffer Offset 1990 | push cx // Sector read count 1991 | push word 0x10 // Record size 1992 | 1993 | mov eax, dword ptr cs:[FATWorkDataBytesPerSector] 1994 | movzx ecx, cx 1995 | mul ecx 1996 | mov ebx, eax 1997 | 1998 | mov ah, 0x42 1999 | mov dl, byte ptr cs:[FATWorkDriveNumber] 2000 | 2001 | push ss 2002 | pop ds 2003 | mov si, sp 2004 | 2005 | int 0x13 2006 | jc Hang 2007 | 2008 | add esp,16 2009 | 2010 | pop ds 2011 | pop esi 2012 | pop edx 2013 | ret 2014 | } 2015 | 2016 | { // Read cluster procedure 2017 | .bits(16) 2018 | ReadCluster: 2019 | lea eax, [esi - 2] 2020 | 2021 | mov ecx, dword ptr cs:[FATWorkDataSectorsPerCluster] 2022 | mul ecx 2023 | 2024 | add eax, dword ptr cs:[FATWorkDataDataOffset] 2025 | 2026 | call ReadSector 2027 | 2028 | mov edx, dword ptr cs:[FATWorkDataFATSize] 2029 | cmp edx, 32 2030 | je ReadClusterFAT32 2031 | cmp edx, 16 2032 | je ReadClusterFAT16 2033 | 2034 | ReadClusterFAT12: 2035 | 2036 | // OldCluster:=CurrentCluster; 2037 | mov eax, esi 2038 | 2039 | // (esi * 3) / 2 2040 | imul esi, eax, 3 2041 | shr esi, 1 2042 | 2043 | // Get next cluster 2044 | push ds 2045 | push word FATBufferSegment 2046 | pop ds 2047 | movzx esi, word ptr ds:[si] 2048 | pop ds 2049 | 2050 | test eax, 1 2051 | jz short ReadClusterEvenFAT12 2052 | shr esi, 4 2053 | ReadClusterEvenFAT12: 2054 | 2055 | // EOF Test 2056 | and esi, 0xfff 2057 | cmp esi, 0xff8 2058 | cmc 2059 | ret 2060 | 2061 | ReadClusterFAT16: 2062 | 2063 | mov eax, 2 2064 | mul esi 2065 | div dword ptr cs:[FATWorkDataBytesPerSector] 2066 | mov esi, edx 2067 | 2068 | push es 2069 | 2070 | push word FATBufferSegment 2071 | pop es 2072 | 2073 | movzx ecx, word ptr cs:[vbpbReservedSectors] 2074 | add eax, ecx 2075 | 2076 | mov ecx, 1 2077 | 2078 | call ReadSector 2079 | 2080 | // Get next cluster 2081 | movzx esi, word ptr es:[si] 2082 | 2083 | pop es 2084 | 2085 | cmp esi,0xfff8 2086 | cmc 2087 | ret 2088 | 2089 | ReadClusterFAT32: 2090 | 2091 | mov eax,dword ptr cs:[FATWorkDataBytesPerSector] 2092 | xchg eax, esi 2093 | shl eax, 2 2094 | div esi 2095 | 2096 | push dx 2097 | 2098 | movzx esi, word ptr cs:[vbpbReservedSectors] 2099 | add esi, eax 2100 | 2101 | movzx eax, word ptr cs:[vbpb32Flags] 2102 | and al, 0xf 2103 | mul dword ptr cs:[vbpb32SectorsPerFAT] 2104 | 2105 | add eax, esi 2106 | 2107 | pop si 2108 | 2109 | push es 2110 | push ebx 2111 | 2112 | push word FATBufferSegment 2113 | pop es 2114 | 2115 | mov ecx, 1 2116 | 2117 | call ReadSector 2118 | 2119 | mov esi, dword ptr es:[si] 2120 | 2121 | pop ebx 2122 | pop es 2123 | 2124 | and esi, 0xfffffff 2125 | cmp esi, 0xffffff8 2126 | cmc 2127 | ret 2128 | } 2129 | 2130 | { 2131 | MemorySize: 2132 | dq 0 2133 | } 2134 | 2135 | { 2136 | .align(16) 2137 | BootInfo: 2138 | dd 0x00000042 // Flags 2139 | resd 2 2140 | BootInfoBootDevice: 2141 | dd 0 2142 | resd 7 2143 | BootInfoMemoryMapLength: 2144 | dd 0 2145 | BootInfoMemoryMapAddress: 2146 | dd MemoryMapAddress 2147 | resd 11 2148 | } 2149 | 2150 | { 2151 | .align(16) 2152 | GDTDescriptor: 2153 | dw ((offset GDTTableEnd) - (offset GDTTable)) - 1 // last byte in table 2154 | dd (CodeSegment << 4) + (offset GDTTable) // start of table 2155 | GDTTable: 2156 | GDTTableEntry0: 2157 | GDTEntry 0x0000, 0x0000, 0x00, 000000000b, 000000000b, 0x00 // entry 0 is always unused 2158 | GDTTableEntry1: // Code, Present, Ring 0, Code, Non-conforming, Readable, Page-granular 2159 | GDTEntry 0xffff, 0x0000, 0x00, 010011010b, 011001111b, 0x00 2160 | GDTTableEntry2: // Data, Present, Ring 0, Data, Expand-up, Writable, Page-granular 2161 | GDTEntry 0xffff, 0x0000, 0x00, 010010010b, 011001111b, 0x00 2162 | GDTTableEntry3: // 64-bit code 2163 | GDTEntry 0xffff, 0x0000, 0x00, 010011011b, 010101111b, 0x00 2164 | .comment{ 2165 | GDTTableEntry4: // Interrupts 2166 | GDTEntry 0xffff, 0x1000, 0x00, 010011110b, 011001111b, 0x00 2167 | } 2168 | GDTTableEnd: 2169 | } 2170 | 2171 | { 2172 | .align(16) 2173 | GDT64Descriptor: 2174 | dw ((offset GDT64TableEnd) - (offset GDT64Table)) - 1 // last byte in table 2175 | dd (CodeSegment << 4) + (offset GDT64Table) // start of table 2176 | GDT64Table: 2177 | GDT64TableEntry0: 2178 | GDTEntry 0x0000, 0x0000, 0x00, 000000000b, 000000000b, 0x00 // entry 0 is always unused 2179 | GDT64TableEntry1: // Ring0 code 2180 | GDTEntry 0x0000, 0x0000, 0x00, 010011010b, 000100000b, 0x00 2181 | GDT64TableEntry2: // Ring0 data 2182 | GDTEntry 0x0000, 0x0000, 0x00, 010010010b, 000100000b, 0x00 2183 | GDT64TableEntry3: // Ring3 code 2184 | GDTEntry 0x0000, 0x0000, 0x00, 011111010b, 000100000b, 0x00 2185 | GDT64TableEntry4: // Ring3 data 2186 | GDTEntry 0x0000, 0x0000, 0x00, 011110010b, 000100000b, 0x00 2187 | GDT64TableEnd: 2188 | } 2189 | 2190 | { 2191 | .align(16) 2192 | IDTDescriptor: 2193 | IDTLength: 2194 | dw 0 2195 | IDTBase: 2196 | dd 0 2197 | } 2198 | 2199 | { 2200 | KernelFileName: db "KERNEL BIN" 2201 | } 2202 | 2203 | .comment{ // just for as reference for the procedural BuildPagingTable routine above, therefore commented out 2204 | .align(4096) 2205 | PagingTableAddress: 2206 | PagingTablePML4T: // Maps 256 TB 2207 | dq (offset PagingTablePDPT) | 000000000011b // Present, R/W, Supervisor 2208 | //resq 511 2209 | dq 511 dup (0) 2210 | PagingTablePDPT: // Maps 512 GB 2211 | dq (offset PagingTablePDT) | 000000000011b // Present, R/W, Supervisor 2212 | //resq 511 2213 | dq 511 dup (0) 2214 | PagingTablePDT: // Maps 1 GB 2215 | dq (offset PagingTablePT) | 000000000011b // Present, R/W, Supervisor 2216 | //resq 511 2217 | dq 511 dup (0) 2218 | PagingTablePT: // Maps 2 MB (4 KB per entry) 2219 | !if(1){ 2220 | !script{ 2221 | // Feel the power of ECMAScript/JavaScript :-) 2222 | for(var i = 0; i < 512; i++){ 2223 | Assembler.parse("dq " + (i * 4096) + " | 000000000011b"); // Present, R/W, Supervisor 2224 | } 2225 | } 2226 | }else{ 2227 | !repeat(512){ 2228 | .local FreezedCounter 2229 | !set FreezedCounter = __COUNTER__ 2230 | dq (FreezedCounter * 4096) | 000000000011b // Present, R/W, Supervisor 2231 | } 2232 | } 2233 | } 2234 | 2235 | } -------------------------------------------------------------------------------- /examples/tinype.asm: -------------------------------------------------------------------------------- 1 | ImageBase = 0x400000 2 | SectionAlignment = 0x4 3 | FileAlignment = 0x4 4 | StackReserve = 0x1000 5 | StackCommit = 0x1000 6 | HeapReserve = 0x1000 7 | HeapCommit = 0x1000 8 | 9 | .cpu(386) 10 | .target(bin) 11 | .startoffset(IMAGEBASE) 12 | 13 | .code { 14 | .entrypoint 15 | .bits(16) 16 | 17 | CodeStart: 18 | 19 | db "MZ" 20 | push dx 21 | ret 22 | 23 | .bits(32) 24 | 25 | PEOptionalHeaderSize = PEOptionalHeaderEnd - PEOptionalHeader 26 | ImageSize = FileEnd - ImageBase 27 | ImportSize = ImportDirectoryEnd - ImportDirectory 28 | 29 | PEHeader: 30 | dd "PE\0\0" // PE Signature 31 | dw 0x014C // cpu (386) 32 | dw 2 // number of sections 33 | dd "BEP\0" // timestamp 34 | dd 0 // symbol table address 35 | dd 0 // number of symbols 36 | dw PEOptionalHeaderSize // size of optional header 37 | dw 0x010F // characteristics 38 | 39 | PEOptionalHeader: 40 | dw 0x010B // magic 41 | dw 0 // linker version 42 | dd 0 // size of code section 43 | dd 0 // size of initialised data 44 | dd 0 // size of uninitialised data 45 | dd EntryPointAddress - ImageBase // entry point address 46 | dd 0 // base of code 47 | dd 0 // base of data 48 | dd ImageBase // base of image 49 | dd SectionAlignment // section Alignment 50 | dd FileAlignment // file Alignment 51 | dw 1 // os version major 52 | dw 0 // os version minor 53 | dw 0 // image version major 54 | dw 0 // image version minor 55 | dw 4 // subsystem version major 56 | dw 0 // subsystem version minor 57 | dd 0 // win32 version (reserved) 58 | dd ImageSize // image size 59 | dd HeaderSize - ImageBase // header size 60 | dd 0 // checksum 61 | dw 0x0002 // subsystem (GUI) 62 | dw 0 // dll characteristics 63 | dd StackReserve // stack reserve size 64 | dd StackCommit // stack commit size 65 | dd HeapReserve // heap reserve size 66 | dd HeapCommit // heap commit size 67 | dd 0 // loader flags (obsolete) 68 | dd 2 // number of directory entries 69 | 70 | DirectoryEntries: 71 | dq 0 // export 72 | dd ImportDirectory - ImageBase // import section rva 73 | dd ImportSize // import section size 74 | 75 | PEOptionalHeaderEnd: 76 | 77 | CodeSize = CodeEnd - CodeStart 78 | CodeHeader: 79 | db "BeRo^fr!" // name 80 | dd CodeSize // virtual size 81 | dd CodeStart - ImageBase // rva 82 | dd CodeSize // raw size 83 | dd CodeStart - ImageBase // raw pointer to data 84 | dd 0 // pointer to relocations 85 | dd 0 // pointer to line numbers 86 | dw 0 // number of relocations 87 | dw 0 // number of line numbers 88 | dd 0x0E0000020 // characteristics 89 | 90 | dummyheader: 91 | db "It's art" // name 92 | dd 0 // virtual size 93 | dd 0 // rva 94 | dd 0 // raw size 95 | dd 0 // raw pointer to data 96 | dd 0 // pointer to relocations 97 | dd 0 // pointer to line numbers 98 | dw 0 // number of relocations 99 | dw 0 // number of line numbers 100 | dd 0x0E0000020 // characteristics 101 | 102 | HeaderSize: 103 | 104 | .align(4) 105 | 106 | ImportDirectory: 107 | dd 0, 0, 0xffffffff, KernelName - ImageBase, KernelTable - ImageBase 108 | dd 0, 0, 0, 0, 0 109 | 110 | KernelName: 111 | db "kernel32.dll\0" 112 | 113 | NameLoadLibraryA: 114 | db "\0\0LoadLibraryA\0" 115 | NameGetProcAddress: 116 | db "\0\0GetProcAddress\0" 117 | 118 | KernelTable: 119 | LoadLibraryAAdr: 120 | dd NameLoadLibraryA - ImageBase 121 | GetProcAddressAdr: 122 | dd NameGetProcAddress - ImageBase 123 | dd 0 124 | 125 | LoadLibraryA = ImageBase + LoadLibraryAAdr 126 | GetProcAddress = ImageBase + GetProcAddressAdr 127 | ImportDirectoryEnd: 128 | 129 | EntryPointAddress: 130 | 131 | call [LoadLibraryAAdr] 132 | 133 | ret 134 | 135 | CodeEnd: 136 | 137 | FileEnd: 138 | 139 | } -------------------------------------------------------------------------------- /examples/x86filter1.asm: -------------------------------------------------------------------------------- 1 | .target(bin); 2 | .startoffset(0); 3 | .cpu(all); 4 | 5 | MAXINSTR=15; 6 | 7 | OP_2BYTE=0x0f; // start of 2-byte opcode 8 | OP_OSIZE=0x66; // operand size prefix 9 | OP_CALLF=0x9a; 10 | OP_RETNI=0xc2; // ret near+immediate 11 | OP_RETN=0xc3; 12 | OP_ENTER=0xc8; 13 | OP_INT3=0xcc; 14 | OP_INTO=0xce; 15 | OP_CALLN=0xe8; 16 | OP_JMPF=0xea; 17 | OP_ICEBP=0xf1; 18 | 19 | // escape codes we use (these need to be 1-byte opcodes without an address or immediate operand!) 20 | ESCAPE=OP_ICEBP; 21 | JUMPTAB=OP_INTO; 22 | 23 | fNM=0x0; // no ModRM 24 | fAM=0x1; // no ModRM, "address mode" (jumps or direct addresses) 25 | fMR=0x2; // ModRM present 26 | fMEXTRA=0x3; // ModRM present, includes extra bits for opcode 27 | fMODE=0x3; // bitmask for mode 28 | 29 | // no ModRM: size of immediate operand 30 | fNI=0x0; // no immediate 31 | fBI=0x4; // byte immediate 32 | fWI=0x8; // word immediate 33 | fDI=0xc; // dword immediate 34 | fTYPE=0xc; // type mask 35 | 36 | // address mode: type of address operand 37 | fAD=0x0; // absolute address 38 | fDA=0x4; // dword absolute jump target 39 | fBR=0x8; // byte relative jump target 40 | fDR=0xc; // dword relative jump target 41 | 42 | // others 43 | fERR=0xf; // denotes invalid opcodes 44 | 45 | fMRfNI = fMR | fNI; 46 | 47 | ST_OP=0; // prefixes, first byte of opcode 48 | ST_SIB=1; // SIB byte 49 | ST_CALL_IDX=2; // call table index 50 | ST_DISP8_R0=3; // byte displacement on ModRM, reg no. 0 and following 51 | ST_DISP8_R1=4; 52 | ST_DISP8_R2=5; 53 | ST_DISP8_R3=6; 54 | ST_DISP8_R4=7; 55 | ST_DISP8_R5=8; 56 | ST_DISP8_R6=9; 57 | ST_DISP8_R7=10; 58 | ST_JUMP8=11; // short jump 59 | ST_IMM8=12; // 8-bit immediate 60 | ST_IMM16=13; // 16-bit immediate 61 | ST_IMM32=14; // 32-bit immediate 62 | ST_DISP32=15; // 32-bit displacement 63 | ST_ADDR32=16; // 32-bit direct address 64 | ST_CALL32=17; // 32-bit call target 65 | ST_JUMP32=18; // 32-bit jump target 66 | 67 | ST_MAX=19; 68 | 69 | // these components of the instruction stream are also identified 70 | // seperately, but stored together with another stream since there's 71 | // high correlation between them (or just because one streams provides 72 | // good context to predict the other) 73 | ST_MODRM=ST_OP; // ModRM byte 74 | ST_OP2=ST_OP; // second byte of opcode 75 | ST_AJUMP32=ST_JUMP32; // absolute jump target 76 | ST_JUMPTBL_COUNT=ST_OP; 77 | 78 | .struct(TDisUnFilterData){ 79 | DestStart dword(1); 80 | StreamEnd dword(1); 81 | NextIsFunc dword(1); 82 | Start dword(1); 83 | Offset16Prefix dword(1); 84 | Streams dword(ST_MAX); 85 | FuncTable dword(256); 86 | } 87 | 88 | DisUnFilterDataSize = TDisUnFilterData; 89 | 90 | .code{ 91 | .bits(32); 92 | 93 | // esi = Src 94 | // edi = Dst 95 | 96 | pushad 97 | 98 | // mov esi, dword ptr Source 99 | // mov edi, dword ptr Destination 100 | 101 | sub esp, DisUnFilterDataSize 102 | mov ebp, esp 103 | 104 | call @DisUnFilterPICCallLabel 105 | @DisUnFilterPICCallLabel: 106 | pop edx 107 | sub edx,offset @DisUnFilterPICCallLabel 108 | 109 | // for i:=0 to 255 do begin 110 | // FuncTable[i]:=0; 111 | // end; 112 | cld 113 | xor eax, eax 114 | mov ecx, eax 115 | inc ch 116 | push edi 117 | lea edi, [ebp + TDisUnFilterData.FuncTable] 118 | rep stosd 119 | pop edi 120 | 121 | // NextIsFunc:=true; 122 | not eax 123 | mov dword ptr [ebp + TDisUnFilterData.NextIsFunc], eax 124 | 125 | // DestStart:=Destination; 126 | mov dword ptr [ebp + TDisUnFilterData.DestStart], edi 127 | 128 | // Hdr:=Source; 129 | // Cur:=@Hdr[ST_MAX*sizeof(longword)]; 130 | // for i:=0 to ST_MAX-1 do begin 131 | // Stream[i]:=Cur; 132 | // inc(Cur,longword(pointer(Hdr)^)); 133 | // inc(pansichar(Hdr),sizeof(longword)); 134 | // end; 135 | // StreamEnd:=Stream[ST_OP+1]; 136 | lea ebx, [esi + ST_MAX * 4] // ebx = Cur 137 | xor ecx, ecx 138 | @DisUnFilterStreamInitLoop: 139 | mov dword ptr [ebp + TDisUnFilterData.Streams + ecx * 4], ebx 140 | lodsd 141 | add ebx, eax 142 | inc ecx 143 | cmp cl, ST_MAX 144 | jne @DisUnFilterStreamInitLoop 145 | @DisUnFilterStreamInitLoopDone: 146 | mov eax, dword ptr [ebp + TDisUnFilterData.Streams + (ST_OP + 1) * 4] 147 | mov dword ptr [ebp + TDisUnFilterData.StreamEnd], eax 148 | 149 | @DisUnFilterStreamMainLoop: 150 | 151 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_OP * 4] 152 | cmp esi, dword ptr [ebp + TDisUnFilterData.StreamEnd] 153 | jae DisUnFilterStreamMainLoopDone 154 | 155 | // Code:=Fetch8(Stream[ST_OP]); 156 | lodsb 157 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_OP * 4], esi 158 | 159 | // if Code=JUMPTAB then begin // jump table escape 160 | cmp al, JUMPTAB 161 | jne @DisUnFilterNoJumpTableEscape 162 | 163 | // Count:=Fetch8(Stream[ST_JUMPTBL_COUNT])+1; 164 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_JUMPTBL_COUNT * 4] 165 | movzx ecx, byte ptr [esi] 166 | inc esi 167 | inc ecx 168 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_JUMPTBL_COUNT * 4], esi 169 | 170 | // for i:=0 to Count-1 do begin 171 | @DisUnFilterJumpTableEscapeLoop: 172 | 173 | // Ind:=Fetch8(Stream[ST_CALL_IDX]); 174 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_CALL_IDX * 4] 175 | movzx eax, byte ptr [esi] 176 | inc esi 177 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_CALL_IDX * 4], esi 178 | 179 | test eax, eax 180 | jz @DisUnFilterJumpTableEscapeIndIsZero 181 | @DisUnFilterJumpTableEscapeIndIsNonZero: 182 | 183 | // Target:=MoveToFront(FuncTable,Ind-1,FuncTable[Ind-1]); 184 | dec eax 185 | mov ebx, dword ptr [ebp + TDisUnFilterData.FuncTable + eax * 4] 186 | call @DisUnFilterMoveToFront 187 | 188 | jmp @DisUnFilterJumpTableEscapeIndIsZeroSkip 189 | @DisUnFilterJumpTableEscapeIndIsZero: 190 | 191 | // Target:=Fetch32B(Stream[ST_CALL32]); 192 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_CALL32 * 4] 193 | lodsd 194 | bswap eax 195 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_CALL32 * 4], esi 196 | 197 | // AddMoveToFront(FuncTable,Target); 198 | call @DisUnFilterAddMoveToFront 199 | 200 | @DisUnFilterJumpTableEscapeIndIsZeroSkip: 201 | 202 | // Write32(Dest,Target); 203 | stosd 204 | 205 | loop @DisUnFilterJumpTableEscapeLoop 206 | 207 | // continue; 208 | jmp @DisUnFilterStreamMainLoop 209 | 210 | @DisUnFilterNoJumpTableEscape: 211 | 212 | // if NextIsFunc and (Code<>OP_INT3) then begin 213 | mov ecx, dword ptr [ebp + TDisUnFilterData.NextIsFunc] 214 | jecxz @DisUnFilterStreamNoNextIsFuncAndOpINT3 215 | cmp al, OP_INT3 216 | je @DisUnFilterStreamNoNextIsFuncAndOpINT3 217 | @DisUnFilterStreamNextIsFuncAndOpINT3: 218 | push eax 219 | // AddMoveToFront(FuncTable,Dest); 220 | mov eax, edi 221 | call @DisUnFilterAddMoveToFront 222 | // NextIsFunc:=false; 223 | xor eax, eax 224 | mov dword ptr [ebp + TDisUnFilterData.NextIsFunc], eax 225 | pop eax 226 | @DisUnFilterStreamNoNextIsFuncAndOpINT3: 227 | 228 | // if Code=ESCAPE then begin 229 | cmp al, ESCAPE 230 | jne @DisUnFilterNoEscape 231 | @DisUnFilterEscape: 232 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_OP * 4] 233 | movsb 234 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_OP * 4], esi 235 | jmp @DisUnFilterNoEscapeSkip 236 | @DisUnFilterNoEscape: 237 | 238 | // Write8(Dest,Code); 239 | stosb 240 | 241 | // o16:=false; 242 | xor ebx, ebx 243 | 244 | // if Code=OP_OSIZE then 245 | cmp al, OP_OSIZE 246 | jne @DisUnFilterNoEscapeOPOSIZESkip 247 | not ebx // o16:=true; 248 | // Code:=Copy8(Dest,Stream[ST_OP]); 249 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_OP * 4] 250 | lodsb 251 | stosb 252 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_OP * 4], esi 253 | @DisUnFilterNoEscapeOPOSIZESkip: 254 | 255 | mov dword ptr [ebp + TDisUnFilterData.Offset16Prefix], ebx 256 | 257 | // if Code in [OP_RETNI,OP_RETN,OP_INT3] then begin 258 | cmp al, OP_RETNI 259 | je @DisUnFilterRETNIRETNINT3 260 | cmp al, OP_RETN 261 | je @DisUnFilterRETNIRETNINT3 262 | cmp al, OP_INT3 263 | jne @DisUnFilterRETNIRETNINT3Skip 264 | @DisUnFilterRETNIRETNINT3: 265 | // NextIsFunc:=true; 266 | xor ebx, ebx 267 | not ebx 268 | mov dword ptr [ebp + TDisUnFilterData.NextIsFunc], ebx 269 | @DisUnFilterRETNIRETNINT3Skip: 270 | 271 | // if Code=OP_2BYTE then begin 272 | cmp al, OP_2BYTE 273 | jne @DisUnFilterNoOP2BYTE 274 | @DisUnFilterOP2BYTE: 275 | // Flags:=Table2[Copy8(Dest,Stream[ST_OP2])]; 276 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_OP2 * 4] 277 | movzx ecx, byte ptr [esi] 278 | mov byte ptr [edi], cl 279 | inc esi 280 | inc edi 281 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_OP2 * 4], esi 282 | inc ch // ch is one, and therefore ecx above 255 283 | // mov cl, byte ptr [Table2 + edx + ecx] 284 | jmp @DisUnFilterNoOP2BYTESkip 285 | @DisUnFilterNoOP2BYTE: 286 | // Flags:=Table1[Code]; 287 | movzx ecx, al 288 | // ch is zero, and therefore ecx below 256 289 | // mov cl, byte ptr [Table1 + edx + ecx] 290 | @DisUnFilterNoOP2BYTESkip: 291 | 292 | // optimized form of: (Tables[ecx >> 1] >> ((ecx & 1) << 2)) & 15 293 | // Table1 contents goes nibble-wise from 0 to 127 294 | // Table2 contents goes nibble-wise from 128 to 255 295 | shr ecx, 1 296 | mov cl, byte ptr [Tables + edx + ecx] 297 | jnc @DisUnFilterOddTableFlag 298 | shr cl, 4 299 | @DisUnFilterOddTableFlag: 300 | and cl, 15 301 | 302 | // if Code in [OP_CALLF,OP_JMPF,OP_ENTER] then begin 303 | cmp al, OP_CALLF 304 | je @DisUnFilterCALLFJMPFENTER 305 | cmp al, OP_JMPF 306 | je @DisUnFilterCALLFJMPFENTER 307 | cmp al, OP_ENTER 308 | jne @DisUnFilterCALLFJMPFENTERSkip 309 | @DisUnFilterCALLFJMPFENTER: 310 | // Copy16Chk(ST_IMM16); 311 | mov bl, ST_IMM16 312 | call @DisUnFilterCopy16 313 | @DisUnFilterCALLFJMPFENTERSkip: 314 | 315 | // if (Flags and fMR)<>0 then begin 316 | test cl, fMR 317 | je @DisPackUnFilterNofMR 318 | 319 | // modrm:=Copy8(Dest,Stream[ST_MODRM]); 320 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_MODRM * 4] 321 | mov bl, byte ptr [esi] 322 | mov byte ptr [edi], bl 323 | inc esi 324 | inc edi 325 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_MODRM * 4], esi 326 | 327 | // sib:=0; 328 | xor bh, bh 329 | 330 | // if Flags=fMEXTRA then begin 331 | cmp cl, fMEXTRA 332 | jne @DisPackUnFilterNotfEXTRA 333 | mov cl, fMRfNI 334 | test bl, 56 335 | jnz @DisPackUnFilterNotfEXTRA 336 | mov ch, byte ptr [edi - 2] 337 | test ch, 8 338 | jnz @DisPackUnFilterNotfEXTRA 339 | add cl, fBI 340 | test ch, 1 341 | jz @DisPackUnFilterNotfEXTRA 342 | add cl, fDI - fBI 343 | // Flags:=TableX[((modrm shr 3) and 7) or ((Code and $01) shl 3) or ((Code and $8) shl 1)]; 344 | // mov ah, bl 345 | // shr ah, 3 346 | // and ah, 7 347 | // mov ch, al 348 | // and ch, 1 349 | // shl ch, 3 350 | // or ah, ch 351 | // mov ch, al 352 | // and ch, 8 353 | // shl ch, 1 354 | // or ah, ch 355 | // movzx ecx, ah 356 | // mov cl, byte ptr [TableX + edx + ecx] 357 | @DisPackUnFilterNotfEXTRA: 358 | 359 | // if ((modrm and 7)=4) and (modrm<$c0) then begin 360 | mov ah, bl 361 | and ah, 7 362 | cmp ah, 4 363 | jne @DisPackUnFilterNoSIB 364 | cmp bl, 192 365 | jae @DisPackUnFilterNoSIB 366 | // sib:=Copy8(Dest,Stream[ST_SIB]); 367 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_SIB * 4] 368 | mov bh, byte ptr [esi] 369 | mov byte ptr [edi], bh 370 | inc esi 371 | inc edi 372 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_SIB * 4], esi 373 | @DisPackUnFilterNoSIB: 374 | 375 | // if (modrm and $c0)=$40 then begin 376 | mov ah, bl 377 | and ah, 192 378 | cmp ah, 64 379 | jne @DisPackUnfilterNoDISPR 380 | push ebx 381 | // st:=(modrm and 7)+ST_DISP8_R0; 382 | and bl, 7 383 | add bl, ST_DISP8_R0 384 | movzx ebx, bl 385 | // Copy8Chk(st); 386 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ebx * 4] 387 | movsb 388 | mov dword ptr [ebp + TDisUnFilterData.Streams + ebx * 4], esi 389 | pop ebx 390 | @DisPackUnfilterNoDISPR: 391 | 392 | // if ((modrm and $c0)=$80) or ((modrm and $c7)=$05) or (((modrm<$40) and ((sib and 7)=5))) then begin 393 | mov ah, bl 394 | and ah, 192 395 | cmp ah, 128 396 | je @DisPackUnFilterADDR32orDISP32 397 | mov ah, bl 398 | and ah, 199 399 | cmp ah, 5 400 | je @DisPackUnFilterADDR32orDISP32 401 | cmp bl, 64 402 | jae @DisPackUnFilterNoADDR32orDISP32 403 | mov ah, bh 404 | and ah, 7 405 | cmp ah, 5 406 | jne @DisPackUnFilterNoADDR32orDISP32 407 | @DisPackUnFilterADDR32orDISP32: 408 | // if (modrm and $c7)=$05 then begin 409 | // st:=ST_ADDR32; 410 | // end else begin 411 | // st:=ST_DISP32; 412 | // end; 413 | and bl, 199 414 | sub bl, 5 415 | neg bl 416 | sbb bl, bl 417 | add bl, ST_ADDR32 418 | // Copy32Chk(st); 419 | call @DisUnFilterCopy32 420 | @DisPackUnFilterNoADDR32orDISP32: 421 | 422 | @DisPackUnFilterNofMR: 423 | 424 | // if (Flags and fMODE)=fAM then begin 425 | mov ah, cl 426 | and ah, fMODE 427 | cmp ah, fAM 428 | jne @DisPackUnFilterNofMODEfAM 429 | 430 | // case Flags and fTYPE of 431 | mov ah, cl 432 | and ah, fTYPE 433 | 434 | // fAD:begin 435 | cmp ah, fAD 436 | je @DisPackUnFilterfMODEfAMfAD 437 | // fDA:begin 438 | cmp ah, fDA 439 | je @DisPackUnFilterfMODEfAMfDA 440 | // fBR:begin 441 | cmp ah, fBR 442 | je @DisPackUnFilterfMODEfAMfBR 443 | // fDR:begin 444 | cmp ah, fDR 445 | je @DisPackUnFilterfMODEfAMfDR 446 | jmp @DisPackUnFilterNofMODEfAMSkip 447 | 448 | @DisPackUnFilterfMODEfAMfAD: 449 | // Copy32Chk(ST_ADDR32); 450 | mov bl, ST_ADDR32 451 | jmp @DisPackUnFilterNofMODEfAMCopy32 452 | 453 | @DisPackUnFilterfMODEfAMfDA: 454 | // Copy32Chk(ST_AJUMP32); 455 | mov bl, ST_AJUMP32 456 | jmp @DisPackUnFilterNofMODEfAMCopy32 457 | 458 | @DisPackUnFilterfMODEfAMfBR: 459 | // Copy8Chk(ST_JUMP8); 460 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_JUMP8 * 4] 461 | movsb 462 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_JUMP8 * 4], esi 463 | jmp @DisPackUnFilterNofMODEfAMSkip 464 | 465 | @DisPackUnFilterfMODEfAMfDR: 466 | // if Code=OP_CALLN then begin 467 | cmp al, OP_CALLN 468 | jne @DisPackUnFilterfMODEfAMfDRNoOPCALLN 469 | 470 | // Ind:=Fetch8(Stream[ST_CALL_IDX]); 471 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_CALL_IDX * 4] 472 | movzx eax, byte ptr [esi] 473 | inc esi 474 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_CALL_IDX * 4], esi 475 | 476 | test eax, eax 477 | jz @DisUnFilterfMODEfAMfDRIndIsZero 478 | @DisUnFilterfMODEfAMfDRIndIsNonZero: 479 | 480 | // Target:=MoveToFront(FuncTable,Ind-1,FuncTable[Ind-1]); 481 | dec eax 482 | mov ebx, dword ptr [ebp + TDisUnFilterData.FuncTable + eax * 4] 483 | call @DisUnFilterMoveToFront 484 | 485 | jmp @DisUnFilterfMODEfAMfDRIndIsZeroSkip 486 | @DisUnFilterfMODEfAMfDRIndIsZero: 487 | 488 | // Target:=Fetch32B(Stream[ST_CALL32]); 489 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_CALL32 * 4] 490 | lodsd 491 | bswap eax 492 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_CALL32 * 4], esi 493 | 494 | // AddMoveToFront(FuncTable,Target); 495 | call @DisUnFilterAddMoveToFront 496 | 497 | @DisUnFilterfMODEfAMfDRIndIsZeroSkip: 498 | 499 | jmp @DisPackUnFilterfMODEfAMfDRNoOPCALLNSkip 500 | 501 | @DisPackUnFilterfMODEfAMfDRNoOPCALLN: 502 | 503 | // Target:=Fetch32B(Stream[ST_JUMP32]); 504 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_JUMP32 * 4] 505 | lodsd 506 | bswap eax 507 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_JUMP32 * 4], esi 508 | 509 | @DisPackUnFilterfMODEfAMfDRNoOPCALLNSkip: 510 | 511 | // dec(Target,Dest+4); 512 | sub eax, byte 4 513 | sub eax, edi 514 | 515 | // Write32(Dest,Target); 516 | stosd 517 | jmp @DisPackUnFilterNofMODEfAMSkip 518 | 519 | @DisPackUnFilterNofMODEfAM: 520 | 521 | // case Flags and fTYPE of 522 | mov ah, cl 523 | and ah, fTYPE 524 | 525 | // fBI:begin 526 | cmp ah, fBI 527 | je @DisPackUnFilterNofMODEfAMfBI 528 | cmp ah, fWI 529 | je @DisPackUnFilterNofMODEfAMfWI 530 | cmp ah, fDI 531 | je @DisPackUnFilterNofMODEfAMfDI 532 | jmp @DisPackUnFilterNofMODEfAMSkip 533 | 534 | @DisPackUnFilterNofMODEfAMfBI: 535 | // Copy8Chk(ST_IMM8); 536 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ST_IMM8 * 4] 537 | movsb 538 | mov dword ptr [ebp + TDisUnFilterData.Streams + ST_IMM8 * 4], esi 539 | jmp @DisPackUnFilterNofMODEfAMSkip 540 | 541 | @DisPackUnFilterNofMODEfAMfWI: 542 | // Copy16Chk(ST_IMM16); 543 | mov bl, ST_IMM16 544 | call @DisUnFilterCopy16 545 | jmp @DisPackUnFilterNofMODEfAMSkip 546 | 547 | @DisPackUnFilterNofMODEfAMfDI: 548 | // if o16 then begin 549 | cmp dword ptr [ebp + TDisUnFilterData.Offset16Prefix], 0 550 | jne @DisPackUnFilterNofMODEfAMfWI 551 | // Copy32Chk(ST_IMM32); 552 | mov bl, ST_IMM32 553 | @DisPackUnFilterNofMODEfAMCopy32: 554 | call @DisUnFilterCopy32 555 | 556 | @DisPackUnFilterNofMODEfAMSkip: 557 | 558 | @DisUnFilterNoEscapeSkip: 559 | 560 | jmp @DisUnFilterStreamMainLoop 561 | 562 | @DisUnFilterCopy16: 563 | push eax 564 | movzx ebx, bl 565 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ebx * 4] 566 | lodsw 567 | xchg ah, al 568 | stosw 569 | mov dword ptr [ebp + TDisUnFilterData.Streams + ebx * 4], esi 570 | pop eax 571 | ret 572 | 573 | @DisUnFilterCopy32: 574 | push eax 575 | movzx ebx, bl 576 | mov esi, dword ptr [ebp + TDisUnFilterData.Streams + ebx * 4] 577 | lodsd 578 | bswap eax 579 | stosd 580 | mov dword ptr [ebp + TDisUnFilterData.Streams + ebx * 4], esi 581 | pop eax 582 | ret 583 | 584 | @DisUnFilterAddMoveToFront: 585 | mov ebx, eax // Val = Val 586 | xor eax, eax // Pos = 255 587 | not al 588 | 589 | @DisUnFilterMoveToFront: 590 | // eax = Pos 591 | // ebx = Val 592 | push ecx 593 | push edx 594 | lea edx, [ebp + TDisUnFilterData.FuncTable + eax * 4] 595 | mov ecx, eax 596 | jecxz @DisUnFilterMoveToFrontDone 597 | @DisUnFilterMoveToFrontLoop: 598 | mov eax, dword ptr [edx - 4] 599 | mov dword ptr [edx], eax 600 | sub edx, byte 4 601 | loop @DisUnFilterMoveToFrontLoop 602 | @DisUnFilterMoveToFrontDone: 603 | // p[0]:=Val; 604 | mov dword ptr [edx], ebx 605 | // result:=Val; 606 | mov eax, ebx 607 | pop edx 608 | pop ecx 609 | ret 610 | 611 | /* 612 | TableX: 613 | db fMR | fBI,fERR ,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI // escapes for 0xf6 614 | db fMR | fDI,fERR ,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI // escapes for 0xf7 615 | db fMR | fNI,fMR | fNI,fERR ,fERR ,fERR ,fERR ,fERR ,fERR // escapes for 0xfe 616 | db fMR | fNI,fMR | fNI,fMR | fNI,fERR ,fMR | fNI,fERR ,fMR | fNI,fERR // escapes for 0xff 617 | */ 618 | 619 | !script{ 620 | 621 | var fNM = 0x0; // no ModRM 622 | var fAM = 0x1; // no ModRM, "address mode" (jumps | direct addresses) 623 | var fMR = 0x2; // ModRM present 624 | var fMEXTRA = 0x3; // ModRM present, includes extra bits for opcode 625 | var fMODE = 0x3; // bitmask for mode 626 | 627 | // no ModRM: size of immediate operand 628 | var fNI = 0x0; // no immediate 629 | var fBI = 0x4; // byte immediate 630 | var fWI = 0x8; // word immediate 631 | var fDI = 0xc; // dword immediate 632 | var fTYPE = 0xc; // type mask 633 | 634 | // address mode: type of address operand 635 | var fAD = 0x0; // absolute address 636 | var fDA = 0x4; // dword absolute jump target 637 | var fBR = 0x8; // byte relative jump target 638 | var fDR = 0xc; // dword relative jump target 639 | 640 | // others 641 | var fERR = 0xf; // denotes invalid opcodes 642 | 643 | // 1-byte opcodes 0 1 2 3 4 5 6 7 8 9 a b c d e f 644 | var Table1 = [fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fNM | fBI,fNM | fDI,fNM | fNI,fNM | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fNM | fBI,fNM | fDI,fNM | fNI,fNM | fNI, // 0 645 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fNM | fBI,fNM | fDI,fNM | fNI,fNM | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fNM | fBI,fNM | fDI,fNM | fNI,fNM | fNI, // 1 646 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fNM | fBI,fNM | fDI,fNM | fNI,fNM | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fNM | fBI,fNM | fDI,fNM | fNI,fNM | fNI, // 2 647 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fNM | fBI,fNM | fDI,fNM | fNI,fNM | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fNM | fBI,fNM | fDI,fNM | fNI,fNM | fNI, // 3 648 | fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI, // 4 649 | fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI, // 5 650 | fNM | fNI,fNM | fNI,fMR | fNI,fMR | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fDI,fMR | fDI,fNM | fBI,fMR | fBI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI, // 6 651 | fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR, // 7 652 | fMR | fBI,fMR | fDI,fMR | fBI,fMR | fBI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // 8 653 | fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fAM | fDA,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI, // 9 654 | fAM | fAD,fAM | fAD,fAM | fAD,fAM | fAD,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fBI,fNM | fDI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI, // a 655 | fNM | fBI,fNM | fBI,fNM | fBI,fNM | fBI,fNM | fBI,fNM | fBI,fNM | fBI,fNM | fBI,fNM | fDI,fNM | fDI,fNM | fDI,fNM | fDI,fNM | fDI,fNM | fDI,fNM | fDI,fNM | fDI, // b 656 | fMR | fBI,fMR | fBI,fNM | fWI,fNM | fNI,fMR | fNI,fMR | fNI,fMR | fBI,fMR | fDI,fNM | fBI,fNM | fNI,fNM | fWI,fNM | fNI,fNM | fNI,fNM | fBI,fERR ,fNM | fNI, // c 657 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fNM | fBI,fNM | fBI,fNM | fNI,fNM | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // d 658 | fAM | fBR,fAM | fBR,fAM | fBR,fAM | fBR,fNM | fBI,fNM | fBI,fNM | fBI,fNM | fBI,fAM | fDR,fAM | fDR,fAM | fAD,fAM | fBR,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI, // e 659 | fNM | fNI,fERR ,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fMEXTRA ,fMEXTRA ,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI, fMEXTRA ,fMEXTRA]; // f 660 | 661 | // 2-byte opcodes 0 1 2 3 4 5 6 7 8 9 a b c d e f 662 | var Table2 = [fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fNM | fNI,fERR ,fNM | fNI,fNM | fNI,fERR ,fERR ,fERR ,fERR ,fERR ,fERR , // 0 663 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR , // 1 664 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fERR ,fERR ,fERR ,fERR ,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // 2 665 | fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fERR ,fNM | fNI,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR , // 3 666 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // 4 667 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // 5 668 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // 6 669 | fMR | fBI,fMR | fBI,fMR | fBI,fMR | fBI,fMR | fNI,fMR | fNI,fMR | fNI,fNM | fNI,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fMR | fNI,fMR | fNI, // 7 670 | fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR,fAM | fDR, // 8 671 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // 9 672 | fNM | fNI,fNM | fNI,fNM | fNI,fMR | fNI,fMR | fBI,fMR | fNI,fMR | fNI,fMR | fNI,fERR ,fERR ,fERR ,fMR | fNI,fMR | fBI,fMR | fNI,fERR ,fMR | fNI, // a 673 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fERR ,fERR ,fERR ,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // b 674 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI,fNM | fNI, // c 675 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // d 676 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // e 677 | fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fERR]; // f 678 | 679 | // escape opcodes using ModRM byte to get more variants 680 | // 0 1 2 3 4 5 6 7 681 | var TableX = [fMR | fBI,fERR ,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // escapes for 0xf6 682 | fMR | fDI,fERR ,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // escapes for 0xf7 683 | fMR | fNI,fMR | fNI,fERR ,fERR ,fERR ,fERR ,fERR ,fERR , // escapes for 0xfe 684 | fMR | fNI,fMR | fNI,fMR | fNI,fERR ,fMR | fNI,fERR ,fMR | fNI,fERR]; // escapes for 0xff 685 | 686 | var Tables = new Array(256); 687 | 688 | function CombineTable1AndTable2(){ 689 | for(var i = 0; i < 256; i++){ 690 | var j = (i & 127) << 1; 691 | var v = (i < 128) ? (Table1[j] | (Table1[j + 1] << 4)) : (Table2[j] | (Table2[j + 1] << 4)); 692 | if((v & 0xf) == fERR){ 693 | v &= 0xf0; 694 | } 695 | if((v >> 4) == fERR){ 696 | v &= 0x0f; 697 | } 698 | Tables[i] = v; 699 | } 700 | } 701 | 702 | function OutputCombinedTable1AndTable2(){ 703 | Assembler.parse("Tables:"); 704 | for(var i = 0; i < 256; i++){ 705 | Assembler.parse("db " + Tables[i].toString()); 706 | } 707 | } 708 | 709 | CombineTable1AndTable2(); 710 | OutputCombinedTable1AndTable2(); 711 | 712 | } 713 | 714 | DisUnFilterStreamMainLoopDone: 715 | 716 | add esp, DisUnFilterDataSize 717 | 718 | popad 719 | 720 | // ret 721 | 722 | } 723 | -------------------------------------------------------------------------------- /examples/x86filter2.asm: -------------------------------------------------------------------------------- 1 | .target(bin); 2 | .startoffset(0); 3 | .cpu(all); 4 | 5 | NBUFFERS = 20; 6 | 7 | .struct(dataArea){ 8 | buffer dword(NBUFFERS); 9 | offset dword(1) 10 | lastJump dword(1) 11 | nextFunc dword(1) 12 | jumpTable dword(1) 13 | codebuf byte(1) 14 | modrmbuf byte(1) 15 | _pad byte(2) 16 | funcTable dword(256) 17 | } 18 | 19 | fNM=0x0; // no ModRM 20 | fAM=0x1; // no ModRM, "address mode" (jumps or direct addresses) 21 | fMR=0x2; // ModRM present 22 | fMO=0x3; // ModRM present, includes extra bits for opcode 23 | fMODE=0x3; // bitmask for mode 24 | 25 | fNI=0x0; // no immediate 26 | fBI=0x4; // byte immediate 27 | fDI=0x8; // dword immediate 28 | fWI=0xc; // word immediate 29 | fTYPE=0xc; // type mask 30 | 31 | fAD=0x0; // absolute address 32 | fBR=0x4; // byte relative jump target 33 | fDR=0xc; // dword relative jump target 34 | 35 | fERR=0x0; // denotes invalid opcodes 36 | 37 | .code{ 38 | .bits(32) 39 | 40 | DisUnfilter: 41 | sub esp, dataArea 42 | mov ebp, esp 43 | 44 | mov ebx, edi 45 | sub ebx, byte 4 46 | mov [ebp+dataArea.offset], ebx 47 | 48 | xor eax, eax 49 | mov [ebp+dataArea.lastJump], eax 50 | inc eax 51 | mov [ebp+dataArea.nextFunc], eax 52 | mov [ebp+dataArea.funcTable], eax 53 | neg eax 54 | mov [ebp+dataArea.jumpTable], eax 55 | 56 | lea ebx, [esi+NBUFFERS*4] 57 | xor ecx, ecx 58 | 59 | @init: lodsd 60 | mov [ebp+dataArea.Buffer+ecx*4], ebx 61 | add ebx, eax 62 | inc ecx 63 | cmp cl, NBUFFERS 64 | jne @init 65 | 66 | mov esi, [ebp+dataArea.Buffer+1*4] 67 | xchg esi, [ebp+dataArea.Buffer] 68 | 69 | @main: cmp esi, [ebp+dataArea.Buffer] 70 | jne @chkjt // @gotins 71 | 72 | add esp, dataArea 73 | jmp DefilterDone 74 | 75 | @chkjt: cmp edi, [ebp+dataArea.jumpTable] 76 | jb @gotins 77 | jne @jtclr 78 | 79 | xchg esi, [ebp+dataArea.Buffer+15*4] 80 | lodsd 81 | xchg eax, ecx 82 | rep movsd 83 | xchg esi, [ebp+dataArea.Buffer+15*4] 84 | 85 | @jtclr: or dword [ebp+dataArea.jumpTable], byte -1 86 | jmp short @main 87 | 88 | @gotins: 89 | xor eax, eax 90 | cmp [ebp+dataArea.nextFunc], eax 91 | lodsb 92 | je @testes 93 | 94 | cmp al, 0xcc // int3 (padding used by vc) 95 | je @testes 96 | 97 | lea ecx, [edi-4] 98 | sub ecx, [ebp+dataArea.offset] 99 | 100 | mov ebx, [ebp+dataArea.funcTable] 101 | mov [ebp+dataArea.funcTable+ebx*4], ecx 102 | @incm: inc byte [ebp+dataArea.funcTable] 103 | jz @incm 104 | 105 | mov byte [ebp+dataArea.nextFunc], 0 106 | 107 | @testes: 108 | cmp al, 0xce // escape 109 | jne @noesc 110 | 111 | movsb 112 | jmp @main 113 | 114 | @noesc: stosb 115 | 116 | xor edx, edx 117 | cmp al, 0x66 // operand size prefix 118 | jne @nopfx 119 | 120 | mov dh, 1 121 | lodsb 122 | stosb 123 | 124 | @nopfx: mov [ebp+dataArea.codebuf], al 125 | mov bl, al 126 | cmp bl, 0xcc 127 | je @isret 128 | sub bl, 0xc2 129 | cmp bl, 1 130 | ja @noret 131 | 132 | @isret: mov byte [ebp+dataArea.nextFunc], 1 // inc? 133 | 134 | @noret: 135 | call @PICCall 136 | @PICCall: 137 | pop ebx 138 | add ebx, (offset Tables) - (offset @PICCall) 139 | cmp al, 0x0f // two-byte opcode 140 | jne @notwo 141 | 142 | lodsb 143 | stosb 144 | mov ah, 1 145 | 146 | @notwo: shr eax, 1 // get flags 147 | xlatb 148 | jnc @flagok 149 | shr al, 4 150 | @flagok: 151 | and al, 0xf 152 | mov cl, al 153 | 154 | test cl, fMR // mod/rm follows? 155 | jz near @nomdrm 156 | 157 | lodsb 158 | stosb 159 | mov [ebp+dataArea.modrmbuf], al 160 | mov ch, al 161 | 162 | mov al, cl 163 | and al, fMODE 164 | cmp al, fMO 165 | jne @noxtra 166 | 167 | mov cl, fMR|fNI 168 | test ch, 0x38 169 | jnz @noxtra 170 | mov bl, [edi-2] 171 | test bl, 0x08 172 | jnz @noxtra 173 | add cl, fBI 174 | test bl, 0x01 175 | jz @noxtra 176 | add cl, fDI-fBI 177 | 178 | @noxtra: 179 | and ch, 0xc7 180 | cmp ch, 0xc4 181 | je @nosib 182 | mov al, ch 183 | and al, 0x07 184 | cmp al, 0x04 185 | jne @nosib 186 | 187 | xchg esi, [ebp+dataArea.Buffer+19*4] 188 | movsb 189 | xchg esi, [ebp+dataArea.Buffer+19*4] 190 | 191 | @nosib: mov dl, ch 192 | and dl, 0xc0 193 | cmp dl, 0x40 194 | jne @nodis8 195 | 196 | movzx ebx, ch 197 | and bl, 0x07 198 | 199 | xchg esi, [ebp+dataArea.Buffer+1*4+ebx*4] 200 | movsb 201 | xchg esi, [ebp+dataArea.Buffer+1*4+ebx*4] 202 | 203 | @nodis8: 204 | cmp dl, 0x80 205 | je @dis32 206 | cmp ch, 0x05 207 | je @dis32 208 | test dl, dl 209 | jnz @nomdrm 210 | mov al, [edi-1] 211 | and al, 0x07 212 | cmp al, 0x05 213 | jne @nomdrm 214 | 215 | @dis32: xor ebx, ebx 216 | cmp ch, 5 217 | jne @nomr5 218 | inc ebx 219 | @nomr5: xchg esi, [ebp+dataArea.Buffer+13*4+ebx*4] 220 | lodsd 221 | xchg esi, [ebp+dataArea.Buffer+13*4+ebx*4] 222 | bswap eax 223 | stosd 224 | 225 | cmp word [ebp+dataArea.codebuf], 0x24ff 226 | jne @nomdrm 227 | mov ebx, [ebp+dataArea.jumpTable] 228 | cmp eax, ebx 229 | jae @nomdrm 230 | mov [ebp+dataArea.jumpTable], eax 231 | 232 | @nomdrm: 233 | mov al, cl 234 | and al, fMODE 235 | cmp al, fAM 236 | jne near @noaddr 237 | 238 | shr cl, 2 239 | jnz @noad 240 | 241 | xchg esi, [ebp+dataArea.Buffer+15*4] 242 | movsd 243 | xchg esi, [ebp+dataArea.Buffer+15*4] 244 | jmp @main 245 | 246 | @noad: dec cl 247 | jnz @dwdrl 248 | 249 | xchg esi, [ebp+dataArea.Buffer+9*4] 250 | movsb 251 | xchg esi, [ebp+dataArea.Buffer+9*4] 252 | jmp @main 253 | 254 | @dwdrl: xor ebx, ebx 255 | cmp byte [edi-1], 0xe8 256 | je @dwcal 257 | 258 | xchg esi, [ebp+dataArea.Buffer+17*4] 259 | lodsd 260 | xchg esi, [ebp+dataArea.Buffer+17*4] 261 | 262 | shr eax, 1 263 | jnc @jmpnc 264 | not eax 265 | 266 | @jmpnc: add eax, [ebp+dataArea.lastJump] 267 | mov [ebp+dataArea.lastJump], eax 268 | jmp short @storad 269 | 270 | @dwcal: xor eax, eax 271 | xchg esi, [ebp+dataArea.Buffer+16*4] 272 | lodsb 273 | xchg esi, [ebp+dataArea.Buffer+16*4] 274 | test al, al 275 | jz @dcesc 276 | 277 | mov eax, [ebp+dataArea.funcTable+eax*4] 278 | jmp short @storad 279 | 280 | @dcesc: xchg esi, [ebp+dataArea.Buffer+18*4] 281 | lodsd 282 | xchg esi, [ebp+dataArea.Buffer+18*4] 283 | 284 | mov ebx, [ebp+dataArea.funcTable] 285 | mov [ebp+dataArea.funcTable+ebx*4], eax 286 | @dcinc: inc byte [ebp+dataArea.funcTable] 287 | jz @dcinc 288 | 289 | @storad: 290 | sub eax, edi 291 | add eax, [ebp+dataArea.offset] 292 | stosd 293 | jmp @main 294 | 295 | @noaddr: 296 | shr cl, 2 297 | jz near @main 298 | 299 | dec cl 300 | jnz @dwow 301 | 302 | xchg esi, [ebp+dataArea.Buffer+10*4] 303 | movsb 304 | xchg esi, [ebp+dataArea.Buffer+10*4] 305 | jmp @main 306 | 307 | @dwow: dec cl 308 | jnz @word 309 | test dh, dh 310 | jnz @word 311 | 312 | xchg esi, [ebp+dataArea.Buffer+12*4] 313 | movsd 314 | xchg esi, [ebp+dataArea.Buffer+12*4] 315 | jmp @main 316 | 317 | @word: xchg esi, [ebp+dataArea.Buffer+11*4] 318 | movsw 319 | xchg esi, [ebp+dataArea.Buffer+11*4] 320 | jmp @main 321 | 322 | !script{ 323 | 324 | var fNM = 0x0; // no ModRM 325 | var fAM = 0x1; // no ModRM, "address mode" (jumps | direct addresses) 326 | var fMR = 0x2; // ModRM present 327 | var fMO = 0x3; // ModRM present, includes extra bits for opcode 328 | var fMODE = 0x3; // bitmask for mode 329 | 330 | // no ModRM: size of immediate operand 331 | var fNI = 0x0; // no immediate 332 | var fBI = 0x4; // byte immediate 333 | var fDI = 0x8; // dword immediate 334 | var fWI = 0xc; // word immediate 335 | var fTYPE = 0xc; // type mask 336 | 337 | // address mode: type of address operand 338 | var fAD = 0x0; // absolute address 339 | var fBR = 0x4; // byte relative jump target 340 | var fDR = 0xc; // dword relative jump target 341 | 342 | // others 343 | var fERR = 0x9; // denotes invalid opcodes 344 | 345 | // 1-byte opcodes 0 1 2 3 4 5 6 7 8 9 a b c d e f 346 | var Table1 = [ fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fNM|fBI,fNM|fDI,fNM|fNI,fNM|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fNM|fBI,fNM|fDI,fNM|fNI,fNM|fNI, // 0 347 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fNM|fBI,fNM|fDI,fNM|fNI,fNM|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fNM|fBI,fNM|fDI,fNM|fNI,fNM|fNI, // 1 348 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fNM|fBI,fNM|fDI,fNM|fNI,fNM|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fNM|fBI,fNM|fDI,fNM|fNI,fNM|fNI, // 2 349 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fNM|fBI,fNM|fDI,fNM|fNI,fNM|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fNM|fBI,fNM|fDI,fNM|fNI,fNM|fNI, // 3 350 | fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI, // 4 351 | fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI, // 5 352 | fNM|fNI,fNM|fNI,fMR|fNI,fMR|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fDI,fMR|fDI,fNM|fBI,fMR|fBI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI, // 6 353 | fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR, // 7 354 | fMR|fBI,fMR|fDI,fMR|fBI,fMR|fBI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI, // 8 355 | fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fERR ,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI, // 9 356 | fAM|fAD,fAM|fAD,fAM|fAD,fAM|fAD,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fBI,fNM|fDI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI, // a 357 | fNM|fBI,fNM|fBI,fNM|fBI,fNM|fBI,fNM|fBI,fNM|fBI,fNM|fBI,fNM|fBI,fNM|fDI,fNM|fDI,fNM|fDI,fNM|fDI,fNM|fDI,fNM|fDI,fNM|fDI,fNM|fDI, // b 358 | fMR|fBI,fMR|fBI,fNM|fWI,fNM|fNI,fMR|fNI,fMR|fNI,fMR|fBI,fMR|fDI,fERR ,fNM|fNI,fNM|fWI,fNM|fNI,fNM|fNI,fNM|fBI,fERR ,fNM|fNI, // c 359 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fNM|fBI,fNM|fBI,fNM|fNI,fNM|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI, // d 360 | fAM|fBR,fAM|fBR,fAM|fBR,fAM|fBR,fNM|fBI,fNM|fBI,fNM|fBI,fNM|fBI,fAM|fDR,fAM|fDR,fAM|fAD,fAM|fBR,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI, // e 361 | fNM|fNI,fERR ,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fMO|fNI,fMO|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fMO|fNI,fMO|fNI]; // f 362 | 363 | // 2-byte opcodes 0 1 2 3 4 5 6 7 8 9 a b c d e f 364 | var Table2 = [ fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR , // 0 365 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR , // 1 366 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fERR ,fERR ,fERR ,fERR ,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI, // 2 367 | fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fERR , // 3 368 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI, // 4 369 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI, // 5 370 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI, // 6 371 | fMR|fBI,fMR|fBI,fMR|fBI,fMR|fBI,fMR|fNI,fMR|fNI,fMR|fNI,fNM|fNI,fERR ,fERR ,fERR ,fERR ,fERR ,fERR ,fMR|fNI,fMR|fNI, // 7 372 | fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR,fAM|fDR, // 8 373 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI, // 9 374 | fNM|fNI,fNM|fNI,fNM|fNI,fMR|fNI,fMR|fBI,fMR|fNI,fMR|fNI,fMR|fNI,fERR ,fERR ,fERR ,fMR|fNI,fMR|fBI,fMR|fNI,fERR ,fMR|fNI, // a 375 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fERR ,fERR ,fERR ,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI, // b 376 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI,fNM|fNI, // c 377 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI, // d 378 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI, // e 379 | fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fMR|fNI,fERR ]; // f 380 | 381 | // escape opcodes using ModRM byte to get more variants 382 | // 0 1 2 3 4 5 6 7 383 | var TableX = [fMR | fBI,fERR ,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // escapes for 0xf6 384 | fMR | fDI,fERR ,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI,fMR | fNI, // escapes for 0xf7 385 | fMR | fNI,fMR | fNI,fERR ,fERR ,fERR ,fERR ,fERR ,fERR , // escapes for 0xfe 386 | fMR | fNI,fMR | fNI,fMR | fNI,fERR ,fMR | fNI,fERR ,fMR | fNI,fERR]; // escapes for 0xff 387 | 388 | var Tables = new Array(256); 389 | 390 | function CombineTable1AndTable2(){ 391 | for(var i = 0; i < 256; i++){ 392 | var j = (i & 127) << 1; 393 | var v = (i < 128) ? (Table1[j] | (Table1[j + 1] << 4)) : (Table2[j] | (Table2[j + 1] << 4)); 394 | if((v & 0xf) == fERR){ 395 | v &= 0xf0; 396 | } 397 | if((v >> 4) == fERR){ 398 | v &= 0x0f; 399 | } 400 | Tables[i] = v; 401 | } 402 | } 403 | 404 | function OutputCombinedTable1AndTable2(){ 405 | Assembler.parse("Tables:"); 406 | for(var i = 0; i < 256; i++){ 407 | Assembler.parse("db " + Tables[i].toString()); 408 | } 409 | } 410 | 411 | CombineTable1AndTable2(); 412 | OutputCombinedTable1AndTable2(); 413 | 414 | } 415 | 416 | DefilterDone: 417 | 418 | } -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | (****************************************************************************** 2 | * zlib license * 3 | *============================================================================* 4 | * * 5 | * Copyright (C) 2003-2017, Benjamin Rosseaux (benjamin@rosseaux.de) * 6 | * * 7 | * This software is provided 'as-is', without any express or implied * 8 | * warranty. In no event will the authors be held liable for any damages * 9 | * arising from the use of this software. * 10 | * * 11 | * Permission is granted to anyone to use this software for any purpose, * 12 | * including commercial applications, and to alter it and redistribute it * 13 | * freely, subject to the following restrictions: * 14 | * * 15 | * 1. The origin of this software must not be misrepresented; you must not * 16 | * claim that you wrote the original software. If you use this software * 17 | * in a product, an acknowledgement in the product documentation would be * 18 | * appreciated but is not required. * 19 | * 2. Altered source versions must be plainly marked as such, and must not be * 20 | * misrepresented as being the original software. * 21 | * 3. This notice may not be removed or altered from any source distribution. * 22 | * * 23 | ******************************************************************************) -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | See beginning comment of src\SASM.inc -------------------------------------------------------------------------------- /src/SASM.inc: -------------------------------------------------------------------------------- 1 | (****************************************************************************** 2 | * SASM Scriptable ASseMbler * 3 | ****************************************************************************** 4 | * Version see SASMCopyrightString in SASMCore.pas * 5 | ****************************************************************************** 6 | * zlib license * 7 | *============================================================================* 8 | * * 9 | * Copyright (C) 2003-2017, Benjamin Rosseaux (benjamin@rosseaux.de) * 10 | * * 11 | * This software is provided 'as-is', without any express or implied * 12 | * warranty. In no event will the authors be held liable for any damages * 13 | * arising from the use of this software. * 14 | * * 15 | * Permission is granted to anyone to use this software for any purpose, * 16 | * including commercial applications, and to alter it and redistribute it * 17 | * freely, subject to the following restrictions: * 18 | * * 19 | * 1. The origin of this software must not be misrepresented; you must not * 20 | * claim that you wrote the original software. If you use this software * 21 | * in a product, an acknowledgement in the product documentation would be * 22 | * appreciated but is not required. * 23 | * 2. Altered source versions must be plainly marked as such, and must not be * 24 | * misrepresented as being the original software. * 25 | * 3. This notice may not be removed or altered from any source distribution. * 26 | * * 27 | ****************************************************************************** 28 | * General guidelines for code contributors * 29 | *============================================================================* 30 | * * 31 | * 1. Make sure you are legally allowed to make a contribution under the zlib * 32 | * license. * 33 | * 2. The zlib license header goes at the top of each source file, with * 34 | * appropriate copyright notice. * 35 | * 3. After a pull request, check the status of your pull request on * 36 | http://github.com/BeRo1985/sasm * 37 | * 4. Write code, which is compatible with Delphi 7-XE7 and FreePascal >= 3.0 * 38 | * so don't use generics/templates, operator overloading and another newer * 39 | * syntax features than Delphi 7 has support for that, but if needed, make * 40 | * it out-ifdef-able. * 41 | * 5. Don't use Delphi-only, FreePascal-only or Lazarus-only libraries/units, * 42 | * but if needed, make it out-ifdef-able. * 43 | * 6. No use of third-party libraries/units as possible, but if needed, make * 44 | * it out-ifdef-able. * 45 | * 7. Try to use const when possible. * 46 | * 8. Make sure to comment out writeln, used while debugging. * 47 | * 9. Make sure the code compiles on 32-bit and 64-bit platforms (x86-32, * 48 | * x86-64, ARM, ARM64, etc.). * 49 | * * 50 | ******************************************************************************) 51 | {$ifdef fpc} 52 | {$mode delphi} 53 | {$ifdef cpui386} 54 | {$define cpu386} 55 | {$endif} 56 | {$ifdef cpu386} 57 | {$asmmode intel} 58 | {$endif} 59 | {$ifdef cpuamd64} 60 | {$asmmode intel} 61 | {$endif} 62 | {$ifdef fpc_little_endian} 63 | {$define little_endian} 64 | {$else} 65 | {$ifdef fpc_big_endian} 66 | {$define big_endian} 67 | {$endif} 68 | {$endif} 69 | {$ifdef fpc_has_internal_sar} 70 | {$define HasSAR} 71 | {$endif} 72 | {-$pic off} 73 | {$define caninline} 74 | {$ifdef FPC_HAS_TYPE_EXTENDED} 75 | {$define HAS_TYPE_EXTENDED} 76 | {$else} 77 | {$undef HAS_TYPE_EXTENDED} 78 | {$endif} 79 | {$ifdef FPC_HAS_TYPE_DOUBLE} 80 | {$define HAS_TYPE_DOUBLE} 81 | {$else} 82 | {$undef HAS_TYPE_DOUBLE} 83 | {$endif} 84 | {$ifdef FPC_HAS_TYPE_SINGLE} 85 | {$define HAS_TYPE_SINGLE} 86 | {$else} 87 | {$undef HAS_TYPE_SINGLE} 88 | {$endif} 89 | {$else} 90 | {$realcompatibility off} 91 | {$localsymbols on} 92 | {$define little_endian} 93 | {$ifndef cpu64} 94 | {$define cpu32} 95 | {$endif} 96 | {$define delphi} 97 | {$undef HasSAR} 98 | {$define UseDIV} 99 | {$define HAS_TYPE_EXTENDED} 100 | {$define HAS_TYPE_DOUBLE} 101 | {$define HAS_TYPE_SINGLE} 102 | {$endif} 103 | {$ifdef cpu386} 104 | {$define cpux86} 105 | {$endif} 106 | {$ifdef cpuamd64} 107 | {$define cpux86} 108 | {$endif} 109 | {$ifdef win32} 110 | {$define windows} 111 | {$endif} 112 | {$ifdef win64} 113 | {$define windows} 114 | {$endif} 115 | {$ifdef wince} 116 | {$define windows} 117 | {$endif} 118 | {$ifdef windows} 119 | {$define win} 120 | {$endif} 121 | {$ifdef sdl20} 122 | {$define sdl} 123 | {$endif} 124 | {$rangechecks off} 125 | {$extendedsyntax on} 126 | {$writeableconst on} 127 | {$hints off} 128 | {$booleval off} 129 | {$typedaddress off} 130 | {$stackframes off} 131 | {$varstringchecks on} 132 | {$typeinfo on} 133 | {$overflowchecks off} 134 | {$longstrings on} 135 | {$openstrings on} 136 | {$ifndef HAS_TYPE_DOUBLE} 137 | {$error No double floating point precision} 138 | {$endif} 139 | {$ifdef fpc} 140 | {$define caninline} 141 | {$else} 142 | {$undef caninline} 143 | {$ifdef ver180} 144 | {$define caninline} 145 | {$else} 146 | {$ifdef conditionalexpressions} 147 | {$if compilerversion>=18} 148 | {$define caninline} 149 | {$ifend} 150 | {$endif} 151 | {$endif} 152 | {$endif} 153 | 154 | -------------------------------------------------------------------------------- /src/SASMData.pas: -------------------------------------------------------------------------------- 1 | unit SASMData; 2 | {$i SASM.inc} 3 | 4 | interface 5 | 6 | {$i SASMDataContent.inc} 7 | 8 | implementation 9 | 10 | end. 11 | -------------------------------------------------------------------------------- /src/TRILinker.pas: -------------------------------------------------------------------------------- 1 | unit TRILinker; 2 | {$ifdef fpc} 3 | {$mode delphi} 4 | {$ifdef cpui386} 5 | {$define cpu386} 6 | {$endif} 7 | {$ifdef cpu386} 8 | {$asmmode intel} 9 | {$endif} 10 | {$endif} 11 | 12 | interface 13 | 14 | uses Windows{$ifdef CreamTrackerGUI},SysUtils,Classes,NativeCodeMemoryManager{$endif}{$ifdef memdebug},FastMM4{$endif}; 15 | 16 | type TGetNameCode=function(Name:pansichar):ansichar; 17 | 18 | TGetExternalPointer=function(Context:pointer;Name:pansichar):pointer; 19 | 20 | TSetPublicPointer=procedure(Context:pointer;Name:pansichar;ThePointer:pointer); 21 | 22 | PTRIInstance=^TTRIInstance; 23 | TTRIInstance=record 24 | ImageData:pointer; 25 | ImageSize:longint; 26 | CodeSize:longint; 27 | end; 28 | 29 | function ComparePAnsiChar(a,b:pansichar):boolean; register; 30 | 31 | {$ifdef CreamTrackerGUI} 32 | procedure TRIStrip(RawCode:pointer;RawCodeSize:longint;var OutputData:pointer;var OutputSize:longint;GetNameCode:TGetNameCode); 33 | {$endif} 34 | function TRILink(RawCode:pointer;RawCodeSize:longint;Context:pointer;GetExternalPointer:TGetExternalPointer;SetPublicPointer:TSetPublicPointer):PTRIInstance; 35 | function TRIFree(Instance:PTRIInstance):boolean; 36 | 37 | implementation 38 | 39 | {$undef OldDelphi} 40 | {$ifndef fpc} 41 | {$ifdef conditionalexpressions} 42 | {$if CompilerVersion>=23.0} 43 | {$undef OldDelphi} 44 | type qword=uint64; 45 | ptruint=NativeUInt; 46 | ptrint=NativeInt; 47 | {$elseif true} 48 | {$define OldDelphi} 49 | {$ifend} 50 | {$else} 51 | {$define OldDelphi} 52 | {$endif} 53 | {$endif} 54 | {$ifdef OldDelphi} 55 | type qword=int64; 56 | {$ifdef cpu64} 57 | ptruint=qword; 58 | ptrint=int64; 59 | {$else} 60 | ptruint=longword; 61 | ptrint=longint; 62 | {$endif} 63 | {$endif} 64 | 65 | function ComparePAnsiChar(a,b:pansichar):boolean; register; 66 | var ac,bc:ansichar; 67 | begin 68 | result:=true; 69 | if assigned(a) and assigned(b) then begin 70 | while (a^<>#0) and (b^<>#0) do begin 71 | ac:=a^; 72 | bc:=b^; 73 | if ac in ['A'..'Z'] then begin 74 | inc(ac,ord('a')-ord('A')); 75 | end; 76 | if bc in ['A'..'Z'] then begin 77 | inc(bc,ord('a')-ord('A')); 78 | end; 79 | if ac<>bc then begin 80 | result:=false; 81 | break; 82 | end; 83 | inc(a); 84 | inc(b); 85 | end; 86 | if a^<>b^ then begin 87 | result:=false; 88 | end; 89 | end; 90 | end; 91 | 92 | {$ifdef CreamTrackerGUI} 93 | procedure TRIStrip(RawCode:pointer;RawCodeSize:longint;var OutputData:pointer;var OutputSize:longint;GetNameCode:TGetNameCode); 94 | var OutputAllocated:longint; 95 | function Write(const Src;Bytes:longint):longint; 96 | begin 97 | if (OutputSize+Bytes)>=OutputAllocated then begin 98 | while (OutputSize+Bytes)>=OutputAllocated do begin 99 | inc(OutputAllocated,OutputAllocated); 100 | end; 101 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 102 | ReallocMem(OutputData,OutputAllocated); 103 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 104 | end; 105 | Move(Src,PAnsiChar(OutputData)[OutputSize],Bytes); 106 | inc(OutputSize,Bytes); 107 | result:=Bytes; 108 | end; 109 | var ImageCodeSize,ImageSize,ImageRelocations,ImagePublics,i,Position,Len:longint; 110 | r,p:pansichar; 111 | t,Bits,Relative:byte; 112 | ExternalName,PublicName:pansichar; 113 | OutputImageRelocations,OutputImageRelocationsOffset,OutputImagePublics,OutputImagePublicsOffset:longint; 114 | NameCode:ansichar; 115 | begin 116 | OutputSize:=0; 117 | OutputAllocated:=65536; 118 | GetMem(OutputData,OutputAllocated); 119 | if assigned(RawCode) and (RawCodeSize>0) then begin 120 | if not ((pansichar(RawCode)[0]='T') and (pansichar(RawCode)[1]='R') and (pansichar(RawCode)[2]='I') and (pansichar(RawCode)[3]=#00)) then begin 121 | exit; 122 | end; 123 | Write(pansichar(RawCode)[0],4*SizeOf(ansichar)); 124 | ImageCodeSize:=longint(pointer(@pansichar(RawCode)[4])^); 125 | Write(ImageCodeSize,SizeOf(longint)); 126 | ImageSize:=longint(pointer(@pansichar(RawCode)[8])^); 127 | Write(ImageSize,SizeOf(longint)); 128 | ImageRelocations:=longint(pointer(@pansichar(RawCode)[12])^); 129 | Write(ImageRelocations,SizeOf(longint)); 130 | ImagePublics:=longint(pointer(@pansichar(RawCode)[16])^); 131 | Write(ImagePublics,SizeOf(longint)); 132 | Write(pansichar(RawCode)[20],4*SizeOf(ansichar)); 133 | Write(pansichar(RawCode)[24],4*SizeOf(ansichar)); 134 | r:=pointer(@pansichar(RawCode)[longint(pointer(@pansichar(RawCode)[20])^)]); 135 | p:=pointer(@pansichar(RawCode)[longint(pointer(@pansichar(RawCode)[24])^)]); 136 | Write(pointer(@pansichar(RawCode)[28])^,ImageCodeSize); 137 | OutputImageRelocations:=0; 138 | OutputImageRelocationsOffset:=OutputSize; 139 | for i:=1 to ImageRelocations do begin 140 | t:=byte(pointer(r)^); 141 | inc(r); 142 | case t of 143 | 1:begin 144 | // Relocation 145 | inc(OutputImageRelocations); 146 | Write(t,sizeof(byte)); 147 | Write(byte(pointer(r)^),sizeof(byte)); // Bits 148 | inc(r); 149 | Write(byte(pointer(r)^),sizeof(byte)); // Relative 150 | inc(r); 151 | Write(longint(pointer(r)^),sizeof(longint)); // Position 152 | inc(r,sizeof(longint)); 153 | end; 154 | 2:begin 155 | // External 156 | Bits:=byte(pointer(r)^); 157 | inc(r); 158 | Relative:=byte(pointer(r)^); 159 | inc(r); 160 | Position:=longint(pointer(r)^); 161 | inc(r,sizeof(longint)); 162 | Len:=longint(pointer(r)^); 163 | inc(r,sizeof(longint)); 164 | ExternalName:=pointer(r); 165 | inc(r,Len); 166 | if assigned(addr(GetNameCode)) then begin 167 | NameCode:=GetNameCode(ExternalName); 168 | end else begin 169 | NameCode:=#$00; 170 | end; 171 | if NameCode<>#$00 then begin 172 | inc(OutputImageRelocations); 173 | Write(t,sizeof(byte)); 174 | Write(Bits,sizeof(byte)); 175 | Write(Relative,sizeof(byte)); 176 | Write(Position,sizeof(longint)); 177 | Len:=2; 178 | Write(Len,sizeof(longint)); 179 | Write(NameCode,sizeof(ansichar)); 180 | NameCode:=#0; 181 | Write(NameCode,sizeof(ansichar)); 182 | end; 183 | end; 184 | 3:begin 185 | // Import 186 | inc(OutputImageRelocations); 187 | Write(t,sizeof(byte)); 188 | Write(byte(pointer(r)^),sizeof(byte)); // Bits 189 | inc(r); 190 | Write(byte(pointer(r)^),sizeof(byte)); // Relative 191 | inc(r); 192 | Write(longint(pointer(r)^),sizeof(longint)); // Position 193 | inc(r,sizeof(longint)); 194 | Len:=longint(pointer(r)^); 195 | Write(Len,sizeof(longint)); // Len 196 | inc(r,sizeof(longint)); 197 | Write(r^,Len); // LibName 198 | inc(r,Len); 199 | Len:=longint(pointer(r)^); 200 | Write(Len,sizeof(longint)); // Len 201 | inc(r,sizeof(longint)); 202 | Write(r^,Len); // LibImportName 203 | inc(r,Len); 204 | end; 205 | end; 206 | end; 207 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 208 | // Publics 209 | OutputImagePublics:=0; 210 | OutputImagePublicsOffset:=OutputSize; 211 | for i:=1 to ImagePublics do begin 212 | Len:=longint(pointer(p)^); 213 | inc(p,sizeof(longint)); 214 | PublicName:=p; 215 | inc(p,Len); 216 | Position:=longint(pointer(p)^); 217 | inc(p,sizeof(longint)); 218 | if assigned(addr(GetNameCode)) then begin 219 | NameCode:=GetNameCode(PublicName); 220 | end else begin 221 | NameCode:=#$00; 222 | end; 223 | if NameCode<>#$00 then begin 224 | inc(OutputImagePublics); 225 | Len:=2; 226 | Write(Len,sizeof(longint)); 227 | Write(NameCode,sizeof(ansichar)); 228 | NameCode:=#0; 229 | Write(NameCode,sizeof(ansichar)); 230 | Write(Position,sizeof(longint)); 231 | end; 232 | end; 233 | longint(pointer(@pansichar(OutputData)[12])^):=OutputImageRelocations; 234 | longint(pointer(@pansichar(OutputData)[16])^):=OutputImagePublics; 235 | longint(pointer(@pansichar(OutputData)[20])^):=OutputImageRelocationsOffset; 236 | longint(pointer(@pansichar(OutputData)[24])^):=OutputImagePublicsOffset; 237 | ReallocMem(OutputData,OutputSize); 238 | end; 239 | end; 240 | {$endif} 241 | 242 | function TRILink(RawCode:pointer;RawCodeSize:longint;Context:pointer;GetExternalPointer:TGetExternalPointer;SetPublicPointer:TSetPublicPointer):PTRIInstance; 243 | var ImageCodeSize,ImageSize,ImageRelocations,ImagePublics,i,Position,Len:longint; 244 | r,p,ExternalName,LibName,LibImportName,PublicName:pansichar; 245 | t,Bits:byte; 246 | Relative:boolean; 247 | ExternalPointer,LibImportPointer,ImageData:pointer; 248 | begin 249 | result:=nil; 250 | if assigned(RawCode) and (RawCodeSize>0) then begin 251 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 252 | if not ((pansichar(RawCode)[0]='T') and (pansichar(RawCode)[1]='R') and (pansichar(RawCode)[2]='I') and (pansichar(RawCode)[3]=#00)) then begin 253 | exit; 254 | end; 255 | ImageCodeSize:=longint(pointer(@pansichar(RawCode)[4])^); 256 | ImageSize:=longint(pointer(@pansichar(RawCode)[8])^); 257 | ImageRelocations:=longint(pointer(@pansichar(RawCode)[12])^); 258 | ImagePublics:=longint(pointer(@pansichar(RawCode)[16])^); 259 | r:=pointer(@pansichar(RawCode)[longint(pointer(@pansichar(RawCode)[20])^)]); 260 | p:=pointer(@pansichar(RawCode)[longint(pointer(@pansichar(RawCode)[24])^)]); 261 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 262 | GetMem(result,SizeOf(TTRIInstance)); 263 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 264 | {$ifdef CreamTrackerGUI} 265 | ImageData:=NativeCodeMemoryManagerInstance.GetMemory(ImageSize); 266 | {$else} 267 | ImageData:=VirtualAlloc(nil,ImageSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE); 268 | {$endif} 269 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 270 | result^.ImageData:=ImageData; 271 | result^.ImageSize:=ImageSize; 272 | result^.CodeSize:=ImageCodeSize; 273 | FillChar(ImageData^,ImageSize,AnsiChar(#0)); 274 | Move(pointer(@pansichar(RawCode)[28])^,ImageData^,ImageCodeSize); 275 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 276 | for i:=1 to ImageRelocations do begin 277 | t:=byte(pointer(r)^); 278 | inc(r); 279 | case t of 280 | 1:begin 281 | // Relocation 282 | Bits:=byte(pointer(r)^); 283 | inc(r); 284 | Relative:=byte(pointer(r)^)<>0; 285 | inc(r); 286 | Position:=longint(pointer(r)^); 287 | inc(r,sizeof(longint)); 288 | if not Relative then begin 289 | case Bits of 290 | 8:begin 291 | inc(byte(pointer(@pansichar(ImageData)[Position])^),ptruint(ImageData)); 292 | end; 293 | 16:begin 294 | inc(word(pointer(@pansichar(ImageData)[Position])^),ptruint(ImageData)); 295 | end; 296 | 32:begin 297 | inc(longword(pointer(@pansichar(ImageData)[Position])^),ptruint(ImageData)); 298 | end; 299 | 64:begin 300 | inc(int64(pointer(@pansichar(ImageData)[Position])^),ptruint(ImageData)); 301 | end; 302 | end; 303 | end; 304 | end; 305 | 2:begin 306 | // External 307 | Bits:=byte(pointer(r)^); 308 | inc(r); 309 | Relative:=byte(pointer(r)^)<>0; 310 | inc(r); 311 | Position:=longint(pointer(r)^); 312 | inc(r,sizeof(longint)); 313 | Len:=longint(pointer(r)^); 314 | inc(r,sizeof(longint)); 315 | ExternalName:=pointer(r); 316 | inc(r,Len); 317 | if assigned(@GetExternalPointer) then begin 318 | ExternalPointer:=GetExternalPointer(Context,ExternalName); 319 | end else begin 320 | ExternalPointer:=nil; 321 | end; 322 | if assigned(ExternalPointer) then begin 323 | if Relative then begin 324 | case Bits of 325 | 8:begin 326 | inc(byte(pointer(@pansichar(ImageData)[Position])^),ptruint(ExternalPointer)-ptruint(ImageData)); 327 | end; 328 | 16:begin 329 | inc(word(pointer(@pansichar(ImageData)[Position])^),ptruint(ExternalPointer)-ptruint(ImageData)); 330 | end; 331 | 32:begin 332 | inc(longword(pointer(@pansichar(ImageData)[Position])^),ptruint(ExternalPointer)-ptruint(ImageData)); 333 | end; 334 | 64:begin 335 | inc(int64(pointer(@pansichar(ImageData)[Position])^),ptruint(ExternalPointer)-ptruint(ImageData)); 336 | end; 337 | end; 338 | end else begin 339 | case Bits of 340 | 8:begin 341 | inc(byte(pointer(@pansichar(ImageData)[Position])^),ptruint(ExternalPointer)); 342 | end; 343 | 16:begin 344 | inc(word(pointer(@pansichar(ImageData)[Position])^),ptruint(ExternalPointer)); 345 | end; 346 | 32:begin 347 | inc(longword(pointer(@pansichar(ImageData)[Position])^),ptruint(ExternalPointer)); 348 | end; 349 | 64:begin 350 | inc(int64(pointer(@pansichar(ImageData)[Position])^),ptruint(ExternalPointer)); 351 | end; 352 | end; 353 | end; 354 | end; 355 | end; 356 | 3:begin 357 | // Import 358 | Bits:=byte(pointer(r)^); 359 | inc(r); 360 | Relative:=byte(pointer(r)^)<>0; 361 | inc(r); 362 | Position:=longint(pointer(r)^); 363 | inc(r,sizeof(longint)); 364 | Len:=longint(pointer(r)^); 365 | inc(r,sizeof(longint)); 366 | LibName:=r; 367 | inc(r,Len); 368 | Len:=longint(pointer(r)^); 369 | inc(r,sizeof(longint)); 370 | LibImportName:=r; 371 | inc(r,Len); 372 | LibImportPointer:=GetProcAddress(LoadLibraryA(LibName),LibImportName); 373 | if Relative then begin 374 | case Bits of 375 | 8:begin 376 | inc(byte(pointer(@pansichar(ImageData)[Position])^),ptruint(LibImportPointer)-ptruint(ImageData)); 377 | end; 378 | 16:begin 379 | inc(word(pointer(@pansichar(ImageData)[Position])^),ptruint(LibImportPointer)-ptruint(ImageData)); 380 | end; 381 | 32:begin 382 | inc(longword(pointer(@pansichar(ImageData)[Position])^),ptruint(LibImportPointer)-ptruint(ImageData)); 383 | end; 384 | 64:begin 385 | inc(int64(pointer(@pansichar(ImageData)[Position])^),ptruint(LibImportPointer)-ptruint(ImageData)); 386 | end; 387 | end; 388 | end else begin 389 | case Bits of 390 | 8:begin 391 | inc(byte(pointer(@pansichar(ImageData)[Position])^),ptruint(LibImportPointer)); 392 | end; 393 | 16:begin 394 | inc(word(pointer(@pansichar(ImageData)[Position])^),ptruint(LibImportPointer)); 395 | end; 396 | 32:begin 397 | inc(longword(pointer(@pansichar(ImageData)[Position])^),ptruint(LibImportPointer)); 398 | end; 399 | 64:begin 400 | inc(int64(pointer(@pansichar(ImageData)[Position])^),ptruint(LibImportPointer)); 401 | end; 402 | end; 403 | end; 404 | end; 405 | end; 406 | end; 407 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 408 | // Publics 409 | for i:=1 to ImagePublics do begin 410 | Len:=longint(pointer(p)^); 411 | inc(p,sizeof(longint)); 412 | PublicName:=p; 413 | inc(p,Len); 414 | Position:=longint(pointer(p)^); 415 | inc(p,sizeof(longint)); 416 | if assigned(@SetPublicPointer) then begin 417 | SetPublicPointer(Context,PublicName,pointer(@pansichar(ImageData)[Position])); 418 | end; 419 | end; 420 | end; 421 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 422 | end; 423 | 424 | function TRIFree(Instance:PTRIInstance):boolean; 425 | begin 426 | result:=assigned(Instance); 427 | if result then begin 428 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 429 | {$ifdef CreamTrackerGUI} 430 | NativeCodeMemoryManagerInstance.FreeMemory(Instance^.ImageData); 431 | {$else} 432 | VirtualFree(Instance^.ImageData,Instance^.ImageSize,MEM_DECOMMIT); 433 | {$endif} 434 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 435 | FreeMem(Instance); 436 | {$ifdef memdebug}ScanMemoryPoolForCorruptions;{$endif} 437 | end; 438 | end; 439 | {$hints on} 440 | 441 | end. -------------------------------------------------------------------------------- /src/sasm.dpr: -------------------------------------------------------------------------------- 1 | program sasm; 2 | 3 | {$IFDEF FPC} 4 | {$MODE Delphi} 5 | {$ENDIF} 6 | 7 | {$ifdef Win32} 8 | {$APPTYPE CONSOLE} 9 | {$endif} 10 | {$ifdef Win64} 11 | {$APPTYPE CONSOLE} 12 | {$endif} 13 | 14 | {%File 'SASMDataContent.inc'} 15 | {%File 'BESEN\BESEN.inc'} 16 | {%File 'SASM.inc'} 17 | 18 | uses 19 | SysUtils, 20 | PUCU in 'PUCU.pas', 21 | SASMCore in 'SASMCore.pas', 22 | SASMData in 'SASMData.pas'{$ifdef SASMBESEN}, 23 | BESEN in 'BESEN\BESEN.pas', 24 | BESENArrayUtils in 'BESEN\BESENArrayUtils.pas', 25 | BESENASTNodes in 'BESEN\BESENASTNodes.pas', 26 | BESENBaseObject in 'BESEN\BESENBaseObject.pas', 27 | BESENCharset in 'BESEN\BESENCharset.pas', 28 | BESENCode in 'BESEN\BESENCode.pas', 29 | BESENCodeContext in 'BESEN\BESENCodeContext.pas', 30 | BESENCodeGeneratorContext in 'BESEN\BESENCodeGeneratorContext.pas', 31 | BESENCodeJIT in 'BESEN\BESENCodeJIT.pas', 32 | BESENCodeJITx64 in 'BESEN\BESENCodeJITx64.pas', 33 | BESENCodeJITx86 in 'BESEN\BESENCodeJITx86.pas', 34 | BESENCodeSnapshot in 'BESEN\BESENCodeSnapshot.pas', 35 | BESENCollector in 'BESEN\BESENCollector.pas', 36 | BESENCollectorObject in 'BESEN\BESENCollectorObject.pas', 37 | BESENCompiler in 'BESEN\BESENCompiler.pas', 38 | BESENConstants in 'BESEN\BESENConstants.pas', 39 | BESENContext in 'BESEN\BESENContext.pas', 40 | BESENDateUtils in 'BESEN\BESENDateUtils.pas', 41 | BESENDeclarativeEnvironmentRecord in 'BESEN\BESENDeclarativeEnvironmentRecord.pas', 42 | BESENDecompiler in 'BESEN\BESENDecompiler.pas', 43 | BESENDoubleList in 'BESEN\BESENDoubleList.pas', 44 | BESENEnvironmentRecord in 'BESEN\BESENEnvironmentRecord.pas', 45 | BESENErrors in 'BESEN\BESENErrors.pas', 46 | BESENEvalCache in 'BESEN\BESENEvalCache.pas', 47 | BESENEvalCacheItem in 'BESEN\BESENEvalCacheItem.pas', 48 | BESENGarbageCollector in 'BESEN\BESENGarbageCollector.pas', 49 | BESENGlobals in 'BESEN\BESENGlobals.pas', 50 | BESENHashMap in 'BESEN\BESENHashMap.pas', 51 | BESENHashUtils in 'BESEN\BESENHashUtils.pas', 52 | BESENInt64SelfBalancedTree in 'BESEN\BESENInt64SelfBalancedTree.pas', 53 | BESENIntegerList in 'BESEN\BESENIntegerList.pas', 54 | BESENKeyIDManager in 'BESEN\BESENKeyIDManager.pas', 55 | BESENLexer in 'BESEN\BESENLexer.pas', 56 | BESENLexicalEnvironment in 'BESEN\BESENLexicalEnvironment.pas', 57 | BESENLocale in 'BESEN\BESENLocale.pas', 58 | BESENNativeCodeMemoryManager in 'BESEN\BESENNativeCodeMemoryManager.pas', 59 | BESENNativeObject in 'BESEN\BESENNativeObject.pas', 60 | BESENNumberUtils in 'BESEN\BESENNumberUtils.pas', 61 | BESENObject in 'BESEN\BESENObject.pas', 62 | BESENObjectArgGetterFunction in 'BESEN\BESENObjectArgGetterFunction.pas', 63 | BESENObjectArgSetterFunction in 'BESEN\BESENObjectArgSetterFunction.pas', 64 | BESENObjectArray in 'BESEN\BESENObjectArray.pas', 65 | BESENObjectArrayConstructor in 'BESEN\BESENObjectArrayConstructor.pas', 66 | BESENObjectArrayPrototype in 'BESEN\BESENObjectArrayPrototype.pas', 67 | BESENObjectBindingFunction in 'BESEN\BESENObjectBindingFunction.pas', 68 | BESENObjectBoolean in 'BESEN\BESENObjectBoolean.pas', 69 | BESENObjectBooleanConstructor in 'BESEN\BESENObjectBooleanConstructor.pas', 70 | BESENObjectBooleanPrototype in 'BESEN\BESENObjectBooleanPrototype.pas', 71 | BESENObjectConsole in 'BESEN\BESENObjectConsole.pas', 72 | BESENObjectConstructor in 'BESEN\BESENObjectConstructor.pas', 73 | BESENObjectDate in 'BESEN\BESENObjectDate.pas', 74 | BESENObjectDateConstructor in 'BESEN\BESENObjectDateConstructor.pas', 75 | BESENObjectDatePrototype in 'BESEN\BESENObjectDatePrototype.pas', 76 | BESENObjectDeclaredFunction in 'BESEN\BESENObjectDeclaredFunction.pas', 77 | BESENObjectEnvironmentRecord in 'BESEN\BESENObjectEnvironmentRecord.pas', 78 | BESENObjectError in 'BESEN\BESENObjectError.pas', 79 | BESENObjectErrorConstructor in 'BESEN\BESENObjectErrorConstructor.pas', 80 | BESENObjectErrorPrototype in 'BESEN\BESENObjectErrorPrototype.pas', 81 | BESENObjectFunction in 'BESEN\BESENObjectFunction.pas', 82 | BESENObjectFunctionArguments in 'BESEN\BESENObjectFunctionArguments.pas', 83 | BESENObjectFunctionConstructor in 'BESEN\BESENObjectFunctionConstructor.pas', 84 | BESENObjectFunctionPrototype in 'BESEN\BESENObjectFunctionPrototype.pas', 85 | BESENObjectGlobal in 'BESEN\BESENObjectGlobal.pas', 86 | BESENObjectJSON in 'BESEN\BESENObjectJSON.pas', 87 | BESENObjectMath in 'BESEN\BESENObjectMath.pas', 88 | BESENObjectNativeFunction in 'BESEN\BESENObjectNativeFunction.pas', 89 | BESENObjectNumber in 'BESEN\BESENObjectNumber.pas', 90 | BESENObjectNumberConstructor in 'BESEN\BESENObjectNumberConstructor.pas', 91 | BESENObjectNumberPrototype in 'BESEN\BESENObjectNumberPrototype.pas', 92 | BESENObjectPropertyDescriptor in 'BESEN\BESENObjectPropertyDescriptor.pas', 93 | BESENObjectPrototype in 'BESEN\BESENObjectPrototype.pas', 94 | BESENObjectRegExp in 'BESEN\BESENObjectRegExp.pas', 95 | BESENObjectRegExpConstructor in 'BESEN\BESENObjectRegExpConstructor.pas', 96 | BESENObjectRegExpPrototype in 'BESEN\BESENObjectRegExpPrototype.pas', 97 | BESENObjectString in 'BESEN\BESENObjectString.pas', 98 | BESENObjectStringConstructor in 'BESEN\BESENObjectStringConstructor.pas', 99 | BESENObjectStringPrototype in 'BESEN\BESENObjectStringPrototype.pas', 100 | BESENObjectThrowTypeErrorFunction in 'BESEN\BESENObjectThrowTypeErrorFunction.pas', 101 | BESENOpcodes in 'BESEN\BESENOpcodes.pas', 102 | BESENParser in 'BESEN\BESENParser.pas', 103 | BESENPointerList in 'BESEN\BESENPointerList.pas', 104 | BESENPointerSelfBalancedTree in 'BESEN\BESENPointerSelfBalancedTree.pas', 105 | BESENRandomGenerator in 'BESEN\BESENRandomGenerator.pas', 106 | BESENRegExp in 'BESEN\BESENRegExp.pas', 107 | BESENRegExpCache in 'BESEN\BESENRegExpCache.pas', 108 | BESENScope in 'BESEN\BESENScope.pas', 109 | BESENSelfBalancedTree in 'BESEN\BESENSelfBalancedTree.pas', 110 | BESENStringList in 'BESEN\BESENStringList.pas', 111 | BESENStringTree in 'BESEN\BESENStringTree.pas', 112 | BESENStringUtils in 'BESEN\BESENStringUtils.pas', 113 | BESENTypes in 'BESEN\BESENTypes.pas', 114 | BESENUnicodeTables in 'BESEN\BESENUnicodeTables.pas', 115 | BESENUtils in 'BESEN\BESENUtils.pas', 116 | BESENValue in 'BESEN\BESENValue.pas', 117 | BESENValueContainer in 'BESEN\BESENValueContainer.pas', 118 | BESENVersionConstants in 'BESEN\BESENVersionConstants.pas'{$endif}; 119 | 120 | var ASMx86:TAssembler; 121 | SrcFileName,DstFileName,Defines,LastStatus,StatusTitle:ansistring; 122 | StatusOldLen:longint; 123 | 124 | procedure ParseParameter; 125 | var i,m{,c,o}:longint; 126 | p:boolean; 127 | s,l:ansistring; 128 | begin 129 | if ParamCount<>0 then begin 130 | m:=0; 131 | for i:=1 to ParamCount do begin 132 | s:=ParamStr(i); 133 | if length(s)>0 then begin 134 | if not (s[1] in ['-','+','/']) then begin 135 | case m of 136 | 0:begin 137 | SrcFileName:=s; 138 | end; 139 | 1:begin 140 | DstFileName:=s; 141 | end; 142 | end; 143 | inc(m); 144 | end else begin 145 | p:=true; 146 | case s[1] of 147 | '+','/':p:=true; 148 | '-':p:=false; 149 | end; 150 | l:=copy(s,2,length(s)-1); 151 | s:=UpperCase(l); 152 | if Pos('D',s)=1 then begin 153 | l:=copy(s,2,length(s)-1); 154 | if Pos('=',s)>0 then begin 155 | Defines:=Defines+l+#13; 156 | end else begin 157 | if p then begin 158 | Defines:=Defines+l+'=1'+#13; 159 | end else begin 160 | Defines:=Defines+l+'=0'+#13; 161 | end; 162 | end; 163 | end; 164 | end; 165 | end; 166 | end; 167 | end else begin 168 | SrcFileName:=''; 169 | DstFileName:=''; 170 | end; 171 | end; 172 | 173 | procedure StatusProc(s:ansistring); 174 | var Counter,StatusLen:longint; 175 | begin 176 | if s<>LastStatus then begin 177 | StatusLen:=length(StatusTitle)+length(s); 178 | write(#13,StatusTitle,s); 179 | for Counter:=1 to StatusOldLen-StatusLen do begin 180 | write(' '); 181 | end; 182 | StatusOldLen:=StatusLen; 183 | LastStatus:=s; 184 | end; 185 | end; 186 | 187 | begin 188 | 189 | writeln('SASM - Scriptable Assembler - Version '+SASMVersionString); 190 | writeln(SASMCopyrightString); 191 | 192 | SrcFileName:=''; 193 | DstFileName:=''; 194 | Defines:=''; 195 | LastStatus:=''; 196 | StatusOldLen:=0; 197 | 198 | ParseParameter; 199 | 200 | if length(SrcFileName)>0 then begin 201 | if not FileExists(SrcFileName) then begin 202 | SrcFileName:=ChangeFileExt(SrcFileName,'.asm'); 203 | end; 204 | //SrcFileName:=GetAbsoluteFile(GetCurrentDir,SrcFileName); 205 | if FileExists(SrcFileName) then begin 206 | if length(DstFileName)=0 then begin 207 | DstFileName:=ChangeFileExt(SrcFileName,'.bin'); 208 | end; 209 | end; 210 | writeln('Assembling "'+SrcFileName+'" to "'+DstFileName+'" . . .'); 211 | ASMx86:=TAssembler.Create; 212 | try 213 | ASMx86.Status:=StatusProc; 214 | LastStatus:=''; 215 | StatusTitle:='Reading . . . '; 216 | if length(Defines)>0 then begin 217 | ASMx86.ParseDefines(Defines); 218 | end; 219 | ASMx86.ParseFile(SrcFileName); 220 | LastStatus:=''; 221 | StatusTitle:='Assembling . . . '; 222 | ASMx86.WriteFile(DstFileName); 223 | if ASMx86.AreErrors then begin 224 | StatusTitle:='Errors ! ! !'; 225 | end else begin 226 | StatusTitle:='Done ! ! !'; 227 | end; 228 | StatusProc(''); 229 | writeln; 230 | if ASMx86.AreErrors then begin 231 | writeln(ASMx86.Errors); 232 | end; 233 | if ASMx86.AreWarnings then begin 234 | writeln(ASMx86.Warnings); 235 | end; 236 | finally 237 | ASMx86.Free; 238 | end; 239 | end else begin 240 | writeln(' Usage: '+UPPERCASE(ChangeFileExt(ExtractFileName(PARAMSTR(0)),''))+' [infile] [outfile] [-|+|/|options]'); 241 | writeln('Options: +Dx=y = Define a constant symbol x with value x'); 242 | writeln(' +Dx = Define a constant symbol x with value 1'); 243 | writeln(' -Dx = Define a constant symbol x with value 0'); 244 | end; 245 | writeln; 246 | {$ifndef fpc} 247 | if DebugHook<>0 then begin 248 | readln; 249 | end; 250 | {$endif} 251 | end. 252 | -------------------------------------------------------------------------------- /src/sasm.lpi: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | <UseAppBundle Value="False"/> 16 | <ResourceType Value="res"/> 17 | </General> 18 | <BuildModes Count="1"> 19 | <Item1 Name="Default" Default="True"/> 20 | </BuildModes> 21 | <PublishOptions> 22 | <Version Value="2"/> 23 | </PublishOptions> 24 | <RunParams> 25 | <local> 26 | <FormatVersion Value="1"/> 27 | <CommandLineParams Value="elf64.asm"/> 28 | <WorkingDirectory Value="D:\GitHubSVN\SASM.github\trunk\examples"/> 29 | </local> 30 | </RunParams> 31 | <RequiredPackages Count="1"> 32 | <Item1> 33 | <PackageName Value="LCL"/> 34 | </Item1> 35 | </RequiredPackages> 36 | <Units Count="4"> 37 | <Unit0> 38 | <Filename Value="sasm.dpr"/> 39 | <IsPartOfProject Value="True"/> 40 | </Unit0> 41 | <Unit1> 42 | <Filename Value="SASMCore.pas"/> 43 | <IsPartOfProject Value="True"/> 44 | </Unit1> 45 | <Unit2> 46 | <Filename Value="SASMData.pas"/> 47 | <IsPartOfProject Value="True"/> 48 | </Unit2> 49 | <Unit3> 50 | <Filename Value="PUCU.pas"/> 51 | <IsPartOfProject Value="True"/> 52 | </Unit3> 53 | </Units> 54 | </ProjectOptions> 55 | <CompilerOptions> 56 | <Version Value="11"/> 57 | <PathDelim Value="\"/> 58 | <Target> 59 | <Filename Value="../bin/sasm"/> 60 | </Target> 61 | <SearchPaths> 62 | <IncludeFiles Value="$(ProjOutDir)"/> 63 | </SearchPaths> 64 | <Parsing> 65 | <SyntaxOptions> 66 | <SyntaxMode Value="Delphi"/> 67 | </SyntaxOptions> 68 | </Parsing> 69 | <CodeGeneration> 70 | <TargetCPU Value="x86_64"/> 71 | </CodeGeneration> 72 | <Linking> 73 | <Debugging> 74 | <UseExternalDbgSyms Value="True"/> 75 | </Debugging> 76 | </Linking> 77 | <Other> 78 | <CustomOptions Value="-dSASMBESEN"/> 79 | </Other> 80 | </CompilerOptions> 81 | <Debugging> 82 | <Exceptions Count="3"> 83 | <Item1> 84 | <Name Value="EAbort"/> 85 | </Item1> 86 | <Item2> 87 | <Name Value="ECodetoolError"/> 88 | </Item2> 89 | <Item3> 90 | <Name Value="EFOpenError"/> 91 | </Item3> 92 | </Exceptions> 93 | </Debugging> 94 | </CONFIG> 95 | -------------------------------------------------------------------------------- /src/x86conv.lpi: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <CONFIG> 3 | <ProjectOptions> 4 | <Version Value="9"/> 5 | <PathDelim Value="\"/> 6 | <General> 7 | <Flags> 8 | <MainUnitHasUsesSectionForAllUnits Value="False"/> 9 | <MainUnitHasCreateFormStatements Value="False"/> 10 | <MainUnitHasTitleStatement Value="False"/> 11 | </Flags> 12 | <SessionStorage Value="InProjectDir"/> 13 | <MainUnit Value="0"/> 14 | <Title Value="x86conv"/> 15 | <UseAppBundle Value="False"/> 16 | <ResourceType Value="res"/> 17 | </General> 18 | <BuildModes Count="1"> 19 | <Item1 Name="Default" Default="True"/> 20 | </BuildModes> 21 | <PublishOptions> 22 | <Version Value="2"/> 23 | </PublishOptions> 24 | <RunParams> 25 | <local> 26 | <FormatVersion Value="1"/> 27 | </local> 28 | </RunParams> 29 | <RequiredPackages Count="1"> 30 | <Item1> 31 | <PackageName Value="LCL"/> 32 | </Item1> 33 | </RequiredPackages> 34 | <Units Count="1"> 35 | <Unit0> 36 | <Filename Value="x86conv.dpr"/> 37 | <IsPartOfProject Value="True"/> 38 | </Unit0> 39 | </Units> 40 | </ProjectOptions> 41 | <CompilerOptions> 42 | <Version Value="11"/> 43 | <PathDelim Value="\"/> 44 | <Parsing> 45 | <SyntaxOptions> 46 | <SyntaxMode Value="delphi"/> 47 | </SyntaxOptions> 48 | </Parsing> 49 | </CompilerOptions> 50 | <Debugging> 51 | <Exceptions Count="3"> 52 | <Item1> 53 | <Name Value="EAbort"/> 54 | </Item1> 55 | <Item2> 56 | <Name Value="ECodetoolError"/> 57 | </Item2> 58 | <Item3> 59 | <Name Value="EFOpenError"/> 60 | </Item3> 61 | </Exceptions> 62 | </Debugging> 63 | </CONFIG> 64 | -------------------------------------------------------------------------------- /src/x86format.dpr: -------------------------------------------------------------------------------- 1 | program x86conv; 2 | 3 | {$IFDEF FPC} 4 | {$MODE Delphi} 5 | {$ENDIF} 6 | 7 | {$ifdef Win32} 8 | {$APPTYPE CONSOLE} 9 | {$endif} 10 | {$ifdef Win64} 11 | {$APPTYPE CONSOLE} 12 | {$endif} 13 | 14 | uses 15 | SysUtils, 16 | Classes, 17 | Math; 18 | 19 | procedure ParseStringIntoStringList(const StringList:TStringList;const StringValue:ansistring); 20 | var StringPosition,StringLength:longint; 21 | Line:ansistring; 22 | CurrentChar:ansichar; 23 | begin 24 | StringPosition:=1; 25 | StringLength:=length(StringValue); 26 | Line:=''; 27 | while StringPosition<=StringLength do begin 28 | CurrentChar:=StringValue[StringPosition]; 29 | case CurrentChar of 30 | #10:begin 31 | StringList.Add(Line); 32 | Line:=''; 33 | end; 34 | #13:begin 35 | end; 36 | else begin 37 | Line:=Line+CurrentChar; 38 | end; 39 | end; 40 | inc(StringPosition); 41 | end; 42 | if length(Line)>0 then begin 43 | StringList.Add(Line); 44 | end; 45 | end; 46 | 47 | type TChars=set of ansichar; 48 | 49 | function Parse(const s:ansistring;const c:TChars;var Position:longint;const DoContinue:boolean):ansistring; 50 | var StartPosition,EndPosition,StringLength:longint; 51 | begin 52 | StartPosition:=Position; 53 | EndPosition:=Position-1; 54 | StringLength:=length(s); 55 | while Position<=StringLength do begin 56 | if s[Position] in c then begin 57 | EndPosition:=Position-1; 58 | inc(Position); 59 | if DoContinue then begin 60 | while (Position<=StringLength) and (s[Position] in c) do begin 61 | inc(Position); 62 | end; 63 | end; 64 | break; 65 | end else begin 66 | EndPosition:=Position; 67 | inc(Position); 68 | end; 69 | end; 70 | result:=copy(s,StartPosition,(EndPosition-StartPosition)+1); 71 | end; 72 | 73 | procedure Formatx86Ins; 74 | var Lines,NewLines:TStringList; 75 | LineIndex,i,j:longint; 76 | Line,Opcode,Operands,OperandEncoding,OperandTuple,Sequence,Flags:ansistring; 77 | MaxOpcodeLen,MaxOperandsLen,MaxSequenceLen:longint; 78 | begin 79 | MaxOpcodeLen:=0; 80 | MaxOperandsLen:=0; 81 | MaxSequenceLen:=0; 82 | Lines:=TStringList.Create; 83 | NewLines:=TStringList.Create; 84 | try 85 | Lines.LoadFromFile('x86ins.txt'); 86 | 87 | for LineIndex:=0 to Lines.Count-1 do begin 88 | Line:=StringReplace(trim(Lines[LineIndex]),#9,#32,[rfReplaceAll]); 89 | 90 | repeat 91 | i:=pos(';',Line); 92 | if i>0 then begin 93 | Line:=trim(copy(Line,1,i-1)); 94 | end else begin 95 | i:=pos('#',Line); 96 | if i>0 then begin 97 | Line:=trim(copy(Line,1,i-1)); 98 | end else begin 99 | break; 100 | end; 101 | end; 102 | until false; 103 | 104 | if length(Line)=0 then begin 105 | continue; 106 | end; 107 | 108 | i:=1; 109 | 110 | Opcode:=trim(Parse(Line,[#1..#32],i,true)); 111 | Operands:=trim(Parse(Line,[#1..#32],i,true)); 112 | Parse(Line,['['],i,true); 113 | Sequence:=trim(Parse(Line,[']'],i,true)); 114 | j:=pos(':',Sequence); 115 | if j>0 then begin 116 | OperandEncoding:=copy(Sequence,1,j-1); 117 | Delete(Sequence,1,j); 118 | Sequence:=trim(Sequence); 119 | j:=pos(':',Sequence); 120 | if j>0 then begin 121 | OperandTuple:=copy(Sequence,1,j-1); 122 | Delete(Sequence,1,j); 123 | Sequence:=trim(Sequence); 124 | end else begin 125 | OperandTuple:=''; 126 | end; 127 | end else begin 128 | OperandEncoding:=''; 129 | OperandTuple:=''; 130 | end; 131 | while length(OperandEncoding)<4 do begin 132 | OperandEncoding:=' '+OperandEncoding; 133 | end; 134 | while length(OperandTuple)<5 do begin 135 | OperandTuple:=' '+OperandTuple; 136 | end; 137 | Sequence:='['+OperandEncoding+': '+OperandTuple+': '+Sequence+']'; 138 | Parse(Line,[#1..#32],i,true); 139 | Flags:=trim(Parse(Line,[#1..#32],i,true)); 140 | 141 | MaxOpcodeLen:=max(MaxOpcodeLen,length(Opcode)); 142 | MaxOperandsLen:=max(MaxOperandsLen,length(Operands)); 143 | MaxSequenceLen:=max(MaxSequenceLen,length(Sequence)); 144 | end; 145 | 146 | for LineIndex:=0 to Lines.Count-1 do begin 147 | Line:=StringReplace(trim(Lines[LineIndex]),#9,#32,[rfReplaceAll]); 148 | 149 | repeat 150 | i:=pos(';',Line); 151 | if i>0 then begin 152 | Line:=trim(copy(Line,1,i-1)); 153 | end else begin 154 | i:=pos('#',Line); 155 | if i>0 then begin 156 | Line:=trim(copy(Line,1,i-1)); 157 | end else begin 158 | break; 159 | end; 160 | end; 161 | until false; 162 | 163 | if length(Line)=0 then begin 164 | continue; 165 | end; 166 | 167 | i:=1; 168 | 169 | Opcode:=trim(Parse(Line,[#1..#32],i,true)); 170 | if (Opcode='DB') or 171 | (Opcode='DW') or 172 | (Opcode='DD') or 173 | (Opcode='DQ') or 174 | (Opcode='DT') or 175 | (Opcode='DO') or 176 | (Opcode='DY') or 177 | (Opcode='DZ') or 178 | (Opcode='RESB') or 179 | (Opcode='RESW') or 180 | (Opcode='RESD') or 181 | (Opcode='RESQ') or 182 | (Opcode='REST') or 183 | (Opcode='RESO') or 184 | (Opcode='RESY') or 185 | (Opcode='RESZ') or 186 | (Opcode='EQU') or 187 | (Opcode='INCBIN') then begin 188 | continue; 189 | end; 190 | 191 | Operands:=trim(Parse(Line,[#1..#32],i,true)); 192 | Parse(Line,['['],i,true); 193 | 194 | Sequence:=trim(Parse(Line,[']'],i,true)); 195 | 196 | j:=pos(':',Sequence); 197 | if j>0 then begin 198 | OperandEncoding:=copy(Sequence,1,j-1); 199 | Delete(Sequence,1,j); 200 | Sequence:=trim(Sequence); 201 | j:=pos(':',Sequence); 202 | if j>0 then begin 203 | OperandTuple:=copy(Sequence,1,j-1); 204 | Delete(Sequence,1,j); 205 | Sequence:=trim(Sequence); 206 | end else begin 207 | OperandTuple:=''; 208 | end; 209 | end else begin 210 | OperandEncoding:=''; 211 | OperandTuple:=''; 212 | end; 213 | while length(OperandEncoding)<4 do begin 214 | OperandEncoding:=' '+OperandEncoding; 215 | end; 216 | while length(OperandTuple)<5 do begin 217 | OperandTuple:=' '+OperandTuple; 218 | end; 219 | Sequence:='['+OperandEncoding+': '+OperandTuple+': '+Sequence+']'; 220 | Parse(Line,[#1..#32],i,true); 221 | Flags:=trim(Parse(Line,[#1..#32],i,true)); 222 | 223 | while length(Opcode)<MaxOpcodeLen do begin 224 | Opcode:=Opcode+' '; 225 | end; 226 | while length(Operands)<MaxOperandsLen do begin 227 | Operands:=Operands+' '; 228 | end; 229 | delete(Sequence,length(Sequence),1); 230 | while length(Sequence)<(MaxSequenceLen-1) do begin 231 | Sequence:=Sequence+' '; 232 | end; 233 | Sequence:=Sequence+']'; 234 | 235 | NewLines.Add(trim(Opcode+' '+Operands+' '+Sequence+' '+Flags)); 236 | 237 | end; 238 | 239 | NewLines.SaveToFile('x86ins.txt'); 240 | 241 | finally 242 | NewLines.Free; 243 | Lines.Free; 244 | end; 245 | end; 246 | 247 | procedure Formatx86Regs; 248 | var Lines,NewLines:TStringList; 249 | LineIndex,i:longint; 250 | Line,RegisterName,RegisterClass,RegisterNumber,Flags:ansistring; 251 | MaxRegisterNameLen,MaxRegisterClassLen,MaxRegisterNumberLen:longint; 252 | begin 253 | MaxRegisterNameLen:=0; 254 | MaxRegisterClassLen:=0; 255 | MaxRegisterNumberLen:=0; 256 | Lines:=TStringList.Create; 257 | NewLines:=TStringList.Create; 258 | try 259 | Lines.LoadFromFile('x86regs.txt'); 260 | 261 | for LineIndex:=0 to Lines.Count-1 do begin 262 | Line:=StringReplace(trim(Lines[LineIndex]),#9,#32,[rfReplaceAll]); 263 | 264 | repeat 265 | i:=pos(';',Line); 266 | if i>0 then begin 267 | Line:=trim(copy(Line,1,i-1)); 268 | end else begin 269 | i:=pos('#',Line); 270 | if i>0 then begin 271 | Line:=trim(copy(Line,1,i-1)); 272 | end else begin 273 | break; 274 | end; 275 | end; 276 | until false; 277 | 278 | if length(Line)=0 then begin 279 | continue; 280 | end; 281 | 282 | i:=1; 283 | 284 | RegisterName:=trim(Parse(Line,[#1..#32],i,true)); 285 | RegisterClass:=trim(Parse(Line,[#1..#32],i,true)); 286 | //Parse(Line,[#1..#32],i,true); 287 | RegisterNumber:=trim(Parse(Line,[#1..#32],i,true)); 288 | Flags:=trim(Parse(Line,[#1..#32],i,true)); 289 | 290 | MaxRegisterNameLen:=max(MaxRegisterNameLen,length(RegisterName)); 291 | MaxRegisterClassLen:=max(MaxRegisterClassLen,length(RegisterClass)); 292 | MaxRegisterNumberLen:=max(MaxRegisterNumberLen,length(RegisterNumber)); 293 | end; 294 | 295 | for LineIndex:=0 to Lines.Count-1 do begin 296 | Line:=StringReplace(trim(Lines[LineIndex]),#9,#32,[rfReplaceAll]); 297 | 298 | repeat 299 | i:=pos(';',Line); 300 | if i>0 then begin 301 | Line:=trim(copy(Line,1,i-1)); 302 | end else begin 303 | i:=pos('#',Line); 304 | if i>0 then begin 305 | Line:=trim(copy(Line,1,i-1)); 306 | end else begin 307 | break; 308 | end; 309 | end; 310 | until false; 311 | 312 | if length(Line)=0 then begin 313 | continue; 314 | end; 315 | 316 | i:=1; 317 | 318 | RegisterName:=trim(Parse(Line,[#1..#32],i,true)); 319 | RegisterClass:=trim(Parse(Line,[#1..#32],i,true)); 320 | //Parse(Line,[#1..#32],i,true); 321 | RegisterNumber:=trim(Parse(Line,[#1..#32],i,true)); 322 | Flags:=trim(Parse(Line,[#1..#32],i,true)); 323 | 324 | while length(RegisterName)<MaxRegisterNameLen do begin 325 | RegisterName:=RegisterName+' '; 326 | end; 327 | while length(RegisterClass)<MaxRegisterClassLen do begin 328 | RegisterClass:=RegisterClass+' '; 329 | end; 330 | while length(RegisterNumber)<MaxRegisterNumberLen do begin 331 | RegisterNumber:=RegisterNumber+' '; 332 | end; 333 | 334 | NewLines.Add(trim(RegisterName+' '+RegisterClass+' '+RegisterNumber+' '+Flags)); 335 | 336 | end; 337 | 338 | NewLines.SaveToFile('x86regs.txt'); 339 | 340 | finally 341 | NewLines.Free; 342 | Lines.Free; 343 | end; 344 | end; 345 | 346 | procedure Formatx86Keywords; 347 | var Lines,NewLines:TStringList; 348 | LineIndex:longint; 349 | Line:ansistring; 350 | begin 351 | Lines:=TStringList.Create; 352 | NewLines:=TStringList.Create; 353 | try 354 | Lines.LoadFromFile('x86keywords.txt'); 355 | for LineIndex:=0 to Lines.Count-1 do begin 356 | Line:=Uppercase(StringReplace(trim(Lines[LineIndex]),#9,#32,[rfReplaceAll])); 357 | if length(Line)>0 then begin 358 | NewLines.Add(Line); 359 | end; 360 | end; 361 | NewLines.SaveToFile('x86keywords.txt'); 362 | finally 363 | NewLines.Free; 364 | Lines.Free; 365 | end; 366 | end; 367 | 368 | begin 369 | Formatx86Ins; 370 | Formatx86Regs; 371 | Formatx86Keywords; 372 | end. 373 | -------------------------------------------------------------------------------- /src/x86format.lpi: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <CONFIG> 3 | <ProjectOptions> 4 | <Version Value="9"/> 5 | <PathDelim Value="\"/> 6 | <General> 7 | <Flags> 8 | <MainUnitHasUsesSectionForAllUnits Value="False"/> 9 | <MainUnitHasCreateFormStatements Value="False"/> 10 | <MainUnitHasTitleStatement Value="False"/> 11 | </Flags> 12 | <SessionStorage Value="InProjectDir"/> 13 | <MainUnit Value="0"/> 14 | <Title Value="x86format"/> 15 | <UseAppBundle Value="False"/> 16 | <ResourceType Value="res"/> 17 | </General> 18 | <VersionInfo> 19 | <StringTable ProductVersion=""/> 20 | </VersionInfo> 21 | <BuildModes Count="1"> 22 | <Item1 Name="Default" Default="True"/> 23 | </BuildModes> 24 | <PublishOptions> 25 | <Version Value="2"/> 26 | </PublishOptions> 27 | <RunParams> 28 | <local> 29 | <FormatVersion Value="1"/> 30 | </local> 31 | </RunParams> 32 | <RequiredPackages Count="1"> 33 | <Item1> 34 | <PackageName Value="LCL"/> 35 | </Item1> 36 | </RequiredPackages> 37 | <Units Count="1"> 38 | <Unit0> 39 | <Filename Value="x86format.dpr"/> 40 | <IsPartOfProject Value="True"/> 41 | <UnitName Value="x86conv"/> 42 | </Unit0> 43 | </Units> 44 | </ProjectOptions> 45 | <CompilerOptions> 46 | <Version Value="11"/> 47 | <PathDelim Value="\"/> 48 | <Parsing> 49 | <SyntaxOptions> 50 | <SyntaxMode Value="delphi"/> 51 | </SyntaxOptions> 52 | </Parsing> 53 | </CompilerOptions> 54 | <Debugging> 55 | <Exceptions Count="3"> 56 | <Item1> 57 | <Name Value="EAbort"/> 58 | </Item1> 59 | <Item2> 60 | <Name Value="ECodetoolError"/> 61 | </Item2> 62 | <Item3> 63 | <Name Value="EFOpenError"/> 64 | </Item3> 65 | </Exceptions> 66 | </Debugging> 67 | </CONFIG> 68 | -------------------------------------------------------------------------------- /src/x86keywords.txt: -------------------------------------------------------------------------------- 1 | ABS EXPRESSION 2 | ADDRESS EXPRESSION 3 | ALIGN DIRECTIVE 4 | BITS DIRECTIVE 5 | BYTE EXPRESSION STRUCT 6 | BYTEDIFF DIRECTIVE 7 | CODE DIRECTIVE 8 | COMMENT DIRECTIVE 9 | CPU DIRECTIVE 10 | DB PSEUDOOP 11 | DD PSEUDOOP 12 | DDQ PSEUDOOP 13 | DEFAULT DIRECTIVE 14 | DEFINE DIRECTIVE 15 | DIRECTORYENTRY DIRECTIVE 16 | DISPLACEMENT EXPRESSION 17 | DO PSEUDOOP 18 | DOUBLE EXPRESSION STRUCT 19 | DQ PSEUDOOP 20 | DQWORD EXPRESSION STRUCT 21 | DSTR PSEUDOOP 22 | DT PSEUDOOP 23 | DUP DATAPSEUDOOP 24 | DW PSEUDOOP 25 | DWORD EXPRESSION STRUCT 26 | DWSTR PSEUDOOP 27 | DY PSEUDOOP 28 | DZ PSEUDOOP 29 | ELSE DIRECTIVE 30 | END DIRECTIVE 31 | ENTRYPOINT DIRECTIVE 32 | EQU EQU 33 | ERROR DIRECTIVE 34 | EXPORT DIRECTIVE 35 | EXTENDED EXPRESSION STRUCT 36 | EXTERNAL DIRECTIVE 37 | FAR EXPRESSION 38 | FLOAT EXPRESSION STRUCT 39 | IF DIRECTIVE IFELSE 40 | IMPORT DIRECTIVE 41 | INCBIN DIRECTIVE 42 | INCLUDE DIRECTIVE 43 | LIBRARY DIRECTIVE 44 | LONG EXPRESSION STRUCT 45 | MACRO DIRECTIVE 46 | NEAR EXPRESSION 47 | NOSPLIT EXPRESSION 48 | OFFSET DIRECTIVE EXPRESSION 49 | OFS16 EXPRESSION 50 | OPTIMIZE DIRECTIVE 51 | ORG DIRECTIVE 52 | OWORD EXPRESSION STRUCT 53 | PARSE DIRECTIVE 54 | PTR EXPRESSION 55 | PUBLIC DIRECTIVE 56 | QWORD EXPRESSION STRUCT 57 | REL EXPRESSION 58 | REPEAT DIRECTIVE 59 | RESB PSEUDOOP 60 | RESD PSEUDOOP 61 | RESDQ PSEUDOOP 62 | RESO PSEUDOOP 63 | RESQ PSEUDOOP 64 | REST PSEUDOOP 65 | RESW PSEUDOOP 66 | RESY PSEUDOOP 67 | RESZ PSEUDOOP 68 | SCRIPT DIRECTIVE 69 | SECTION DIRECTIVE 70 | SEG16 EXPRESSION 71 | SEGMENT DIRECTIVE 72 | SET DIRECTIVE 73 | SHORT EXPRESSION 74 | SMARTLINK DIRECTIVE 75 | STARTOFFSET DIRECTIVE 76 | STRICT EXPRESSION 77 | STRUCT DIRECTIVE 78 | TARGET DIRECTIVE 79 | TIMES PSEUDOOP 80 | TO EXPRESSION 81 | TWORD EXPRESSION STRUCT 82 | UNMACRO DIRECTIVE 83 | USE16 DIRECTIVE 84 | USE32 DIRECTIVE 85 | USE64 DIRECTIVE 86 | WARNING DIRECTIVE 87 | WHILE DIRECTIVE 88 | WORD EXPRESSION STRUCT 89 | XMMWORD EXPRESSION STRUCT 90 | YMMWORD EXPRESSION STRUCT 91 | YWORD EXPRESSION STRUCT 92 | ZMMWORD EXPRESSION STRUCT 93 | ZWORD EXPRESSION STRUCT 94 | __BASE__ EXPRESSION 95 | __COUNTER__ EXPRESSION 96 | __DEFINED__ EXPRESSION 97 | __EVAL__ EXPRESSION 98 | __FLOAT128__ EXPRESSION 99 | __FLOAT16__ EXPRESSION 100 | __FLOAT256__ EXPRESSION 101 | __FLOAT32__ EXPRESSION 102 | __FLOAT512__ EXPRESSION 103 | __FLOAT64__ EXPRESSION 104 | __FLOAT80__ EXPRESSION 105 | __FLOAT8__ EXPRESSION 106 | __GOTOFF__ EXPRESSION 107 | __GOTPC__ EXPRESSION 108 | __GOTTPOFF__ EXPRESSION 109 | __GOT__ EXPRESSION 110 | __HERE__ EXPRESSION 111 | __INTEGER__ EXPRESSION 112 | __NOBASE__ EXPRESSION 113 | __NO_RELOCATION__ EXPRESSION 114 | __PARAMETER__ EXPRESSION 115 | __PLT__ EXPRESSION 116 | __RAWINT__ EXPRESSION 117 | __RELOCATION__ EXPRESSION 118 | __STRCOPY__ EXPRESSION 119 | __STRING__ EXPRESSION 120 | __STRLEN__ EXPRESSION 121 | __SYM__ EXPRESSION 122 | __TLSIE__ EXPRESSION 123 | __UTF16BE__ EXPRESSION 124 | __UTF16LE__ EXPRESSION 125 | __UTF16__ EXPRESSION 126 | __UTF32BE__ EXPRESSION 127 | __UTF32LE__ EXPRESSION 128 | __UTF32__ EXPRESSION 129 | __UTF8__ EXPRESSION 130 | __VALUE___ EXPRESSION 131 | -------------------------------------------------------------------------------- /src/x86prefixes.txt: -------------------------------------------------------------------------------- 1 | a16 2 | a32 3 | a64 4 | asp 5 | lock 6 | o16 7 | o32 8 | o64 9 | osp 10 | rep 11 | repe 12 | repne 13 | repnz 14 | repz 15 | wait 16 | xacquire 17 | xrelease 18 | bnd 19 | nobnd 20 | evex 21 | vex3 22 | vex2 -------------------------------------------------------------------------------- /src/x86regs.txt: -------------------------------------------------------------------------------- 1 | al REG_AL 0 2 | ah REG_HIGH 4 3 | ax REG_AX 0 4 | eax REG_EAX 0 5 | rax REG_RAX 0 6 | bl REG8NA 3 7 | bh REG_HIGH 7 8 | bx REG16NA 3 9 | ebx REG32NA 3 10 | rbx REG64NA 3 11 | cl REG_CL 1 12 | ch REG_HIGH 5 13 | cx REG_CX 1 14 | ecx REG_ECX 1 15 | rcx REG_RCX 1 16 | dl REG_DL 2 17 | dh REG_HIGH 6 18 | dx REG_DX 2 19 | edx REG_EDX 2 20 | rdx REG_RDX 2 21 | spl REG8NA 4 22 | sp REG16NA 4 23 | esp REG32NA 4 24 | rsp REG64NA 4 25 | bpl REG8NA 5 26 | bp REG16NA 5 27 | ebp REG32NA 5 28 | rbp REG64NA 5 29 | sil REG8NA 6 30 | si REG16NA 6 31 | esi REG32NA 6 32 | rsi REG64NA 6 33 | dil REG8NA 7 34 | di REG16NA 7 35 | edi REG32NA 7 36 | rdi REG64NA 7 37 | r8-15b REG8NA 8 38 | r8-15w REG16NA 8 39 | r8-15d REG32NA 8 40 | r8-15 REG64NA 8 41 | es REG_ES 0 42 | cs REG_CS 1 43 | ss REG_SS 2 44 | ds REG_DS 3 45 | fs REG_FS 4 46 | gs REG_GS 5 47 | segr6-7 REG_SEG67 6 48 | cr0-15 REG_CREG 0 49 | dr0-15 REG_DREG 0 50 | tr0-7 REG_TREG 0 51 | st0 FPU0 0 52 | st1-7 FPUREG 1 53 | mm0-7 MMXREG 0 54 | xmm0 XMM0 0 55 | xmm1-15 XMM_L16 1 56 | xmm16-31 XMMREG 16 57 | ymm0 YMM0 0 58 | ymm1-15 YMM_L16 1 59 | ymm16-31 YMMREG 16 60 | zmm0 ZMM0 0 61 | zmm1-15 ZMM_L16 1 62 | zmm16-31 ZMMREG 16 63 | k0 OPMASK0 0 64 | k1-7 OPMASKREG 1 TFLAG_BRC_OPT 65 | bnd0-3 BNDREG 0 66 | rip REG_RIP 0 67 | --------------------------------------------------------------------------------