Name

Nasm::X86 - Generate Nasm assembler code

Synopsis

Write and run some assembler code to start a process and wait for it:

 Start;
 Fork;
 Test rax,rax;
 If                                                                            # Parent
  {Mov rbx, rax;
   WaitPid;
   Mov rcx, rax;
   PrintOutRegisterInHex rcx;
   PrintOutRegisterInHex rbx;
  }
 sub                                                                           # Child
  {PrintOutRegisterInHex rax;
  };
 Exit;

 assemble();

#   rax: 0000 0000 0000 0000  Pid as seen by child
#   rcx: 0000 0000 0002 EB35  Pid that terminated as seen by parent
#   rbx: 0000 0000 0002 EB35  Pid of child as seen by parent

Description

Generate Nasm assembler code

Version "20210401".

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

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');

  my $d = Ds('0'x64);                                                           # Output area  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  Vmovdqu32(xmm0, "[$q]");                                                      # Load
  Vprolq   (xmm0,   xmm0, 32);                                                  # Rotate double words in quad words
  Vmovdqu32("[$d]", xmm0);                                                      # Save
  PrintOutString($d, 16);
  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";

  my $m = Rs($s);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  Mov rsi, $m;
  PrintOutString rsi, length($s);
  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";
  my $m = Rs($s);
  Mov rsi, $m;
  PrintOutString rsi, length($s);
  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

Lea($target, $source)

Load effective address

   Parameter  Description
1  $target    Target
2  $source    Source

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;
  ok assemble() =~ m(r8: 0000 0000 0000 0005.*r9: 0000 0000 0000 0003.*rax: 0000 0000 0000 0001)s;

Mov($target, $source)

Move data

   Parameter  Description
1  $target    Target
2  $source    Source

Example:

  Start;
  Comment "Print a string from memory";
  my $s = "Hello World";
  my $m = Rs($s);

  Mov rsi, $m;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  PrintOutString rsi, length($s);
  Exit;
  ok assemble =~ m(Hello World);

PushR(@r)

Push registers onto the stack

   Parameter  Description
1  @r         Register

PopR(@r)

Pop registers in reverse order from the stack so the same parameter list can be shared with pushR

   Parameter  Description
1  @r         Register

Example:

  Start;
  my $q = Rs(('a'..'p')x4);
  my $d = Ds('0'x128);
  Vmovdqu32(zmm0, "[$q]");
  Vprolq   (zmm0,   zmm0, 32);
  Vmovdqu32("[$d]", zmm0);
  PrintOutString($d, 64);
  Sub rsp, 64;
  Vmovdqu64 "[rsp]", zmm0;

  PopR rax;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  PrintOutRaxInHex;
  Exit;
  ok assemble() =~ m(efghabcdmnopijklefghabcdmnopijklefghabcdmnopijklefghabcdmnopijkl)s;

Sub($target, $source)

Subtract

   Parameter  Description
1  $target    Target
2  $source    Source

PrintOutNl()

Write a new line

Example:

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

PrintOutString($string, $length)

One: Write a constant string to sysout. Two write the bytes addressed for the specified length to sysout

   Parameter  Description
1  $string    String
2  $length    Length

Example:

  Start;

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

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

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;

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;

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;
  ok assemble() =~ m(r8: 0000 0000 0000 0005.*r9: 0000 0000 0000 0003.*rax: 0000 0000 0000 0001)s;

Xor($t, $s)

Xor

   Parameter  Description
1  $t         Target
2  $s         Source

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;

Test($t, $s)

Test

   Parameter  Description
1  $t         Target
2  $s         Source

Vmovdqu8($r, $m)

Move memory in 8 bit blocks to an x/y/zmm* register

   Parameter  Description
1  $r         Register
2  $m         Memory

Example:

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

  Vmovdqu8 xmm0, "[$q]";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  PrintOutRegisterInHex xmm0;
  Exit;
  ok assemble() =~ m(xmm0: 706F 6E6D 6C6B 6A69   6867 6665 6463 6261)s;

Vmovdqu32($r, $m)

Move memory in 32 bit blocks to an x/y/zmm* register

   Parameter  Description
1  $r         Register
2  $m         Memory

Example:

  Start;
  my $q = Rs('a'..'z');
  my $d = Ds('0'x64);                                                           # Output area

  Vmovdqu32(xmm0, "[$q]");                                                      # Load  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  Vprolq   (xmm0,   xmm0, 32);                                                  # Rotate double words in quad words

  Vmovdqu32("[$d]", xmm0);                                                      # Save  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  PrintOutString($d, 16);
  Exit;
  ok assemble() =~ m(efghabcdmnopijkl)s;

Vmovdqu64($r, $m)

Move memory in 64 bit blocks to an x/y/zmm* register

   Parameter  Description
1  $r         Register
2  $m         Memory

Example:

  Start;
  my $q = Rs(('a'..'p')x4);
  my $d = Ds('0'x128);
  Vmovdqu32(zmm0, "[$q]");
  Vprolq   (zmm0,   zmm0, 32);
  Vmovdqu32("[$d]", zmm0);
  PrintOutString($d, 64);
  Sub rsp, 64;

  Vmovdqu64 "[rsp]", zmm0;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  PopR rax;
  PrintOutRaxInHex;
  Exit;
  ok assemble() =~ m(efghabcdmnopijklefghabcdmnopijklefghabcdmnopijklefghabcdmnopijkl)s;

Vprolq($r, $m, $bits)

Rotate left within quad word indicated number of bits

   Parameter  Description
1  $r         Register
2  $m         Memory
3  $bits      Number of bits to rotate

Example:

  Start;
  my $q = Rs('a'..'z');
  my $d = Ds('0'x64);                                                           # Output area
  Vmovdqu32(xmm0, "[$q]");                                                      # Load

  Vprolq   (xmm0,   xmm0, 32);                                                  # Rotate double words in quad words  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  Vmovdqu32("[$d]", xmm0);                                                      # Save
  PrintOutString($d, 16);
  Exit;
  ok assemble() =~ m(efghabcdmnopijkl)s;

allocateMemory($s)

Allocate memory via mmap

   Parameter  Description
1  $s         Amount of memory to allocate

Example:

  Start;
  my $N = 2048;
  my $n = Rq($N);
  my $q = Rs('a'..'p');

  allocateMemory "[$n]";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  PrintOutRegisterInHex rax;
  Vmovdqu8 xmm0, "[$q]";
  Vmovdqu8 "[rax]", xmm0;
  PrintOutString rax,16;
  PrintOutNl;

  Mov rbx, rax;
  freeMemory rbx, "[$n]";
  PrintOutRegisterInHex rax;
  Vmovdqu8 "[rbx]", xmm0;
  Exit;
  ok assemble() =~ m(abcdefghijklmnop)s;

freeMemory($a, $l)

Free memory via mmap

   Parameter  Description
1  $a         Address of memory to free
2  $l         Length of memory to free

Example:

  Start;
  my $N = 2048;
  my $n = Rq($N);
  my $q = Rs('a'..'p');
  allocateMemory "[$n]";
  PrintOutRegisterInHex rax;
  Vmovdqu8 xmm0, "[$q]";
  Vmovdqu8 "[rax]", xmm0;
  PrintOutString rax,16;
  PrintOutNl;

  Mov rbx, rax;

  freeMemory rbx, "[$n]";  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  PrintOutRegisterInHex rax;
  Vmovdqu8 "[rbx]", xmm0;
  Exit;
  ok assemble() =~ m(abcdefghijklmnop)s;

Fork()

Fork

Example:

  Start;

  Fork;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  Test rax,rax;
  If                                                                            # Parent
   {Mov rbx, rax;
    WaitPid;
    Mov rcx, rax;
    PrintOutRegisterInHex rcx;
    PrintOutRegisterInHex rbx;
   }  sub                                                                       # Child
   {PrintOutRegisterInHex rax;
   };
  Exit;
  my $r = assemble();

#   rax: 0000 0000 0000 0000  Pid as seen by child
#   rcx: 0000 0000 0002 EB35  Pid that terminated as seen by parent
#   rbx: 0000 0000 0002 EB35  Pid of child as seen by parent

  if ($r =~ m(rax:( 0000){4} .*rcx:(.*)\s{5,}rbx:(.*)\s{2,})s)
   {ok $2 eq $3;
   }
  else
   {ok 0;
   }

GetPid()

Get process identifier - at the moment it will return the id of the parent process due to a documented error in getpid. We should read: /proc/self to get the current pid accurately

Example:

  Start;
  Fork;
  Test rax,rax;
  If                                                                            # Parent
   {Mov rbx, rax;
    WaitPid;
    Mov rcx, rax;
    PrintOutRegisterInHex rcx;
    PrintOutRegisterInHex rbx;
   }  sub                                                                       # Child
   {PrintOutRegisterInHex rax;
   };
  Exit;
  my $r = assemble();

#   rax: 0000 0000 0000 0000  Pid as seen by child
#   rcx: 0000 0000 0002 EB35  Pid that terminated as seen by parent
#   rbx: 0000 0000 0002 EB35  Pid of child as seen by parent

  if ($r =~ m(rax:( 0000){4} .*rcx:(.*)\s{5,}rbx:(.*)\s{2,})s)
   {ok $2 eq $3;
   }
  else
   {ok 0;
   }

WaitPid()

Wait for the pid in rax to complete

Example:

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

    WaitPid;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov rcx, rax;
    PrintOutRegisterInHex rcx;
    PrintOutRegisterInHex rbx;
   }  sub                                                                       # Child
   {PrintOutRegisterInHex rax;
   };
  Exit;
  my $r = assemble();

#   rax: 0000 0000 0000 0000  Pid as seen by child
#   rcx: 0000 0000 0002 EB35  Pid that terminated as seen by parent
#   rbx: 0000 0000 0002 EB35  Pid of child as seen by parent

  if ($r =~ m(rax:( 0000){4} .*rcx:(.*)\s{5,}rbx:(.*)\s{2,})s)
   {ok $2 eq $3;
   }
  else
   {ok 0;
   }

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;

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;

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 allocateMemory - Allocate memory via mmap

2 assemble - Assemble the generated code

3 Comment - Insert a comment into the assembly code

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

5 Dbwdq - Layout data

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

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

8 Ds - Layout bytes in memory and return their label

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

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

11 Fork - Fork

12 freeMemory - Free memory via mmap

13 GetPid - Get process identifier - at the moment it will return the id of the parent process due to a documented error in getpid.

14 If - If

15 label - Create a unique label

16 Lea - Load effective address

17 Mov - Move data

18 PopR - Pop registers in reverse order from the stack so the same parameter list can be shared with pushR

19 PrintOutNl - Write a new line

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

21 PrintOutRegisterInHex - Print any register as a hex string

22 PrintOutRegistersInHex - Print the general purpose registers in hex

23 PrintOutString - One: Write a constant string to sysout.

24 PushR - Push registers onto the stack

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

26 Rbwdq - Layout data

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

28 readTimeStampCounter - Read the time stamp counter

29 RestoreFirstFour - Restore the first 4 parameter registers

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

31 RestoreFirstSeven - Restore the first 7 parameter registers

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

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

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

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

36 SaveFirstFour - Save the first 4 parameter registers

37 SaveFirstSeven - Save the first 7 parameter registers

38 Start - Initialize the assembler

39 Sub - Subtract

40 Test - Test

41 Vmovdqu32 - Move memory in 32 bit blocks to an x/y/zmm* register

42 Vmovdqu64 - Move memory in 64 bit blocks to an x/y/zmm* register

43 Vmovdqu8 - Move memory in 8 bit blocks to an x/y/zmm* register

44 Vprolq - Rotate left within quad word indicated number of bits

45 WaitPid - Wait for the pid in rax to complete

46 Xor - Xor

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.