The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

Name

Nasm::X86 - Generate Nasm assembler code

Synopsis

Write and execute x64 instructions from perl, for example:

Use avx512 instructions to reorder data using 512 bit zmm registers:

  Start;
  my $q = Rs my $s = join '', ('a'..'p')x4;;
  Mov rax, Ds('0'x128);

  Vmovdqu32 zmm0, "[$q]";
  Vprolq    zmm1, zmm0, 32;
  Vmovdqu32 "[rax]", zmm1;

  Mov rdi, length $s;
  PrintOutMemory;
  Exit;

  ok $s         =~ m(abcdefghijklmnopabcdefghijklmnopabcdefghijklmnopabcdefghijklmnop)s;
  ok assemble() =~ m(efghabcdmnopijklefghabcdmnopijklefghabcdmnopijklefghabcdmnopijkl)s;

Start a child process and wait for it, printing out the process identifiers of each process involved:

  Start;                                                                        # Start the program
  Fork;                                                                         # Fork

  Test rax,rax;
  If                                                                            # Parent
   {Mov rbx, rax;
    WaitPid;
    PrintOutRegisterInHex rax;
    PrintOutRegisterInHex rbx;
    GetPid;                                                                     # Pid of parent as seen in parent
    Mov rcx,rax;
    PrintOutRegisterInHex rcx;
   }
  sub                                                                           # Child
   {Mov r8,rax;
    PrintOutRegisterInHex r8;
    GetPid;                                                                     # Child pid as seen in child
    Mov r9,rax;
    PrintOutRegisterInHex r9;
    GetPPid;                                                                    # Parent pid as seen in child
    Mov r10,rax;
    PrintOutRegisterInHex r10;
   };

  Exit;                                                                         # Return to operating system

  my $r = assemble();

  #    r8: 0000 0000 0000 0000   #1 Return from fork as seen by child
  #    r9: 0000 0000 0003 0C63   #2 Pid of child
  #   r10: 0000 0000 0003 0C60   #3 Pid of parent from child
  #   rax: 0000 0000 0003 0C63   #4 Return from fork as seen by parent
  #   rbx: 0000 0000 0003 0C63   #5 Wait for child pid result
  #   rcx: 0000 0000 0003 0C60   #6 Pid of parent

Read this file:

  Start;                                                                        # Start the program
  Mov rax, Rs($0);                                                              # File to read
  ReadFile;                                                                     # Read file
  PrintOutMemory;                                                               # Print memory
  Exit;                                                                         # Return to operating system

  my $r = assemble();                                                           # Assemble and execute
  ok index($r, readFile($0)) > -1;                                              # Output contains this file

Installation

You will need the Intel Software Development Emulator and the Networkwide Assembler installed on your test system. For full details of how to do this see: https://github.com/philiprbrenan/NasmX86/blob/main/.github/workflows/main.yml

Description

Generate Nasm assembler code

Version "202104013".

The following sections describe the methods in each functional area of this module. For an alphabetic listing of all methods by name see Index.

Generate Network Assembler Code

Generate assembler code that can be assembled with Nasm

SetLabel($l)

Set a label in the code section

     Parameter  Description
  1  $l         Label

Start()

Initialize the assembler

Example:

    Start;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutString "Hello World";
    Exit;
    ok assemble =~ m(Hello World);

Ds(@d)

Layout bytes in memory and return their label

     Parameter  Description
  1  @d         Data to be laid out

Example:

    Start;
    my $q = Rs('a'..'z');

    Mov rax, Ds('0'x64);                                                          # Output area  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Vmovdqu32(xmm0, "[$q]");                                                      # Load
    Vprolq   (xmm0,   xmm0, 32);                                                  # Rotate double words in quad words
    Vmovdqu32("[rax]", xmm0);                                                      # Save
    Mov rdi, 16;
    PrintOutMemory;
    Exit;
    ok assemble() =~ m(efghabcdmnopijkl)s;

Rs(@d)

Layout bytes in read only memory and return their label

     Parameter  Description
  1  @d         Data to be laid out

Example:

    Start;
    Comment "Print a string from memory";
    my $s = "Hello World";

    Mov rax, Rs($s);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov rdi, length $s;
    PrintOutMemory;
    Exit;
    ok assemble =~ m(Hello World);

Dbwdq($s, @d)

Layout data

     Parameter  Description
  1  $s         Element size
  2  @d         Data to be laid out

Db(@bytes)

Layout bytes in the data segment and return their label

     Parameter  Description
  1  @bytes     Bytes to layout

Dw(@words)

Layout words in the data segment and return their label

     Parameter  Description
  1  @words     Words to layout

Dd(@dwords)

Layout double words in the data segment and return their label

     Parameter  Description
  1  @dwords    Double words to layout

Dq(@qwords)

Layout quad words in the data segment and return their label

     Parameter  Description
  1  @qwords    Quad words to layout

Rbwdq($s, @d)

Layout data

     Parameter  Description
  1  $s         Element size
  2  @d         Data to be laid out

Rb(@bytes)

Layout bytes in the data segment and return their label

     Parameter  Description
  1  @bytes     Bytes to layout

Rw(@words)

Layout words in the data segment and return their label

     Parameter  Description
  1  @words     Words to layout

Rd(@dwords)

Layout double words in the data segment and return their label

     Parameter  Description
  1  @dwords    Double words to layout

Rq(@qwords)

Layout quad words in the data segment and return their label

     Parameter  Description
  1  @qwords    Quad words to layout

Comment(@comment)

Insert a comment into the assembly code

     Parameter  Description
  1  @comment   Text of comment

Example:

    Start;

    Comment "Print a string from memory";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $s = "Hello World";
    Mov rax, Rs($s);
    Mov rdi, length $s;
    PrintOutMemory;
    Exit;
    ok assemble =~ m(Hello World);

Exit($c)

Exit with the specified return code or zero if no return code supplied

     Parameter  Description
  1  $c         Return code

Example:

    Start;
    PrintOutString "Hello World";

    Exit;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ok assemble =~ m(Hello World);

SaveFirstFour()

Save the first 4 parameter registers

RestoreFirstFour()

Restore the first 4 parameter registers

RestoreFirstFourExceptRax()

Restore the first 4 parameter registers except rax so it can return its value

SaveFirstSeven()

Save the first 7 parameter registers

RestoreFirstSeven()

Restore the first 7 parameter registers

RestoreFirstSevenExceptRax()

Restore the first 7 parameter registers except rax which is being used to return the result

RestoreFirstSevenExceptRaxAndRdi()

Restore the first 7 parameter registers except rax and rdi which are being used to return the results

If($then, $else)

If

     Parameter  Description
  1  $then      Then - required
  2  $else      Else - optional

Example:

    Start;
    Mov rax, 0;
    Test rax,rax;

    If  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {PrintOutRegisterInHex rax;
     } sub
     {PrintOutRegisterInHex rbx;
     };
    Mov rax, 1;
    Test rax,rax;

    If  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {PrintOutRegisterInHex rcx;
     } sub
     {PrintOutRegisterInHex rdx;
     };
    Exit;
    ok assemble() =~ m(rbx.*rcx)s;

For($body, $register, $limit, $increment)

For

     Parameter   Description
  1  $body       Body
  2  $register   Register
  3  $limit      Limit on loop
  4  $increment  Increment

Example:

    Start;                                                                        # Start the program

    For  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {PrintOutRegisterInHex rax
     } rax, 16, 1;
    Exit;                                                                         # Return to operating system
    my $r = assemble;
    ok $r =~ m(( 0000){3} 0000)i;
    ok $r =~ m(( 0000){3} 000F)i;

S($body, %options)

Create a sub with optional parameters name=> the name of the subroutine so it can be reused rather than regenerated, comment=> a comment describing the sub

     Parameter  Description
  1  $body      Body
  2  %options   Options.

registerSize($r)

Return the size of a register

     Parameter  Description
  1  $r         Register

PushR(@r)

Push registers onto the stack

     Parameter  Description
  1  @r         Register

PopR(@r)

Pop registers from the stack

     Parameter  Description
  1  @r         Register

Example:

    Start;
    my $q = Rs my $s = join '', ('a'..'p')x4;;
    Mov rax, Ds('0'x128);

    Vmovdqu32 zmm0, "[$q]";
    Vprolq    zmm1, zmm0, 32;
    Vmovdqu32 "[rax]", zmm1;

    Mov rdi, length $s;
    PrintOutMemory;
    Exit;

    ok $s         =~ m(abcdefghijklmnopabcdefghijklmnopabcdefghijklmnopabcdefghijklmnop)s;
    ok assemble() =~ m(efghabcdmnopijklefghabcdmnopijklefghabcdmnopijklefghabcdmnopijkl)s;

PeekR($r)

Peek at register on stack

     Parameter  Description
  1  $r         Register

PrintOutNl()

Write a new line

Example:

    Start;
    Comment "Print a string from memory";
    my $s = "Hello World";
    Mov rax, Rs($s);
    Mov rdi, length $s;
    PrintOutMemory;
    Exit;
    ok assemble =~ m(Hello World);

PrintOutString($string)

Write a constant string to sysout.

     Parameter  Description
  1  $string    String

Example:

    Start;

    PrintOutString "Hello World";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Exit;
    ok assemble =~ m(Hello World);

PrintOutMemory()

Print the memory addressed by rax for a length of rdi

PrintOutRaxInHex()

Write the content of register rax to stderr in hexadecimal in big endian notation

Example:

    Start;
    my $q = Rs('abababab');
    Mov(rax, "[$q]");
    PrintOutString "rax: ";

    PrintOutRaxInHex;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutNl;
    Xor rax, rax;
    PrintOutString "rax: ";

    PrintOutRaxInHex;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutNl;
    Exit;
    ok assemble() =~ m(rax: 6261 6261 6261 6261.*rax: 0000 0000 0000 0000)s;

ClearRegisters(@registers)

Clear registers by setting them to zero

     Parameter   Description
  1  @registers  Registers

ReverseBytesInRax()

Reverse the bytes in rax

PrintOutRaxInReverseInHex()

Write the content of register rax to stderr in hexadecimal in little endian notation

Example:

    Start;
    Mov rax, 0x88776655;
    Shl rax, 32;
    Or  rax, 0x44332211;
    PrintOutRaxInHex;

    PrintOutRaxInReverseInHex;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Exit;
    ok assemble =~ m(8877 6655 4433 2211 1122 3344 5566 7788)s;

PrintOutRegisterInHex($r)

Print any register as a hex string

     Parameter  Description
  1  $r         Name of the register to print

Example:

    Start;
    my $q = Rs(('a'..'p')x4);
    Mov r8,"[$q]";

    PrintOutRegisterInHex r8;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Exit;
    ok assemble() =~ m(r8: 6867 6665 6463 6261)s;

PrintOutRipInHex()

Print the instruction pointer in hex

PrintOutRflagsInHex()

Print the flags register in hex

PrintOutRegistersInHex()

Print the general purpose registers in hex

Example:

    Start;
    my $q = Rs('abababab');
    Mov(rax, 1);
    Mov(rbx, 2);
    Mov(rcx, 3);
    Mov(rdx, 4);
    Mov(r8,  5);
    Lea r9,  "[rax+rbx]";

    PrintOutRegistersInHex;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Exit;
    my $r = assemble();
    ok $r =~ m( r8: 0000 0000 0000 0005.* r9: 0000 0000 0000 0003.*rax: 0000 0000 0000 0001)s;
    ok $r =~ m(rbx: 0000 0000 0000 0002.*rcx: 0000 0000 0000 0003.*rdx: 0000 0000 0000 0004)s;

PrintOutMemoryInHex()

Dump memeory from teh address in rax for the length in rdi

allocateMemory()

Allocate the amount of memory specified in rax via mmap and return the address of the allocated memeory in rax

Example:

    Start;
    my $N = 2048;
    my $q = Rs('a'..'p');
    Mov rax, $N;

    allocateMemory;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;

    Vmovdqu8 xmm0, "[$q]";
    Vmovdqu8 "[rax]", xmm0;
    Mov rdi,16;
    PrintOutMemory;
    PrintOutNl;

    Mov rdi, $N;
    freeMemory;
    PrintOutRegisterInHex rax;
    Exit;
    ok assemble() =~ m(abcdefghijklmnop)s;

    Start;
    my $N = 4096;
    my $S = registerSize rax;
    Mov rax, $N;

    allocateMemory;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
    Mov rdi, $N;
    MemoryClear;
    PrintOutRegisterInHex rax;
    PrintOutMemoryInHex;
    Exit;

    my $r = assemble;
    if ($r =~ m((0000.*0000))s)
     {is_deeply length($1), 10269;
     }

freeMemory()

Free memory via mmap. The address of the memory is in rax, the length to free is in rdi

Example:

    Start;
    my $N = 2048;
    my $q = Rs('a'..'p');
    Mov rax, $N;
    allocateMemory;
    PrintOutRegisterInHex rax;

    Vmovdqu8 xmm0, "[$q]";
    Vmovdqu8 "[rax]", xmm0;
    Mov rdi,16;
    PrintOutMemory;
    PrintOutNl;

    Mov rdi, $N;

    freeMemory;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
    Exit;
    ok assemble() =~ m(abcdefghijklmnop)s;

    Start;
    my $N = 4096;
    my $S = registerSize rax;
    Mov rax, $N;
    allocateMemory;
    PrintOutRegisterInHex rax;
    Mov rdi, $N;
    MemoryClear;
    PrintOutRegisterInHex rax;
    PrintOutMemoryInHex;
    Exit;

    my $r = assemble;
    if ($r =~ m((0000.*0000))s)
     {is_deeply length($1), 10269;
     }

Fork()

Fork

Example:

    Start;                                                                        # Start the program

    Fork;                                                                         # Fork  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲


    Test rax,rax;
    If                                                                            # Parent
     {Mov rbx, rax;
      WaitPid;
      PrintOutRegisterInHex rax;
      PrintOutRegisterInHex rbx;
      GetPid;                                                                     # Pid of parent as seen in parent
      Mov rcx,rax;
      PrintOutRegisterInHex rcx;
     }
    sub                                                                           # Child
     {Mov r8,rax;
      PrintOutRegisterInHex r8;
      GetPid;                                                                     # Child pid as seen in child
      Mov r9,rax;
      PrintOutRegisterInHex r9;
      GetPPid;                                                                    # Parent pid as seen in child
      Mov r10,rax;
      PrintOutRegisterInHex r10;
     };

    Exit;                                                                         # Return to operating system

    my $r = assemble();

  #    r8: 0000 0000 0000 0000   #1 Return from fork as seen by child
  #    r9: 0000 0000 0003 0C63   #2 Pid of child
  #   r10: 0000 0000 0003 0C60   #3 Pid of parent from child
  #   rax: 0000 0000 0003 0C63   #4 Return from fork as seen by parent
  #   rbx: 0000 0000 0003 0C63   #5 Wait for child pid result
  #   rcx: 0000 0000 0003 0C60   #6 Pid of parent

    if ($r =~ m(r8:( 0000){4}.*r9:(.*)\s{5,}r10:(.*)\s{5,}rax:(.*)\s{5,}rbx:(.*)\s{5,}rcx:(.*)\s{2,})s)
     {ok $2 eq $4;
      ok $2 eq $5;
      ok $3 eq $6;
      ok $2 gt $6;
     }

    Start;                                                                        # Start the program
    GetUid;                                                                       # Userid
    PrintOutRegisterInHex rax;
    Exit;                                                                         # Return to operating system
    my $r = assemble();
    ok $r =~ m(rax:( 0000){3});

GetPid()

Get process identifier

Example:

    Start;                                                                        # Start the program
    Fork;                                                                         # Fork

    Test rax,rax;
    If                                                                            # Parent
     {Mov rbx, rax;
      WaitPid;
      PrintOutRegisterInHex rax;
      PrintOutRegisterInHex rbx;

      GetPid;                                                                     # Pid of parent as seen in parent  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Mov rcx,rax;
      PrintOutRegisterInHex rcx;
     }
    sub                                                                           # Child
     {Mov r8,rax;
      PrintOutRegisterInHex r8;

      GetPid;                                                                     # Child pid as seen in child  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Mov r9,rax;
      PrintOutRegisterInHex r9;
      GetPPid;                                                                    # Parent pid as seen in child
      Mov r10,rax;
      PrintOutRegisterInHex r10;
     };

    Exit;                                                                         # Return to operating system

    my $r = assemble();

  #    r8: 0000 0000 0000 0000   #1 Return from fork as seen by child
  #    r9: 0000 0000 0003 0C63   #2 Pid of child
  #   r10: 0000 0000 0003 0C60   #3 Pid of parent from child
  #   rax: 0000 0000 0003 0C63   #4 Return from fork as seen by parent
  #   rbx: 0000 0000 0003 0C63   #5 Wait for child pid result
  #   rcx: 0000 0000 0003 0C60   #6 Pid of parent

    if ($r =~ m(r8:( 0000){4}.*r9:(.*)\s{5,}r10:(.*)\s{5,}rax:(.*)\s{5,}rbx:(.*)\s{5,}rcx:(.*)\s{2,})s)
     {ok $2 eq $4;
      ok $2 eq $5;
      ok $3 eq $6;
      ok $2 gt $6;
     }

    Start;                                                                        # Start the program
    GetUid;                                                                       # Userid
    PrintOutRegisterInHex rax;
    Exit;                                                                         # Return to operating system
    my $r = assemble();
    ok $r =~ m(rax:( 0000){3});

GetPPid()

Get parent process identifier

Example:

    Start;                                                                        # Start the program
    Fork;                                                                         # Fork

    Test rax,rax;
    If                                                                            # Parent
     {Mov rbx, rax;
      WaitPid;
      PrintOutRegisterInHex rax;
      PrintOutRegisterInHex rbx;
      GetPid;                                                                     # Pid of parent as seen in parent
      Mov rcx,rax;
      PrintOutRegisterInHex rcx;
     }
    sub                                                                           # Child
     {Mov r8,rax;
      PrintOutRegisterInHex r8;
      GetPid;                                                                     # Child pid as seen in child
      Mov r9,rax;
      PrintOutRegisterInHex r9;

      GetPPid;                                                                    # Parent pid as seen in child  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Mov r10,rax;
      PrintOutRegisterInHex r10;
     };

    Exit;                                                                         # Return to operating system

    my $r = assemble();

  #    r8: 0000 0000 0000 0000   #1 Return from fork as seen by child
  #    r9: 0000 0000 0003 0C63   #2 Pid of child
  #   r10: 0000 0000 0003 0C60   #3 Pid of parent from child
  #   rax: 0000 0000 0003 0C63   #4 Return from fork as seen by parent
  #   rbx: 0000 0000 0003 0C63   #5 Wait for child pid result
  #   rcx: 0000 0000 0003 0C60   #6 Pid of parent

    if ($r =~ m(r8:( 0000){4}.*r9:(.*)\s{5,}r10:(.*)\s{5,}rax:(.*)\s{5,}rbx:(.*)\s{5,}rcx:(.*)\s{2,})s)
     {ok $2 eq $4;
      ok $2 eq $5;
      ok $3 eq $6;
      ok $2 gt $6;
     }

    Start;                                                                        # Start the program
    GetUid;                                                                       # Userid
    PrintOutRegisterInHex rax;
    Exit;                                                                         # Return to operating system
    my $r = assemble();
    ok $r =~ m(rax:( 0000){3});

GetUid()

Get userid of current process

WaitPid()

Wait for the pid in rax to complete

Example:

    Start;                                                                        # Start the program
    Fork;                                                                         # Fork

    Test rax,rax;
    If                                                                            # Parent
     {Mov rbx, rax;

      WaitPid;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      PrintOutRegisterInHex rax;
      PrintOutRegisterInHex rbx;
      GetPid;                                                                     # Pid of parent as seen in parent
      Mov rcx,rax;
      PrintOutRegisterInHex rcx;
     }
    sub                                                                           # Child
     {Mov r8,rax;
      PrintOutRegisterInHex r8;
      GetPid;                                                                     # Child pid as seen in child
      Mov r9,rax;
      PrintOutRegisterInHex r9;
      GetPPid;                                                                    # Parent pid as seen in child
      Mov r10,rax;
      PrintOutRegisterInHex r10;
     };

    Exit;                                                                         # Return to operating system

    my $r = assemble();

  #    r8: 0000 0000 0000 0000   #1 Return from fork as seen by child
  #    r9: 0000 0000 0003 0C63   #2 Pid of child
  #   r10: 0000 0000 0003 0C60   #3 Pid of parent from child
  #   rax: 0000 0000 0003 0C63   #4 Return from fork as seen by parent
  #   rbx: 0000 0000 0003 0C63   #5 Wait for child pid result
  #   rcx: 0000 0000 0003 0C60   #6 Pid of parent

    if ($r =~ m(r8:( 0000){4}.*r9:(.*)\s{5,}r10:(.*)\s{5,}rax:(.*)\s{5,}rbx:(.*)\s{5,}rcx:(.*)\s{2,})s)
     {ok $2 eq $4;
      ok $2 eq $5;
      ok $3 eq $6;
      ok $2 gt $6;
     }

    Start;                                                                        # Start the program
    GetUid;                                                                       # Userid
    PrintOutRegisterInHex rax;
    Exit;                                                                         # Return to operating system
    my $r = assemble();
    ok $r =~ m(rax:( 0000){3});

readTimeStampCounter()

Read the time stamp counter

Example:

    Start;
    for(1..10)

     {readTimeStampCounter;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      PrintOutRegisterInHex rax;
     }
    Exit;
    my @s = split /
/, assemble();
    my @S = sort @s;
    is_deeply \@s, \@S;

OpenRead()

Open a file, whose name is addressed by rax, for read and return the file descriptor in rax

Example:

    Start;                                                                        # Start the program
    Mov rax, Rs($0);                                                              # File to stat

    OpenRead;                                                                     # Open file  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
    Close(rax);                                                                   # Close file
    PrintOutRegisterInHex rax;
    Exit;                                                                         # Return to operating system
    my $r = assemble();
    ok $r =~ m(( 0000){3} 0003)i;                                                 # Expected file number
    ok $r =~ m(( 0000){4})i;                                                      # Expected file number

Close($fdes)

Close a file descriptor

     Parameter  Description
  1  $fdes      File descriptor

Example:

    Start;                                                                        # Start the program
    Mov rax, Rs($0);                                                              # File to stat
    OpenRead;                                                                     # Open file
    PrintOutRegisterInHex rax;

    Close(rax);                                                                   # Close file  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
    Exit;                                                                         # Return to operating system
    my $r = assemble();
    ok $r =~ m(( 0000){3} 0003)i;                                                 # Expected file number
    ok $r =~ m(( 0000){4})i;                                                      # Expected file number

localData()

Map local data

LocalData::start($local)

Start a local data area on the stack

     Parameter  Description
  1  $local     Local data descriptor

LocalData::free($local)

Free a local data area on the stack

     Parameter  Description
  1  $local     Local data descriptor

LocalData::variable($local, $length, $comment)

Add a local variable

     Parameter  Description
  1  $local     Local data descriptor
  2  $length    Length of data
  3  $comment   Optional comment

LocalVariable::stack($variable)

Address a local variable on the stack

     Parameter  Description
  1  $variable  Variable

LocalData::allocate8($local, @comments)

Add some 8 byte local variables and return an array of variable definitions

     Parameter  Description
  1  $local     Local data descriptor
  2  @comments  Optional comment

AllocateAll8($N)

Create a local data descriptor consisting of the specified number of 8 byte local variables and return an array: (local data descriptor, variable definitions...)

     Parameter  Description
  1  $N         Number of variables required

MemoryClear()

Clear memory - the address of the memory is in rax, the length in rdi

StatSize()

Stat a file whise name is addressed by rax to get its size in rax

Example:

    Start;                                                                        # Start the program
    Mov rax, Rs($0);                                                              # File to stat

    StatSize;                                                                     # Stat the file  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
    Exit;                                                                         # Return to operating system
    my $r = assemble() =~ s( ) ()gsr;
    if ($r =~ m(rax:([0-9a-f]{16}))is)                                            # Compare file size obtained with that from fileSize()
     {is_deeply $1, sprintf("%016X", fileSize($0));
     }

ReadFile()

Read a file whose name is addressed by rax into memory. The address of the mapped memory and its length are returned in registers rax,rdi

Example:

    Start;                                                                        # Start the program
    Mov rax, Rs($0);                                                              # File to read

    ReadFile;                                                                     # Read file  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutMemory;                                                               # Print memory
    Exit;                                                                         # Return to operating system
    my $r = assemble();                                                           # Assemble and execute
    ok index($r, readFile($0)) > -1;                                              # Output contains this file

assemble(%options)

Assemble the generated code

     Parameter  Description
  1  %options   Options

Example:

    Start;
    PrintOutString "Hello World";
    Exit;

    ok assemble =~ m(Hello World);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

Private Methods

label()

Create a unique label

Index

1 AllocateAll8 - Create a local data descriptor consisting of the specified number of 8 byte local variables and return an array: (local data descriptor, variable definitions.

2 allocateMemory - Allocate the amount of memory specified in rax via mmap and return the address of the allocated memeory in rax

3 assemble - Assemble the generated code

4 ClearRegisters - Clear registers by setting them to zero

5 Close - Close a file descriptor

6 Comment - Insert a comment into the assembly code

7 Db - Layout bytes in the data segment and return their label

8 Dbwdq - Layout data

9 Dd - Layout double words in the data segment and return their label

10 Dq - Layout quad words in the data segment and return their label

11 Ds - Layout bytes in memory and return their label

12 Dw - Layout words in the data segment and return their label

13 Exit - Exit with the specified return code or zero if no return code supplied

14 For - For

15 Fork - Fork

16 freeMemory - Free memory via mmap.

17 GetPid - Get process identifier

18 GetPPid - Get parent process identifier

19 GetUid - Get userid of current process

20 If - If

21 label - Create a unique label

22 localData - Map local data

23 LocalData::allocate8 - Add some 8 byte local variables and return an array of variable definitions

24 LocalData::free - Free a local data area on the stack

25 LocalData::start - Start a local data area on the stack

26 LocalData::variable - Add a local variable

27 LocalVariable::stack - Address a local variable on the stack

28 MemoryClear - Clear memory - the address of the memory is in rax, the length in rdi

29 OpenRead - Open a file, whose name is addressed by rax, for read and return the file descriptor in rax

30 PeekR - Peek at register on stack

31 PopR - Pop registers from the stack

32 PrintOutMemory - Print the memory addressed by rax for a length of rdi

33 PrintOutMemoryInHex - Dump memeory from teh address in rax for the length in rdi

34 PrintOutNl - Write a new line

35 PrintOutRaxInHex - Write the content of register rax to stderr in hexadecimal in big endian notation

36 PrintOutRaxInReverseInHex - Write the content of register rax to stderr in hexadecimal in little endian notation

37 PrintOutRegisterInHex - Print any register as a hex string

38 PrintOutRegistersInHex - Print the general purpose registers in hex

39 PrintOutRflagsInHex - Print the flags register in hex

40 PrintOutRipInHex - Print the instruction pointer in hex

41 PrintOutString - Write a constant string to sysout.

42 PushR - Push registers onto the stack

43 Rb - Layout bytes in the data segment and return their label

44 Rbwdq - Layout data

45 Rd - Layout double words in the data segment and return their label

46 ReadFile - Read a file whose name is addressed by rax into memory.

47 readTimeStampCounter - Read the time stamp counter

48 registerSize - Return the size of a register

49 RestoreFirstFour - Restore the first 4 parameter registers

50 RestoreFirstFourExceptRax - Restore the first 4 parameter registers except rax so it can return its value

51 RestoreFirstSeven - Restore the first 7 parameter registers

52 RestoreFirstSevenExceptRax - Restore the first 7 parameter registers except rax which is being used to return the result

53 RestoreFirstSevenExceptRaxAndRdi - Restore the first 7 parameter registers except rax and rdi which are being used to return the results

54 ReverseBytesInRax - Reverse the bytes in rax

55 Rq - Layout quad words in the data segment and return their label

56 Rs - Layout bytes in read only memory and return their label

57 Rw - Layout words in the data segment and return their label

58 S - Create a sub with optional parameters name=> the name of the subroutine so it can be reused rather than regenerated, comment=> a comment describing the sub

59 SaveFirstFour - Save the first 4 parameter registers

60 SaveFirstSeven - Save the first 7 parameter registers

61 SetLabel - Set a label in the code section

62 Start - Initialize the assembler

63 StatSize - Stat a file whise name is addressed by rax to get its size in rax

64 WaitPid - Wait for the pid in rax to complete

Installation

This module is written in 100% Pure Perl and, thus, it is easy to read, comprehend, use, modify and install via cpan:

  sudo cpan install Nasm::X86

Author

philiprbrenan@gmail.com

http://www.appaapps.com

Copyright

Copyright (c) 2016-2021 Philip R Brenan.

This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.