User Tools

Site Tools


ocmbytecode

OCM VM basics

The OCM bytecode machine is an interpreter for a stack based language. That means that the operands are pushed on a stack first, than the operation is encoded that takes the operands from the stack and puts the result back on the stack. Some typical stack-based languages include RPN calculators, PostScript, Forth and the Java VM. These are specific properties of the OCM machine:

  • It has 256 global variables that are addressed using a single byte.
    • Entry 252 (0xFC): blob with 8 bytes created from gettimeofday
    • Entry 253 (0xFD): blob with 1024 bytes: function pointers for byte codes (patched by interpreter extensions)
    • Entry 254 (0xFE): shortint, hiword/loword are major/minor OCM machine version (3.3 for OpenMG 3.4)
    • Entry 255 (0xFF): shortint, in OpenMG 3.4: constant 1
  • It has a hash table for further global variables that is indexed by a 32 bit number.
  • It has a second, alternat stack. This stack is used to save context information for call/return, but also provides operands to certain instructions or can be used as general purpose storage. As it is used for saving the return context, add the end of a code block you must not have anything left on the alternate stack that was not there at the beginning.
  • The interpreter can do simple multithreading
  • The interpreter has a Stream RNG to decode the instructions (although instruction decoding is initially off)
  • The interpreter has a User RNG with a 63 byte state (totally seperate from the stream RNG!)
  • It provides a "backdoor" in that you can load native x86 code and execute it.

OCM Datatypes

Small numbers are a value type, whereas all other types are reference types, i.e. the values are merely references to reference counted objects. The term object means the thing the reference points to. Reference counting can be disabled on individual objects, making the permanent.

Small numbers are stored directly in the stack. Other objects are accessed through an intermediate data structure (handle) that points to the object. The value on the stack then is a pointer to the handle, shifted by two bits to the right. The highest two bits contain the type.

  struct stack_value
    {
      union
        {
          unsigned int value : 30;
          void *handle_div_4;
        };
      unsigned int type : 2;
    };

  struct bigint_handle
    {
      uint8_t refcount;
      uint8_t is_negative;
      uint16_t len_in_32bitwords;
      uint32_t payload[0]; // Variable-length-array
    };

  struct blob_handle
    {
      uint8_t refcount;
      uint8_t heap_allocated;
      uint8_t unknown;
      uint8_t zero; // Location of data pointer for 0 byte blocks.
      uint32_t length;
      void *data;
    };

  struct array_handle
    {
      uint8_t refcount;
      uint8_t unused;
      uint16_t nr_elements;
      stack_value data[0]; // Variable length array, entries are handles/smallints
    };

Small numbers (tag 0): signed 16 bit numbers

Large integers (tag 1): arbitraty precision integers

Serialization format: Length followed by two's complement little endian representation. The length is according to ASN.1 lengths: Length is directly encoded as one byte for lengths 0..127. A length encoding starting with 128 is invalid (would mean unspecified). If the first byte of the length is above 128, subtract 128 and take that many bytes. They make up a big-endian unsigned integer.

Binary blobs (tag 2)

Serialization format: Length followed by the bytes. Length is encoded as for the integers.

Array (tag 3): An heterogenous array of OCM objects (may contain arrays)

Serialization format: ASN.1 heterogenous sequence

OCM Opcodes

Opcodes 00..0F

Opcode 0x00: NOP

does nothing

Opcode 0x01: Immediate byte (value)

immediate data: 1 byte (plaintext, even if OCM code encryption is enabled)

effect: pushes the unsigned 8 bit value of the immediate operand to the stack as small number

Opcode 0x02: Immediate word (value)

immediate data: 1 16-bit-word (plaintext, even if OCM code encryption is enabled)

effect: pushes the signed 16 bit value of the immediate operand to the stack as small number

note: This is used to set up a new decryption key before a 0x73 (Set initial bytecode decryption key in the interpreter) instruction.

Opcode 0x03: Immediate BigInt (value)

immediate data: 1 big int (plaintext, even if OCM code encryption is enabled)

effect: pushes the big int onto stack (after deserialization)

Opcode 0x04: Immediate Blob (value)

immediate data: 1 blob (plaintext, even if OCM code encryption is enabled)

effect: pushes the blob onto stack (after deserialization)

Opcode 0x05: Duplicate Top-Of-Stack (dup)

stack input: one value of any type

effect: leaves the input on the stack and pushes a (shallow) copy

Opcode 0x06: Duplicate if not Zero (dupnonzero)

stack input: one value of any type

effect: duplicates the value like opcode 05, unless it is zero stored as a small int. In that case: no effect

Opcode 0x07: Pop (pop)

stack input: one value of any type

effect: the top-of-stack value is deleted. If the stack would get empty, a small int zero is pushed.

Opcode 0x08: Pop & Delete (destroy)

stack input: one value of any type

effect: Like Pop, but instead of just dropping the reference count for references, the object gets deleted at once. Mostly useful for permanent objects.

Opcode 0x09 (09): Exchange (exch)

effect: exchanges top of stack with next-to-top-of-stack

Opcode 0x0A (10): Next To Top (index)

effect: pushes a copy of the next-to-top value.

PostScript equivalent: "1 index"

Opcode 0x0B (11): Fetch from Somewhere in Stack (index)

stack input: an index into the stack (call it n); must be small integer and > 0

effect: pushes a copy of the value at n below the input operand. So "Immediate 1;FetchStack" is the same as "Duplicate" and "Immediate 2;FetchStack" is the same as "NextToTop".

PostScript equivalent: "1 sub index"

Opcode 0x0C (12): Move Top-2 to Top (exch)

effect: The value at Top-2 gets moved to top of stack, top of stack becomes top-1 and top-1 is moved to top-2

PostScript equivalent: "3 -1 roll"

Opcode 0x0D (13): Move Any to Top (rollin)

stack input: in index into the stack (call it n); must be small integer and > 1

effect: moves the n-th operand below the input operand n to top of stack, shifting everything inbetween downwards. "Immediate 2;MoveToTop" is the same as "Exchange".

PostScript equivalent: "-1 roll"

Opcode 0x0E (14): Set in Big dictionary (setudict)

stack input: value (any type, next-to-top); Key (blob of 4 bytes at top of stack)

effect: Adds/Updates an entry in the user dictionary.

Opcode 0x0F (15): Set in Any Dictionary (setdict)

stack input: value (any type, next-to-top); Key (blob of 4 bytes OR small int at top of stack)

effect: If top of stack is a small int, the value is stored in the system dictionary at the given index. Must be below 0x100. If top of stack is a blob, like SetInUserDict.

Opcodes 10..1F

Opcode 0x10 (16): Get from dictionary (getdict)

stack input: dictionary key (either nonnegative smallint < 0x100 or 4 byte blob)

effect: Looks up the given key in the system dictionary (if a small int) or the user dictionary otherwise. OCM exception gets thrown if the key is not found

stack output: the result of the dictionary lookup

Opcode 0x11 (17): Add Small Ints (add)

stack input: smallint a (next to top); smallint b (top of stack)

stack output: smallint containing a+b

Opcode 0x12 (18): Subtract Small Ints (sub)

stack input: smallint a (next to top); smallint b (top of stack)

stack output: smallint containing a-b

Opcode 0x13 (19): Multipy Small Ints (mul)

stack input: smallint a (next to top); smallint b (top of stack)

stack output: smallint containing lowest 16 bits of a*b

Opcode 0x14 (20): Divide Small Ints (div)

stack input: smallint a (next to top); smallint b (top of stack)

stack output: smallint containing a/b

Opcode 0x15 (21): Divide and Modulus of Small Ints (moddiv)

stack input: smallint a (next to top); smallint b (top of stack)

stack output: smallint containing a/b (next to top); smallint containing a%b (top of stack)

Opcode 0x16 (22): Modulus of Small Ints (divmod)

stack input: smallint a (next to top); smallint b (top of stack)

stack output: smallint containing a%b

Opcode 0x17 (23): Xor Small Ints (xor)

stack input: smallint a (next to top); smallint b (top of stack)

stack output: smallint containing a ^ b

Opcode 0x18 (24): And Small Ints (and)

stack input: smallint a (next to top); smallint b (top of stack)

stack output: smallint containing a & b

Opcode 0x19 (25): Or Small Ints === (or)

stack input: smallint a (next to top); smallint b (top of stack)

stack output: smallint containing a | b

Opcode 0x1A (26): Bitwise Negate Small Int (neg)

stack input: smallint a

stack output: smallint containing ~a

Opcode 0x1B (27): Shift Left Small Int (shl)

stack input: smallint a (next to top); smallint count (top of stack)

stack output: smallint containing a « count

Opcode 0x1C (28): Shift Right Small Int (shr)

stack input: smallint a (next to top); smallint count (top of stack)

stack output: smallint containing ( (unsigned)a) » count

Opcode 0x1D (29): Shift Right Arithmetic Small Int (sar)

stack input: smallint a (next to top); smallint count (top of stack)

stack output: smallint containing a » count

Opcode 0x1E (30): Compare Small Ints for Greater (cmp)

stack input: smallint a (next to top); smallint b (top of stack)

stack output: smallint containing 1 if a > b, 0 otherwise

Opcode 0x1F (31): Compare Small Ints for Less (cmp)

stack input: smallint a (next to top); smallint b (top of stack)

stack output: smallint containing 1 if a < b, 0 otherwise

Opcodes 20..2F

Opcode 0x20 (32): Compare Small Ints for equal (cmp)

stack input: smallint a (next to top); smallint b (top of stack)

stack output: smallint containing 1 if a == b, 0 otherwise

Opcode 0x21 (33): Test for Small Int Zero (iszerow)

stack input: object of any type (maybe only smallint intended)

stack output: 1 if object has type smallint and is zero

Opcode 0x22 (34): Add DWORDs (add)

stack input: small/big int a (next to top); small/big int b (top of stack)

stack output: 32 bit bigint containing a+b

note: DWORD instructions only use the 32 least significant bits in bigint input operands, and samllint operands are treated as unsigned for unknown reasons. All arithmetic is unsigned. As bigints are in sign/magnitude representation, the input sign is ignored for bigints, but not for small ints that are two's complement. But do not use the function with negative inputs unless you wrote the OCM bytecode interpreter, because the sign of the output is undefined in that case (unless you know the internals of the interpreter, that is)

Opcode 0x23 (35): Subtract DWORDs (sub)

stack input: small/big int a (next to top); small/big int b (top of stack)

stack output: 32 bit bigint containing a-b

note: See Opcode 22 for important notes on DWORD instructions.

Opcode 0x24 (36): Multiply DWORDs (mul)

stack input: small/big int a (next to top); small/big int b (top of stack)

stack output: 32 bit bigint containing a*b (low order 32 bits)

note: See Opcode 22 for important notes on DWORD instructions.

Opcode 0x25 (37): Divide DWORDs (div)

stack input: small/big int a (next to top); small/big int b (top of stack)

stack output: 32 bit bigint containing a/b

note: See Opcode 22 for important notes on DWORD instructions.

Opcode 0x26 (38): Division and Modulus of DWORDs (divmod)

stack input: small/big int a (next to top); small/big int b (top of stack)

stack output: 32 bit bigint containing a/b (next-to-top); 32 bit bigint containing a%b (top of stack)

note: See Opcode 22 for important notes on DWORD instructions.

Opcode 0x27 (39): Modulus of DWORDs (moddiv)

stack input: small/big int a (next to top); small/big int b (top of stack)

stack output: 32 bit bigint containing a%b

note: See Opcode 22 for important notes on DWORD instructions.

Opcode 0x28 (40): Xor DWORDs (xor)

stack input: small/big int a (next to top); small/big int b (top of stack)

stack output: 32 bit bigint containing a ^ b

note: See Opcode 22 for important notes on DWORD instructions.

Opcode 0x29 (41): And DWORDs (and)

stack input: small/big int a (next to top); small/big int b (top of stack)

stack output: 32 bit bigint containing a & b

note: See Opcode 22 for important notes on DWORD instructions.

Opcode 0x2A (42): Or DWORDs (or)

stack input: small/big int a (next to top); small/big int b (top of stack)

stack output: 32 bit bigint containing a | b

note: See Opcode 22 for important notes on DWORD instructions.

Opcode 0x2B (43): Bitwise Not DWORD (not)

stack input: small/big int a (top of stack)

stack output: 32 bit bigint containing ~a

note: See Opcode 22 for important notes on DWORD instructions.

Opcode 0x2C (44): Shift Left DWORD (shl)

stack input: small/big int a (next to top); small/big int count (top of stack)

stack output: 32 bit bigint containing a « count

note: See Opcode 0x22 for important notes on DWORD instructions.

Opcode 0x2D (45): Shift Right DWORD (shr)

stack input: small/big int a (next to top); small/big int count (top of stack)

stack output: 32 bit bigint containing a » count

note: See Opcode 22 for important notes on DWORD instructions.

Opcode 0x2E (46): Compare DWORDs for Less (cmp)

stack input: small/big int a (next to top); small/big int b (top of stack)

stack output: smallint containing 1 if a < b; 0 otherwise

note: See Opcode 22 for important notes on DWORD instructions.

Opcode 0x2F (47): Compare DWORDs for Greater (cmp.gt)

stack input: small/big int a (next to top); small/big int b (top of stack)

stack output: smallint containing 1 if a > b; 0 otherwise

note: See Opcode 22 for important notes on DWORD instructions.

Opcodes 30..3F

Opcode 0x30 (48): Compare DWORDs for Equality (cmp.eq)

stack input: small/big int a (next to top); small/big int b (top of stack)

stack output: smallint containing 1 if a == b; 0 otherwise

note: See Opcode 22 for important notes on DWORD instructions.

Opcode 0x31 (49): Execute (exec)

stack input: binary blob containing bytecode

effect: executes the code from the binary blob, continuing after the Execute instruction after the end of the block has been reached.

note: The current execution context is saved on the alternate stack. The blob must not leave something behind on the alternate stack or bad things will happen. The blob also shouldn't try to access the context information on the alternate stack, as it might contain arbitrary 32 bit data that can not be validly interpreted as OCM language objects. Of course the standard stack might be altered by the code in the subblock.

PostScript equivalent: "exec"

Opcode 0x32 (50): If/Else (ifelse)

stack input: selector (smallint at second to top of stack), blob for the true case (next to top), blob for the false case (top of stack)

effect: if the selector is not zero, the true blob is executed (as in Opcode 31), otherwise the false blob is executed.

Opcode 0x33 (51): While (while)

stack input: condition flag (smallint)

alternate stack input: blob to execute (not removed by this instruction)

effect: if the condition flag is not zero, the blob at the top of the alternate stack is executed. After execution, the while instruction is restarted, examining the value now at the top of the stack.

note: The blob reference on the alternate stack is not removed by this instruction, just the condition flag on the standard stack.

Opcode 0x34 (52): Push to alternate stack (toalt)

stack input: value of any type

alternate stack output: that value of any type

effect: The value is moved from the standard stack to the alternate stack

Opcode 0x35 (53): Pop from alternate stack (fromalt)

alternate stack input: value of any type

stack output: that value

effect: The value is moved from the alternate stack to the standard stack

Opcode 0x36 (54): Peek alternate stack (peekalt)

alternate stack input: value of any type (not removed by this instruction)

stack output: that value

effect: The value is copied from the alternate stack to the standard stack

Opcode 0x37 (55): Push 0 (0)

stack output: smallint containing 0

Opcode 0x38 (56): Push 1 (1)

stack output: smallint containing 1

Opcode 0x39 (57): Push 2 (2)

stack output: smallint containing 2

Opcode 0x3A (58): Push 3 (3)

stack output: smallint containing 3

Opcode 0x3B (59): Push 4 (4)

stack output: smallint containing 4

Opcode 0x3C (60): Push 5 (5)

stack output: smallint containing 5

Opcode 0x3D (61): Push 6 (6)

stack output: smallint containing 6

Opcode 0x3E (62): Push 7 (7)

stack output: smallint containing 7

Opcode 0x3F (63): Push 8 (8)

stack output: smallint containing 8

Opcodes 40..4F

Opcode 0x40 (64): Push 9

stack output: smallint containing 9

Opcode 0x41 (65): Push -1

stack output: smallint containing -1

Opcode 0x42 (66): Push -2

stack output: smallint containing -2

Opcode 0x43 (67): Push -3

stack output: smallint containing -3

Opcode 0x44 (68): Test Small Int Positive

stack input: smallint a

stack ouput: smallint 1 if a > 0, smallint 0 else

Opcode 0x45 (69): Test Small Int Negative

stack input: smallint a

stack ouput: smallint 1 if a < 0, smallint 0 else

Opcode 0x46 (70): Test Small Int for Zero

stack input: smallint a

stack ouput: smallint 1 if a == 0, smallint 0 else

note: in contrast to Opcode 21 "Test for Small Int Zero", this opcode has undefined behaviour of the operand is not a small integer.

Opcode 0x47 (71): Duplicate second-to-top (index.1)

effect: pushes a copy of the second-to-top (the third value if you call top-of-stack the first one) to the standard stack.

PostScript equivalent: "2 index"

Opcode 0x48 (72): Duplicate third-to-top (index.2)

effect: pushes a copy of the third-to-top (the fourth value if you call top-of-stack the first one) to the standard stack.

PostScript equivalent: "3 index"

Opcode 0x49 (73): Duplicate fourth-to-top (index.3)

effect: pushes a copy of the fourth-to-top (the 5th value if you call top-of-stack the first one) to the standard stack.

PostScript equivalent: "4 index"

Opcode 0x4A (74): Duplicate 5th-to-top (index.4)

effect: pushes a copy of the 5th-to-top (the 6th value if you call top-of-stack the first one) to the standard stack.

PostScript equivalent: "5 index"

Opcode 0x4B (75): Move Top-3 to top (rollin.5)

effect: The value at Top-3 gets moved to top of stack, top of stack becomes top-1 and so on.

PostScript equivalent: "4 -1 roll"

Opcode 0x4C (76): Move Top-4 to top (rollin.4)

effect: The value at Top-4 gets moved to top of stack, top of stack becomes top-1 and so on.

PostScript equivalent: "5 -1 roll"

Opcode 0x4D (77): Move Top-5 to top (rollin.3)

effect: The value at Top-5 gets moved to top of stack, top of stack becomes top-1 and so on.

PostScript equivalent: "6 -1 roll"

Opcode 0x4E (78): Increment Small Int (inc.w)

stack input: smallint a

stack ouput: smallint (a+1)

Opcode 0x4F (79): Decrement Small Int (dec.w)

stack input: smallint a

stack output: smallint (a-1)

Opcodes 50..5F

Opcode 0x50 (80): Convert to signed number (cvtnum.s)

stack input: value a that is not an array

stack output: a if a is numeric (smallint or bigint). If a is a blob, is is read as a two's complement signed big-endian number and returned in a bigint.

Opcode 0x51 (81): Convert to unsigned number (cvtnum.u)

stack input: value a that is not an array

stack output: a if a is numeric (smallint or bigint). If a is a blob, is is read as an unsigned big-endian number and returned in a bigint.

note: Negative smallints or bigints are unchanged by this operation. Compare opcode 53 "Make operand unsigned".

Opcode 0x52 (82): Make blob (cvtblob)

stack input: value a that is not an array

stack output: If the input is a blob, it remains unchanged. Otherwise, it is returned as two's complement big-endian number in a blob.

Opcode 0x53 (83): Make operand unsigned (numunsigned)

stack input: numeric value a

stack output: A numeric value that results from interpreting the bits in a as unsigned number. I.e. smallints 0..32767 are returned unchanged. smallints -1..-32768 are converted to bigints 65536..32768 respsctively. Negative big-ints are sign-extended to whole bytes and the resulting value is treated as unsigned value

Opcode 0x54 (84): Truncate to Small Int (trunc16)

stack input: numeric value a

stack output: smallints stay unchanged. The low 16 bits of the absolute value are returned for bigints, so unless you know what you are doing, only use this instruction for the range 0..32767

Opcode 0x55 (85): Pack to Array (array.astore)

stack input: n value of any type; smallint n (at top of stack)

stack output: (reference to) a newly created array containing the n elements from the stack below the count itself

Opcode 0x56 (86): Unpack Array (aload.length)

stack input: an array of n elements

stack output: n values of any type (the array element); smallint n (count of elements; at top of stack)

Opcode 0x57 (87): Array Length (length.arr)

stack input: an array with n elements

stack output: smallint n

Opcode 0x58 (88): Insert to Array (ainsert)

stack input: entry (any type, second to top); an array (next to top); index (small or big int at top of stack)

stack output: A (reference to a) copy of the array with the new element entry inserted before the index'th element (moving all elements after the inserted one position to the end of the array)

Opcode 0x59 (89): Delete from Array (acut)

stack input: an array (next to top); index (small or big int at top of stack)

stack output: A (reference to a) copy of the array with the element at position index removed (and all further elements moved one position to the front)

Opcode 0x5A (90): Get Array Element (get)

stack input: (reference to) an array (next to top); smallint k (top of stack)

stack output: The k'th element of the array.

Opcode 0x5B (91): Set Array Element (set)

stack input: value x of any type (second to top); (reference to) an array (next to top); smallint k (at top)

stack output: The k'th element of the array before replacing it.

effect: The k'th element of the array is replaced by x.

note: This operation does not copy the array, so the element changes globally.

Opcode 0x5C (92): Create Array (array)

stack input: n (smallint at top of stack)

stack output: A newly allocated array of n elements. All elements are initialized with smallint zero.

Opcode 0x5D (93): Encode ASN.1 (asn1encode)

stack input: value to encode (any type)

stack output: A blob that contains the ASN.1 representation of the value.

note: Encoding uses universal tags as follows:

  • smallints and bigints are encoded as INTEGER (ASN.1 tag 0x02)
  • blobs are encoded as OCTET STRING (ASN.1 tag 0x04)
  • arrays are encoded as SEQUENCE (ASN.1 tag 0x30), the sequence is always encoded as unknown-length and double-zero-terminated.

Opcode 0x5E (94): Catenate to Sequence (asn1array)

stack input: n blobs (should contain ASN.1 encoded data, first element pushed first, last element next-to-top); n (smallint at top of stack)

stack output: a blob containing an ASN.1 sequence of the n encoded objects.

note: The output is just 0x30 (SEQUENCE); 0x80 (unknown length); catenation of all blobs; 0x00; 0x00

Opcode 0x5F (95): Decode ASN.1 (asn1decode)

stack input: a blob containing an ASN.1 encoded object.

stack ouput: the decoded object.

note: The following objects are recognized:

  • Tag 0x01 (BOOLEAN) → decoded as smallint 0 or 1
  • Tag 0x02 (INTEGER) → Values 0..32767 as smallint; other values as bigint
  • Tag 0x17, Tag 0x18 (UTCTime, GeneralizedTime) → bigint containing a unix timestamp (seconds since 1.1.1970, 00:00 GMT)
  • all other univesal tags with composed object bit clear (0x03-0x16;0x19-0x1F) → decoded as blob
  • Tag 0x30, Tag 0x31 (SEQUENCE, SET) → decoded as array
  • all context-specific tags (0x80..0xBF) → decoded as blob

Opcodes 60..6F

Opcode 0x60 (96): Enclose Smallint (enclose)

stack input: A smallint

stack output: A blob containing the little-endian (host byte order) representation of the smallint

Note: the blob that gets returned is non-refcounted and lives until explicit destruction (for example by opcode 08)

Opcode 0x61 (97): Get Enclosed Smallint (disclose)

stack input: A blob that encloses a small integer, created by opcode 60

stack output: The enclosed small integer

Opcode 0x62 (98): Get Significant Bits (countbits)

stack input: Object of any type

stack ouput: Significant bit in that object. For smallints and bigints its the minimal number of bits to represent the absolute value of that number, for blobs the number of bytes multiplied by 8 and for arrays the sum of the number of significant bits of all entries.

Opcode 0x63 (99): Immediate Crypted Byte (0x??w)

immediate data: 1 byte (encrypted if OCM code encryption is enabled)

effect: pushes the unsigned 8 bit value of the immediate operand to the stack as small number

note: Is often used to refer to the dictionary index where the data is stored.

Opcode 0x64 (100): Immediate Crypted Word (0x?w)

immediate data: 1 16-bit-word (encrypted if OCM code encryption is enabled)

effect: pushes the signed 16 bit value of the immediate operand to the stack as small number

Opcode 0x65 (101): Immediate Crypted BigInt (value)

immediate data: 1 big int (encrypted if OCM code encryption is enabled)

effect: pushes the big int onto stack (after deserialization)

note: If the OCM module uses the DWORD-based decryptor (it doesn't start with 03 01 in that case, we did not encounter such a module yet), it is important to know that the immediate arg is decrypted in three parts: (1) initial length byte, (2) extra length bytes, optional, (3) data bytes.

Opcode 0x66 (102): Immediate Crypted Blob (value)

immediate data: 1 blob (encrypted if OCM code encryption is enabled)

effect: pushes the blob onto stack (after deserialization)

note: If the OCM module uses the DWORD-based decryptor (it doesn't start with 03 01 in that case, we did not encounter such a module yet), it is important to know that the immediate arg is decrypted in three parts: (1) initial length byte, (2) extra length bytes, optional, (3) data bytes.

Opcode 0x67 (103): Start Threads (threads)

stack input: common thread arg (any type); n blobs containing byte code; smallint n (at top of stack)

effect: Starts pseudo-parallel execution of all n blobs. Execution of the main code (that invoked this opcode) stops until all threads are finished or the threaded evaluation mode is cancelled. All threads have their own stack, each containing just the common arg. Also every thread has its private alternate stack.

Opcode 0x68 (104): Set Time Slice Length (timeslice)

stack input: smallint or bigint len

effect: Sets the time slice length for this subthread to len. That is the number of bytecode instructions executed for this thread until execution continues with another thread. The current timeslice is unmodified, it just affects the following slices.

Opcode 0x69 (105): Cancel Threaded Execution (killthreads)

effect: Aborts executing of all subthreads and immediately continues the main thread past its start threads opcode.

Opcode 0x6A (106): Push To Main Thread Stack (tomain)

stack input: a value of any type

effect: Moves that value to the stack of the currently suspended main thread.

note: This opcode does only make sense in subthreads.

Opcode 0x6B (107): Pop From Main Thread Stack (frommain)

effect: Pops the top value from the stack of the suspended main thread

stack output: the value removed from the suspended main thread's stack.

note: This opcode does only make sense in subthreads.

Opcode 0x6C (108): Copy From Main Thread Stack (peekmain)

effect: Copies the top value from the stack of the suspended main thread

stack output: the value at the top of the suspended main thread's stack.

note: This opcode does only make sense in subthreads.

Opcode 0x6D (109): gettimeofday (gettimeofday)

stack output: seconds since midnight (tv_sec) as bigint (next to top); microseconds within current second (tv_usec) as bigint (top of stack)

Opcode 0x6E (110): mktime (mktime)

stack input: 6 smallint or bigint values in the following order: seconds, minutes, hours, day (1-based), month (0-based), year (top of stack)

stack output: the corresponding unix timestamp

Opcode 0x6F (111): localtime (localtime)

stack input: a small/big int containing a unix timestamp

stack output: 6 smallints in this order: seconds, minutes, hours, day (1-based), month (0-based), year (top of stack)

Opcodes 70..7F

Opcode 0x70 (112): Get Type (type)

stack input: object of any type

stack output: The type tag of that object (see top of the page)

Opcode 0x71 (113): Get Random Number (rng.skipget)

stack input: smallint n of values to skip

stack output: The number generated by the user RNG after skipping n values.

Opcode 0x72 (114): Set User RNG Autoskip (rng.autoskip)

stack input: smallint n

effect: Enables autoskipping, i.e. advancing the user RNG by n for every opcode executed. n==0 disables it.

Opcode 0x73 (115): Seed and Enable Stream Decryptor (decryptseed)

stack input: smallint n as 16 bit seed value.

effect: Turn on the Stream RNG that generates a key stream to decode all following instruction.

note: This will indicate that the following bytes are encrypted.

Opcode 0x74 (116): Load Stream Decryptor Table (decrypttable)

stack input: A reference to a block of bytes. The size must be a power of 2

effect: Replaces the standard table in the Stream PRNG by the one given as parameter

Opcode 0x75 (117): Load Native Module (natmod)

stack input: A blob containing a (possibly compressed) module of native code

stack ouput: smallint containing the module handle. (a one-byte number)

effect: The contents of that blob gets loaded into the virtual machine. The first 0x60 bytes of the blob are a header for the module that, amongst other things, contains the name of the module which is used to identify it. The module is decompressed, relocated and the exported names are put into the salwrap global exports table (unless the module is named "bc", in that case, exports are not yet loaded)

Opcode 0x76 (118): Unload native module (addexports)

stack input: A module handle (as smallint)

stack ouput: 1 if the module had on-demand-exports, 0 otherwise (probably wrong description)

effect: Unloads the given native module. If it is not named "bc", the exports are removed from the global symbol table before unloading the module.

Opcode 0x77 (119): Call a native module (callmod)

stack input: args for the native module (type(s) module specific); module handle (smallint at top)

stack output: result from the native module (type(s) module specific)

effect: Runs the native code associated with the given module handle. It removes the module handle from the stack before running that module. The module itself can do to the stack whatever it wants.

Opcode 0x78 (120): Run Unloaded Native Module (callblobmod)

stack input: possible module args; a blob containing a non-compressed module (at top; like for Opcode 75)

stack output: possible module results

effect: Executes the native code from the blob given as parameter. The blob is relocated and exports are loaded (unless it is a "bc" named blob). As the blob is non-permanent, there better are no exports. The entrypoint is finally called (Like Opcode 77 does for a loaded module)

Opcode 0x79 (121): Get Module Name (modname)

stack input: module handle (as smallint)

stack ouput: blob containing name of that module

Opcode 0x7A (122): Get Module Handle (modhnd)

stack input: blob containing of module name

stack ouput: smallint containing module handle

Opcode 0x7B (123): Create Module For Blob (modcreate)

stack input: module name (blob next to top); module contents (blob at top)

stack output: smallint containing module handle

Creates an entry in the module list that references the address range of the blob.

Opcode 0x7C (124): Create Bytecode Module (bcmodcreate)

stack input: module contents (blob); module name (blob at top, optional)

stack output: smallint containing module handle

Copies the blob contents into the interpreter as bytecode module. If top of stack is ⇐ 8 chars, it is treated as a name. Otherwise the standard name "bc" is used instead.

Opcode 0x7D (125): Run OCM Module (bcmodcall)

stack input: smallint containing module handle.

effect: the module handle must refer to a module not containing native code, but some byte code. This bytecode is executed (as a subroutine)

note: The ocm module is stored in the global dictionary. This instruction is used to "import" the device.sal library declarations to a programs environment. The ocm module data and the global dictionary reference to it are loaded using the salwrap function setDeviceSal.

Opcode 0x7E (126): Seed User RNG (rng.seed)

stack input: smallint; blob (at top of stack)

effect: uses the smallint and the blob to seed the User PRNG.

Opcode 0x7F (127): Nop

effect: none

Opcodes 80..86

Opcode 0x80 (128): unknown purpose

stack input: codenum (smallint)

effect: if codenum is zero, calls a hookable function in salwrap (export 0x68), otherwise does nothing

Opcode 0x81 (129): Pop w/o dropping refcount (pop.nounref.XX)

stack input: value of any type

effect: removes the value from the stack without adjusting its reference count.

note: is the same as 84

Opcode 0x82 (130): Nop

effect: none

Opcode 0x83 (131): Nop

effect: none

Opcode 0x84 (132): Pop w/o dropping refcount (pop.nounref.XX)

stack input: value of any type

effect: removes the value from the stack without adjusting its reference count.

note: is the same as 81

Opcode 0x85 (133): Call dictionary proc (calldict)

stack input: dictionary key (smallint for system dict, 32 bit blob for user dictionary)

effect: Gets the blob at the given dictionary index, as opcode 10 would do too, and then invokes it like opcode 31 would do, but this call opcode is the only possibility to do clean inter-module calls, at only it uses the context (Stream PRNG, OCM header valid for blob) stored in the dict alongside the value.

Opcode 0x86 (134): rdtsc (rdtsc)

stack output: a 64 bit bigint containing the result of rdtsc

Extra opcodes

Opcode FB:

complicated calling instruction, probably including stack swapping. Might by something like try/catch

Documentation for the "extrins" module

Contains long number arithmetic (arbitrary precision). small/bigint indicates parameters that are auto-promoted to bigints if given as smallint. The usual signed interpretation of smallints is used (opposed to dword arithmetic instructions)

A datatype "fuzzed integer" is used in some opcodes. Technically, its just a big int, but semantically, it has been transformed to not have the number directly in core. This transformation is dependent on the modulus in modular artihmetics, so "fuzzed integers" are specific to one modules

Opcode 0x87..0x8F

Opcode 0x87 (135): Add Big Integers

stack input: small/big int a; small/big int b

stack output: bigint a + b

Opcode 0x88 (136): Subtract Big Integers

stack input: small/big int a; small/big int b

stack output: bigint a - b

Opcode 0x89 (137): Multiply Big Integers

stack input: small/big int a; small/big int b

stack output: bigint a * b

Opcode 0x8A (138): Divide Big Integers

stack input: small/big int a; small/big int b

stack output: bigint a / b

Opcode 0x8B (139): Divide and Modulus of Big Integers

stack input: small/big int a; small/big int b

stack output: bigint a % b; a / b (careful, different order than DivMod for smallints and dwords. Somerthing wrong here?)

Opcode 0x8C (140): Modulus of Big Integers

stack input: small/big int a; small/big int b

stack output: bigint a % b

Opcode 0x8D (141): Compare Big Integers for Greater

stack input: small/big int a; small/big int b

stack output: smallint 1 if a>b, smallint 0 otherwise

Opcode 0x8E (142): Compare Big Integers for Less

stack input: small/big int a; small/big int b

stack output: smallint 1 if a<b, smallint 0 otherwise

Opcode 0x8F (143): Compare Big Integers for Equal

stack input: small/big int a; small/big int b

stack output: smallint 1 if a==b, smallint 0 otherwise

Opcode 0x90..0x9F

Opcode 0x90 (144): Bitwise XOR Big Integers

stack input: small/big int a; small/big int b

stack output: bigint a & b

Opcode 0x91 (145): Bitwise AND Big Integers

stack input: small/big int a; small/big int b

stack output: bigint a | b

Opcode 0x92 (146): Bitwise OR Big Integers

stack input: small/big int a; small/big int b

stack output: bigint a ^ b

Opcode 0x93 (147): Shift Left Big Integers

stack input: small/big int a; DWORD b

stack output: bigint a « b

note: DWORDs means that smallints are treated as unsigned 16 bit values in that case. See Instruction 0x22 for details.

Opcode 0x94 (148): Shift Right Big Integers

stack input: small/big int a; DWORD b

stack output: bigint a » b

note: DWORDs means that smallints are treated as unsigned 16 bit values in that case. See Instruction 0x22 for details.

Opcode 0x95 (149): Add Big Integers (in Modular Arithmetics)

stack input: small/big int a; small/big int b; small/big int m

stack output: bigint a + b (mod m)

Opcode 0x96 (150): Subtract Big Integers (in Modular Arithmetics)

stack input: small/big int a; small/big int b; small/big int m

stack output: bigint a - b (mod m)

Opcode 0x97 (151): Multiply Big Integers (in Modular Arithmetics)

stack input: small/big int a; small/big int b; small/big int m

stack output: bigint a * b (mod m)

Opcode 0x98 (152): Negate Big Integer (in Modular Arithmetics)

stack input: small/big int a; small/big int m

stack output: bigint -a (mod m)

Opcode 0x99 (153): Reciprocal of Big Integer (in Modular Arithmetics)

stack input: small/big int a; small/big int m

stack output: bigint (1 / a) (mod m)

Opcode 0x9A (154): Power of Big Integers (in Modular Arithmetics)

stack input: small/big int a; small/big int e; small/big int m

stack output: bigint (a to the e'th power (mod m) )

Opcode 0x9B (155): Product of Powers of Big Integers (in Modular Arithmetics)

stack input: small/big int a1; small/big int e1; small/big int a2; small/big int e2; small/big int m

stack output: bigint (a1 to the e1'th power * a2 to the e2'th power (mod m) )

note: This is more efficient than using 0x9A twice and then multiply the result with 0x97, but yields the same result.

Opcode 0x9C (156): Root of Big Integer (in Modular Arithmetics)

stack input: small/big int a; small/big int m

stack output bigint r such that r*r == a (mod m), or r == 0 if no value satisfies that equation.

Opcode 0x9D (157): Initialize Fuzzing Context

stack input: small/big int m

stack ouptut: fuzzing context object for modulus m

Opcode 0x9E (158): Fuzz Number

stack input: small/big int a; fuzzing context

stack output: fuzzed value of a

Opcode 0x9F (159): Unfuzz Number

stack input: fuzzed int f; fuzzing context

stack ouput: unfuzzed value of f

Opcode 0xA0..0xAF

Opcode 0xA0 (160): Add Fuzzed Numbers (Modular arithmetics)

stack input: fuzzed int f; fuzzed int g; fuzzing context

stack ouput: fuzzed int f+g (mod m from fuzzing context)

Opcode 0xA1 (161): Subtracted Fuzzed Numbers (Modular arithmetics)

stack input: fuzzed int f; fuzzed int g; fuzzing context

stack ouput: fuzzed int f-g (mod m from fuzzing context)

Opcode 0xA2 (162): Multiply Fuzzed Numbers (Modular arithmetics)

stack input: fuzzed int f; fuzzed int g; fuzzing context

stack ouput: fuzzed int f*g (mod m from fuzzing context)

Opcode 0xA3 (163): Negate Fuzzed Numbers (Modular arithmetics)

stack input: fuzzed int f; fuzzing context

stack ouput: fuzzed int -f (mod m from fuzzing context)

Opcode 0xA4 (164): Reciprocal of Fuzzed Number (Modular arithmetics)

stack input: fuzzed int f; fuzzing context

stack ouput: fuzzed int 1 / f (mod m from fuzzing context)

Opcode 0xA5 (165): Power of Fuzzed Number (Modular arithmetics)

stack input: fuzzed int f; (unfuzzed) small/big int e; fuzzing context

stack ouput: fuzzed int f to the e'th power (mod m from fuzzing context)

Opcode 0xA6 (166): Product of Powers of Fuzzed Numbers (in Modular Arithmetics)

stack input: fuzzed int f1; (unfuzzed) small/big int e1; fuzzed int a2; (unfuzzed) small/big int e2; fuzzing context

stack output: fuzzed int (f1 to the e1'th power * f2 to the e2'th power (mod m from fuzzing context) )

note: This is more efficient than using 0xA5 twice and then multiply the result with 0xA2, but yields the same result.

Opcode 0xA7 (167): Initialize Power Context

stack input: fuzzed int base; DWORD bits; DWORD parts; fuzzing context

stack output: power context for the given parameters.

note: A power context contains helper data to calculate different powers of the same base in with the same modulus. The power context gets optimized for exponents with approximately bits significant bits. The underlying algorithm is a divide-and-conquer algorithm. The number of parts the exponent will be divided to is given in parts, with an upper bound of 16.

Opcode 0xA8 (168): Calculate Power using Power Context

stack input: small/big int exp; power context

stack output: unfuzzed(!) result of base (from the context) to the exp'th power.

Opcode 0xA9 (169): Calculate Product of Powers using Power Contexts

stack input: small/big int exp1; power context ctx1; small/big int exp2; power context ctx2

stack output: bigint containing base1 to the exp1'th power multiplied by base2 to the exp2'th power (bases taken from contexts)

note: Does only work if the modulus in ctx1 und ctx2 is the same. Otherwise strange things will happen.

Opcode 0xAA (170): Create Mod-P Elliptic Curve Context

stack input: small/big int p; small/big int a; small/big int b

stack output: elliptic curve context describing the elliptic curve with the parameters a and b in the finite field of modular arithmetics to the base p, which should be prime.

Opcode 0xAB (171): Add Points in Mod-P Elliptic Curve

stack input: small/big int x1; small/big int y1; small/big int x2; small/big int y2; elliptic curve context

stack output: bigint xr; bigint yr (such that (xr,yr) = (x1,y1)+(x2,y2))

note: This is about addition within an elliptic curve. This is not standard vector addition, it is just called addition, as it has a mathematical similar structure. If you want to understand what is really going on, read an introduction into elliptic curve arithmetics.

Opcode 0xAC (172): Negate in Mod-P Elliptic Curve

stack input: small/big int x; small/big int y; elliptic curve context

stack output: bigint x; bigint -y (mod p from context)

Opcode 0xAD (173): Multiplication with Scalar in Mod-P Elliptic Curve

stack input: small/big int n; small/big int x; small/big int y; elliptic curve context

stack output: bigint xres; bigint yres, satisfying (xres,yres) = n*(x,y)

note: This is multiplication with a scalar within an elliptic curve. It is the same as adding up (x,y) n times by elliptic curve addition. It is not standard vector multiplication. Especially, the output does not resemble (n*x, n*y) in any way.

Opcode 0xAE (174): Dual Multiplication with Scalar in Mod-P Elliptic Curve

stack input: small/big int n1; small/big int x1; small/big int y1; small/big int n2; small/big int x2; small/big int y2; elliptic curve context

stack output: bigint xres; bigint yres, satisfying (xres,yres) = n1*(x1,y1) + n2*(x2,y2)

note: This is faster than doing two multiplications with 0xAD and adding with 0xAB, but yields the same result. Notes of that opcodes apply here, too.

Opcode 0xAF (175): Create Mod-P Elliptic Curve Multiplication Context

stack input: small/big int x; small/big int y; DWORD bits; DWORD parts; elliptic curve context

stack output: elliptic curve multiplication context to calculate multiples of (x,y) on the given elliptic curve.

note: An elliptic curve multiplication context contains helper data to calculate different multiples of the same point in with the same modulus. The multiplication context gets optimized for scalar factors with approximately bits significant bits. The underlying algorithm is a divide-and-conquer algorithm. The number of parts the scalar factor will be divided to is given in parts, with an upper bound of 16.

Opcode 0xB0..0xC1

Opcode 0xB0: Calculate Product using Mod-P Elliptic Curve Multiplication Context

stack input: small/big int n; elliptic curve multiplication context

stack output: bigint x; bigint y: satifying (x,y) = n*(x0,y0) (from the context)

Opcode 0xB1: Calculate Sum Of Products using Mod-P Elliptic Curve Multiplication Contexts

stack input: small/big int n1; elliptic curve multiplication context ctx1; small/big int n2; elliptic curve multiplication context ctx2

stack output: bigint x; bigint y: satifying (x,y) = n1*(x1,y1)+n2*(x2,y2) (x1, y1, x2, y2 from the contexts)

note: Does only work if the modulus and the a and b parameters in ctx1 und ctx2 is the same. Otherwise strange things will happen.

Opcode 0xB2: Create Galois Field (GF) Elliptic Curve Context

stack input: DWORD n; DWORD m; small/big int a; small/big int b; (n > m; m > 0)

stack output: GF elliptic curve context describing the elliptic curve with the parameters a and b in the finite field GF_{2^n} defined by the irreducible polynomial t^n+t^m+1

Opcode 0xB3: Add Points in GF Elliptic Curve

stack input: small/big int x1; small/big int y1; small/big int x2; small/big int y2; GF elliptic curve context

stack output: bigint xr; bigint yr (such that (xr,yr) = (x1,y1)+(x2,y2))

note: This is about addition within an elliptic curve. This is not standard vector addition, it is just called addition, as it has a mathematical similar structure. If you want to understand what is really going on, read an introduction into elliptic curve arithmetics.

Opcode 0xB4: Negate in GF Elliptic Curve

stack input: small/big int x; small/big int y; GF elliptic curve context

stack output: bigint xr; bigint yr, such that (xr,yr) + (x,y) results in the point at infinity.

Opcode 0xB5: Multiplication with Scalar in GF Elliptic Curve

stack input: small/big int n; small/big int x; small/big int y; GF elliptic curve context

stack output: bigint xres; bigint yres, satisfying (xres,yres) = n*(x,y)

note: This is multiplication with a scalar within an elliptic curve. It is the same as adding up (x,y) n times by elliptic curve addition. It is not standard vector multiplication. Especially, the output does not resemble (n*x, n*y) in any way.

Opcode 0xB6: Dual Multiplication with Scalar in GF Elliptic Curve

stack input: small/big int n1; small/big int x1; small/big int y1; small/big int n2; small/big int x2; small/big int y2; GF elliptic curve context

stack output: bigint xres; bigint yres, satisfying (xres,yres) = n1*(x1,y1) + n2*(x2,y2)

note: This is faster than doing two multiplications with 0xB5 and adding with 0xB3, but yields the same result. Notes of that opcodes apply here, too.

Opcode 0xB7: Create GF Elliptic Curve Multiplication Context

stack input: small/big int x; small/big int y; DWORD bits; DWORD parts; GF elliptic curve context

stack output: GF elliptic curve multiplication context to calculate multiples of (x,y) on the given elliptic curve.

note: An elliptic curve multiplication context contains helper data to calculate different multiples of the same point in with the same modulus. The multiplication context gets optimized for scalar factors with approximately bits significant bits. The underlying algorithm is a divide-and-conquer algorithm. The number of parts the scalar factor will be divided to is given in parts, with an upper bound of 16.

Opcode 0xB8: Calculate Product using GF Elliptic Curve Multiplication Context

stack input: small/big int n; GF elliptic curve multiplication context

stack output: bigint x; bigint y: satifying (x,y) = n*(x0,y0) (from the context)

Opcode 0xB9: Calculate Sum Of Products using GF Elliptic Curve Multiplication Contexts

stack input: small/big int n1; GF elliptic curve multiplication context ctx1; small/big int n2; GF elliptic curve multiplication context ctx2

stack output: bigint x; bigint y: satifying (x,y) = n1*(x1,y1)+n2*(x2,y2) (x1, y1, x2, y2 from the contexts)

note: Does only work if the polynomial and the a and b parameters in ctx1 und ctx2 is the same. Otherwise strange things will happen.

Opcode 0xBA: Create Galois Field Efficient Squaring (GFES) Elliptic Curve Context

stack input: DWORD bits; small/big int a; small/big int b;

stack output: GF elliptic curve context describing the elliptic curve with the parameters a and b in the finite field GF_{2^bits}. An representation of that Galois field is chosen in which squaring is very efficient. More info about that representation to come later.

Opcode 0xBB: Add Points in GFES Elliptic Curve

stack input: small/big int x1; small/big int y1; small/big int x2; small/big int y2; GFES elliptic curve context

stack output: bigint xr; bigint yr (such that (xr,yr) = (x1,y1)+(x2,y2))

note: This is about addition within an elliptic curve. This is not standard vector addition, it is just called addition, as it has a mathematical similar structure. If you want to understand what is really going on, read an introduction into elliptic curve arithmetics.

Opcode 0xBC: Negate in GFES Elliptic Curve

stack input: small/big int x; small/big int y; GFES elliptic curve context

stack output: bigint xr; bigint yr, such that (xr,yr) + (x,y) results in the point at infinity.

Opcode 0xBD: Multiplication with Scalar in GFES Elliptic Curve

stack input: small/big int n; small/big int x; small/big int y; GFES elliptic curve context

stack output: bigint xres; bigint yres, satisfying (xres,yres) = n*(x,y)

note: This is multiplication with a scalar within an elliptic curve. It is the same as adding up (x,y) n times by elliptic curve addition. It is not standard vector multiplication. Especially, the output does not resemble (n*x, n*y) in any way.

Opcode 0xBE: Dual Multiplication with Scalar in GFES Elliptic Curve

stack input: small/big int n1; small/big int x1; small/big int y1; small/big int n2; small/big int x2; small/big int y2; GFES elliptic curve context

stack output: bigint xres; bigint yres, satisfying (xres,yres) = n1*(x1,y1) + n2*(x2,y2)

note: This is faster than doing two multiplications with 0xBD and adding with 0xBB, but yields the same result. Notes of that opcodes apply here, too.

Opcode 0xBF: Create GFES Elliptic Curve Multiplication Context

stack input: small/big int x; small/big int y; DWORD bits; DWORD parts; GFES elliptic curve context

stack output: GFES elliptic curve multiplication context to calculate multiples of (x,y) on the given elliptic curve.

note: An elliptic curve multiplication context contains helper data to calculate different multiples of the same point in with the same modulus. The multiplication context gets optimized for scalar factors with approximately bits significant bits. The underlying algorithm is a divide-and-conquer algorithm. The number of parts the scalar factor will be divided to is given in parts, with an upper bound of 16.

Opcode 0xC0: Calculate Product using GFES Elliptic Curve Multiplication Context

stack input: small/big int n; GFES elliptic curve multiplication context

stack output: bigint x; bigint y: satifying (x,y) = n*(x0,y0) (from the context)

Opcode 0xC1: Calculate Sum Of Products using GFES Elliptic Curve Multiplication Contexts

stack input: small/big int n1; GFES elliptic curve multiplication context ctx1; small/big int n2; GFES elliptic curve multiplication context ctx2

stack output: bigint x; bigint y: satifying (x,y) = n1*(x1,y1)+n2*(x2,y2) (x1, y1, x2, y2 from the contexts)

note: Does only work if the bit count and the a and b parameters in ctx1 und ctx2 is the same. Otherwise strange things will happen.

Preliminary documentation for "compat" module

This list shows an overview over the opcodes C2..E0 (from compat, a module inside init.ocm). The numbers are relative opcode numbers, i.e. the opcode minus the base opcode of C2.

Opcode 0xC2 (194): Extracts a subblob of a given (length) beginning at position (index) from blob (blob.part)

If the length is -1, the subblob is taken until the end of the blob.

stack input: string; index; length

stack output: substring

dd 1 (0xc3)

dd offset BCX_01_Concat	; firstpart secondpart --> concatenated

dd 2 (0xc4)

dd offset BCX_02_CompareBlob ; blob1 blob2 --> cmpresult

			; (lexicographically)

dd 3 (0xc5)

dd offset BCX_03_CompareN ; blob1 blob2	count --> cmpresult

			; (lexicographically, but trimm	blob1 and blob2	to count before)

dd 4 (0xc6)

dd offset BCX_04_IndexBlob ; blob idx --> char_at_idx

dd 5 (0xc7)

dd offset BCX_05_BlobLen ; blob	--> length (16 bit OR bigint)

dd 6 (0xc8)

dd offset BCX_06_XorBlobs ; blob1 blob2	--> blob1^blob2

			; extends shorter blob with zero bytes

dd 7 (0xc9)

dd offset BCX_07_XorBlobsRepeating ; blob1 blob2 --> blob1 ^ blob2

			; the shorter blobs gets repeated to reach the length of the longer blob.

			; If the length	of the longer blob is not evenly divisible by the length of the	shorter	blob

			;   -->	runtime	error

dd 8 (0xca)

dd offset BCX_08_RepeatNUL ; count --> blob

dd 9 (0xcb)

dd offset BCX_09_ReplaceSubblob	; bigblob offset newdata --> patchedbigblob

dd 0Ah (0xcc)

dd offset BCX_0A_FloatAdd ; num1 num2 --> num1+num2

dd 0Bh (0xcd)

dd offset BCX_0B_FloatSub ; num1 num2 --> num1-num2

dd 0Ch (0xce)

dd offset BCX_0C_FloatMul ; num1 num2 --> num1*num2

dd 0Dh (0xcf)

dd offset BCX_0D_FloatDiv ; num1 num2 --> num1/num2

dd 0Eh (0xd0)

dd offset BCX_0E_FloatEq ; flt1	flt2 --> flt1==flt2

dd 0Fh (0xd1)

dd offset BCX_0F_FloatLt ; flt1	flt2 --> flt2 <	flt1

dd 10h (0xd2)

dd offset BCX_10_FloatGt ; flt1	flt2 --> flt2 >	flt1

dd 11h (0xd3)

dd offset BCX_11_FloatToInt ; flt --> int

			; Does not handle ints > 32 bits

dd 12h (0xd4)

dd offset BCX_12_atof	; ascii-blob --> float

dd 13h (0xd5)

dd offset BCX_13_nop

dd 14h (0xd6)

dd offset BCX_14_DESSetKey ; keyblob --> scheduleblob

dd 15h (0xd7)

dd offset BCX_15_DESEncrypt1 ; data keyschedule	--> encrypted data

dd 16h (0xd8)

dd offset BCX_16_DESDecrypt1 ; data keyschedule	--> decrypted data

dd 17h (0xd9)

dd offset BCX_17_DES_ECB_Encrypt ; data	keyschedule -->	encrypted data

dd 18h (0xda)

dd offset BCX_18_DES_ECB_Decrypt ; data	keyschedule -->	decrypted data

dd 19h (0xdb)

dd offset BCX_19_InitSHA1 ; -->	SHA1 state object

dd 1Ah (0xdc)

dd offset BCX_1A_SHA1AddData ; data length state --> newstate

Marcus: I have seen LENGTH being 0, which I can only suppose means that the whole blob DATA is added.

dd 1Bh (0xdd)

dd offset BCX_1B_SHA1Finish ; state -->	hash

dd 1Ch (0xde)

dd offset BCX_1C_GetPRNGBytes ;	count --> blob

dd 1Dh (0xdf)

dd offset DES_CBC_Encrypt ; data iv keyschedule magic -> data'

			; magic	must be	DES_ECB_Encrypt	or DES_ECB_Decrypt opcode as blob

dd 1Eh (0xe0)

dd offset DES_CBC_Decrypt ; data iv keyschedule magic -> data'

			; magic	must be	DES_ECB_Encrypt	or DES_ECB_Decrypt opcode as blob
ocmbytecode.txt · Last modified: 2023/04/23 15:05 by nopsled

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki