// version 0.03 // Author: Pavel Iakovlev // http://shell-storm.org/online/Online-Assembler-and-Disassembler/?inst=&arch=arm#assembly - online compiler (Little endian:) #pragma option OST #pragma option ON #pragma option cri- #pragma option -CPA #initallvar 0 #jumptomain FALSE #startaddress 0x10000 #code32 TRUE char os_name[8] = {'M','E','N','U','E','T','0','1'}; dword os_version = 0x00000001; dword start_addr = #main; dword final_addr = #______STOP______+32; dword alloc_mem = 20000; dword x86esp_reg = 20000; dword I_Param = #param; dword I_Path = #program_path; char param[4096] ={0}; char program_path[4096] = {0}; // test opcode arm, compiler (http://shell-storm.org/online/Online-Assembler-and-Disassembler/?inst=mov+r0%2C1%0D%0Amov+r5%2C2%0D%0Amov+r2%2C+r0%2C+lsl+r5&arch=arm#assembly) (Little endian:) dword test_bytecode = "\x04\x10\x5f\xe5\x7b\x00\x00\x00"; // -------------------- struct _reg // registers arm { dword r0; dword r1; dword r2; dword r3; dword r4; dword r5; dword r6; dword r7; dword r8; dword r9; dword r10; dword r11; dword r12; // (Intra-Procedure-call scratch register) dword r13; // (Stack Pointer) dword r14; // (Link Register) dword r15; // PC (Program Counter) }; _reg reg = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // clear and init registers dword REG = #reg; struct _flags { byte negative; byte zero; byte carry; byte overflow; }; _flags flags = {0,0,0,0}; // clear and init flags struct _mode { byte User; byte FastInterrupt; byte Interrupt; byte Supervisor; }; _mode mode = {0,0,0,0}; // processor mode struct _mask { byte IRQ; byte FIRQ; }; _mask mask = {0,0}; // processor mask void main() { callOpcode(#test_bytecode,1); EAX = -1; $int 0x40; } dword callOpcode(dword binary, lengthInstruction) { dword command = 0; dword PC = 0; byte flag = 0; byte pMask = 0; byte pMode = 0; while(lengthInstruction) { //PC = reg.r15 >> 2 & 0xFFFFFF; flag = reg.r15 >> 28; pMask = reg.r15 >> 26; flags.negative = flag & 0x8; flags.zero = flag & 0x4; flags.carry = flag & 0x2; flags.overflow = flag & 0x1; mask.IRQ = pMask & 0x2; mask.FIRQ = pMask & 0x1; switch(reg.r15 & 3) { case 0: DSDWORD[#mode] = 0x000000FF; break; case 1: DSDWORD[#mode] = 0x0000FF00; break; case 2: DSDWORD[#mode] = 0x00FF0000; break; case 3: DSDWORD[#mode] = 0xFF000000; break; } command = DSDWORD[binary + PC]; // generation PC instruction //EAX = DSDWORD[command >> 28 << 2 + #opcodeExec]; // get opcodeExecition call instruction //EAX(command); // call opcodeExecition //IF (command & 0xC000000 == 0) opcodeExec0(command); if (command & 0x0FFFFFF0 == 0x12FFF10) BranchExchange(command); else if (command & 0x0FF00FF0 == 0x1000090) SingleDataSwap(command); else if (command & 0x0FC000F0 == 0x0000090) Multiply(command); else if (command & 0x0FC000F0 == 0x0800090) MultiplyLong(command); else if (command & 0x0C000000 == 0x0000000) DataProcessing(command); else if (command & 0xE000010 == 0x6000010) ;// undefined else if (command & 0xC000000 == 0x4000000) SingleDataTransfer(command, binary); PC += 4; // addition 4 for reg15 or PC instruction //PC <<= 2; flag = 0; IF (flags.negative) flag |= 0x8; IF (flags.zero) flag |= 0x4; IF (flags.carry) flag |= 0x2; IF (flags.overflow) flag |= 0x1; pMask = 0; IF (mask.IRQ) pMask |= 0x2; IF (mask.FIRQ) pMask |= 0x1; if (mode.User) pMode = 0; else IF (mode.FastInterrupt) pMode = 1; else IF (mode.Interrupt) pMode = 2; else IF (mode.Supervisor) pMode = 3; //reg.r15 = flag << 28 | PC | pMode; lengthInstruction--; } } dword Multiply(dword command) { } dword MultiplyLong(dword command) { } dword SingleDataSwap(dword command) { } dword BranchExchange(dword command) { } dword SingleDataTransfer(dword command, binary) { dword Rd = #reg; dword Rn = #reg; dword offset = 0; Rd += command >> 12 & 0xF << 2; Rn += command >> 16 & 0xF << 2; offset = command & 0xFFF; IF (command >> 16 & 0xF != 15) IF (command & 0x800000 == 0) $neg offset; IF (command & 0x400000) // byte { IF (command >> 16 & 0xF == 15) { IF (command & 0x100000) DSDWORD[Rd] = DSBYTE[binary + offset]; ELSE DSBYTE[binary + offset] = DSDWORD[Rd]; } ELSE { Rn = DSDWORD[Rn]; IF (command & 0x2000000 == 0) Rn += offset; IF (command & 0x100000) DSDWORD[Rd] = DSDWORD[binary + Rn]; ELSE DSDWORD[binary + Rn] = DSDWORD[Rd]; } } ELSE // dword { Rn = DSDWORD[Rn]; IF (command & 0x2000000 == 0) Rn += offset; IF (command & 0x100000) DSDWORD[Rd] = DSDWORD[binary + Rn]; ELSE DSDWORD[binary + Rn] = DSDWORD[Rd]; } } dword DataProcessing(dword command) // Data Processing / PSR Transfer { dword opcode = 0; dword Rd = #reg; dword Rn = #reg; dword operand = 0; word sdvig = 0; word context = 0; byte typeSdvig = 0; opcode = command >> 21 & 0xF; Rd += command >> 12 & 0xF << 2; Rn += command >> 16 & 0xF << 2; context = command & 0xFFF; IF (command & 0x2000000) operand = context; ELSE operand = DSDWORD[context & 1111b << 2 + #reg]; typeSdvig = context >> 5 & 11b; IF (context & 10000b) sdvig = DSBYTE[context >> 8 & 1111b << 2 + #reg]; ELSE sdvig = context >> 7 & 11111b; switch (typeSdvig) // type sdvig { case 0: // logic left operand <<= sdvig; break; case 1: // logic right operand >>= sdvig; break; case 2: // arifmetic left break; case 3: // arifmetic right break; } switch (opcode) { case 0: // and DSDWORD[Rd] = DSDWORD[Rn] & operand; break; case 1: // eor DSDWORD[Rd] = DSDWORD[Rn] | operand; break; case 2: // sub DSDWORD[Rd] = DSDWORD[Rn] - operand; break; case 3: // rsb DSDWORD[Rd] = operand - DSDWORD[Rn]; break; case 4: // add DSDWORD[Rd] = DSDWORD[Rn] + operand; break; case 5: // adc DSDWORD[Rd] = DSDWORD[Rn] + operand; break; case 6: // sbc break; case 7: // rsc break; case 8: // tst break; case 9: // teq break; case 10: // cmp break; case 11: // cmn break; case 12: // orr DSDWORD[Rd] = DSDWORD[Rn] | operand; break; case 13: // mov DSDWORD[Rd] = operand; break; case 14: // bic $not operand; DSDWORD[Rd] = DSDWORD[Rn] & operand; break; case 15: // mvn DSDWORD[Rd] = DSDWORD[Rn] + operand; break; } } ______STOP______: