Skip to content

Assembly Attribute

Aman Priyadarshi edited this page Dec 23, 2016 · 7 revisions

An Attribute which declares a method to emit literal assembly code.

Attribute

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class AssemblyAttribute : Attribute>
{
    public readonly bool CalliHeader;
    public AssemblyAttribute(bool requiredCallingHeader = false) { ... }
}
  • CalliHeader
  • Tells Compiler to emit calli assembly stubs.
  • Follows __stdcall calling convention.
  • Default Value: false

Usage

  • Declaration
using Atomixilc.Machine;
using Atomixilc.Attributes;
using Atomixilc.Machine.x86;
...
[Assembly]
internal static int Random()
{
   // Do Something
}
  • To Enable __stdcall calli stubs use [Assembly(true)].
  • Method Body
  • Assembly Methods are directly invoked by the Compiler.
  • Directly invocation causes no direct link to non-Assembly stuffs.
  • Like It is impossible to refer parameters/fields/functions directly.
  • Assembly Instruction can be added by creating an instance of required instruction.
  • Example - (CalliHeader = false)
  • C# code void Test()
 [Assembly]
 internal static int Test()
 {
     new Cli(); // clear interrupts
     // push ESP register onto the stack
     new Push { DestinationReg = Register.ESP };
     new Sti(); // store interrupts
 }
  • Generated code
 cli
 push dword ESP
 sti
  • Example - (CalliHeader = true)
  • C# code
 [Assembly(true)]
 internal static int Test()
 {
     new Cli(); // clear interrupts
     // push ESP register onto the stack
     new Push { DestinationReg = Register.ESP };
     new Sti(); // store interrupts
 }
  • Generated code
 push dword EBP
 mov dword EBP, ESP
 cli
 push dword ESP
 sti
 xor dword ECX, ECX
 leave
 ret 0x0

Behavior

  • CalliHeader = false
  • Return value should be saved in EAX register.
  • Make sure you clear ECX register before exiting. (Read: Exceptions)
  • You can use NoException Attribute if does not want to clear ECX register.
  • Last Argument: [ESP + 0x4] (ESP: Initial Stack Position)
  • Second Last Argument: [ESP + 0x4 + sizeof(Last Argument)] and so on
  • CalliHeader = true
  • Return value should be pushed onto the stack.
  • Last Argument: [EBP + 0x8]
  • Second Last Argument: [EBP + 0x8 + sizeof(Last Argument)] and so on

Instructions

  • DestinationSourceSize
  • Mnemonic SIZE DES, SRC
  • SIZE (bytes) = {BYTE (8),WORD (16),DWORD (32 default), QWORD (64)}
  • DES/SRC = {Register Reference, Memory Reference} + {Displacement, Indirect}
  • DestinationSource
  • Mnemonic DES, SRC
  • DestinationOnly
  • Mnemonic DES
  • OnlySize
  • Mnemonic SIZE

Example

  • Return Sum of Two Numbers
  [Assembly(true)]
  internal static int Sum(int A, int B)
  {
      // mov eax, [ebp+0x8] ; mov eax, B
      new Mov
      {
          DestinationReg = Register.EAX,
          SourceReg = Register.EBP,
          SourceDisplacement = 0x8,
          SourceIndirect = true
      };
      // mov ebx, [ebp+0xc] ; mov ebx, A
      new Mov
      {
          DestinationReg = Register.EBX,
          SourceReg = Register.EBP,
          SourceDisplacement = 0xC,
          SourceIndirect = true
      };
      // add eax, ebx
      new Add { DestinationReg = Register.EAX, SourceReg = Register.EBX };
      new Push { DestinationReg = Register.EAX };
  }
Clone this wiki locally