libantispyOther

The libantispy namespace encapsulates a suite of functions and utilities designed to enhance software security by providing mechanisms for anti-debugging, data obfuscation, and encryption. More...

Enums

TypeName
uint8_tvm_ternary_op
uint8_tvm_binary_op
uint8_tvm_unary_op
uint8_tvm_nullary_op
uint8_tvm_register

Functions

TypeName
const char *get_version ()
booldebugger_present ()
uintptr_tbreak_me (const uintptr_t me, uint64_t check)
TRetcorrupt_call (TRet(*func)(TArgs...), TArgs... args)
voidcorrupt_call (void(*func)(TArgs...), TArgs... args)
constexpr automake_const_buffer (const char *str) noexcept
constexpr automake_const_string (const char32_t(&str)[N]) noexcept
encrypted_pointer< _Ty >make_encrypted (_Types &&... _Args)
voidmake_encrypted (_Types &&...)=delete

Detailed Description

The primary focus of the libantispy namespace is to protect applications from unauthorized access and analysis. It includes functionality for detecting the presence of debuggers, performing secure data manipulation using techniques like XOR operations, encryption and decryption through virtual machines, and managing obfuscated function calls. These tools are essential for creating resilient software that can resist reverse engineering and tampering.

Key Components:

  • Anti-Debugging : Functions that detect whether a debugger is attached to the process, enabling the application to take protective measures.

  • Data Obfuscation : Classes and functions that perform operations like XOR, rotation, and other transformations in a secure and obfuscated manner to protect sensitive data.

  • Encryption/Decryption : Utilities for encrypting and decrypting data using customized algorithms and callback mechanisms to ensure that the data remains secure.

  • Virtual Machine Operations : Implementation of cryptographic and logical operations inside a virtual machine, adding an extra layer of obfuscation to the operations.

Enums

vm_ternary_op

Enum representing ternary operations in the virtual machine (VM).

Detailed Description

The vm_ternary_op enum class defines the set of operations within the VM that require three operands. These operations are fundamental to the functioning of the VM and are used in various computational tasks, such as bitwise manipulation and rotation operations. Each operation is represented by a unique value of type uint8_t , which serves as an opcode in the VM's instruction set.

Ternary Operations:

Ternary operations differ from unary and binary operations in that they involve three distinct operands. These operands could represent values stored in registers, immediate values, or memory locations. The operations defined in this enum class are integral to the VM's capability to perform complex computational tasks that require more than two inputs.

The vm_ternary_op enum values are used in conjunction with the VM's instruction decoder, which interprets these values as commands to execute the corresponding operation with three operands.

The actual implementation of these operations may vary depending on the architecture and design of the VM. The operations typically involve bitwise manipulation, such as rotation, which is a common task in cryptographic algorithms and data processing.

rol_

Rotate left operation.

Detailed Description

The rol_ (Rotate Left) operation is a bitwise operation that shifts the bits of a given value to the left by a specified number of positions. The bits that are shifted out of the leftmost position are reintroduced on the right side, effectively wrapping around the bit positions.

This operation is commonly used in low-level data manipulation, cryptography, and situations where bit-level control is required. The rotation ensures that no bits are lost during the shift, making it different from a simple left shift operation, where bits shifted out of the boundary are lost.

Operation Details:

  • Input Operands :

    • The first operand is the value whose bits are to be rotated.

    • The second operand specifies the number of bit positions to rotate.

    • The third operand defines the bit width of the data type being rotated (e.g., 32 bits for a uint32_t , 64 bits for a uint64_t ).

  • Process :

    • The bits of the first operand are shifted to the left by the number of positions specified by the second operand.

    • The bits that fall off the left edge are wrapped around and placed back on the right side.

    • The operation ensures that the result stays within the confines of the data type's bit width.

Example:

Consider a uint8_t value 0b10110010 (178 in decimal) and rotating it left by 3 positions:

Initial value: 10110010 Rotate left by 3: 10010110

Here, the three leftmost bits 101 are rotated to the rightmost positions.

Usage in Virtual Machine (VM):

In the context of the VM, the rol_ operation is executed as part of the instruction set. The VM interprets the rol_ opcode and applies the rotation to the specified operands, which could be registers, immediate values, or memory locations. This operation is crucial for implementing algorithms that require circular shifts, such as certain cryptographic functions.

Performance Considerations:

  • The rol_ operation is typically very efficient in hardware, as many processors have direct support for bitwise rotation instructions.

  • In software, it can be implemented using a combination of shifts and bitwise OR operations.

Implementation Note:

  • When implementing the rol_ operation in the VM, it's essential to ensure that the rotation is performed correctly according to the data type's bit width. For example, rotating a uint32_t value should wrap around within 32 bits, not across a broader or narrower bit range.

Common Use Cases:

  • Cryptography : Rotations are often used in cryptographic algorithms to mix bits in a reversible manner.

  • Data Encoding : Bitwise rotations can be part of data encoding and decoding processes, where the integrity of the bit pattern must be preserved.

  • Hash Functions : Hash functions frequently use bitwise rotations to achieve a high degree of bit diffusion.

ror_

Rotate right operation.

Detailed Description

The ror_ (Rotate Right) operation is a bitwise operation that shifts the bits of a given value to the right by a specified number of positions. The bits that are shifted out of the rightmost position are reintroduced on the left side, effectively wrapping around the bit positions.

This operation is widely used in low-level programming, cryptography, and scenarios requiring precise control over individual bits. Unlike a simple right shift operation, where the bits shifted out of the boundary are lost, ror_ ensures that all bits are preserved by wrapping the shifted-out bits around to the leftmost positions.

Operation Details:

  • Input Operands :

    • The first operand is the value whose bits are to be rotated.

    • The second operand specifies the number of bit positions to rotate.

    • The third operand defines the bit width of the data type being rotated (e.g., 32 bits for a uint32_t , 64 bits for a uint64_t ).

  • Process :

    • The bits of the first operand are shifted to the right by the number of positions specified by the second operand.

    • The bits that fall off the right edge are wrapped around and placed back on the left side.

    • The operation ensures that the result stays within the confines of the data type's bit width.

Example:

Consider a uint8_t value 0b10110010 (178 in decimal) and rotating it right by 3 positions:

Initial value: 10110010 Rotate right by 3: 01010110

Here, the three rightmost bits 010 are rotated to the leftmost positions.

Usage in Virtual Machine (VM):

In the context of the VM, the ror_ operation is executed as part of the instruction set. The VM interprets the ror_ opcode and applies the rotation to the specified operands, which could be registers, immediate values, or memory locations. This operation is essential for implementing algorithms that require circular shifts, such as certain cryptographic functions.

Performance Considerations:

  • The ror_ operation is generally very efficient in hardware, as many processors have direct support for bitwise rotation instructions.

  • In software, it can be implemented using a combination of shifts and bitwise OR operations.

Implementation Note:

  • When implementing the ror_ operation in the VM, it's crucial to ensure that the rotation is performed correctly according to the data type's bit width. For example, rotating a uint32_t value should wrap around within 32 bits, not across a broader or narrower bit range.

Common Use Cases:

  • Cryptography : Rotations are often used in cryptographic algorithms to mix bits in a reversible manner.

  • Data Encoding : Bitwise rotations can be part of data encoding and decoding processes, where the integrity of the bit pattern must be preserved.

  • Hash Functions : Hash functions frequently use bitwise rotations to achieve a high degree of bit diffusion.

size_

Represents the total number of ternary operations.

Detailed Description

The size_ enumerator is used to define the total count of ternary operations available in the vm_ternary_op enum class. This value is not an operation itself but serves as a marker for the size of the enum, indicating the maximum number of ternary operations that can be represented by this enum class.

Purpose:

  • Enumeration Bound : The size_ value is used to establish an upper bound for the ternary operations. This is particularly useful in scenarios where the operations are stored in a fixed-size array or when iterating over all possible operations.

  • Array Sizing : In the virtual machine (VM) implementation, this value can be used to size arrays or tables that store function pointers or other data associated with each ternary operation. By using size_ , the VM ensures that it allocates exactly the right amount of space for all possible ternary operations.

  • Iteration and Validation : The size_ value is also helpful for iterating through the enum values. It provides a convenient way to validate that an operation falls within the expected range of the enum, thereby preventing invalid or out-of-bounds operations from being executed.

Implementation Details:

  • The value 0x10 (16 in decimal) indicates that there are a total of 16 possible ternary operations in this enum.

  • This count includes any operations defined explicitly within the enum, such as rol_ , ror_ , and any other ternary operations that may be added in the future.

Importance in Virtual Machines:

  • Safety : Using size_ to define array bounds or iteration limits helps prevent buffer overflows or out-of-range errors.

  • Scalability : As more ternary operations are added to the enum, size_ automatically adjusts to reflect the new total, making the system easier to maintain and scale.

Conclusion:

The size_ enumerator is a crucial part of the vm_ternary_op enum, serving as a marker for the total number of ternary operations. It is primarily used for array sizing, iteration, and validation, ensuring that the VM handles ternary operations efficiently and safely.

vm_binary_op

Enum class representing binary operations in the virtual machine.

Detailed Description

The vm_binary_op enum class defines a set of binary operations that are fundamental to the instruction set of the virtual machine (VM). Each operation involves two operands and performs various arithmetic, logical, or control-flow tasks. The operations are encoded as 8-bit unsigned integers, which are used by the VM to identify and execute the appropriate instructions during program execution.

Purpose:

  • Binary Operations : The operations in this enum involve two operands, making it a core component of the virtual machine's instruction set. These operations are essential for arithmetic calculations, data manipulation, and control flow within the VM.

  • Instruction Encoding : Each operation is assigned a unique hexadecimal value, which is used to encode instructions in the virtual machine's bytecode. This allows the VM to decode and dispatch the correct operation when processing instructions.

  • Execution Flow : The VM relies on these binary operations to perform various tasks, such as arithmetic calculations, bitwise manipulation, memory operations, and conditional jumps. These operations are critical for implementing the logic and behavior of programs running within the VM.

add_

Addition operation.

Detailed Description

The add_ enumerator represents the addition operation within the virtual machine's binary instruction set. This operation takes two operands, adds their values together, and stores the result in a specified destination register. The add_ operation is a fundamental arithmetic operation used in a wide variety of computations, from simple arithmetic to complex algorithms.

Operation Details:

  • Operands : The add_ operation typically involves two source registers and one destination register.

  • Execution : The virtual machine reads the values from the two source registers, performs the addition, and then writes the result back to the destination register.

  • Example : If the virtual machine's instruction is encoded as add_ r1, r2, r3 , the operation performed would be: r1 = r2 + r3 . Here, r2 and r3 are the source operands, and r1 is the destination operand where the result of the addition is stored.

  • Flags : Depending on the implementation of the virtual machine, the addition operation may affect certain processor flags, such as the carry flag (if the addition results in an overflow), the zero flag (if the result is zero), and the sign flag (if the result is negative in a signed context).

Encoding:

  • Value : The add_ operation is encoded with the hexadecimal value 0x0 .

  • Instruction Encoding : This value is used by the virtual machine to decode and identify the addition operation when executing instructions. For example, in a bytecode stream, the presence of 0x0 as the opcode indicates that the following instruction is an addition operation.

Usage Scenarios:

  • Arithmetic Computations : The add_ operation is used in arithmetic expressions, such as calculating sums, totals, and other numeric results.

  • Pointer Arithmetic : In certain contexts, the add_ operation may be used to perform pointer arithmetic, such as calculating offsets within arrays or data structures.

  • Loop Counters : Addition is commonly used in incrementing loop counters, where a counter variable is incremented by a fixed value on each iteration of the loop.

  • Accumulation : In algorithms that involve accumulation (such as summing an array of numbers), the add_ operation is repeatedly used to accumulate the total sum.

The add_ operation is a building block for many higher-level operations and is essential in any arithmetic processing performed by the virtual machine.

sub_

Subtraction operation.

Detailed Description

The sub_ enumerator represents the subtraction operation within the virtual machine's binary instruction set. This operation takes two operands, subtracts the second operand from the first, and stores the result in a specified destination register. The sub_ operation is a fundamental arithmetic operation, widely used in various computational tasks, such as decrementing counters, calculating differences, and implementing certain algorithms.

Operation Details:

  • Operands : The sub_ operation typically involves two source registers and one destination register.

  • Execution : The virtual machine reads the values from the two source registers, performs the subtraction, and then writes the result back to the destination register.

  • Example : If the virtual machine's instruction is encoded as sub_ r1, r2, r3 , the operation performed would be: r1 = r2 - r3 . Here, r2 is the minuend (the value from which the subtraction is performed), r3 is the subtrahend (the value to be subtracted), and r1 is the destination register where the result is stored.

  • Flags : Depending on the implementation of the virtual machine, the subtraction operation may affect certain processor flags, such as the carry or borrow flag (if the subtraction results in an underflow), the zero flag (if the result is zero), and the sign flag (if the result is negative in a signed context).

Encoding:

  • Value : The sub_ operation is encoded with the hexadecimal value 0x1 .

  • Instruction Encoding : This value is used by the virtual machine to decode and identify the subtraction operation when executing instructions. In a bytecode stream, the presence of 0x1 as the opcode indicates that the following instruction is a subtraction operation.

Usage Scenarios:

  • Arithmetic Computations : The sub_ operation is used in arithmetic expressions, such as calculating differences between numbers or adjusting values based on some criteria.

  • Loop Counters : Subtraction is commonly used to decrement loop counters, where a counter variable is decremented by a fixed value on each iteration of the loop.

  • Distance/Offset Calculation : In certain contexts, subtraction is used to calculate distances or offsets, such as finding the difference between two pointers or time intervals.

  • Reversal of Addition : The sub_ operation is often used to reverse the effect of a prior addition, effectively restoring a value to its original state before the addition occurred.

The sub_ operation is a critical component of many arithmetic processes, allowing the virtual machine to perform subtraction as part of its computational capabilities.

mul_

Multiplication operation.

Detailed Description

The mul_ enumerator represents the multiplication operation within the virtual machine's binary instruction set. This operation takes two operands, multiplies them together, and stores the result in a specified destination register. The mul_ operation is a fundamental arithmetic operation used in various computational tasks, such as scaling values, calculating products, and implementing mathematical algorithms.

Operation Details:

  • Operands : The mul_ operation typically involves two source registers and one destination register.

  • Execution : The virtual machine reads the values from the two source registers, multiplies them together, and then writes the product back to the destination register.

  • Example : If the virtual machine's instruction is encoded as mul_ r1, r2, r3 , the operation performed would be: r1 = r2 * r3 . Here, r2 and r3 are the multiplicands (the values to be multiplied), and r1 is the destination register where the product is stored.

  • Flags : Depending on the implementation of the virtual machine, the multiplication operation may affect certain processor flags, such as the overflow flag (if the product exceeds the maximum value that can be stored in the destination register) or the zero flag (if the product is zero).

Encoding:

  • Value : The mul_ operation is encoded with the hexadecimal value 0x2 .

  • Instruction Encoding : This value is used by the virtual machine to decode and identify the multiplication operation when executing instructions. In a bytecode stream, the presence of 0x2 as the opcode indicates that the following instruction is a multiplication operation.

Usage Scenarios:

  • Arithmetic Computations : The mul_ operation is used in arithmetic expressions, such as calculating the product of numbers or scaling values by a factor.

  • Matrix and Vector Multiplication : In certain computational contexts, such as graphics or scientific computing, multiplication is used to perform matrix and vector multiplications, where the mul_ operation plays a critical role.

  • Exponential Calculations : The multiplication operation can be used in repeated multiplication processes for calculating powers or implementing algorithms that require multiplicative scaling.

  • Financial and Economic Calculations : In financial applications, multiplication is often used to calculate interest, returns, or other multiplicative relationships between values.

The mul_ operation is a vital component of many arithmetic processes, allowing the virtual machine to perform multiplication as part of its computational capabilities. It is widely used in scenarios that require the scaling or combination of numerical values.

div_

Division operation.

Detailed Description

The div_ enumerator represents the division operation within the virtual machine's binary instruction set. This operation takes two operands, divides the first operand by the second, and stores the quotient in a specified destination register. The div_ operation is essential in arithmetic computations where division is required, such as calculating ratios, scaling down values, or determining proportional relationships.

Operation Details:

  • Operands : The div_ operation involves two source registers and one destination register.

  • Execution : The virtual machine reads the values from the two source registers, divides the value in the first register by the value in the second register, and then writes the quotient back to the destination register.

  • Example : If the virtual machine's instruction is encoded as div_ r1, r2, r3 , the operation performed would be: r1 = r2 / r3 . Here, r2 is the dividend (the value to be divided), r3 is the divisor (the value by which to divide), and r1 is the destination register where the quotient is stored.

  • Flags : Depending on the virtual machine's design, the division operation may affect certain processor flags, such as the zero flag (if the quotient is zero) or a division-by-zero exception if r3 is zero. Handling division by zero is critical to avoid runtime errors.

Encoding:

  • Value : The div_ operation is encoded with the hexadecimal value 0x3 .

  • Instruction Encoding : This value is used by the virtual machine to decode and identify the division operation when executing instructions. In a bytecode stream, the presence of 0x3 as the opcode indicates that the following instruction is a division operation.

Usage Scenarios:

  • Arithmetic Computations : The div_ operation is used in arithmetic expressions that require division, such as calculating averages, ratios, or reducing quantities by a given factor.

  • Financial Calculations : In financial applications, division is used to calculate interest rates, returns, or other ratios that involve dividing one value by another.

  • Proportional Scaling : Division is often used to scale down values proportionally, such as converting larger units to smaller units or normalizing data.

  • Geometry and Physics : In geometry, division can be used to calculate slopes, gradients, or other ratios. In physics, it may be used to calculate speed (distance divided by time) or density (mass divided by volume).

The div_ operation is an essential part of many arithmetic processes, allowing the virtual machine to perform division as part of its computational capabilities. It is widely used in scenarios that require the calculation of ratios, scaling down of values, or proportional adjustments.

mod_

Modulus operation.

Detailed Description

The mod_ enumerator represents the modulus (remainder) operation within the virtual machine's binary instruction set. This operation takes two operands, divides the first operand by the second, and stores the remainder of the division in a specified destination register. The modulus operation is commonly used in arithmetic computations where the remainder of a division is of interest, such as in cyclic operations, even/odd checking, and periodic functions.

Operation Details:

  • Operands : The mod_ operation involves two source registers and one destination register.

  • Execution : The virtual machine reads the values from the two source registers, divides the value in the first register by the value in the second register, and then writes the remainder of the division to the destination register.

  • Example : If the virtual machine's instruction is encoded as mod_ r1, r2, r3 , the operation performed would be: r1 = r2 % r3 . Here, r2 is the dividend (the value to be divided), r3 is the divisor (the value by which to divide), and r1 is the destination register where the remainder is stored.

  • Flags : Depending on the virtual machine's design, the modulus operation may affect certain processor flags, such as a zero flag (if the remainder is zero) or a division-by-zero exception if r3 is zero. Proper handling of division by zero is critical to avoid runtime errors.

Encoding:

  • Value : The mod_ operation is encoded with the hexadecimal value 0x4 .

  • Instruction Encoding : This value is used by the virtual machine to decode and identify the modulus operation when executing instructions. In a bytecode stream, the presence of 0x4 as the opcode indicates that the following instruction is a modulus operation.

Usage Scenarios:

  • Cyclic Operations : The mod_ operation is often used in cyclic or periodic processes, such as calculating wrap-around behavior in circular buffers or ensuring that indices remain within bounds in circular arrays.

  • Even/Odd Checking : The modulus operation is commonly used to check the parity of a number by computing the remainder when dividing by 2 ( mod_ 2 ).

  • Hashing : In hashing algorithms, the modulus operation is frequently used to map large numbers into a fixed range, such as when determining the index for storing elements in a hash table.

  • Time Calculations : Modulus is used in time calculations, such as converting elapsed time into hours, minutes, and seconds.

  • Geometry and Physics : In geometry, modulus can be used to find the remainder when calculating angles, ensuring they fall within a standard range (e.g., 0-360 degrees). In physics, it may be used to determine phase shifts or periodic movements.

The mod_ operation is a vital part of arithmetic processes in the virtual machine, providing the capability to compute remainders as part of more complex calculations. It is widely used in scenarios that involve cyclic behavior, parity checks, hashing, and time calculations.

xor_

Bitwise XOR operation.

Detailed Description

The xor_ enumerator represents the bitwise XOR (exclusive OR) operation in the virtual machine's binary instruction set. This operation takes two operands and performs a bitwise XOR between them, storing the result in a designated destination register. The XOR operation is fundamental in various computing tasks, particularly in cryptography, error detection, and low-level bit manipulation.

Operation Details:

  • Operands : The xor_ operation involves two source registers and one destination register.

  • Execution : The virtual machine reads the values from the two source registers, performs a bitwise XOR operation on these values, and writes the result to the destination register.

  • Bitwise XOR : The XOR operation compares corresponding bits of the two operands:

    • If the bits are different, the resulting bit is set to 1 .

    • If the bits are the same, the resulting bit is set to 0 .

  • Example : If the virtual machine's instruction is encoded as xor_ r1, r2, r3 , the operation performed would be: r1 = r2 ^ r3 . Here, r2 and r3 are the operands, and r1 is the destination register where the result of the XOR operation is stored.

Encoding:

  • Value : The xor_ operation is encoded with the hexadecimal value 0x5 .

  • Instruction Encoding : This value is used by the virtual machine to decode and identify the XOR operation when executing instructions. In a bytecode stream, the presence of 0x5 as the opcode indicates that the following instruction is a bitwise XOR operation.

Usage Scenarios:

  • Cryptography : XOR is a crucial operation in many cryptographic algorithms. It is used in creating and breaking ciphers, such as in the implementation of stream ciphers where plaintext is XORed with a keystream.

  • Parity Checks : XOR can be used to detect errors in data transmission. A simple parity check can be implemented by XORing all the bits in a data word; the result indicates whether the number of set bits is even or odd.

  • Masking Operations : XOR is useful in toggling bits. For example, XORing a number with a mask can flip specific bits, which is often used in setting or clearing flags.

  • Swapping Values : A well-known technique for swapping two values without a temporary variable involves a series of XOR operations.

  • Checksum Calculations : XOR is commonly used in checksum algorithms to detect errors in data.

  • Data Comparison : XOR can be used to compare two numbers bit by bit, as it will result in 0 only if the numbers are identical.

The xor_ operation is a fundamental tool in bitwise arithmetic, enabling powerful manipulations of binary data. It is indispensable in fields like cryptography, data integrity checks, and low-level programming where direct control over individual bits is required. The operation's versatility in performing tasks like toggling bits, generating parity bits, and cryptographic transformations makes it an essential component of the virtual machine's instruction set.

shl_

Shift left operation.

Detailed Description

The shl_ enumerator represents the bitwise shift left (SHL) operation in the virtual machine's binary instruction set. This operation shifts the bits of a value in the first operand to the left by a specified number of positions indicated by the second operand, filling the vacated bits with zeros. The result is stored in a designated destination register.

Operation Details:

  • Operands : The shl_ operation involves two source operands:

    • The first operand ( r1 ) is the value to be shifted.

    • The second operand ( r2 ) specifies the number of positions to shift.

  • Execution : The virtual machine reads the value from the first operand ( r1 ), shifts its bits to the left by the number specified in the second operand ( r2 ), and stores the result in the destination register.

  • Bitwise Shift Left (SHL) : Shifting a binary number to the left by one position is equivalent to multiplying the number by 2. Each left shift operation effectively multiplies the number by a power of two:

    • Example: Shifting 0b0011 (which is 3 in decimal) to the left by one position results in 0b0110 (which is 6).
  • Example : If the virtual machine's instruction is encoded as shl_ r1, r2, r3 , the operation performed would be: r1 = r2 << r3 . Here, r2 is the value to be shifted, and r3 specifies the number of positions to shift, with r1 being the destination register where the result is stored.

Encoding:

  • Value : The shl_ operation is encoded with the hexadecimal value 0x6 .

  • Instruction Encoding : This value is used by the virtual machine to decode and identify the shift left operation when executing instructions. In a bytecode stream, the presence of 0x6 as the opcode indicates that the following instruction is a bitwise shift left operation.

Usage Scenarios:

  • Arithmetic Operations : Bitwise shift left is commonly used in arithmetic operations, particularly in multiplication by powers of two, where shifting a number left by n positions is equivalent to multiplying it by 2^n .

  • Bit Manipulation : The SHL operation is often used in bit manipulation tasks, such as constructing bitmasks, encoding data, or preparing a binary value for further bitwise operations.

  • Performance Optimization : In some low-level programming scenarios, SHL can be used as a performance optimization over multiplication, as shifting is typically faster in hardware.

  • Data Alignment : SHL can be employed to align data in memory or adjust the positioning of bits for subsequent operations.

The shl_ operation is a fundamental tool in bitwise arithmetic, allowing efficient bit manipulation and multiplication by powers of two. It is widely used in scenarios that require precise control over the positioning of bits within binary data, making it an essential component of the virtual machine's instruction set.

shr_

Shift right operation.

Detailed Description

The shr_ enumerator represents the bitwise shift right (SHR) operation in the virtual machine's binary instruction set. This operation shifts the bits of a value in the first operand to the right by a specified number of positions indicated by the second operand, filling the vacated bits on the left with zeros. The result is stored in a designated destination register.

Operation Details:

  • Operands : The shr_ operation involves two source operands:

    • The first operand ( r1 ) is the value to be shifted.

    • The second operand ( r2 ) specifies the number of positions to shift.

  • Execution : The virtual machine reads the value from the first operand ( r1 ), shifts its bits to the right by the number specified in the second operand ( r2 ), and stores the result in the destination register.

  • Bitwise Shift Right (SHR) : Shifting a binary number to the right by one position is equivalent to dividing the number by 2, discarding the least significant bit (which effectively rounds down). Each right shift operation effectively divides the number by a power of two:

    • Example: Shifting 0b1100 (which is 12 in decimal) to the right by one position results in 0b0110 (which is 6).
  • Example : If the virtual machine's instruction is encoded as shr_ r1, r2, r3 , the operation performed would be: r1 = r2 >> r3 . Here, r2 is the value to be shifted, and r3 specifies the number of positions to shift, with r1 being the destination register where the result is stored.

Encoding:

  • Value : The shr_ operation is encoded with the hexadecimal value 0x7 .

  • Instruction Encoding : This value is used by the virtual machine to decode and identify the shift right operation when executing instructions. In a bytecode stream, the presence of 0x7 as the opcode indicates that the following instruction is a bitwise shift right operation.

Usage Scenarios:

  • Arithmetic Operations : Bitwise shift right is commonly used in arithmetic operations, particularly in division by powers of two, where shifting a number right by n positions is equivalent to dividing it by 2^n .

  • Bit Manipulation : The SHR operation is often used in bit manipulation tasks, such as clearing bits, encoding data, or preparing a binary value for further bitwise operations.

  • Performance Optimization : In some low-level programming scenarios, SHR can be used as a performance optimization over division, as shifting is typically faster in hardware.

  • Data Alignment : SHR can be employed to align data in memory or adjust the positioning of bits for subsequent operations.

The shr_ operation is a fundamental tool in bitwise arithmetic, allowing efficient bit manipulation and division by powers of two. It is widely used in scenarios that require precise control over the positioning of bits within binary data, making it an essential component of the virtual machine's instruction set.

write_

Write operation to memory.

Detailed Description

The write_ enumerator represents the memory write operation in the virtual machine's binary instruction set. This operation takes two operands: a destination address and a value. The value is written directly to the memory location specified by the destination address.

Operation Details:

  • Operands : The write_ operation involves two source operands:

    • The first operand ( r1 ) is the destination memory address where the data will be written.

    • The second operand ( r2 ) is the value to be written to the memory address.

  • Execution : The virtual machine reads the value from the second operand ( r2 ) and writes it to the memory location specified by the first operand ( r1 ).

  • Example : If the virtual machine's instruction is encoded as write_ r1, r2 , the operation performed would be: *(uint64_t*)r1 = r2 . Here, r1 holds the memory address, and r2 is the value to be written to that address.

Encoding:

  • Value : The write_ operation is encoded with the hexadecimal value 0x8 .

  • Instruction Encoding : This value is used by the virtual machine to decode and identify the write operation when executing instructions. In a bytecode stream, the presence of 0x8 as the opcode indicates that the following instruction is a memory write operation.

Usage Scenarios:

  • Memory Management : The write_ operation is a fundamental operation in memory management, allowing the virtual machine to modify memory contents at specific addresses during execution.

  • Data Storage : This operation is used to store values in memory, which can later be retrieved or modified by other operations within the virtual machine.

  • System Programming : In low-level system programming, the ability to directly write to memory is essential for tasks such as setting up hardware registers, configuring system state, or manipulating data structures.

  • Interfacing with Hardware : The write_ operation can be used to write to memory-mapped I/O addresses, effectively interfacing with hardware components or peripheral devices.

The write_ operation is crucial for directly manipulating memory contents, enabling a wide range of functionalities from simple data storage to complex system-level operations. It is an essential part of the virtual machine's instruction set, providing the means to interact with and modify memory at runtime.

mov_

Move operation.

Detailed Description

The mov_ enumerator represents the move operation in the virtual machine's binary instruction set. This operation is used to transfer data from one register to another. Unlike memory operations, mov_ works entirely within the registers of the virtual machine, making it a fundamental operation for managing and manipulating data in the virtual machine's execution environment.

Operation Details:

  • Operands : The mov_ operation involves two operands:

    • The first operand ( r1 ) is the destination register where the data will be moved to.

    • The second operand ( r2 ) is the source register from which the data will be taken.

  • Execution : The virtual machine reads the value stored in the source register ( r2 ) and writes it to the destination register ( r1 ). The original value in r1 is overwritten.

  • Example : If the virtual machine's instruction is encoded as mov_ r1, r2 , the operation performed would be: r1 = r2 . Here, r1 will hold the same value as r2 after the operation is executed.

Encoding:

  • Value : The mov_ operation is encoded with the hexadecimal value 0x9 .

  • Instruction Encoding : This value is used by the virtual machine to decode and identify the move operation when executing instructions. In a bytecode stream, the presence of 0x9 as the opcode indicates that the following instruction is a register-to-register data transfer.

Usage Scenarios:

  • Data Transfer : The mov_ operation is essential for transferring data between registers, which is a common task in most computation and data processing operations within the virtual machine.

  • Initialization : The mov_ operation is often used to initialize registers with specific values before performing operations on them.

  • Data Copying : This operation is used to copy values from one register to another, enabling the reuse or modification of data without altering the original value.

  • Flow Control : In some cases, mov_ is used to set up registers before conditional or arithmetic operations, ensuring the correct data is in place for subsequent instructions.

The mov_ operation is a cornerstone of register-based computation, providing the mechanism to move data between registers efficiently. It is a basic but powerful instruction that facilitates data manipulation and control within the virtual machine, supporting a wide range of computational and logical operations.

jump_rel_nz_

Conditional jump if not zero.

Detailed Description

The jump_rel_nz_ enumerator represents a conditional jump operation in the virtual machine's binary instruction set. This operation allows the virtual machine to alter the flow of execution based on the value of a specific register. If the value in the given register is not zero, the program counter is adjusted by a relative offset, effectively jumping to a new location in the code.

Operation Details:

  • Operands : The jump_rel_nz_ operation involves two operands:

    • The first operand ( r1 ) is the register whose value is checked.

    • The second operand ( offset ) is the relative offset to be added to the program counter (PC) if the condition is met.

  • Execution : The virtual machine evaluates the value stored in the register specified by the first operand ( r1 ):

    • If the value is not zero, the program counter is updated by adding the relative offset .

    • If the value is zero, the program counter remains unchanged, and execution proceeds to the next instruction in sequence.

  • Example : If the virtual machine's instruction is encoded as jump_rel_nz_ r1, offset , the operation checks the value of r1 :

    • If r1 != 0 , the PC is modified by adding the offset to jump to a different part of the code.

    • If r1 == 0 , no jump occurs, and the next instruction is executed.

Encoding:

  • Value : The jump_rel_nz_ operation is encoded with the hexadecimal value 0xA .

  • Instruction Encoding : This value is used by the virtual machine to decode and identify the conditional jump operation when executing instructions. In a bytecode stream, the presence of 0xA as the opcode indicates that the following instruction will be a conditional jump based on the non-zero status of a register.

Usage Scenarios:

  • Conditional Logic : The jump_rel_nz_ operation is commonly used to implement conditional branching in the code, allowing the virtual machine to make decisions based on the state of data in registers.

  • Loop Control : This operation can control loops by checking if a loop counter has reached zero. If not, it can jump back to the start of the loop or to other instructions within the loop.

  • Flow Control : The jump_rel_nz_ operation can be used to skip certain sections of code if a specific condition is met, allowing for more dynamic and flexible execution paths.

The jump_rel_nz_ operation is an essential part of implementing control flow in the virtual machine, providing a way to conditionally alter the execution path based on the state of a register. It supports the creation of loops, conditional branches, and other flow control structures that are critical for complex program logic.

jump_rel_ez_

Conditional jump if zero.

Detailed Description

The jump_rel_ez_ enumerator represents a conditional jump operation in the virtual machine's binary instruction set. This operation allows the virtual machine to alter the flow of execution based on the value of a specific register. If the value in the given register is zero, the program counter is adjusted by a relative offset, effectively jumping to a new location in the code.

Operation Details:

  • Operands : The jump_rel_ez_ operation involves two operands:

    • The first operand ( r1 ) is the register whose value is checked.

    • The second operand ( offset ) is the relative offset to be added to the program counter (PC) if the condition is met.

  • Execution : The virtual machine evaluates the value stored in the register specified by the first operand ( r1 ):

    • If the value is zero, the program counter is updated by adding the relative offset , causing the execution to jump.

    • If the value is not zero, the program counter remains unchanged, and execution proceeds to the next instruction in sequence.

  • Example : If the virtual machine's instruction is encoded as jump_rel_ez_ r1, offset , the operation checks the value of r1 :

    • If r1 == 0 , the PC is modified by adding the offset to jump to a different part of the code.

    • If r1 != 0 , no jump occurs, and the next instruction is executed.

Encoding:

  • Value : The jump_rel_ez_ operation is encoded with the hexadecimal value 0xB .

  • Instruction Encoding : This value is used by the virtual machine to decode and identify the conditional jump operation when executing instructions. In a bytecode stream, the presence of 0xB as the opcode indicates that the following instruction will be a conditional jump based on the zero status of a register.

Usage Scenarios:

  • Conditional Logic : The jump_rel_ez_ operation is commonly used to implement conditional branching in the code, allowing the virtual machine to make decisions based on the state of data in registers.

  • Loop Control : This operation can control loops by checking if a loop counter has reached zero, and if so, it can exit the loop or jump to a different part of the code.

  • Flow Control : The jump_rel_ez_ operation can be used to skip certain sections of code if a specific condition is met, allowing for more dynamic and flexible execution paths.

The jump_rel_ez_ operation is an essential part of implementing control flow in the virtual machine, providing a way to conditionally alter the execution path based on the state of a register. It supports the creation of loops, conditional branches, and other flow control structures that are critical for complex program logic.

or_

Bitwise OR operation.

Detailed Description

The or_ enumerator represents the bitwise OR operation within the virtual machine's binary instruction set. This operation performs a bitwise inclusive OR between the bits of two operands and stores the result in a designated register. It is a fundamental operation in many low-level programming tasks, including bit manipulation, flag setting, and condition evaluation.

Operation Details:

  • Operands : The or_ operation involves two operands:

    • The first operand ( r1 ) is the register where the result of the operation will be stored.

    • The second operand ( r2 ) is the register whose value will be OR-ed with the value in r1 .

  • Execution : The virtual machine performs a bitwise OR between the contents of the two registers:

    • The operation checks each bit of the two registers.

    • If either corresponding bit in r1 or r2 is 1 , the resulting bit in r1 is set to 1 .

    • If both corresponding bits are 0 , the resulting bit in r1 is set to 0 .

  • Example : Given two binary numbers:

    • r1 = 0b1010 and r2 = 0b1100

    • The result of r1 | r2 will be 0b1110 , which is then stored in r1 .

Encoding:

  • Value : The or_ operation is encoded with the hexadecimal value 0xC .

  • Instruction Encoding : This value is used by the virtual machine to identify and execute the bitwise OR operation. When 0xC is found as the opcode in a bytecode stream, the virtual machine knows to perform the OR operation between the specified registers.

Usage Scenarios:

  • Flag Manipulation : The bitwise OR operation is often used to set specific flags within a register without altering other bits. For example, setting a specific control bit in a status register.

  • Bitwise Operations : It is frequently used in bitwise algorithms where multiple bit patterns need to be combined.

  • Conditional Evaluations : The OR operation can be used to combine multiple conditions where at least one of them must be true.

The or_ operation is a crucial part of the virtual machine's instruction set, enabling efficient bit manipulation. It supports a wide range of operations, including setting specific bits in registers, combining multiple binary conditions, and implementing various low-level algorithms that require bitwise logic.

and_

Bitwise AND operation.

Detailed Description

The and_ enumerator represents the bitwise AND operation within the virtual machine's binary instruction set. This operation performs a bitwise logical AND between the bits of two operands and stores the result in a designated register. The AND operation is fundamental in scenarios where you need to mask bits, clear specific bits, or evaluate multiple conditions simultaneously.

Operation Details:

  • Operands : The and_ operation involves two operands:

    • The first operand ( r1 ) is the register where the result of the operation will be stored.

    • The second operand ( r2 ) is the register whose value will be AND-ed with the value in r1 .

  • Execution : The virtual machine performs a bitwise AND between the contents of the two registers:

    • The operation checks each bit of the two registers.

    • If both corresponding bits in r1 and r2 are 1 , the resulting bit in r1 is set to 1 .

    • If either or both corresponding bits are 0 , the resulting bit in r1 is set to 0 .

  • Example : Given two binary numbers:

    • r1 = 0b1010 and r2 = 0b1100

    • The result of r1 & r2 will be 0b1000 , which is then stored in r1 .

Encoding:

  • Value : The and_ operation is encoded with the hexadecimal value 0xD .

  • Instruction Encoding : This value is used by the virtual machine to identify and execute the bitwise AND operation. When 0xD is found as the opcode in a bytecode stream, the virtual machine knows to perform the AND operation between the specified registers.

Usage Scenarios:

  • Bit Masking : The bitwise AND operation is often used to mask certain bits in a register, effectively clearing or retaining specific bits. For example, to clear all bits except the lower 4 bits of a register, one might AND the register with 0x0F .

  • Condition Evaluation : It can be used to check if certain bits are set in a status register, which is useful in implementing conditional logic.

  • Data Integrity Checks : AND operations are also used in checksum algorithms and parity checks where specific bit patterns need to be validated.

The and_ operation is a crucial component of the virtual machine's instruction set, allowing for efficient bit manipulation. Its ability to perform logical AND operations at the bit level makes it indispensable in scenarios requiring fine-grained control over data. Whether you're working with bit masks, implementing conditional logic, or ensuring data integrity, the and_ operation is a powerful tool.

call_vfunc_

Call virtual function operation.

Detailed Description

The call_vfunc_ enumerator represents the operation for invoking a virtual function within the virtual machine's binary instruction set. This operation is used to perform a dynamic dispatch, where a function is called based on the contents of a virtual function table (vtable). This mechanism is fundamental in object-oriented programming for implementing polymorphism, allowing the behavior of objects to be determined at runtime.

Operation Details:

  • Operands : The call_vfunc_ operation involves two operands:

    • The first operand ( r1 ) is a register that holds the address of the object whose virtual function is to be called.

    • The second operand ( r2 ) is a register that holds the index into the virtual function table (vtable) to identify which function to call.

  • Execution :

    • The virtual machine retrieves the vtable from the object located at the address stored in r1 .

    • It then uses the index in r2 to locate the specific function in the vtable.

    • The identified function is then invoked, with the virtual machine passing control to this function.

    • After the function executes, the control returns to the virtual machine.

  • Example :

    • Suppose r1 contains the address of an object, and r2 contains the index 3 .

    • The virtual machine will look up the 3rd entry in the object's vtable and call the corresponding function.

Encoding:

  • Value : The call_vfunc_ operation is encoded with the hexadecimal value 0xE .

  • Instruction Encoding : This value is used by the virtual machine to identify and execute the call to a virtual function. When 0xE is found as the opcode in a bytecode stream, the virtual machine knows to perform the virtual function call.

Usage Scenarios:

  • Polymorphism : The call_vfunc_ operation is essential for implementing polymorphism in object-oriented systems. It allows objects to decide at runtime which function implementation to execute based on their actual type, even if they are referenced by a base class type.

  • Dynamic Dispatch : This operation enables dynamic dispatch, where the method that gets called depends on the type of the object rather than being determined at compile-time.

  • Inheritance Hierarchies : In systems with complex inheritance hierarchies, call_vfunc_ ensures that the correct method is called, respecting the override mechanisms of derived classes.

The call_vfunc_ operation is a critical feature of the virtual machine, enabling advanced object-oriented programming techniques such as polymorphism and dynamic dispatch. It ensures that function calls are resolved at runtime based on the actual object type, which is crucial for implementing flexible and maintainable code in systems that use inheritance and virtual functions.

size_

Represents the total number of binary operations.

Detailed Description

The size_ enumerator is used to define the total number of binary operations available in the virtual machine's instruction set. This value is particularly useful for iterating over the binary operations or for validating instructions within the virtual machine.

Purpose:

  • Count of Operations : The size_ enumerator serves as a constant representing the count of all binary operations defined in the vm_binary_op enum class. It is set to 0x10 , which corresponds to the total number of unique binary operations (including arithmetic, logical, and control operations).

  • Upper Bound : This value can also act as an upper bound when performing range checks on binary operations or when generating new instructions. For example, it can be used to ensure that an opcode falls within the valid range of binary operations.

  • Iterating Over Operations : When iterating over all possible binary operations, size_ provides the necessary boundary to avoid going out of range.

Encoding:

  • Value : The size_ enumerator is encoded with the hexadecimal value 0x10 , which is equivalent to 16 in decimal.

  • Instruction Set Size : This value indicates that there are 16 distinct binary operations in the virtual machine's binary instruction set. Each of these operations is identified by a unique opcode, ranging from 0x0 to 0xF .

Usage Scenarios:

  • Instruction Validation : size_ can be used to validate whether a given opcode corresponds to a valid binary operation. For example, when decoding instructions, the virtual machine can check if an opcode is less than size_ to ensure it is a valid binary operation.

  • Iteration : Developers can use size_ to loop over all defined binary operations, making it easier to manage and extend the instruction set.

  • Static Assertions : In cases where the virtual machine's binary operation count must remain constant, size_ can be used in static assertions to enforce this constraint during compilation.

The size_ enumerator is a crucial part of the virtual machine's binary operation enumeration. It ensures that the instruction set remains well-defined, bounded, and easy to manage, supporting robust implementation and validation of binary operations.

vm_unary_op

Enum class representing unary operations in the virtual machine.

Detailed Description

The vm_unary_op enum class defines a set of operations that take a single operand. These operations are typically used for arithmetic, logical, and control flow instructions within the virtual machine.

Each enumerator in this enum class represents a distinct unary operation that the virtual machine can execute. Unary operations typically modify a single register or affect the flow of execution based on the value of a single operand.

Encoding:

  • Underlying Type : The underlying type for the enum is uint8_t , meaning each operation is represented by an 8-bit value.

  • Operation Codes : Each enumerator is assigned a unique hexadecimal value, starting from 0x0 , which acts as the operation code (opcode) for that unary operation.

List of Unary Operations:

The following are the unary operations available in the virtual machine, each with a brief description:

jump_

Unconditional jump operation.

Detailed Description

The jump_ operation is one of the core control flow instructions within a virtual machine's instruction set. This operation unconditionally transfers the execution flow to a new address specified by the operand, which is typically a memory address or an offset.

Execution Flow:

When the jump_ operation is encountered, the virtual machine immediately updates the instruction pointer (IP), program counter (PC), or the equivalent register that tracks the current execution point to the address specified by the operand.

Operand:

  • Target Address : The operand for this operation is the target address or offset where execution should continue. The address can be:
    • An absolute memory address in the virtual machine's memory space.

    • A relative offset, depending on the virtual machine's design, which is added to the current instruction pointer to determine the new execution location.

Usage Scenarios:

  • Function Calls : In combination with other operations, such as setting up a stack frame or saving the return address, the jump_ operation can be used to implement function calls.

  • Loop Constructs : It is often used to create loops by jumping back to a previous instruction, facilitating repeated execution of a block of code.

  • Branching : While conditional jumps depend on certain conditions being true or false, jump_ allows for unconditional branching, which is essential for implementing simple and complex control flows within the virtual machine.

inc_

Increment operation.

Detailed Description

The inc_ operation increments the value stored in a specified register by one. This operation is commonly used in loops, counters, and arithmetic operations within a virtual machine's instruction set.

Execution Flow:

When the inc_ operation is executed, the virtual machine retrieves the value from the specified operand (which is typically a register), adds one to this value, and then stores the result back into the same register.

Operand:

  • Target Register : The operand for this operation is the target register whose value will be incremented. The register holds the current value before the operation and will contain the incremented value after the operation.

Usage Scenarios:

  • Counters : The inc_ operation is ideal for incrementing counters in loops, especially in scenarios where a block of code needs to be executed a certain number of times.

  • Pointer Arithmetic : In scenarios involving arrays or memory manipulation, inc_ can be used to advance a pointer to the next element in an array or to move to the next memory address.

  • General Arithmetic : While simple, incrementing is a fundamental operation in arithmetic expressions and can be used in combination with other operations for more complex calculations.

dec_

Decrement operation.

Detailed Description

The dec_ operation decrements the value stored in a specified register by one. This operation is commonly used in loops, counters, and arithmetic operations within a virtual machine's instruction set.

Execution Flow:

When the dec_ operation is executed, the virtual machine retrieves the value from the specified operand (which is typically a register), subtracts one from this value, and then stores the result back into the same register.

Operand:

  • Target Register : The operand for this operation is the target register whose value will be decremented. The register holds the current value before the operation and will contain the decremented value after the operation.

Usage Scenarios:

  • Counters : The dec_ operation is useful for decrementing counters in loops, especially in scenarios where a block of code needs to be executed a certain number of times, with each iteration reducing the counter value.

  • Pointer Arithmetic : In scenarios involving arrays or memory manipulation, dec_ can be used to move a pointer to the previous element in an array or to the previous memory address.

  • General Arithmetic : Decrementing is a fundamental operation in arithmetic expressions and can be used in combination with other operations for more complex calculations.

read_

Read operation from memory.

Detailed Description

The read_ unary operation reads a value from a memory address specified in a register and loads it into another register or the same register. This operation allows the virtual machine to access data from memory and use it in subsequent instructions.

Execution Flow:

When the read_ operation is executed, the virtual machine:

  • Interprets the operand as the register holding the memory address.

  • Accesses the value stored at that memory address.

  • Loads the retrieved value back into the return register.

Operand:

  • Source Register : The register containing the memory address from which the data is to be read.

Usage Scenarios:

  • Data Retrieval : The read_ operation is used to load data from a specific memory address into a register, making the data available for subsequent operations.

  • Pointer Operations : In operations involving pointers, read_ can be used to dereference the pointer and obtain the value stored at the pointed-to memory address.

  • Indirect Addressing : The read_ operation facilitates indirect addressing, where the memory address is stored in a register, allowing dynamic data access based on the value in the register.

jump_rel_

Relative jump operation.

Detailed Description

The jump_rel_ unary operation performs a jump to a new instruction address relative to the current instruction pointer. This operation allows the virtual machine to alter the control flow based on relative offsets.

Execution Flow:

When the jump_rel_ operation is executed, the virtual machine:

  • Interprets the operand as a signed or unsigned value that represents the offset from the current instruction pointer.

  • Adds the offset to the current instruction pointer.

  • Updates the instruction pointer to the new location, effectively jumping to the specified instruction.

Operand:

  • Offset : A value in the register that specifies the distance to jump relative to the current instruction pointer. The offset can be positive (jump forward) or negative (jump backward).

Usage Scenarios:

  • Control Flow : The jump_rel_ operation is commonly used in loops, conditional statements, and other control flow constructs to navigate between instructions within the code.

  • Efficient Branching : By using relative jumps, the virtual machine can perform efficient branching without needing absolute memory addresses, making the code more flexible and position-independent.

  • Dynamic Execution Paths : This operation enables dynamic changes in the execution path based on calculated or variable offsets, useful in scenarios like state machines or event-driven code.

push_

Push operation onto the stack.

Detailed Description

The push_ unary operation pushes a value from a specified register onto the virtual machine's stack. This operation is essential for managing function calls, local variables, and intermediate values in a LIFO (Last In, First Out) manner.

Execution Flow:

When the push_ operation is executed, the virtual machine:

  • Reads the value from the specified register.

  • Pushes the value onto the top of the stack.

  • Updates the stack pointer to reflect the new top of the stack.

Operand:

  • Register : The operand is the register containing the value to be pushed onto the stack. The register is specified in the instruction.

Usage Scenarios:

  • Function Calls : The push_ operation is used to pass arguments to functions and save return addresses before branching to a function's entry point.

  • Local Variables : In function or procedure execution, push_ can be used to allocate space on the stack for local variables.

  • Temporary Storage : This operation is often used to temporarily store intermediate results or state information during complex calculations or algorithmic processes.

Stack Management:

  • Stack Growth : The stack grows downwards (or upwards depending on the architecture) as values are pushed onto it. Each push operation decreases (or increases) the stack pointer accordingly.

  • Overflow Considerations : Care should be taken to avoid stack overflow by ensuring that the stack does not exceed its allocated size when pushing values.

pop_

Pop operation from the stack.

Detailed Description

The pop_ unary operation retrieves a value from the top of the virtual machine's stack and stores it into a specified register. This operation is crucial for managing function returns, restoring local variables, and retrieving intermediate values from the stack.

Execution Flow:

When the pop_ operation is executed, the virtual machine:

  • Retrieves the value from the top of the stack.

  • Stores the retrieved value into the specified register.

  • Updates the stack pointer to reflect the new top of the stack after the value has been removed.

Operand:

  • Register : The operand is the register into which the value popped from the stack will be stored. The register is specified in the instruction.

Usage Scenarios:

  • Function Returns : The pop_ operation is used to restore the return address from the stack before returning control to the calling function.

  • Local Variables : In function or procedure execution, pop_ can be used to restore local variables or parameters that were previously pushed onto the stack.

  • Retrieving Temporary Values : This operation is commonly used to retrieve intermediate results or state information that were stored on the stack during the execution of complex calculations or algorithms.

Stack Management:

  • Stack Shrinkage : The stack shrinks (or grows upwards depending on the architecture) as values are popped from it. Each pop operation increases (or decreases) the stack pointer accordingly.

  • Underflow Considerations : Care should be taken to avoid stack underflow by ensuring that the stack is not empty when attempting to pop values.

call_

Call function operation.

Detailed Description

The call_ unary operation is used to invoke a function or procedure within the virtual machine's environment. This operation facilitates the execution of subroutines by transferring control to a different part of the code, while preserving the return address to enable a proper return to the calling location after the function completes.

Execution Flow:

When the call_ operation is executed, the virtual machine performs the following steps:

  • Save Return Address : The address of the next instruction after the call_ operation is saved onto the stack. This allows the function to return control to the appropriate location after execution.

  • Jump to Function Address : The virtual machine then jumps to the address of the function or procedure specified by the operand.

  • Execute Function : The function code is executed, potentially involving operations on local variables, parameters, and temporary storage.

  • Return to Caller : Upon completion of the function, the virtual machine retrieves the saved return address from the stack and transfers control back to that address.

Operand:

  • Function Address : The operand for the call_ operation is the address of the function or procedure to be called. This is specified in the instruction and directs the virtual machine to the correct location in the code.

Usage Scenarios:

  • Subroutine Invocation : The call_ operation is fundamental in invoking subroutines or functions, allowing for code modularity and reusability.

  • Function Calls with Parameters : In a context where parameters are passed to functions, call_ is used after pushing the necessary parameters onto the stack.

  • Recursive Function Calls : The call_ operation can be used to implement recursion, where a function calls itself to solve a problem iteratively.

Stack Management:

  • Return Address Handling : The return address is automatically managed by the call_ operation, ensuring that after the function completes, control returns to the appropriate place in the calling code.

  • Stack Frame Creation : Depending on the virtual machine's implementation, the call_ operation might also initiate a new stack frame to manage local variables and parameters specific to the called function.

Error Handling:

  • Invalid Function Address : Care must be taken to ensure that the function address is valid and points to a callable section of the code to prevent undefined behavior or crashes.

size_

Total number of unary operations.

Detailed Description

The size_ enumeration value represents the total count of unary operations defined in the vm_unary_op enum. This value is primarily used to determine the size of data structures, such as arrays or tables, that manage or reference these unary operations within the virtual machine's implementation.

Purpose:

  • Boundary Validation : The size_ value is often used in the virtual machine to validate or ensure that any index used to access the unary operations array or table is within a valid range.

  • Loop Boundaries : In scenarios where the virtual machine iterates over all unary operations, size_ provides a convenient boundary for loops.

  • Array Sizing : When creating static arrays or buffers that map or store information related to unary operations, size_ is used to ensure the correct allocation size.

Usage Scenario:

  • Operation Dispatch Tables : If the virtual machine uses a dispatch table to invoke unary operations based on an opcode, size_ can be used to define the number of entries in that table.

  • Validation Checks : During the decoding of instructions, size_ can be used to verify that a decoded operation code corresponds to a valid unary operation.

Value:

  • Numeric Representation : The size_ is set to 0x10 , which corresponds to the total number of unary operations in this enumeration, ensuring that any iteration or indexing covers all defined operations.

vm_nullary_op

Enum representing nullary operations in the virtual machine.

Detailed Description

The vm_nullary_op enum class defines operations that do not take any operands. These operations are executed directly without the need for additional data, making them simpler and faster in certain scenarios.

Purpose:

  • Nullary Operations : Operations defined in this enum perform actions that are either standalone or affect the virtual machine's state without needing input parameters.

  • Virtual Machine Control : Many of the operations in this enum are used to control the flow of execution or manage the internal state of the virtual machine.

Usage Scenario:

  • Instruction Decoding : When the virtual machine decodes an instruction that corresponds to a nullary operation, it references this enum to determine the action to take.

  • Efficient Execution : Nullary operations are typically more efficient as they do not require operand fetching, making them ideal for simple tasks within the virtual machine.

Example Operations:

  • Halt : A typical nullary operation might be to halt the execution of the virtual machine.

ret_

Return from function operation.

Detailed Description

The ret_ operation is a nullary operation that instructs the virtual machine to return from the current function or execution context. This operation typically restores the previous state of the virtual machine, such as the instruction pointer, to the point where the current function was called.

Purpose:

  • Function Return : The ret_ operation is used to return control to the caller function after the execution of a subroutine or function is complete.

  • Stack Management : In some virtual machines, the ret_ operation may involve manipulating the call stack, such as popping the return address from the stack to resume execution.

Usage Scenario:

  • End of Function : When a function completes its task, the ret_ operation is executed to exit the function and continue execution from the calling location.

  • Control Flow : The ret_ operation is a key element in controlling the flow of execution within the virtual machine, ensuring that functions return to their correct caller.

crash_

Cause a crash operation.

Detailed Description

The crash_ operation is a nullary operation that deliberately causes the virtual machine to crash or terminate abnormally. This operation is typically used to simulate or trigger a fatal error condition within the virtual machine, leading to an immediate halt in execution.

Purpose:

  • Error Simulation : The crash_ operation can be used during testing or debugging to simulate fatal errors and observe how the virtual machine or surrounding system handles such conditions.

  • Security Measures : In some security-focused implementations, the crash_ operation may be used as a defensive mechanism to halt execution when suspicious or unauthorized behavior is detected.

Usage Scenario:

  • Intentional Halt : Developers may use the crash_ operation to intentionally halt the virtual machine during specific conditions, such as detecting tampering or corruption in the code.

  • Debugging : During development, this operation can be used to test the virtual machine's robustness in handling unexpected termination scenarios.

Effects:

  • Immediate Termination : When the crash_ operation is executed, the virtual machine's execution is immediately terminated, and control is not returned to the calling function or program.

  • Potential Side Effects : Depending on the implementation, executing this operation may result in the loss of data or state within the virtual machine, as it does not perform any cleanup before crashing.

halt_

Halt execution operation.

Detailed Description

The halt_ operation is a nullary operation that stops the execution of the virtual machine. When this operation is encountered, the virtual machine halts all further processing and returns control to the calling environment or terminates the current execution context.

Purpose:

  • End of Execution : The halt_ operation is typically used to signal the end of the program or script running within the virtual machine. It marks the completion of all intended operations and prevents any further instructions from being executed.

  • Safe Termination : Unlike the crash_ operation, which causes an abnormal termination, the halt_ operation provides a controlled and safe way to stop the virtual machine's execution.

Usage Scenario:

  • Program Termination : Developers may place the halt_ operation at the end of a sequence of instructions to ensure that the virtual machine stops once all tasks have been completed.

  • Interrupt Handling : In scenarios where the virtual machine needs to stop due to an external interrupt or signal, the halt_ operation can be invoked to terminate execution cleanly.

Effects:

  • Controlled Stop : Upon encountering the halt_ operation, the virtual machine ceases all further execution of instructions, and no additional operations are processed.

  • Return Value : If applicable, the virtual machine may return a final result or status code to the calling environment when the halt_ operation is executed.

Comparison with Other Operations:

  • **vs. crash_ ** : While the crash_ operation causes an abrupt and potentially destructive termination, the halt_ operation stops execution in a planned and controlled manner.

  • **vs. ret_ ** : The ret_ operation is used to return from a function call, while the halt_ operation stops the entire virtual machine's execution.

dbg_present_

Check if a debugger is present operation.

Detailed Description

The dbg_present_ operation is a nullary operation used to check if a debugger is currently attached to the process running the virtual machine. This operation is crucial for security-sensitive environments where detecting a debugger can trigger specific countermeasures or alter the behavior of the virtual machine to prevent tampering or reverse engineering.

Purpose:

  • Security and Anti-Tampering : The primary purpose of the dbg_present_ operation is to detect the presence of a debugger. In security-critical applications, detecting a debugger allows the software to take appropriate action, such as terminating the process, obfuscating sensitive data, or altering execution flow to mislead the debugger.

  • Integrity Verification : Ensuring that the application is not being debugged is a common practice in protecting intellectual property and sensitive algorithms from being exposed through reverse engineering techniques.

Usage Scenario:

  • Real-time Debugger Detection : This operation can be invoked at strategic points within the virtual machine's execution flow to continuously monitor whether a debugger has been attached at any stage.

  • Conditional Execution : Based on the result of this operation, the virtual machine or the containing program can decide whether to proceed with normal execution or engage anti-debugging measures.

Effects:

  • Return Value : The operation typically sets a specific register or memory location with a value indicating whether a debugger is detected. The exact implementation may vary, but a common approach is to set a flag or return a boolean value.

  • Behavior Modification : If a debugger is detected, the virtual machine might alter its behavior to prevent effective debugging, such as by introducing false paths, corrupting data, or terminating execution.

Comparison with Other Operations:

  • **vs. halt_ ** : While halt_ is used to stop execution, dbg_present_ is used to monitor the execution environment for potential interference by a debugger.

  • **vs. crash_ ** : The dbg_present_ operation does not inherently cause a crash, but it might lead to such an outcome if a debugger is detected, depending on how the operation's result is handled.

Security Considerations:

  • Anti-Debugging Techniques : The effectiveness of the dbg_present_ operation depends on how well it is integrated with other anti-debugging techniques. Sophisticated attackers may bypass simple debugger detection mechanisms, so this operation is often part of a larger suite of security measures.

  • Stealth : Care should be taken to ensure that the use of dbg_present_ does not itself become a point of interest for attackers, who might attempt to neutralize or circumvent its effects.

ternary_

Ternary operation marker.

Detailed Description

The ternary_ operation marker is a nullary operation used to indicate the start or presence of a ternary operation within the virtual machine's execution flow. This marker does not perform any direct computation by itself but serves as a control indicator to manage how the virtual machine interprets and processes subsequent instructions that require three operands.

Purpose:

  • Instruction Categorization : The primary role of the ternary_ marker is to signal that the following operation in the instruction stream is a ternary operation, meaning it involves three distinct operands.

  • Execution Flow Control : By marking the beginning of a ternary operation, this marker helps the virtual machine correctly fetch, decode, and execute instructions that require three inputs, ensuring proper execution flow.

Usage Scenario:

  • Complex Operations : Ternary operations are typically used for more complex computations, such as those involving multiple values where a single instruction must manipulate or combine three operands in a specific way. The ternary_ marker indicates that such an operation is to follow.

  • Virtual Machine Parsing : During the parsing of bytecode or instruction sequences, the ternary_ marker allows the virtual machine to anticipate and prepare for operations that differ from simpler unary or binary instructions.

Effects:

  • No Direct Computation : The ternary_ marker itself does not change any registers or memory directly; instead, it sets the stage for the following ternary operation, ensuring that the correct number of operands are fetched and handled.

  • Instruction Decoding : When the virtual machine encounters this marker, it transitions into a mode where it expects to process three subsequent operands as part of a single operation. This is crucial for maintaining the integrity of the execution flow, especially in complex instruction sets.

Comparison with Other Markers:

  • vs. unary_ and binary_ Markers : Unlike unary_ and binary_ markers, which indicate operations involving one or two operands respectively, the ternary_ marker is specifically for operations involving three operands, making it unique in its role within the instruction set.

  • vs. Operational Instructions : While operational instructions like add_ , sub_ , or xor_ perform actual computations, the ternary_ marker does not directly manipulate data but rather controls the flow of instruction decoding.

Implementation Considerations:

  • Instruction Alignment : When designing the bytecode or instruction set for the virtual machine, it is essential to correctly place the ternary_ marker before any ternary operation to avoid misinterpretation of instructions and ensure proper execution.

  • Security and Obfuscation : In security-sensitive applications, the use of markers like ternary_ can be strategically placed to obfuscate the real flow of operations, making reverse engineering more difficult.

binary_

Binary operation marker.

Detailed Description

The binary_ operation marker is a nullary operation used to indicate the presence or start of a binary operation within the virtual machine's instruction flow. While it does not perform any computation by itself, this marker plays a crucial role in guiding the virtual machine to interpret and execute instructions that require two operands.

Purpose:

  • Instruction Categorization : The binary_ marker serves as a control signal that indicates the following instruction will involve a binary operation, meaning it requires two operands.

  • Execution Flow Control : By marking the start of a binary operation, this marker helps the virtual machine prepare to correctly fetch, decode, and process instructions that involve two inputs, ensuring accurate execution of the binary operation.

Usage Scenario:

  • Arithmetic and Logical Operations : Binary operations typically include arithmetic (e.g., addition, subtraction) and logical (e.g., AND, OR, XOR) operations. The binary_ marker signals that such an operation will follow, involving two distinct operands.

  • Instruction Parsing : During the parsing of bytecode or an instruction stream, the binary_ marker informs the virtual machine to expect and handle an instruction that operates on two operands, distinguishing it from unary or ternary operations.

Effects:

  • No Direct Computation : The binary_ marker itself does not modify registers or memory directly. Its role is to set up the correct context for the binary operation that follows, ensuring the virtual machine interprets and processes the next instruction with the appropriate number of operands.

  • Instruction Decoding : Upon encountering this marker, the virtual machine transitions to a mode where it expects to process two operands in the subsequent instruction, which is essential for maintaining the proper execution flow.

Comparison with Other Markers:

  • vs. unary_ and ternary_ Markers : Unlike the unary_ marker, which indicates operations involving a single operand, and the ternary_ marker, which involves three operands, the binary_ marker is specifically used for operations that involve two operands.

  • vs. Operational Instructions : Operational instructions such as add_ , sub_ , or and_ perform actual binary operations. The binary_ marker, however, does not execute an operation itself but rather indicates that a binary operation is about to be executed, guiding the decoding process.

Implementation Considerations:

  • Instruction Alignment : It is crucial to correctly place the binary_ marker before any binary operation in the instruction stream to avoid misinterpretation and ensure proper execution of the binary operation.

  • Security and Obfuscation : The strategic placement of markers like binary_ can be used in obfuscation techniques to make the instruction flow less predictable, thereby enhancing security against reverse engineering attempts.

unary_

Unary operation marker.

Detailed Description

The unary_ operation marker is a nullary operation used to indicate the presence or start of a unary operation within the virtual machine's instruction flow. This marker plays a critical role in guiding the virtual machine to interpret and execute instructions that require a single operand.

Purpose:

  • Instruction Categorization : The unary_ marker serves as a control signal that the subsequent instruction will involve a unary operation, meaning it operates on a single operand.

  • Execution Flow Control : By marking the start of a unary operation, this marker helps the virtual machine prepare to correctly fetch, decode, and process instructions that involve one input, ensuring accurate execution of the unary operation.

Usage Scenario:

  • Single Operand Operations : Unary operations typically include actions like incrementing, decrementing, or negating a value. The unary_ marker signals that such an operation will follow, involving a single operand.

  • Instruction Parsing : During the parsing of bytecode or an instruction stream, the unary_ marker informs the virtual machine to expect and handle an instruction that operates on one operand, distinguishing it from binary or ternary operations.

Effects:

  • No Direct Computation : The unary_ marker itself does not perform any computation. Its role is to set up the correct context for the unary operation that follows, ensuring the virtual machine interprets and processes the next instruction with the appropriate operand.

  • Instruction Decoding : Upon encountering this marker, the virtual machine transitions to a mode where it expects to process a single operand in the subsequent instruction, which is crucial for maintaining the proper execution flow.

Comparison with Other Markers:

  • vs. binary_ and ternary_ Markers : Unlike the binary_ marker, which indicates operations involving two operands, and the ternary_ marker, which involves three operands, the unary_ marker is specifically used for operations that involve a single operand.

  • vs. Operational Instructions : Operational instructions such as inc_ , dec_ , or read_ perform actual unary operations. The unary_ marker, however, does not execute an operation itself but rather indicates that a unary operation is about to be executed, guiding the decoding process.

Implementation Considerations:

  • Instruction Alignment : It is crucial to correctly place the unary_ marker before any unary operation in the instruction stream to avoid misinterpretation and ensure proper execution of the unary operation.

  • Security and Obfuscation : The strategic placement of markers like unary_ can be used in obfuscation techniques to make the instruction flow less predictable, thereby enhancing security against reverse engineering attempts.

size_

Total number of nullary operations.

Detailed Description

The size_ enumerator serves as a marker indicating the total count of possible nullary operations defined within the vm_nullary_op enum class. This value is often used to determine the bounds of the enum and to validate or iterate over the possible operations within the virtual machine's instruction set.

Purpose:

  • Boundary Definition : The size_ value represents the upper limit of the enum's range, providing a clear indicator of the total number of nullary operations that the virtual machine supports. This is useful in scenarios where the operations need to be enumerated or checked for validity.

  • Iteration Control : When iterating over nullary operations, size_ can be used as a stopping condition to ensure that the iteration stays within the defined operations.

  • Enum Range Checking : The size_ value is also beneficial in validation logic to check whether a given operation code falls within the valid range of nullary operations.

Usage Scenario:

  • Validation : Before executing an operation, the virtual machine might check that the operation code is within the range defined by size_ to prevent out-of-bounds errors or undefined behavior.

  • Loop Iteration : In loops that need to process or list all available nullary operations, size_ is used to determine the loop's endpoint.

Effects:

  • No Direct Operation : The size_ enumerator does not correspond to an executable operation but rather acts as a reference point for the total number of nullary operations available in the virtual machine's instruction set.

  • Static Bound : As a compile-time constant, size_ provides a reliable and fixed bound for operations related to the vm_nullary_op enum class.

Implementation Considerations:

  • Consistent Updates : Whenever new nullary operations are added to the vm_nullary_op enum class, the value of size_ should be updated accordingly to reflect the correct number of operations.

  • Compiler Optimization : Using size_ in iteration and validation scenarios allows the compiler to optimize these operations, potentially reducing overhead by using the constant value for bounds checking.

  • Enum Integrity : size_ ensures that any logic relying on the number of nullary operations remains accurate and up-to-date, thereby maintaining the integrity of the virtual machine's operation set.

vm_register

Enum class representing the registers available in the virtual machine.

Detailed Description

The vm_register enum class defines the set of registers that can be used within the virtual machine. Registers are special memory locations within the virtual machine that store intermediate values, operands, and results of operations. Each register has a specific purpose and can be accessed using the respective enumerator.

Purpose:

  • Operand Storage : Registers are used to store operands for various instructions executed by the virtual machine.

  • Temporary Results : Intermediate results of computations and operations are stored in registers before being used in further operations or stored in memory.

  • Control Flow : Some registers are used to control the flow of execution, such as storing return addresses or condition flags.

Register Enumerators:

The specific registers defined within this enum class might include, but are not limited to:

  • ** r0 , r1 , r2 , ... rN **: General-purpose registers used for various computations and operations.

  • ** return_register **: Holds the return value from a function or operation.

  • ** from_code **: A special register used internally by the virtual machine.

Usage Scenario:

  • Instruction Execution : During the execution of instructions, the virtual machine will read from and write to these registers to perform the required operations.

  • Function Calls : Registers like return_register and stack_pointer are critical during function calls and returns, managing the call stack and passing return values.

  • Control Flow Management : Registers like instruction_pointer and flags are essential for managing the control flow of the virtual machine, such as branching and loops.

Effects:

  • Direct Memory Access : Operations on registers often involve direct access to memory, especially when registers are used to point to specific memory locations (e.g., stack_pointer or base_pointer ).

  • Performance : Registers provide fast access to operands and intermediate results, making them essential for the efficient execution of virtual machine instructions.

Implementation Considerations:

  • Register Allocation : The virtual machine's register allocator should efficiently manage these registers to avoid unnecessary spills to memory.

  • Optimization : Proper use of registers can lead to significant performance optimizations within the virtual machine, reducing the need for memory access and speeding up execution.

  • Security : In some cases, certain registers might be used to implement security features, such as storing cryptographic keys or managing protected control flows.

Comparison with Other Enums:

  • **vs. vm_binary_op **: While vm_binary_op defines operations that the virtual machine can perform, vm_register defines the storage locations where operands and results are stored.

  • **vs. vm_unary_op and vm_ternary_op **: These enums define operations with one or three operands, respectively, while vm_register provides the locations for those operands.

return_register

Register used to store the result of operations or function calls.

Detailed Description

The return_register is designated for holding the result of the most recent operation or function executed by the virtual machine. It is a central part of the virtual machine's register set and is often used to pass the result of a computation back to the caller. This register ensures that the result of an executed instruction is easily accessible and can be utilized in subsequent operations or returned to the function that initiated the call. Typically, after a function or an operation completes its execution, the final value is stored in the return_register , making it the output of that function or operation.

r1

General-purpose register 1.

Detailed Description

The r1 register is one of the general-purpose registers available in the virtual machine. It can be used for a wide range of operations, such as arithmetic calculations, logical operations, and data manipulation tasks. The r1 register acts as a temporary storage location for intermediate values during computation. Due to its general-purpose nature, it does not have a specific assigned role and can be used in various contexts depending on the instruction being executed. Programmers can leverage the r1 register to store data temporarily, pass parameters between functions, or hold results from intermediate steps in complex operations.

r2

General-purpose register 2.

Detailed Description

The r2 register is another general-purpose register in the virtual machine, similar to r1 . It can be used for a variety of tasks, including arithmetic operations, logical comparisons, and data manipulation. The r2 register often serves as a temporary storage location for intermediate values or as a secondary operand in binary and ternary operations. Due to its flexibility, r2 can be utilized in numerous contexts, such as holding loop counters, storing function parameters, or preserving results from computations. Its usage is determined by the specific needs of the instructions being executed.

r3

General-purpose register 3.

Detailed Description

The r3 register is a general-purpose register in the virtual machine, similar to r1 and r2 . It is used for various computational tasks, such as arithmetic operations, logical operations, and temporary data storage. The r3 register can serve as an additional operand in more complex instructions, such as ternary operations, where three registers are needed. It may also be employed to store intermediate results, function parameters, or other transient data during the execution of a program. The use of r3 provides flexibility in managing data flow and computations within the virtual machine.

r4

General-purpose register 4.

Detailed Description

The r4 register is a versatile general-purpose register within the virtual machine, complementing other registers such as r1 , r2 , and r3 . It is used for storing and manipulating data during the execution of instructions. Like its counterparts, r4 can be employed in arithmetic operations, logical operations, and for holding temporary data. This register is especially useful when additional operands are required in complex operations, or when managing multiple intermediate values in extended sequences of instructions. The availability of r4 enhances the virtual machine's ability to handle sophisticated computational tasks and data management scenarios.

r5

General-purpose register 5.

Detailed Description

The r5 register is another general-purpose register within the virtual machine, similar to r1 through r4 . It is used for a wide range of tasks, including storing intermediate values, performing arithmetic and logical operations, and handling various data manipulations during the execution of virtual machine instructions. The inclusion of r5 provides additional flexibility, allowing the virtual machine to manage more complex operations and temporary data storage requirements, especially in scenarios where multiple registers are needed for computation and data flow control.

r6

General-purpose register 6.

Detailed Description

The r6 register serves as one of the general-purpose registers within the virtual machine. Similar to registers r1 through r5 , r6 is utilized for a variety of operations such as storing intermediate results, executing arithmetic and logical computations, and managing data during the execution of instructions. The availability of r6 adds further capacity for complex processing tasks, enabling more sophisticated data handling and operational flexibility within the virtual machine's execution flow.

r7

General-purpose register 7.

Detailed Description

The r7 register is one of the general-purpose registers available in the virtual machine. It is used for storing data, performing arithmetic and logical operations, and managing intermediate values during instruction execution. As with other general-purpose registers ( r1 through r6 ), r7 contributes to the virtual machine's ability to handle complex calculations and data manipulation, offering additional storage capacity and operational versatility. This register is crucial for executing a wide range of tasks within the virtual machine's instruction set.

r8

General-purpose register 8.

Detailed Description

The r8 register is a general-purpose register in the virtual machine, similar to registers r1 through r7 . It is used for storing data, performing arithmetic and logical operations, and holding intermediate values during the execution of instructions. As with the other general-purpose registers, r8 provides additional storage capacity, enabling the virtual machine to manage more complex tasks and calculations efficiently. The inclusion of r8 expands the machine's ability to handle larger sets of operations and data within its instruction set.

r9

General-purpose register 9.

Detailed Description

The r9 register is one of the general-purpose registers in the virtual machine, extending the storage and processing capabilities of the system. Like its counterparts r1 through r8 , r9 is utilized for a variety of tasks, including arithmetic operations, logical operations, and holding intermediate results during instruction execution. The availability of r9 allows the virtual machine to handle more complex operations and manage larger datasets more effectively, contributing to the overall flexibility and power of the virtual machine's instruction set.

rA

General-purpose register A.

Detailed Description

The rA register is a general-purpose register in the virtual machine, identified by the hexadecimal code 0xA . Similar to other general-purpose registers like r1 through r9 , rA is used for various operations such as arithmetic computations, logical operations, and temporarily holding values during instruction execution. The inclusion of rA expands the virtual machine's ability to perform complex tasks by providing additional storage and operational flexibility within the register set.

rB

General-purpose register B.

Detailed Description

The rB register is a general-purpose register in the virtual machine, identified by the hexadecimal code 0xB . It functions similarly to other general-purpose registers, such as r1 through rA , and is used to store intermediate values, perform arithmetic and logical operations, and hold data temporarily during instruction execution. The rB register adds to the virtual machine's versatility by providing additional storage capacity and operational flexibility, which is essential for handling more complex operations and enhancing the overall efficiency of the system.

rC

General-purpose register C.

Detailed Description

The rC register is a general-purpose register in the virtual machine, identified by the hexadecimal code 0xC . It serves as a versatile storage location for intermediate values during instruction execution. Like other general-purpose registers (r1 through rB), rC is utilized in various operations such as arithmetic, logic, and data manipulation. The availability of this register increases the capacity for handling more complex tasks and enhances the flexibility and performance of the virtual machine.

rD

General-purpose register D.

Detailed Description

The rD register is a general-purpose register in the virtual machine, identified by the hexadecimal code 0xD . It functions similarly to other general-purpose registers, such as r1 through rC , and is used for storing intermediate values during the execution of instructions. The rD register plays a crucial role in performing various operations, including arithmetic, logical, and data manipulation tasks, thereby enhancing the virtual machine's capability to execute complex computations efficiently.

rE

General-purpose register E.

Detailed Description

The rE register is one of the general-purpose registers in the virtual machine, identified by the hexadecimal code 0xE . Like other general-purpose registers, rE is used to store intermediate data and results during instruction execution. It can be employed for a wide range of operations, including arithmetic calculations, logical operations, and memory manipulation. The flexibility and versatility of the rE register make it an integral part of the virtual machine's computational capabilities, enabling the execution of complex programs and algorithms.

from_code

Register value obtained from code.

Detailed Description

The from_code register, identified by the hexadecimal code 0xF , is a special-purpose register in the virtual machine. Unlike general-purpose registers that hold intermediate data, from_code is used to store values directly obtained from the virtual machine's code stream. This register is essential for operations that require dynamic values to be extracted and used during instruction execution. It plays a critical role in the interpretation of instructions where operands are specified within the code itself, enabling the virtual machine to handle a wide variety of runtime scenarios.

size

Total number of registers.

Detailed Description

The size constant, represented by the hexadecimal value 0x10 , indicates the total number of registers available in the virtual machine. This includes all general-purpose registers ( r1 to rE ), the return_register , and the from_code register. The total count is essential for managing register operations and ensuring that the virtual machine can efficiently allocate and utilize these registers during execution. This value helps define the boundary for register indexing and is used to prevent out-of-bounds access within the register set.

Functions

const char * get_version ()

Retrieves the current version of the libantispy library.

Definition

const char * libantispy::get_version

Detailed Description

The get_version function returns a string that contains the version number of the antispy SDK library. This version information can be useful for logging, debugging, or ensuring compatibility with different components that depend on specific versions of the library.

Returns

A C-string ( const char* ) representing the version of the antispy SDK library.

bool debugger_present ()

Checks if a debugger is currently attached to the process.

Definition

bool libantispy::debugger_present

Detailed Description

The debugger_present function detects whether a debugger is attached to the current process. This can be used to implement anti-debugging techniques, where the presence of a debugger might trigger specific actions, such as terminating the process, altering code execution, or logging a security event.

Returns

true if a debugger is detected, false otherwise.

uintptr_t break_me (const uintptr_t me, uint64_t check)

Breaks code obfuscation by executing a corrupted function call.

Definition

uintptr_t libantispy::break_me

Detailed Description

This function obfuscates code execution by applying several layers of memory manipulation and function call corruption. It is designed to make reverse engineering more difficult by introducing unexpected behavior when certain conditions are met.

Template Parameters

  • N: The size or value used to influence the obfuscation process.

Parameters

  • me: The base address that is used in the obfuscation logic.

  • check: A value that is XORed with the base address to determine the execution path.

Returns

The result of the corrupted function call, or 1 if call corruption is disabled.

The function works by:

  • XORing the check value with the me address to determine the execution path.

  • If the result of the XOR operation is 0 , the function proceeds to obfuscate the function call by generating random data, calculating memory offsets, and making indirect function calls.

  • Memory is manipulated through the use of gap_0 and gap_1 arrays, which hold random data.

  • The function ultimately makes an obfuscated function call by interpreting the addr and thrash values as function pointers.

  • If the obfuscation condition is not met or if call corruption is disabled (via the ANTISPY_DISABLE_CALL_CORRUPTION macro), the function simply returns 1 .

Example usage:

#include <antispy/libantispy.h>

int main() {
   int base_address = 0;
   int check_value = 12;

   uintptr_t result = libantispy::break_me<42>(reinterpret_cast<uintptr_t>(std::addressof(base_address)), reinterpret_cast<uintptr_t>(std::addressof(check_value)));
}

This function should be used in environments where protection against debugging and reverse engineering is crucial. It introduces complexity and may have performance implications.

TRet corrupt_call (TRet(*func)(TArgs...), TArgs... args)

Executes a function call with obfuscation and potential corruption.

Definition

TRet libantispy::corrupt_call

Detailed Description

This function template is designed to obfuscate a function call, making it more difficult for reverse engineers to analyze the code. The function call is executed within an obfuscated block that may alter or corrupt the behavior depending on specific conditions.

Template Parameters

  • N: The size or value used to influence the obfuscation process.

  • TRet: The return type of the function being called.

  • TArgs: The types of the arguments being passed to the function.

Parameters

  • func: A pointer to the function that will be called.

  • args: The arguments to be passed to the function.

Returns

The result of the function call.

The corrupt_call function works by:

  • Wrapping the function call in a macro ANTISPY_BREAK_OBFUSCATED_BLOCK that introduces obfuscation.

  • The obfuscation may include manipulating memory, inserting random data, or calling other functions that obscure the intended behavior.

  • The result of the function call is stored in the variable res , which is then returned after the obfuscation block completes.

  • The obfuscation block ensures that the function call's behavior can be unpredictable, adding a layer of protection against debugging and reverse engineering.

Example usage:

#include <antispy/libantispy.h>

int secure_function(int a, int b) {
   return a + b;
}

int main() {
   int arg1 = 40;
   int arg2 = 2;

   // Obfuscating a function call
   int result = libantispy::corrupt_call<42>(secure_function, arg1, arg2);
}

This function should be used in environments where protecting the function call from analysis or tampering is crucial. The obfuscation introduces complexity and may have performance implications.

void corrupt_call (void(*func)(TArgs...), TArgs... args)

Executes a function call with obfuscation and potential corruption (void return type).

Definition

void libantispy::corrupt_call

Detailed Description

This function template is designed to obfuscate a function call that does not return a value. The function is executed within an obfuscated block that may alter or corrupt the behavior depending on specific conditions, making it more difficult for reverse engineers to analyze the code.

Template Parameters

  • N: The size or value used to influence the obfuscation process.

  • TArgs: The types of the arguments being passed to the function.

Parameters

  • func: A pointer to the function that will be called.

  • args: The arguments to be passed to the function.

The corrupt_call function works by:

  • Wrapping the function call in a macro ANTISPY_BREAK_OBFUSCATED_BLOCK that introduces obfuscation.

  • The obfuscation may include manipulating memory, inserting random data, or calling other functions that obscure the intended behavior.

  • Since the function does not return a value, the result is not captured, but the obfuscation block ensures that the function call's behavior can be unpredictable, adding a layer of protection against debugging and reverse engineering.

Example usage:

#include <antispy/libantispy.h>
#include <iostream>

void secure_function(int a, int b) {
   std::cout << a + b << '\n';
}

int main() {
   int arg1 = 40;
   int arg2 = 2;

   libantispy::corrupt_call<42>(secure_function, arg1, arg2);
}

This function should be used in environments where protecting the function call from analysis or tampering is crucial. The obfuscation introduces complexity and may have performance implications.

constexpr auto make_const_buffer (const char *str) noexcept

Factory function to create a const_buffer object with compile-time encryption.

Definition

constexpr auto libantispy::make_const_buffer

Detailed Description

The make_const_buffer function template provides a convenient way to create a const_buffer object by encrypting a given string at compile-time. This function simplifies the creation of const_buffer instances by encapsulating the encryption process and returning the encrypted buffer directly.

This function is particularly useful when working with sensitive string data that needs to be protected against unauthorized access or tampering. By encrypting the string at compile-time, it ensures that the original content is never exposed in plain text within the application code or binary.

Template Parameters

  • Key: The encryption key used to encrypt the buffer. This is a compile-time constant and ensures that the same key is used consistently throughout the encryption process.

  • Hash: A compile-time constant representing the hash of the buffer. This hash value is used for identification or integrity checks, allowing the encrypted data to be uniquely identified.

  • N: The size of the buffer (number of characters in the string). This parameter determines the length of the string to be encrypted.

Parameters

  • str: The source string to be encrypted. It is expected to be a null-terminated C-string with a length of N characters or fewer.

Returns

A const_buffer object containing the encrypted version of the provided string.

The encryption process is applied at compile-time, ensuring that the original string content is never exposed in plain text within the compiled binary.

The function uses the WIN_SUPRESS_4309 macro to suppress specific compiler warnings related to the narrowing of integer constants. This is necessary because the encryption process may involve operations that could trigger these warnings in certain compiler settings.

Example Usage:

#include <antispy/libantispy.h>

int main() {
   constexpr auto encrypted_buffer = libantispy::make_const_buffer<1234, 5678, 13>("SensitiveData");
}

This example creates a const_buffer object that securely stores the encrypted version of the string "SensitiveData". The encryption key is 1234 , and the buffer is identified by the hash 5678 .

The const_buffer object can be used to retrieve the encrypted string as a std::string or as raw data.

constexpr auto make_const_string (const char32_t(&str)[N]) noexcept

Creates a const_string object with compile-time encryption.

Definition

constexpr auto libantispy::make_const_string

Detailed Description

The make_const_string function template generates a const_string object that securely stores a string in an encrypted form at compile time. This function is primarily used to create constant strings that are protected against unauthorized access or tampering.

Detailed Description:

  • Template Parameters :

    • Key : The encryption key used to encrypt the string. This is a compile-time constant that determines the specific encryption applied to the string.

    • Hash : A compile-time constant representing the hash of the string. This hash can be used for quick comparisons or integrity checks.

    • N : The size of the string (number of characters). This is automatically deduced based on the input string.

  • Function Parameters :

    • str : A reference to the input string that will be encrypted and stored in the const_string object. The string is expected to be a UTF-32 encoded string (i.e., char32_t array) and its size is determined by the template parameter N .
  • Return Value :

    • Returns a const_string<Key, Hash, N> object that contains the encrypted version of the input string str .

    • The returned object is a fully constructed const_string instance, which securely stores the encrypted string data and allows controlled access through its member functions.

  • Encryption Process :

    • The function applies compile-time encryption to the input string using the provided Key and stores the encrypted data in a const_string object.

    • The encryption process ensures that the original string is not exposed in plain text within the compiled binary, adding a layer of security to the string data.

  • Hashing :

    • The Hash parameter is used to store a precomputed hash of the string. This hash can be used for quick comparisons or to verify the integrity of the string without needing to decrypt it first.
  • Use Case :

    • This function is intended for situations where constant strings need to be stored securely within an application. By encrypting the string at compile time, the function prevents the string from being easily extracted or modified by attackers.
  • Example Usage :

#include <antispy/libantispy.h>

int main() {
   constexpr auto encrypted_string = libantispy::make_const_string<0xABCDEF, 0x12345678>(U"SensitiveData");
}

In this example, the string "SensitiveData" is encrypted using the key 0xABCDEF and stored in the const_string object encrypted_string . The hash 0x12345678 uniquely identifies the content.

  • Compiler Directives :
    • WIN_SUPRESS_4309 : This macro suppresses specific compiler warnings related to integer constant narrowing, which may occur during the encryption process. It ensures that the function can be compiled without unnecessary warnings.

Template Parameters

  • Key: The encryption key used to encrypt the string. This is a compile-time constant.

  • Hash: The compile-time constant hash of the string. Used for quick comparisons and integrity checks.

  • N: The size of the string (number of characters).

Parameters

  • str: The input string to be encrypted. This string is expected to be a UTF-32 encoded array of char32_t .

Returns

A const_string<Key, Hash, N> object that securely stores the encrypted string.

encrypted_pointer< _Ty > make_encrypted (_Types &&... _Args)

Creates an encrypted_pointer object that securely manages a dynamically allocated instance of a type.

Definition

encrypted_pointer< _Ty > libantispy::make_encrypted

Detailed Description

This function template constructs an encrypted_pointer object by dynamically allocating an instance of the specified type _Ty , forwarding the provided arguments to the constructor of _Ty . The returned encrypted_pointer ensures that the pointer to the allocated object is encrypted, providing an additional layer of security.

Template Parameters

  • _Ty: The type of the object to be managed by the encrypted_pointer . This type should not be an array type.

  • _Types: The types of the arguments that are forwarded to the constructor of _Ty .

Parameters

  • _Args: The arguments to be forwarded to the constructor of _Ty .

Returns

An encrypted_pointer<_Ty> that securely manages the dynamically allocated object.

Details:

  • Memory Management : The function dynamically allocates an object of type _Ty using new . The pointer to this object is then managed by the encrypted_pointer , which ensures that the pointer is stored in an encrypted form.

  • Type Constraints : This function uses std::enable_if_t to disable its instantiation if _Ty is an array type. This constraint is enforced because array types require different memory management strategies that are not handled by this template.

  • Security : The returned encrypted_pointer encapsulates the raw pointer in a way that protects it from direct memory access, ensuring that the pointer is only accessible in decrypted form within controlled contexts.

Example:

#include <antispy/libantispy.h>

struct MyStruct {
    int a;
    double b;
    MyStruct(int x, double y) : a(x), b(y) {}
};

int main() {
   auto enc_ptr = libantispy::make_encrypted<MyStruct>(10, 20.5);
   // enc_ptr now securely manages a pointer to a dynamically allocated MyStruct instance
}

In the example above, make_encrypted is used to create an encrypted_pointer that manages a dynamically allocated instance of MyStruct . The arguments 10 and 20.5 are forwarded to the constructor of MyStruct .

void make_encrypted (_Types &&...)=delete

Disabled overload of make_encrypted for array types.

Definition

void libantispy::make_encrypted

Detailed Description

This function template is explicitly deleted to prevent the creation of an encrypted_pointer for array types. The deletion ensures that attempts to use make_encrypted with an array type _Ty will result in a compilation error.

Template Parameters

  • _Ty: The type of the object, which in this case is an array type. The template is disabled when _Ty represents an array type.

  • _Types: The types of the arguments that would have been forwarded to the constructor of _Ty if this overload were not deleted.

Parameters

  • _Args: The arguments that would have been forwarded to the constructor of _Ty if this overload were not deleted.

The presence of this deleted overload enforces the constraint that make_encrypted can only be used with non-array types. Arrays require different handling, such as size management and potentially custom deallocation strategies, which are not addressed by this template.

  • Reason for Deletion : This function template is deleted to prevent incorrect usage of make_encrypted with array types, which could lead to undefined behavior or resource management issues. The standard new operator does not correctly handle arrays in this context, so this safeguard is necessary.

  • Template Specialization : The template is enabled (and subsequently deleted) when the extent of _Ty is not zero, which indicates that _Ty is an array type.

Example:

#include <antispy/libantispy.h>

int main() {
   // This will cause a compilation error because _Ty is an array type:
   // auto enc_ptr = libantispy::make_encrypted<int[10]>(arguments);
}