Self-modifying code that works under Linux
#1

(this is not a release, more of a proof-of-concept)

tl;dr: demo code at the bottom

I recently noticed that reading AMX opcodes under Linux is completely different from Windows - on Windows you get the opcodes when you read them, but on Linux you get pointers to strange values I couldn't figure out what they were.. So I simply embraced them instead!

Here's some code that essentially reads the values of most opcodes and stores them into variables, ready to use.

So now, instead of doing this:
pawn Код:
#emit CONST.pri   119
#emit SREF.S.pri  some_addr
Do this:
pawn Код:
LoadOpcodes();

#emit LOAD.pri    OP_FILL
#emit SREF.S.pri  some_addr
Here's an example of a memset function that replaces two NOP instructions with FILL <param>.

pawn Код:
stock raw_memset(address, cells, value) {
    new param_adr;
   
    LoadOpcodes();
   
    // "cells" now actually holds the number of bytes
    cells *= 4;
   
    // This block reads the address of the first NOP, relative to DAT.
    #emit LCTRL       6
    #emit MOVE.alt
    #emit LCTRL       0
    #emit ADD
    #emit MOVE.alt
    #emit LCTRL       1
    #emit SUB.alt
    #emit ADD.C       120
   
    // Store it
    #emit STOR.S.pri  param_adr
   
    // Put the FILL opcode at [param_adr]
    #emit LOAD.pri    OP_FILL
    #emit SREF.S.pri  param_adr
   
    // Put the parameter for FILL, which is the number of bytes
    #emit LOAD.S.pri  param_adr
    #emit ADD.C       4
    #emit STOR.S.pri  param_adr
    #emit LOAD.S.pri  cells
    #emit SREF.S.pri  param_adr
   
    #emit LOAD.S.alt  address
    #emit LOAD.S.pri  value
    #emit NOP
    #emit NOP
}
Here's the code for LoadOpcodes():
pawn Код:
enum E_OPCODE {
         Opcode,
         Name[11],
    bool:HasParam
};

stock const g_Opcodes[114][E_OPCODE] = {
    {  1, "LOAD.pri",    true}, {  2, "LOAD.alt",    true}, {  3, "LOAD.S.pri",  true},
    {  4, "LOAD.S.alt",  true}, {  5, "LREF.pri",    true}, {  6, "LREF.alt",    true},
    {  7, "LREF.S.pri",  true}, {  8, "LREF.S.alt",  true}, {  9, "LOAD.I",     false},
    { 10, "LODB.I",      true}, { 11, "CONST.pri",   true}, { 12, "CONST.alt",   true},
    { 13, "ADDR.pri",    true}, { 14, "ADDR.alt",    true}, { 15, "STOR.pri",    true},
    { 16, "STOR.alt",    true}, { 17, "STOR.S.pri",  true}, { 18, "STOR.S.alt",  true},
    { 19, "SREF.pri",    true}, { 20, "SREF.alt",    true}, { 21, "SREF.S.pri",  true},
    { 22, "SREF.S.alt",  true}, { 23, "STOR.I",     false}, { 24, "STRB.I",      true},
    { 25, "LIDX",       false}, { 26, "LIDX.B",      true}, { 27, "IDXADDR",    false},
    { 28, "IDXADDR.B",   true}, { 29, "ALIGN.pri",   true}, { 30, "ALIGN.alt",   true},
    { 31, "LCTRL",       true}, { 32, "SCTRL",       true}, { 33, "MOVE.pri",   false},
    { 34, "MOVE.alt",   false}, { 35, "XCHG",       false}, { 36, "PUSH.pri",   false},
    { 37, "PUSH.alt",   false}, { 38, "PUSH.R",      true}, { 39, "PUSH.C",      true},
    { 40, "PUSH",        true}, { 41, "PUSH.S",      true}, { 42, "POP.pri",    false},
    { 43, "POP.alt",    false}, { 44, "STACK",       true}, { 45, "HEAP",        true},
    { 46, "PROC",       false}, { 47, "RET",        false}, { 48, "RETN",       false},
//  { 49, "CALL",        true},
    { 50, "CALL.pri",   false},
//  { 51, "JUMP",        true}, { 52, "JREL",        true}, { 53, "JZER",        true},
//  { 54, "JNZ",         true}, { 55, "JEQ",         true}, { 56, "JNEQ",        true},
//  { 57, "JLESS",       true}, { 58, "JLEQ",        true}, { 59, "JGRTR",       true},
//  { 60, "JGEQ",        true}, { 61, "JSLESS",      true}, { 62, "JSLEQ",       true},
//  { 63, "JSGRTR",      true}, { 64, "JSGEQ",       true},
    { 65, "SHL",        false}, { 66, "SHR",        false}, { 67, "SSHR",       false},
    { 68, "SHL.C.pri",   true}, { 69, "SHL.C.alt",   true}, { 70, "SHR.C.pri",   true},
    { 71, "SHR.C.alt",   true}, { 72, "SMUL",       false}, { 73, "SDIV",       false},
    { 74, "SDIV.alt",   false}, { 75, "UMUL",       false}, { 76, "UDIV",       false},
    { 77, "UDIV.alt",   false}, { 78, "ADD",        false}, { 79, "SUB",        false},
    { 80, "SUB.alt",    false}, { 81, "AND",        false}, { 82, "OR",         false},
    { 83, "XOR",        false}, { 84, "NOT",        false}, { 85, "NEG",        false},
    { 86, "INVERT",     false}, { 87, "ADD.C",       true}, { 88, "SMUL.C",      true},
    { 89, "ZERO.pri",   false}, { 90, "ZERO.alt",   false}, { 91, "ZERO",        true},
    { 92, "ZERO.S",      true}, { 93, "SIGN.pri",   false}, { 94, "SIGN.alt",   false},
    { 95, "EQ",         false}, { 96, "NEQ",        false}, { 97, "LESS",       false},
    { 98, "LEQ",        false}, { 99, "GRTR",       false}, {100, "GEQ",        false},
    {101, "SLESS",      false}, {102, "SLEQ",       false}, {103, "SGRTR",      false},
    {104, "SGEQ",       false}, {105, "EQ.C.pri",    true}, {106, "EQ.C.alt",    true},
    {107, "INC.pri",    false}, {108, "INC.alt",    false}, {109, "INC",         true},
    {110, "INC.S",       true}, {111, "INC.I",      false}, {112, "DEC.pri",    false},
    {113, "DEC.alt",    false}, {114, "DEC",         true}, {115, "DEC.S",       true},
    {116, "DEC.I",      false}, {117, "MOVS",        true}, {118, "CMPS",        true},
    {119, "FILL",        true}, {120, "HALT",        true}, {121, "BOUNDS",      true},
    {122, "SYSREQ.pri", false}, {123, "SYSREQ.C",    true}, {128, "JUMP.pri",   false},
//  {129, "SWITCH",      true}, {130, "CASETBL",    false},
    {131, "SWAP.pri",   false}, {132, "SWAP.alt",   false}, {133, "PUSH.ADR",    true},
    {134, "NOP",        false}, {137, "BREAK",      false}
};

enum {
    E_OP_LOAD_PRI, E_OP_LOAD_ALT, E_OP_LOAD_S_PRI,
    E_OP_LOAD_S_ALT, E_OP_LREF_PRI, E_OP_LREF_ALT,
    E_OP_LREF_S_PRI, E_OP_LREF_S_ALT, E_OP_LOAD_I,
    E_OP_LODB_I, E_OP_CONST_PRI, E_OP_CONST_ALT,
    E_OP_ADDR_PRI, E_OP_ADDR_ALT, E_OP_STOR_PRI,
    E_OP_STOR_ALT, E_OP_STOR_S_PRI, E_OP_STOR_S_ALT,
    E_OP_SREF_PRI, E_OP_SREF_ALT, E_OP_SREF_S_PRI,
    E_OP_SREF_S_ALT, E_OP_STOR_I, E_OP_STRB_I,
    E_OP_LIDX, E_OP_LIDX_B, E_OP_IDXADDR,
    E_OP_IDXADDR_B, E_OP_ALIGN_PRI, E_OP_ALIGN_ALT,
    E_OP_LCTRL, E_OP_SCTRL, E_OP_MOVE_PRI,
    E_OP_MOVE_ALT, E_OP_XCHG, E_OP_PUSH_PRI,
    E_OP_PUSH_ALT, E_OP_PUSH_R, E_OP_PUSH_C,
    E_OP_PUSH, E_OP_PUSH_S, E_OP_POP_PRI,
    E_OP_POP_ALT, E_OP_STACK, E_OP_HEAP,
    E_OP_PROC, E_OP_RET, E_OP_RETN,
//  E_OP_CALL,
    E_OP_CALL_PRI,
//  E_OP_JUMP, E_OP_JREL, E_OP_JZER,
//  E_OP_JNZ, E_OP_JEQ, E_OP_JNEQ,
//  E_OP_JLESS, E_OP_JLEQ, E_OP_JGRTR,
//  E_OP_JGEQ, E_OP_JSLESS, E_OP_JSLEQ,
//  E_OP_JSGRTR, E_OP_JSGEQ,
    E_OP_SHL, E_OP_SHR, E_OP_SSHR,
    E_OP_SHL_C_PRI, E_OP_SHL_C_ALT, E_OP_SHR_C_PRI,
    E_OP_SHR_C_ALT, E_OP_SMUL, E_OP_SDIV,
    E_OP_SDIV_ALT, E_OP_UMUL, E_OP_UDIV,
    E_OP_UDIV_ALT, E_OP_ADD, E_OP_SUB,
    E_OP_SUB_ALT, E_OP_AND, E_OP_OR,
    E_OP_XOR, E_OP_NOT, E_OP_NEG,
    E_OP_INVERT, E_OP_ADD_C, E_OP_SMUL_C,
    E_OP_ZERO_PRI, E_OP_ZERO_ALT, E_OP_ZERO,
    E_OP_ZERO_S, E_OP_SIGN_PRI, E_OP_SIGN_ALT,
    E_OP_EQ, E_OP_NEQ, E_OP_LESS,
    E_OP_LEQ, E_OP_GRTR, E_OP_GEQ,
    E_OP_SLESS, E_OP_SLEQ, E_OP_SGRTR,
    E_OP_SGEQ, E_OP_EQ_C_PRI, E_OP_EQ_C_ALT,
    E_OP_INC_PRI, E_OP_INC_ALT, E_OP_INC,
    E_OP_INC_S, E_OP_INC_I, E_OP_DEC_PRI,
    E_OP_DEC_ALT, E_OP_DEC, E_OP_DEC_S,
    E_OP_DEC_I, E_OP_MOVS, E_OP_CMPS,
    E_OP_FILL, E_OP_HALT, E_OP_BOUNDS,
    E_OP_SYSREQ_PRI, E_OP_SYSREQ_C, E_OP_JUMP_PRI,
//  E_OP_SWITCH,
//  E_OP_CASETBL,
    E_OP_SWAP_PRI, E_OP_SWAP_ALT, E_OP_PUSH_ADR,
    E_OP_NOP, E_OP_BREAK
};

stock
    OP_LOAD_PRI, OP_LOAD_ALT, OP_LOAD_S_PRI,
    OP_LOAD_S_ALT, OP_LREF_PRI, OP_LREF_ALT,
    OP_LREF_S_PRI, OP_LREF_S_ALT, OP_LOAD_I,
    OP_LODB_I, OP_CONST_PRI, OP_CONST_ALT,
    OP_ADDR_PRI, OP_ADDR_ALT, OP_STOR_PRI,
    OP_STOR_ALT, OP_STOR_S_PRI, OP_STOR_S_ALT,
    OP_SREF_PRI, OP_SREF_ALT, OP_SREF_S_PRI,
    OP_SREF_S_ALT, OP_STOR_I, OP_STRB_I,
    OP_LIDX, OP_LIDX_B, OP_IDXADDR,
    OP_IDXADDR_B, OP_ALIGN_PRI, OP_ALIGN_ALT,
    OP_LCTRL, OP_SCTRL, OP_MOVE_PRI,
    OP_MOVE_ALT, OP_XCHG, OP_PUSH_PRI,
    OP_PUSH_ALT, OP_PUSH_R, OP_PUSH_C,
    OP_PUSH, OP_PUSH_S, OP_POP_PRI,
    OP_POP_ALT, OP_STACK, OP_HEAP,
    OP_PROC, OP_RET, OP_RETN,
//  OP_CALL,
    OP_CALL_PRI,
//  OP_JUMP, OP_JREL, OP_JZER,
//  OP_JNZ, OP_JEQ, OP_JNEQ,
//  OP_JLESS, OP_JLEQ, OP_JGRTR,
//  OP_JGEQ, OP_JSLESS, OP_JSLEQ,
//  OP_JSGRTR, OP_JSGEQ,
    OP_SHL, OP_SHR, OP_SSHR,
    OP_SHL_C_PRI, OP_SHL_C_ALT, OP_SHR_C_PRI,
    OP_SHR_C_ALT, OP_SMUL, OP_SDIV,
    OP_SDIV_ALT, OP_UMUL, OP_UDIV,
    OP_UDIV_ALT, OP_ADD, OP_SUB,
    OP_SUB_ALT, OP_AND, OP_OR,
    OP_XOR, OP_NOT, OP_NEG,
    OP_INVERT, OP_ADD_C, OP_SMUL_C,
    OP_ZERO_PRI, OP_ZERO_ALT, OP_ZERO,
    OP_ZERO_S, OP_SIGN_PRI, OP_SIGN_ALT,
    OP_EQ, OP_NEQ, OP_LESS,
    OP_LEQ, OP_GRTR, OP_GEQ,
    OP_SLESS, OP_SLEQ, OP_SGRTR,
    OP_SGEQ, OP_EQ_C_PRI, OP_EQ_C_ALT,
    OP_INC_PRI, OP_INC_ALT, OP_INC,
    OP_INC_S, OP_INC_I, OP_DEC_PRI,
    OP_DEC_ALT, OP_DEC, OP_DEC_S,
    OP_DEC_I, OP_MOVS, OP_CMPS,
    OP_FILL, OP_HALT, OP_BOUNDS,
    OP_SYSREQ_PRI, OP_SYSREQ_C, OP_JUMP_PRI,
//  OP_SWITCH,
//  OP_CASETBL,
    OP_SWAP_PRI, OP_SWAP_ALT, OP_PUSH_ADR,
    OP_NOP, OP_BREAK
;

stock LoadOpcodes() {
    static bool:loaded = false;
   
    // We only need to load them once
    if (loaded)
        return;
    else
        loaded = true;
   
    new addr = _LoadOpcodes(), opcode_values[sizeof(g_Opcodes)];
   
    for (new i = 0; i < sizeof(g_Opcodes); i++) {
        new opcode, param;
       
        #emit LREF.S.pri  addr
        #emit STOR.S.pri  opcode
       
        addr += 4;
       
        if (g_Opcodes[i][HasParam]) {
            #emit LREF.S.pri  addr
            #emit STOR.S.pri  param
           
            //printf("%04x%04x %04x%04x", opcode >>> 16, opcode & 0xFFFF, param >>> 16, param & 0xFFFF);
           
            addr += 4;
        } else {
            //printf("%04x%04x", opcode >>> 16, opcode & 0xFFFF);
        }
       
        opcode_values[i] = opcode;
    }
   
    // bleh
    OP_LOAD_PRI = opcode_values[E_OP_LOAD_PRI]; OP_LOAD_ALT = opcode_values[E_OP_LOAD_ALT]; OP_LOAD_S_PRI = opcode_values[E_OP_LOAD_S_PRI];
    OP_LOAD_S_ALT = opcode_values[E_OP_LOAD_S_ALT]; OP_LREF_PRI = opcode_values[E_OP_LREF_PRI]; OP_LREF_ALT = opcode_values[E_OP_LREF_ALT];
    OP_LREF_S_PRI = opcode_values[E_OP_LREF_S_PRI]; OP_LREF_S_ALT = opcode_values[E_OP_LREF_S_ALT]; OP_LOAD_I = opcode_values[E_OP_LOAD_I];
    OP_LODB_I = opcode_values[E_OP_LODB_I]; OP_CONST_PRI = opcode_values[E_OP_CONST_PRI]; OP_CONST_ALT = opcode_values[E_OP_CONST_ALT];
    OP_ADDR_PRI = opcode_values[E_OP_ADDR_PRI]; OP_ADDR_ALT = opcode_values[E_OP_ADDR_ALT]; OP_STOR_PRI = opcode_values[E_OP_STOR_PRI];
    OP_STOR_ALT = opcode_values[E_OP_STOR_ALT]; OP_STOR_S_PRI = opcode_values[E_OP_STOR_S_PRI]; OP_STOR_S_ALT = opcode_values[E_OP_STOR_S_ALT];
    OP_SREF_PRI = opcode_values[E_OP_SREF_PRI]; OP_SREF_ALT = opcode_values[E_OP_SREF_ALT]; OP_SREF_S_PRI = opcode_values[E_OP_SREF_S_PRI];
    OP_SREF_S_ALT = opcode_values[E_OP_SREF_S_ALT]; OP_STOR_I = opcode_values[E_OP_STOR_I]; OP_STRB_I = opcode_values[E_OP_STRB_I];
    OP_LIDX = opcode_values[E_OP_LIDX]; OP_LIDX_B = opcode_values[E_OP_LIDX_B]; OP_IDXADDR = opcode_values[E_OP_IDXADDR];
    OP_IDXADDR_B = opcode_values[E_OP_IDXADDR_B]; OP_ALIGN_PRI = opcode_values[E_OP_ALIGN_PRI]; OP_ALIGN_ALT = opcode_values[E_OP_ALIGN_ALT];
    OP_LCTRL = opcode_values[E_OP_LCTRL]; OP_SCTRL = opcode_values[E_OP_SCTRL]; OP_MOVE_PRI = opcode_values[E_OP_MOVE_PRI];
    OP_MOVE_ALT = opcode_values[E_OP_MOVE_ALT]; OP_XCHG = opcode_values[E_OP_XCHG]; OP_PUSH_PRI = opcode_values[E_OP_PUSH_PRI];
    OP_PUSH_ALT = opcode_values[E_OP_PUSH_ALT]; OP_PUSH_R = opcode_values[E_OP_PUSH_R]; OP_PUSH_C = opcode_values[E_OP_PUSH_C];
    OP_PUSH = opcode_values[E_OP_PUSH]; OP_PUSH_S = opcode_values[E_OP_PUSH_S]; OP_POP_PRI = opcode_values[E_OP_POP_PRI];
    OP_POP_ALT = opcode_values[E_OP_POP_ALT]; OP_STACK = opcode_values[E_OP_STACK]; OP_HEAP = opcode_values[E_OP_HEAP];
    OP_PROC = opcode_values[E_OP_PROC]; OP_RET = opcode_values[E_OP_RET]; OP_RETN = opcode_values[E_OP_RETN];
//  OP_CALL = opcode_values[E_OP_CALL];
    OP_CALL_PRI = opcode_values[E_OP_CALL_PRI];
//  OP_JUMP = opcode_values[E_OP_JUMP]; OP_JREL = opcode_values[E_OP_OP_JREL]; OP_JZER = opcode_values[E_OP_OP_JZER];
//  OP_JNZ = opcode_values[E_OP_OP_JNZ]; OP_JEQ = opcode_values[E_OP_OP_JEQ]; OP_JNEQ = opcode_values[E_OP_OP_JNEQ];
//  OP_JLESS = opcode_values[E_OP_OP_JLESS]; OP_JLEQ = opcode_values[E_OP_OP_JLEQ]; OP_JGRTR = opcode_values[E_OP_OP_JGRTR];
//  OP_JGEQ = opcode_values[E_OP_OP_JGEQ]; OP_JSLESS = opcode_values[E_OP_OP_JSLESS]; OP_JSLEQ = opcode_values[E_OP_OP_JSLEQ];
//  OP_JSGRTR = opcode_values[E_OP_OP_JSGRTR]; OP_JSGEQ = opcode_values[E_OP_OP_JSGEQ];
    OP_SHL = opcode_values[E_OP_SHL]; OP_SHR = opcode_values[E_OP_SHR]; OP_SSHR = opcode_values[E_OP_SSHR];
    OP_SHL_C_PRI = opcode_values[E_OP_SHL_C_PRI]; OP_SHL_C_ALT = opcode_values[E_OP_SHL_C_ALT]; OP_SHR_C_PRI = opcode_values[E_OP_SHR_C_PRI];
    OP_SHR_C_ALT = opcode_values[E_OP_SHR_C_ALT]; OP_SMUL = opcode_values[E_OP_SMUL]; OP_SDIV = opcode_values[E_OP_SDIV];
    OP_SDIV_ALT = opcode_values[E_OP_SDIV_ALT]; OP_UMUL = opcode_values[E_OP_UMUL]; OP_UDIV = opcode_values[E_OP_UDIV];
    OP_UDIV_ALT = opcode_values[E_OP_UDIV_ALT]; OP_ADD = opcode_values[E_OP_ADD]; OP_SUB = opcode_values[E_OP_SUB];
    OP_SUB_ALT = opcode_values[E_OP_SUB_ALT]; OP_AND = opcode_values[E_OP_AND]; OP_OR = opcode_values[E_OP_OR];
    OP_XOR = opcode_values[E_OP_XOR]; OP_NOT = opcode_values[E_OP_NOT]; OP_NEG = opcode_values[E_OP_NEG];
    OP_INVERT = opcode_values[E_OP_INVERT]; OP_ADD_C = opcode_values[E_OP_ADD_C]; OP_SMUL_C = opcode_values[E_OP_SMUL_C];
    OP_ZERO_PRI = opcode_values[E_OP_ZERO_PRI]; OP_ZERO_ALT = opcode_values[E_OP_ZERO_ALT]; OP_ZERO = opcode_values[E_OP_ZERO];
    OP_ZERO_S = opcode_values[E_OP_ZERO_S]; OP_SIGN_PRI = opcode_values[E_OP_SIGN_PRI]; OP_SIGN_ALT = opcode_values[E_OP_SIGN_ALT];
    OP_EQ = opcode_values[E_OP_EQ]; OP_NEQ = opcode_values[E_OP_NEQ]; OP_LESS = opcode_values[E_OP_LESS];
    OP_LEQ = opcode_values[E_OP_LEQ]; OP_GRTR = opcode_values[E_OP_GRTR]; OP_GEQ = opcode_values[E_OP_GEQ];
    OP_SLESS = opcode_values[E_OP_SLESS]; OP_SLEQ = opcode_values[E_OP_SLEQ]; OP_SGRTR = opcode_values[E_OP_SGRTR];
    OP_SGEQ = opcode_values[E_OP_SGEQ]; OP_EQ_C_PRI = opcode_values[E_OP_EQ_C_PRI]; OP_EQ_C_ALT = opcode_values[E_OP_EQ_C_ALT];
    OP_INC_PRI = opcode_values[E_OP_INC_PRI]; OP_INC_ALT = opcode_values[E_OP_INC_ALT]; OP_INC = opcode_values[E_OP_INC];
    OP_INC_S = opcode_values[E_OP_INC_S]; OP_INC_I = opcode_values[E_OP_INC_I]; OP_DEC_PRI = opcode_values[E_OP_DEC_PRI];
    OP_DEC_ALT = opcode_values[E_OP_DEC_ALT]; OP_DEC = opcode_values[E_OP_DEC]; OP_DEC_S = opcode_values[E_OP_DEC_S];
    OP_DEC_I = opcode_values[E_OP_DEC_I]; OP_MOVS = opcode_values[E_OP_MOVS]; OP_CMPS = opcode_values[E_OP_CMPS];
    OP_FILL = opcode_values[E_OP_FILL]; OP_HALT = opcode_values[E_OP_HALT]; OP_BOUNDS = opcode_values[E_OP_BOUNDS];
    OP_SYSREQ_PRI = opcode_values[E_OP_SYSREQ_PRI]; OP_SYSREQ_C = opcode_values[E_OP_SYSREQ_C]; OP_JUMP_PRI = opcode_values[E_OP_JUMP_PRI];
//  OP_SWITCH = opcode_values[E_OP_SWITCH];
//  OP_CASETBL = opcode_values[E_OP_OP_CASETBL];
    OP_SWAP_PRI = opcode_values[E_OP_SWAP_PRI]; OP_SWAP_ALT = opcode_values[E_OP_SWAP_ALT]; OP_PUSH_ADR = opcode_values[E_OP_PUSH_ADR];
    OP_NOP = opcode_values[E_OP_NOP]; OP_BREAK = opcode_values[E_OP_BREAK];
}

stock _LoadOpcodes() {
    // Return the address of "LOAD.pri" below
    #emit LCTRL      6
    #emit MOVE.alt
    #emit LCTRL      0
    #emit ADD
    #emit MOVE.alt
    #emit LCTRL      1
    #emit SUB.alt
    #emit ADD.C      44
    #emit RETN
   
    // The values of the parameters are insignificant, but they must to be there.
    #emit LOAD.pri    1   // 1
    #emit LOAD.alt    2   // 2
    #emit LOAD.S.pri  3   // 3
    #emit LOAD.S.alt  4   // 4
    #emit LREF.pri    5   // 5
    #emit LREF.alt    6   // 6
    #emit LREF.S.pri  7   // 7
    #emit LREF.S.alt  8   // 8
    #emit LOAD.I          // 9
    #emit LODB.I      10  // 10
    #emit CONST.pri   11  // 11
    #emit CONST.alt   12  // 12
    #emit ADDR.pri    13  // 13
    #emit ADDR.alt    14  // 14
    #emit STOR.pri    15  // 15
    #emit STOR.alt    16  // 16
    #emit STOR.S.pri  17  // 17
    #emit STOR.S.alt  18  // 18
    #emit SREF.pri    19  // 19
    #emit SREF.alt    20  // 20
    #emit SREF.S.pri  21  // 21
    #emit SREF.S.alt  22  // 22
    #emit STOR.I          // 23
    #emit STRB.I      24  // 24
    #emit LIDX            // 25
    #emit LIDX.B      26  // 26
    #emit IDXADDR         // 27
    #emit IDXADDR.B   28  // 28
    #emit ALIGN.pri   29  // 29
    #emit ALIGN.alt   30  // 30
    #emit LCTRL       31  // 31
    #emit SCTRL       32  // 32
    #emit MOVE.pri        // 33
    #emit MOVE.alt        // 34
    #emit XCHG            // 35
    #emit PUSH.pri        // 36
    #emit PUSH.alt        // 37
    #emit PUSH.R      38  // 38
    #emit PUSH.C      39  // 39
    #emit PUSH        40  // 40
    #emit PUSH.S      41  // 41
    #emit POP.pri         // 42
    #emit POP.alt         // 43
    #emit STACK       44  // 44
    #emit HEAP        45  // 45
    #emit PROC            // 46
    #emit RET             // 47
    #emit RETN            // 48
//  #emit CALL        49  // 49
    #emit CALL.pri        // 50
//  #emit JUMP        51  // 51
//  #emit JREL        52  // 52
//  #emit JZER        53  // 53
//  #emit JNZ         54  // 54
//  #emit JEQ         55  // 55
//  #emit JNEQ        56  // 56
//  #emit JLESS       57  // 57
//  #emit JLEQ        58  // 58
//  #emit JGRTR       59  // 59
//  #emit JGEQ        60  // 60
//  #emit JSLESS      61  // 61
//  #emit JSLEQ       62  // 62
//  #emit JSGRTR      63  // 63
//  #emit JSGEQ       64  // 64
    #emit SHL             // 65
    #emit SHR             // 66
    #emit SSHR            // 67
    #emit SHL.C.pri   68  // 68
    #emit SHL.C.alt   69  // 69
    #emit SHR.C.pri   70  // 70
    #emit SHR.C.alt   71  // 71
    #emit SMUL            // 72
    #emit SDIV            // 73
    #emit SDIV.alt        // 74
    #emit UMUL            // 75
    #emit UDIV            // 76
    #emit UDIV.alt        // 77
    #emit ADD             // 78
    #emit SUB             // 79
    #emit SUB.alt         // 80
    #emit AND             // 81
    #emit OR              // 82
    #emit XOR             // 83
    #emit NOT             // 84
    #emit NEG             // 85
    #emit INVERT          // 86
    #emit ADD.C       87  // 87
    #emit SMUL.C      88  // 88
    #emit ZERO.pri        // 89
    #emit ZERO.alt        // 90
    #emit ZERO        91  // 91
    #emit ZERO.S      92  // 92
    #emit SIGN.pri        // 93
    #emit SIGN.alt        // 94
    #emit EQ              // 95
    #emit NEQ             // 96
    #emit LESS            // 97
    #emit LEQ             // 98
    #emit GRTR            // 99
    #emit GEQ             // 100
    #emit SLESS           // 101
    #emit SLEQ            // 102
    #emit SGRTR           // 103
    #emit SGEQ            // 104
    #emit EQ.C.pri    105 // 105
    #emit EQ.C.alt    106 // 106
    #emit INC.pri         // 107
    #emit INC.alt         // 108
    #emit INC         109 // 109
    #emit INC.S       110 // 110
    #emit INC.I           // 111
    #emit DEC.pri         // 112
    #emit DEC.alt         // 113
    #emit DEC         114 // 114
    #emit DEC.S       115 // 115
    #emit DEC.I           // 116
    #emit MOVS        117 // 117
    #emit CMPS        118 // 118
    #emit FILL        119 // 119
    #emit HALT        120 // 120
    #emit BOUNDS      121 // 121
    #emit SYSREQ.pri      // 122
    #emit SYSREQ.C    123 // 123
    #emit JUMP.pri        // 128
//  #emit SWITCH      129 // 129
//  #emit CASETBL         // 130
    #emit SWAP.pri        // 131
    #emit SWAP.alt        // 132
    #emit PUSH.ADR    133 // 133
    #emit NOP             // 134
    #emit BREAK           // 137
   
    return 0;
}

Copy & paste this code into PAWN Playground for a demo (I'm unable to save it due to a length limitation).
pawn Код:
#include <a_samp>

stock
    OP_LOAD_PRI, OP_LOAD_ALT, OP_LOAD_S_PRI,
    OP_LOAD_S_ALT, OP_LREF_PRI, OP_LREF_ALT,
    OP_LREF_S_PRI, OP_LREF_S_ALT, OP_LOAD_I,
    OP_LODB_I, OP_CONST_PRI, OP_CONST_ALT,
    OP_ADDR_PRI, OP_ADDR_ALT, OP_STOR_PRI,
    OP_STOR_ALT, OP_STOR_S_PRI, OP_STOR_S_ALT,
    OP_SREF_PRI, OP_SREF_ALT, OP_SREF_S_PRI,
    OP_SREF_S_ALT, OP_STOR_I, OP_STRB_I,
    OP_LIDX, OP_LIDX_B, OP_IDXADDR,
    OP_IDXADDR_B, OP_ALIGN_PRI, OP_ALIGN_ALT,
    OP_LCTRL, OP_SCTRL, OP_MOVE_PRI,
    OP_MOVE_ALT, OP_XCHG, OP_PUSH_PRI,
    OP_PUSH_ALT, OP_PUSH_R, OP_PUSH_C,
    OP_PUSH, OP_PUSH_S, OP_POP_PRI,
    OP_POP_ALT, OP_STACK, OP_HEAP,
    OP_PROC, OP_RET, OP_RETN,
//  OP_CALL,
    OP_CALL_PRI,
//  OP_JUMP, OP_JREL, OP_JZER,
//  OP_JNZ, OP_JEQ, OP_JNEQ,
//  OP_JLESS, OP_JLEQ, OP_JGRTR,
//  OP_JGEQ, OP_JSLESS, OP_JSLEQ,
//  OP_JSGRTR, OP_JSGEQ,
    OP_SHL, OP_SHR, OP_SSHR,
    OP_SHL_C_PRI, OP_SHL_C_ALT, OP_SHR_C_PRI,
    OP_SHR_C_ALT, OP_SMUL, OP_SDIV,
    OP_SDIV_ALT, OP_UMUL, OP_UDIV,
    OP_UDIV_ALT, OP_ADD, OP_SUB,
    OP_SUB_ALT, OP_AND, OP_OR,
    OP_XOR, OP_NOT, OP_NEG,
    OP_INVERT, OP_ADD_C, OP_SMUL_C,
    OP_ZERO_PRI, OP_ZERO_ALT, OP_ZERO,
    OP_ZERO_S, OP_SIGN_PRI, OP_SIGN_ALT,
    OP_EQ, OP_NEQ, OP_LESS,
    OP_LEQ, OP_GRTR, OP_GEQ,
    OP_SLESS, OP_SLEQ, OP_SGRTR,
    OP_SGEQ, OP_EQ_C_PRI, OP_EQ_C_ALT,
    OP_INC_PRI, OP_INC_ALT, OP_INC,
    OP_INC_S, OP_INC_I, OP_DEC_PRI,
    OP_DEC_ALT, OP_DEC, OP_DEC_S,
    OP_DEC_I, OP_MOVS, OP_CMPS,
    OP_FILL, OP_HALT, OP_BOUNDS,
    OP_SYSREQ_PRI, OP_SYSREQ_C, OP_JUMP_PRI,
//  OP_SWITCH,
//  OP_CASETBL,
    OP_SWAP_PRI, OP_SWAP_ALT, OP_PUSH_ADR,
    OP_NOP, OP_BREAK
;

main() {
    new test[20] = {4, ...};
   
    memset(test[5], 10, 1234);
   
    for (new i = 0; i < sizeof(test); i++) {
        printf("test[%d] = %d", i, test[i]);
    }

    #if defined quit
            quit();
    #endif
}

stock memset(variable[], cells, value) {
    new address;
   
    #emit LOAD.S.pri  variable
    #emit STOR.S.pri  address
   
    raw_memset(address, cells, value);
}

stock raw_memset(address, cells, value) {
    new param_adr;
   
    LoadOpcodes();
   
    // "cells" now actually holds the number of bytes
    cells *= 4;
   
    // This block reads the address of the first NOP, relative to DAT.
    #emit LCTRL       6
    #emit MOVE.alt
    #emit LCTRL       0
    #emit ADD
    #emit MOVE.alt
    #emit LCTRL       1
    #emit SUB.alt
    #emit ADD.C       120
   
    // Store it
    #emit STOR.S.pri  param_adr
   
    // Put the FILL opcode at [param_adr]
    #emit LOAD.pri    OP_FILL
    #emit SREF.S.pri  param_adr
   
    // Put the parameter for FILL, which is the number of bytes
    #emit LOAD.S.pri  param_adr
    #emit ADD.C       4
    #emit STOR.S.pri  param_adr
    #emit LOAD.S.pri  cells
    #emit SREF.S.pri  param_adr
   
    #emit LOAD.S.alt  address
    #emit LOAD.S.pri  value
    #emit NOP
    #emit NOP
}











enum E_OPCODE {
         Opcode,
         Name[11],
    bool:HasParam
};

stock const g_Opcodes[114][E_OPCODE] = {
    {  1, "LOAD.pri",    true}, {  2, "LOAD.alt",    true}, {  3, "LOAD.S.pri",  true},
    {  4, "LOAD.S.alt",  true}, {  5, "LREF.pri",    true}, {  6, "LREF.alt",    true},
    {  7, "LREF.S.pri",  true}, {  8, "LREF.S.alt",  true}, {  9, "LOAD.I",     false},
    { 10, "LODB.I",      true}, { 11, "CONST.pri",   true}, { 12, "CONST.alt",   true},
    { 13, "ADDR.pri",    true}, { 14, "ADDR.alt",    true}, { 15, "STOR.pri",    true},
    { 16, "STOR.alt",    true}, { 17, "STOR.S.pri",  true}, { 18, "STOR.S.alt",  true},
    { 19, "SREF.pri",    true}, { 20, "SREF.alt",    true}, { 21, "SREF.S.pri",  true},
    { 22, "SREF.S.alt",  true}, { 23, "STOR.I",     false}, { 24, "STRB.I",      true},
    { 25, "LIDX",       false}, { 26, "LIDX.B",      true}, { 27, "IDXADDR",    false},
    { 28, "IDXADDR.B",   true}, { 29, "ALIGN.pri",   true}, { 30, "ALIGN.alt",   true},
    { 31, "LCTRL",       true}, { 32, "SCTRL",       true}, { 33, "MOVE.pri",   false},
    { 34, "MOVE.alt",   false}, { 35, "XCHG",       false}, { 36, "PUSH.pri",   false},
    { 37, "PUSH.alt",   false}, { 38, "PUSH.R",      true}, { 39, "PUSH.C",      true},
    { 40, "PUSH",        true}, { 41, "PUSH.S",      true}, { 42, "POP.pri",    false},
    { 43, "POP.alt",    false}, { 44, "STACK",       true}, { 45, "HEAP",        true},
    { 46, "PROC",       false}, { 47, "RET",        false}, { 48, "RETN",       false},
//  { 49, "CALL",        true},
    { 50, "CALL.pri",   false},
//  { 51, "JUMP",        true}, { 52, "JREL",        true}, { 53, "JZER",        true},
//  { 54, "JNZ",         true}, { 55, "JEQ",         true}, { 56, "JNEQ",        true},
//  { 57, "JLESS",       true}, { 58, "JLEQ",        true}, { 59, "JGRTR",       true},
//  { 60, "JGEQ",        true}, { 61, "JSLESS",      true}, { 62, "JSLEQ",       true},
//  { 63, "JSGRTR",      true}, { 64, "JSGEQ",       true},
    { 65, "SHL",        false}, { 66, "SHR",        false}, { 67, "SSHR",       false},
    { 68, "SHL.C.pri",   true}, { 69, "SHL.C.alt",   true}, { 70, "SHR.C.pri",   true},
    { 71, "SHR.C.alt",   true}, { 72, "SMUL",       false}, { 73, "SDIV",       false},
    { 74, "SDIV.alt",   false}, { 75, "UMUL",       false}, { 76, "UDIV",       false},
    { 77, "UDIV.alt",   false}, { 78, "ADD",        false}, { 79, "SUB",        false},
    { 80, "SUB.alt",    false}, { 81, "AND",        false}, { 82, "OR",         false},
    { 83, "XOR",        false}, { 84, "NOT",        false}, { 85, "NEG",        false},
    { 86, "INVERT",     false}, { 87, "ADD.C",       true}, { 88, "SMUL.C",      true},
    { 89, "ZERO.pri",   false}, { 90, "ZERO.alt",   false}, { 91, "ZERO",        true},
    { 92, "ZERO.S",      true}, { 93, "SIGN.pri",   false}, { 94, "SIGN.alt",   false},
    { 95, "EQ",         false}, { 96, "NEQ",        false}, { 97, "LESS",       false},
    { 98, "LEQ",        false}, { 99, "GRTR",       false}, {100, "GEQ",        false},
    {101, "SLESS",      false}, {102, "SLEQ",       false}, {103, "SGRTR",      false},
    {104, "SGEQ",       false}, {105, "EQ.C.pri",    true}, {106, "EQ.C.alt",    true},
    {107, "INC.pri",    false}, {108, "INC.alt",    false}, {109, "INC",         true},
    {110, "INC.S",       true}, {111, "INC.I",      false}, {112, "DEC.pri",    false},
    {113, "DEC.alt",    false}, {114, "DEC",         true}, {115, "DEC.S",       true},
    {116, "DEC.I",      false}, {117, "MOVS",        true}, {118, "CMPS",        true},
    {119, "FILL",        true}, {120, "HALT",        true}, {121, "BOUNDS",      true},
    {122, "SYSREQ.pri", false}, {123, "SYSREQ.C",    true}, {128, "JUMP.pri",   false},
//  {129, "SWITCH",      true}, {130, "CASETBL",    false},
    {131, "SWAP.pri",   false}, {132, "SWAP.alt",   false}, {133, "PUSH.ADR",    true},
    {134, "NOP",        false}, {137, "BREAK",      false}
};

enum {
    E_OP_LOAD_PRI, E_OP_LOAD_ALT, E_OP_LOAD_S_PRI,
    E_OP_LOAD_S_ALT, E_OP_LREF_PRI, E_OP_LREF_ALT,
    E_OP_LREF_S_PRI, E_OP_LREF_S_ALT, E_OP_LOAD_I,
    E_OP_LODB_I, E_OP_CONST_PRI, E_OP_CONST_ALT,
    E_OP_ADDR_PRI, E_OP_ADDR_ALT, E_OP_STOR_PRI,
    E_OP_STOR_ALT, E_OP_STOR_S_PRI, E_OP_STOR_S_ALT,
    E_OP_SREF_PRI, E_OP_SREF_ALT, E_OP_SREF_S_PRI,
    E_OP_SREF_S_ALT, E_OP_STOR_I, E_OP_STRB_I,
    E_OP_LIDX, E_OP_LIDX_B, E_OP_IDXADDR,
    E_OP_IDXADDR_B, E_OP_ALIGN_PRI, E_OP_ALIGN_ALT,
    E_OP_LCTRL, E_OP_SCTRL, E_OP_MOVE_PRI,
    E_OP_MOVE_ALT, E_OP_XCHG, E_OP_PUSH_PRI,
    E_OP_PUSH_ALT, E_OP_PUSH_R, E_OP_PUSH_C,
    E_OP_PUSH, E_OP_PUSH_S, E_OP_POP_PRI,
    E_OP_POP_ALT, E_OP_STACK, E_OP_HEAP,
    E_OP_PROC, E_OP_RET, E_OP_RETN,
//  E_OP_CALL,
    E_OP_CALL_PRI,
//  E_OP_JUMP, E_OP_JREL, E_OP_JZER,
//  E_OP_JNZ, E_OP_JEQ, E_OP_JNEQ,
//  E_OP_JLESS, E_OP_JLEQ, E_OP_JGRTR,
//  E_OP_JGEQ, E_OP_JSLESS, E_OP_JSLEQ,
//  E_OP_JSGRTR, E_OP_JSGEQ,
    E_OP_SHL, E_OP_SHR, E_OP_SSHR,
    E_OP_SHL_C_PRI, E_OP_SHL_C_ALT, E_OP_SHR_C_PRI,
    E_OP_SHR_C_ALT, E_OP_SMUL, E_OP_SDIV,
    E_OP_SDIV_ALT, E_OP_UMUL, E_OP_UDIV,
    E_OP_UDIV_ALT, E_OP_ADD, E_OP_SUB,
    E_OP_SUB_ALT, E_OP_AND, E_OP_OR,
    E_OP_XOR, E_OP_NOT, E_OP_NEG,
    E_OP_INVERT, E_OP_ADD_C, E_OP_SMUL_C,
    E_OP_ZERO_PRI, E_OP_ZERO_ALT, E_OP_ZERO,
    E_OP_ZERO_S, E_OP_SIGN_PRI, E_OP_SIGN_ALT,
    E_OP_EQ, E_OP_NEQ, E_OP_LESS,
    E_OP_LEQ, E_OP_GRTR, E_OP_GEQ,
    E_OP_SLESS, E_OP_SLEQ, E_OP_SGRTR,
    E_OP_SGEQ, E_OP_EQ_C_PRI, E_OP_EQ_C_ALT,
    E_OP_INC_PRI, E_OP_INC_ALT, E_OP_INC,
    E_OP_INC_S, E_OP_INC_I, E_OP_DEC_PRI,
    E_OP_DEC_ALT, E_OP_DEC, E_OP_DEC_S,
    E_OP_DEC_I, E_OP_MOVS, E_OP_CMPS,
    E_OP_FILL, E_OP_HALT, E_OP_BOUNDS,
    E_OP_SYSREQ_PRI, E_OP_SYSREQ_C, E_OP_JUMP_PRI,
//  E_OP_SWITCH,
//  E_OP_CASETBL,
    E_OP_SWAP_PRI, E_OP_SWAP_ALT, E_OP_PUSH_ADR,
    E_OP_NOP, E_OP_BREAK
};

stock LoadOpcodes() {
    static bool:loaded = false;
   
    // We only need to load them once
    if (loaded)
        return;
    else
        loaded = true;
   
    new addr = _LoadOpcodes(), opcode_values[sizeof(g_Opcodes)];
   
    for (new i = 0; i < sizeof(g_Opcodes); i++) {
        new opcode, param;
       
        #emit LREF.S.pri  addr
        #emit STOR.S.pri  opcode
       
        addr += 4;
       
        if (g_Opcodes[i][HasParam]) {
            #emit LREF.S.pri  addr
            #emit STOR.S.pri  param
           
            //printf("%04x%04x %04x%04x", opcode >>> 16, opcode & 0xFFFF, param >>> 16, param & 0xFFFF);
           
            addr += 4;
        } else {
            //printf("%04x%04x", opcode >>> 16, opcode & 0xFFFF);
        }
       
        opcode_values[i] = opcode;
    }
   
    // bleh
    OP_LOAD_PRI = opcode_values[E_OP_LOAD_PRI]; OP_LOAD_ALT = opcode_values[E_OP_LOAD_ALT]; OP_LOAD_S_PRI = opcode_values[E_OP_LOAD_S_PRI];
    OP_LOAD_S_ALT = opcode_values[E_OP_LOAD_S_ALT]; OP_LREF_PRI = opcode_values[E_OP_LREF_PRI]; OP_LREF_ALT = opcode_values[E_OP_LREF_ALT];
    OP_LREF_S_PRI = opcode_values[E_OP_LREF_S_PRI]; OP_LREF_S_ALT = opcode_values[E_OP_LREF_S_ALT]; OP_LOAD_I = opcode_values[E_OP_LOAD_I];
    OP_LODB_I = opcode_values[E_OP_LODB_I]; OP_CONST_PRI = opcode_values[E_OP_CONST_PRI]; OP_CONST_ALT = opcode_values[E_OP_CONST_ALT];
    OP_ADDR_PRI = opcode_values[E_OP_ADDR_PRI]; OP_ADDR_ALT = opcode_values[E_OP_ADDR_ALT]; OP_STOR_PRI = opcode_values[E_OP_STOR_PRI];
    OP_STOR_ALT = opcode_values[E_OP_STOR_ALT]; OP_STOR_S_PRI = opcode_values[E_OP_STOR_S_PRI]; OP_STOR_S_ALT = opcode_values[E_OP_STOR_S_ALT];
    OP_SREF_PRI = opcode_values[E_OP_SREF_PRI]; OP_SREF_ALT = opcode_values[E_OP_SREF_ALT]; OP_SREF_S_PRI = opcode_values[E_OP_SREF_S_PRI];
    OP_SREF_S_ALT = opcode_values[E_OP_SREF_S_ALT]; OP_STOR_I = opcode_values[E_OP_STOR_I]; OP_STRB_I = opcode_values[E_OP_STRB_I];
    OP_LIDX = opcode_values[E_OP_LIDX]; OP_LIDX_B = opcode_values[E_OP_LIDX_B]; OP_IDXADDR = opcode_values[E_OP_IDXADDR];
    OP_IDXADDR_B = opcode_values[E_OP_IDXADDR_B]; OP_ALIGN_PRI = opcode_values[E_OP_ALIGN_PRI]; OP_ALIGN_ALT = opcode_values[E_OP_ALIGN_ALT];
    OP_LCTRL = opcode_values[E_OP_LCTRL]; OP_SCTRL = opcode_values[E_OP_SCTRL]; OP_MOVE_PRI = opcode_values[E_OP_MOVE_PRI];
    OP_MOVE_ALT = opcode_values[E_OP_MOVE_ALT]; OP_XCHG = opcode_values[E_OP_XCHG]; OP_PUSH_PRI = opcode_values[E_OP_PUSH_PRI];
    OP_PUSH_ALT = opcode_values[E_OP_PUSH_ALT]; OP_PUSH_R = opcode_values[E_OP_PUSH_R]; OP_PUSH_C = opcode_values[E_OP_PUSH_C];
    OP_PUSH = opcode_values[E_OP_PUSH]; OP_PUSH_S = opcode_values[E_OP_PUSH_S]; OP_POP_PRI = opcode_values[E_OP_POP_PRI];
    OP_POP_ALT = opcode_values[E_OP_POP_ALT]; OP_STACK = opcode_values[E_OP_STACK]; OP_HEAP = opcode_values[E_OP_HEAP];
    OP_PROC = opcode_values[E_OP_PROC]; OP_RET = opcode_values[E_OP_RET]; OP_RETN = opcode_values[E_OP_RETN];
//  OP_CALL = opcode_values[E_OP_CALL];
    OP_CALL_PRI = opcode_values[E_OP_CALL_PRI];
//  OP_JUMP = opcode_values[E_OP_JUMP]; OP_JREL = opcode_values[E_OP_OP_JREL]; OP_JZER = opcode_values[E_OP_OP_JZER];
//  OP_JNZ = opcode_values[E_OP_OP_JNZ]; OP_JEQ = opcode_values[E_OP_OP_JEQ]; OP_JNEQ = opcode_values[E_OP_OP_JNEQ];
//  OP_JLESS = opcode_values[E_OP_OP_JLESS]; OP_JLEQ = opcode_values[E_OP_OP_JLEQ]; OP_JGRTR = opcode_values[E_OP_OP_JGRTR];
//  OP_JGEQ = opcode_values[E_OP_OP_JGEQ]; OP_JSLESS = opcode_values[E_OP_OP_JSLESS]; OP_JSLEQ = opcode_values[E_OP_OP_JSLEQ];
//  OP_JSGRTR = opcode_values[E_OP_OP_JSGRTR]; OP_JSGEQ = opcode_values[E_OP_OP_JSGEQ];
    OP_SHL = opcode_values[E_OP_SHL]; OP_SHR = opcode_values[E_OP_SHR]; OP_SSHR = opcode_values[E_OP_SSHR];
    OP_SHL_C_PRI = opcode_values[E_OP_SHL_C_PRI]; OP_SHL_C_ALT = opcode_values[E_OP_SHL_C_ALT]; OP_SHR_C_PRI = opcode_values[E_OP_SHR_C_PRI];
    OP_SHR_C_ALT = opcode_values[E_OP_SHR_C_ALT]; OP_SMUL = opcode_values[E_OP_SMUL]; OP_SDIV = opcode_values[E_OP_SDIV];
    OP_SDIV_ALT = opcode_values[E_OP_SDIV_ALT]; OP_UMUL = opcode_values[E_OP_UMUL]; OP_UDIV = opcode_values[E_OP_UDIV];
    OP_UDIV_ALT = opcode_values[E_OP_UDIV_ALT]; OP_ADD = opcode_values[E_OP_ADD]; OP_SUB = opcode_values[E_OP_SUB];
    OP_SUB_ALT = opcode_values[E_OP_SUB_ALT]; OP_AND = opcode_values[E_OP_AND]; OP_OR = opcode_values[E_OP_OR];
    OP_XOR = opcode_values[E_OP_XOR]; OP_NOT = opcode_values[E_OP_NOT]; OP_NEG = opcode_values[E_OP_NEG];
    OP_INVERT = opcode_values[E_OP_INVERT]; OP_ADD_C = opcode_values[E_OP_ADD_C]; OP_SMUL_C = opcode_values[E_OP_SMUL_C];
    OP_ZERO_PRI = opcode_values[E_OP_ZERO_PRI]; OP_ZERO_ALT = opcode_values[E_OP_ZERO_ALT]; OP_ZERO = opcode_values[E_OP_ZERO];
    OP_ZERO_S = opcode_values[E_OP_ZERO_S]; OP_SIGN_PRI = opcode_values[E_OP_SIGN_PRI]; OP_SIGN_ALT = opcode_values[E_OP_SIGN_ALT];
    OP_EQ = opcode_values[E_OP_EQ]; OP_NEQ = opcode_values[E_OP_NEQ]; OP_LESS = opcode_values[E_OP_LESS];
    OP_LEQ = opcode_values[E_OP_LEQ]; OP_GRTR = opcode_values[E_OP_GRTR]; OP_GEQ = opcode_values[E_OP_GEQ];
    OP_SLESS = opcode_values[E_OP_SLESS]; OP_SLEQ = opcode_values[E_OP_SLEQ]; OP_SGRTR = opcode_values[E_OP_SGRTR];
    OP_SGEQ = opcode_values[E_OP_SGEQ]; OP_EQ_C_PRI = opcode_values[E_OP_EQ_C_PRI]; OP_EQ_C_ALT = opcode_values[E_OP_EQ_C_ALT];
    OP_INC_PRI = opcode_values[E_OP_INC_PRI]; OP_INC_ALT = opcode_values[E_OP_INC_ALT]; OP_INC = opcode_values[E_OP_INC];
    OP_INC_S = opcode_values[E_OP_INC_S]; OP_INC_I = opcode_values[E_OP_INC_I]; OP_DEC_PRI = opcode_values[E_OP_DEC_PRI];
    OP_DEC_ALT = opcode_values[E_OP_DEC_ALT]; OP_DEC = opcode_values[E_OP_DEC]; OP_DEC_S = opcode_values[E_OP_DEC_S];
    OP_DEC_I = opcode_values[E_OP_DEC_I]; OP_MOVS = opcode_values[E_OP_MOVS]; OP_CMPS = opcode_values[E_OP_CMPS];
    OP_FILL = opcode_values[E_OP_FILL]; OP_HALT = opcode_values[E_OP_HALT]; OP_BOUNDS = opcode_values[E_OP_BOUNDS];
    OP_SYSREQ_PRI = opcode_values[E_OP_SYSREQ_PRI]; OP_SYSREQ_C = opcode_values[E_OP_SYSREQ_C]; OP_JUMP_PRI = opcode_values[E_OP_JUMP_PRI];
//  OP_SWITCH = opcode_values[E_OP_SWITCH];
//  OP_CASETBL = opcode_values[E_OP_OP_CASETBL];
    OP_SWAP_PRI = opcode_values[E_OP_SWAP_PRI]; OP_SWAP_ALT = opcode_values[E_OP_SWAP_ALT]; OP_PUSH_ADR = opcode_values[E_OP_PUSH_ADR];
    OP_NOP = opcode_values[E_OP_NOP]; OP_BREAK = opcode_values[E_OP_BREAK];
}

stock _LoadOpcodes() {
    // Return the address of "LOAD.pri" below
    #emit LCTRL      6
    #emit MOVE.alt
    #emit LCTRL      0
    #emit ADD
    #emit MOVE.alt
    #emit LCTRL      1
    #emit SUB.alt
    #emit ADD.C      44
    #emit RETN
   
    // The values of the parameters are insignificant, but they must to be there.
    #emit LOAD.pri    1   // 1
    #emit LOAD.alt    2   // 2
    #emit LOAD.S.pri  3   // 3
    #emit LOAD.S.alt  4   // 4
    #emit LREF.pri    5   // 5
    #emit LREF.alt    6   // 6
    #emit LREF.S.pri  7   // 7
    #emit LREF.S.alt  8   // 8
    #emit LOAD.I          // 9
    #emit LODB.I      10  // 10
    #emit CONST.pri   11  // 11
    #emit CONST.alt   12  // 12
    #emit ADDR.pri    13  // 13
    #emit ADDR.alt    14  // 14
    #emit STOR.pri    15  // 15
    #emit STOR.alt    16  // 16
    #emit STOR.S.pri  17  // 17
    #emit STOR.S.alt  18  // 18
    #emit SREF.pri    19  // 19
    #emit SREF.alt    20  // 20
    #emit SREF.S.pri  21  // 21
    #emit SREF.S.alt  22  // 22
    #emit STOR.I          // 23
    #emit STRB.I      24  // 24
    #emit LIDX            // 25
    #emit LIDX.B      26  // 26
    #emit IDXADDR         // 27
    #emit IDXADDR.B   28  // 28
    #emit ALIGN.pri   29  // 29
    #emit ALIGN.alt   30  // 30
    #emit LCTRL       31  // 31
    #emit SCTRL       32  // 32
    #emit MOVE.pri        // 33
    #emit MOVE.alt        // 34
    #emit XCHG            // 35
    #emit PUSH.pri        // 36
    #emit PUSH.alt        // 37
    #emit PUSH.R      38  // 38
    #emit PUSH.C      39  // 39
    #emit PUSH        40  // 40
    #emit PUSH.S      41  // 41
    #emit POP.pri         // 42
    #emit POP.alt         // 43
    #emit STACK       44  // 44
    #emit HEAP        45  // 45
    #emit PROC            // 46
    #emit RET             // 47
    #emit RETN            // 48
//  #emit CALL        49  // 49
    #emit CALL.pri        // 50
//  #emit JUMP        51  // 51
//  #emit JREL        52  // 52
//  #emit JZER        53  // 53
//  #emit JNZ         54  // 54
//  #emit JEQ         55  // 55
//  #emit JNEQ        56  // 56
//  #emit JLESS       57  // 57
//  #emit JLEQ        58  // 58
//  #emit JGRTR       59  // 59
//  #emit JGEQ        60  // 60
//  #emit JSLESS      61  // 61
//  #emit JSLEQ       62  // 62
//  #emit JSGRTR      63  // 63
//  #emit JSGEQ       64  // 64
    #emit SHL             // 65
    #emit SHR             // 66
    #emit SSHR            // 67
    #emit SHL.C.pri   68  // 68
    #emit SHL.C.alt   69  // 69
    #emit SHR.C.pri   70  // 70
    #emit SHR.C.alt   71  // 71
    #emit SMUL            // 72
    #emit SDIV            // 73
    #emit SDIV.alt        // 74
    #emit UMUL            // 75
    #emit UDIV            // 76
    #emit UDIV.alt        // 77
    #emit ADD             // 78
    #emit SUB             // 79
    #emit SUB.alt         // 80
    #emit AND             // 81
    #emit OR              // 82
    #emit XOR             // 83
    #emit NOT             // 84
    #emit NEG             // 85
    #emit INVERT          // 86
    #emit ADD.C       87  // 87
    #emit SMUL.C      88  // 88
    #emit ZERO.pri        // 89
    #emit ZERO.alt        // 90
    #emit ZERO        91  // 91
    #emit ZERO.S      92  // 92
    #emit SIGN.pri        // 93
    #emit SIGN.alt        // 94
    #emit EQ              // 95
    #emit NEQ             // 96
    #emit LESS            // 97
    #emit LEQ             // 98
    #emit GRTR            // 99
    #emit GEQ             // 100
    #emit SLESS           // 101
    #emit SLEQ            // 102
    #emit SGRTR           // 103
    #emit SGEQ            // 104
    #emit EQ.C.pri    105 // 105
    #emit EQ.C.alt    106 // 106
    #emit INC.pri         // 107
    #emit INC.alt         // 108
    #emit INC         109 // 109
    #emit INC.S       110 // 110
    #emit INC.I           // 111
    #emit DEC.pri         // 112
    #emit DEC.alt         // 113
    #emit DEC         114 // 114
    #emit DEC.S       115 // 115
    #emit DEC.I           // 116
    #emit MOVS        117 // 117
    #emit CMPS        118 // 118
    #emit FILL        119 // 119
    #emit HALT        120 // 120
    #emit BOUNDS      121 // 121
    #emit SYSREQ.pri      // 122
    #emit SYSREQ.C    123 // 123
    #emit JUMP.pri        // 128
//  #emit SWITCH      129 // 129
//  #emit CASETBL         // 130
    #emit SWAP.pri        // 131
    #emit SWAP.alt        // 132
    #emit PUSH.ADR    133 // 133
    #emit NOP             // 134
    #emit BREAK           // 137
   
    return 0;
}
Reply
#2

It seems to have to do with the number of unique opcodes used, or at least I suspect so.

The values on Linux are absolute pointers, though it gets even more mysterious here.. I collected a few values that the opcode values pointed to, reversed the byte order, and came up with this:
Look at ALIGN.alt/ALIGN.pri! While their pointers were different, they pointed to the same values (perhaps some sort of struct with the same info in the beginning, who knows).

(the lines that are grouped are next to each other in amx.h).

Код:
/*
	Values for opcodes:
	
	ADD       - 0x8B55C089 - 0b10001011010101011100000010001001
	ADD.C     - 0x8B168D46 - 0b10001011000101101000110101000110
	ADDR.alt  - 0x8B55C08D - 0b10001011010101011100000010001101
	ADDR.pri  - 0x8B4DC08D - 0b10001011010011011100000010001101
	ALIGN.alt - 0x8B0683C6 - 0b10001011000001101000001111000110
	ALIGN.pri - 0x8B0683C6 - 0b10001011000001101000001111000110
	
	JZER      - 0x8B45E485 - 0b10001011010001011110010010000101
	LCTRL     - 0x833E068D - 0b10000011001111100000011010001101
	
	MOVE.alt  - 0x8B4DE489 - 0b10001011010011011110010010001001
	MOVE.pri  - 0x8B55C089 - 0b10001011010101011100000010001001
	MOVS      - 0x8B45E48B - 0b10001011010001011110010010001011
	
	NEG       - 0x8B4DC089 - 0b10001011010011011100000010001001
	NEQ       - 0x8B4DBC31 - 0b10001011010011011011110000110001
	NOP       - 0x8B7DC089 - 0b10001011011111011100000010001001
	
	PUSH.alt  - 0x8B45BC8D - 0b10001011010001011011110010001101
	PUSH.pri  - 0x8B45E48D - 0b10001011010001011110010010001101
*/
Reply
#3

Are you suggesting polymorphism?
Reply
#4

It perhaps has to do with that trickery of opcode_list. One should inspect amx sources to be sure of (or to get to know) the reason of this behaviour.
Reply
#5

I think the values read are addresses to labels in amx.c. That's why many of them look similar, they all start with GETPARAM(offs) and some other stuff.

Edit:
Quote:
Originally Posted by amx.c
pawn Код:
/* GNU C version uses the "labels as values" extension to create
 * fast "indirect threaded" interpreter. The Intel C/C++ compiler
 * supports this too.
 */
Reply
#6

Well, you do not actually need to care about values you get(pointer values could change across releases).
By the way, here are excerpts from amx.c so you can see that your values are pointers to opcode labels(token threading technique <wiki>):
Код:
    #if (defined __GNUC__ || defined __ICC || defined ASM32 || defined JIT) && !defined AMX_TOKENTHREADING
      /* relocate opcode (only works if the size of an opcode is at least
       * as big as the size of a pointer (jump address); so basically we
       * rely on the opcode and a pointer being 32-bit
       */
      *(cell *)(code+(int)cip) = opcode_list[op];
    #endif
Код:
static const void * const amx_opcodelist[] = {
        &&op_none,      &&op_load_pri,  &&op_load_alt,  &&op_load_s_pri,
        &&op_load_s_alt,&&op_lref_pri,  &&op_lref_alt,  &&op_lref_s_pri,
        &&op_lref_s_alt,&&op_load_i,    &&op_lodb_i,    &&op_const_pri,
        &&op_const_alt, &&op_addr_pri,  &&op_addr_alt,  &&op_stor_pri,
        &&op_stor_alt,  &&op_stor_s_pri,&&op_stor_s_alt,&&op_sref_pri,
        &&op_sref_alt,  &&op_sref_s_pri,&&op_sref_s_alt,&&op_stor_i,
        &&op_strb_i,    &&op_lidx,      &&op_lidx_b,    &&op_idxaddr,
        &&op_idxaddr_b, &&op_align_pri, &&op_align_alt, &&op_lctrl,
        &&op_sctrl,     &&op_move_pri,  &&op_move_alt,  &&op_xchg,
        &&op_push_pri,  &&op_push_alt,  &&op_push_r,    &&op_push_c,
        &&op_push,      &&op_push_s,    &&op_pop_pri,   &&op_pop_alt,
        &&op_stack,     &&op_heap,      &&op_proc,      &&op_ret,
        &&op_retn,      &&op_call,      &&op_call_pri,  &&op_jump,
        &&op_jrel,      &&op_jzer,      &&op_jnz,       &&op_jeq,
        &&op_jneq,      &&op_jless,     &&op_jleq,      &&op_jgrtr,
        &&op_jgeq,      &&op_jsless,    &&op_jsleq,     &&op_jsgrtr,
        &&op_jsgeq,     &&op_shl,       &&op_shr,       &&op_sshr,
        &&op_shl_c_pri, &&op_shl_c_alt, &&op_shr_c_pri, &&op_shr_c_alt,
        &&op_smul,      &&op_sdiv,      &&op_sdiv_alt,  &&op_umul,
        &&op_udiv,      &&op_udiv_alt,  &&op_add,       &&op_sub,
        &&op_sub_alt,   &&op_and,       &&op_or,        &&op_xor,
        &&op_not,       &&op_neg,       &&op_invert,    &&op_add_c,
        &&op_smul_c,    &&op_zero_pri,  &&op_zero_alt,  &&op_zero,
        &&op_zero_s,    &&op_sign_pri,  &&op_sign_alt,  &&op_eq,
        &&op_neq,       &&op_less,      &&op_leq,       &&op_grtr,
        &&op_geq,       &&op_sless,     &&op_sleq,      &&op_sgrtr,
        &&op_sgeq,      &&op_eq_c_pri,  &&op_eq_c_alt,  &&op_inc_pri,
        &&op_inc_alt,   &&op_inc,       &&op_inc_s,     &&op_inc_i,
        &&op_dec_pri,   &&op_dec_alt,   &&op_dec,       &&op_dec_s,
        &&op_dec_i,     &&op_movs,      &&op_cmps,      &&op_fill,
        &&op_halt,      &&op_bounds,    &&op_sysreq_pri,&&op_sysreq_c,
        &&op_file,      &&op_line,      &&op_symbol,    &&op_srange,
        &&op_jump_pri,  &&op_switch,    &&op_casetbl,   &&op_swap_pri,
        &&op_swap_alt,  &&op_push_adr,  &&op_nop,       &&op_sysreq_n,
        &&op_symtag,    &&op_break,     &&op_push2_c,   &&op_push2,
        &&op_push2_s,   &&op_push2_adr, &&op_push3_c,   &&op_push3,
        &&op_push3_s,   &&op_push3_adr, &&op_push4_c,   &&op_push4,
        &&op_push4_s,   &&op_push4_adr, &&op_push5_c,   &&op_push5,
        &&op_push5_s,   &&op_push5_adr, &&op_load_both, &&op_load_s_both,
        &&op_const,     &&op_const_s,
#if !defined AMX_NO_PACKED_OPC
        &&op_load_p_pri,  &&op_load_p_alt, &&op_load_p_s_pri,&&op_load_p_s_alt,
        &&op_lref_p_pri,  &&op_lref_p_alt, &&op_lref_p_s_pri,&&op_lref_p_s_alt,
        &&op_lodb_p_i,    &&op_const_p_pri,&&op_const_p_alt, &&op_addr_p_pri,
        &&op_addr_p_alt,  &&op_stor_p_pri, &&op_stor_p_alt,  &&op_stor_p_s_pri,
        &&op_stor_p_s_alt,&&op_sref_p_pri, &&op_sref_p_alt,  &&op_sref_p_s_pri,
        &&op_sref_p_s_alt,&&op_strb_p_i,   &&op_lidx_p_b,    &&op_idxaddr_p_b,
        &&op_align_p_pri, &&op_align_p_alt,&&op_push_p_c,    &&op_push_p,
        &&op_push_p_s,    &&op_stack_p,    &&op_heap_p,      &&op_shl_p_c_pri,
        &&op_shl_p_c_alt, &&op_shr_p_c_pri,&&op_shr_p_c_alt, &&op_add_p_c,
        &&op_smul_p_c,    &&op_zero_p,     &&op_zero_p_s,    &&op_eq_p_c_pri,
        &&op_eq_p_c_alt,  &&op_inc_p,      &&op_inc_p_s,     &&op_dec_p,
        &&op_dec_p_s,     &&op_movs_p,     &&op_cmps_p,      &&op_fill_p,
        &&op_halt_p,      &&op_bounds_p,   &&op_push_p_adr,
#endif
        &&op_sysreq_d,  &&op_sysreq_nd };
Note 1: && is special GNUC construction to get a label's address.
Note 2: that opcode_list is actually amx_opcodelist.
This is kind of proof that your code should work(if there's no error in your implementation, though I did not see any.)
Reply
#7

The only little issue that remains is you can't emit SYSREQ.D with #emit because it requires 2 params (only opcodes with 1 param works in #emit due to a bug).
I suppose searching for like 5 pointers in a row would get us the location of amx_opcodelist, which then would get us the pointer for op_sysreq_d.
Reply
#8

You could perhaps get "op_const_s"(the opcode before op_sysreq_d, note that AMX_NO_PACKED_OPC is undefined, thus not accounted for) opcode pointer and increment it by 4 (because we can assert that amx_opcodelist structure won't change and AMX_NO_PACKED_OPC was not defined at time of compiling compiler)
thus getting us address of op_sysreq_d.
Reply
#9

The problem is all those opcodes above op_sysreq_d require more than 1 params, which can't be emitted with the original PAWN compiler.

Edit: Oh, you mean like that.. Of course!

Edit2: The values read from COD are pointers directly to the labels, so that won't work.
Reply
#10

Seems like SYSREQ.d was replaced with SYSREQ.n
Код:
	{135, "sysreq.n",   sIN_CSEG, parm2 },  /* version 9 (replaces SYSREQ.d from earlier version) */
and SYSREQ.n can be compiled(with 1 param though but we do not care about that because we add additional one manually).
Reply
#11

That doesn't work as it seems to silently fail when loading the AMX.

http://slice-vps.nl/ppg/#gist=58965657788cc6b3acd7
Reply
#12

Then only alternative i can think of is looking up in IDA to see raw difference between labels, i.e. (op_sysreq_d - op_const_s) and using that when you want to get op_sysreq_d label(i.e. place op_const_s at some offset where you want op_sysreq_d and increment its value by pointer difference, which should be constant across releases)
Reply
#13

What I don't like about that, though, is if opcodes were to change (they have in the past). Maybe not even changed, but different compiler optimizations could change the size as well.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)