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

Name

Nasm::X86 - Generate X86 assembler code using Perl as a macro pre-processor.

Synopsis

Write and execute x64 instructions using Perl as a macro assembler as shown in the following examples.

Examples

Avx512 instructions

Use avx512 instructions to do 64 comparisons in parallel:

  my $P = "2F";                                                                 # Value to test for
  my $l = Rb 0;  Rb $_ for 1..RegisterSize zmm0;                                # 0..63
  Vmovdqu8 zmm0, "[$l]";                                                        # Load data to test
  PrintOutRegisterInHex zmm0;

  Mov rax, "0x$P";                                                              # Broadcast the value to be tested
  Vpbroadcastb zmm1, rax;
  PrintOutRegisterInHex zmm1;

  for my $c(0..7)                                                               # Each possible test
   {my $m = "k$c";
    Vpcmpub $m, zmm1, zmm0, $c;
    PrintOutRegisterInHex $m;
   }

  Kmovq rax, k0;                                                                # Count the number of trailing zeros in k0
  Tzcnt rax, rax;
  PrintOutRegisterInHex rax;

  is_deeply Assemble, <<END;                                                    # Assemble and test
  zmm0: 3F3E 3D3C 3B3A 3938   3736 3534 3332 3130   2F2E 2D2C 2B2A 2928   2726 2524 2322 2120   1F1E 1D1C 1B1A 1918   1716 1514 1312 1110   0F0E 0D0C 0B0A 0908   0706 0504 0302 0100
  zmm1: 2F2F 2F2F 2F2F 2F2F   2F2F 2F2F 2F2F 2F2F   2F2F 2F2F 2F2F 2F2F   2F2F 2F2F 2F2F 2F2F   2F2F 2F2F 2F2F 2F2F   2F2F 2F2F 2F2F 2F2F   2F2F 2F2F 2F2F 2F2F   2F2F 2F2F 2F2F 2F2F
    k0: 0000 8000 0000 0000
    k1: FFFF 0000 0000 0000
    k2: FFFF 8000 0000 0000
    k3: 0000 0000 0000 0000
    k4: FFFF 7FFF FFFF FFFF
    k5: 0000 FFFF FFFF FFFF
    k6: 0000 7FFF FFFF FFFF
    k7: FFFF FFFF FFFF FFFF
   rax: 0000 0000 0000 002F
END

Dynamic string held in an arena

Create a dynamic byte string, add some content to it, write the byte string to stdout:

  my $a = CreateByteString;                                                     # Create a string
  my $b = CreateByteString;                                                     # Create a string
  $a->q('aa');
  $b->q('bb');
  $a->q('AA');
  $b->q('BB');
  $a->q('aa');
  $b->q('bb');
  $a->out;
  $b->out;
  PrintOutNL;
  is_deeply Assemble, <<END;                                                    # Assemble and execute
aaAAaabbBBbb
END

Process management

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

  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;
   };

  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 a file

Read this file:

  ReadFile(Vq(file, Rs($0)), (my $s = Vq(size)), my $a = Vq(address));          # Read file
  $a->setReg(rax);                                                              # Address of file in memory
  $s->setReg(rdi);                                                              # Length  of file in memory
  PrintOutMemory;                                                               # Print contents of memory to stdout

  my $r = Assemble(1 => (my $f = temporaryFile));                               # Assemble and execute
  ok fileMd5Sum($f) eq fileMd5Sum($0);                                          # Output contains this file

Call functions in Libc

Call C functions by naming them as external and including their library:

  my $format = Rs "Hello %s\n";
  my $data   = Rs "World";

  Extern qw(printf exit malloc strcpy); Link 'c';

  CallC 'malloc', length($format)+1;
  Mov r15, rax;
  CallC 'strcpy', r15, $format;
  CallC 'printf', r15, $data;
  CallC 'exit', 0;

  ok Assemble(eq => <<END);
Hello World
END

Installation

The Intel Software Development Emulator will be required if you do not have a computer with the avx512 instruction set and wish to execute code containing these instructions. For details see:

https://software.intel.com/content/dam/develop/external/us/en/documents/downloads/sde-external-8.63.0-2021-01-18-lin.tar.bz2

The Networkwide Assembler is required to assemble the code produced For full details see:

https://github.com/philiprbrenan/NasmX86/blob/main/.github/workflows/main.yml

Execution Options

The "Assemble(%)" function takes the keywords described below to control assembly and execution of the assembled code:

"Assemble(%)" runs the generated program after a successful assembly unless the keep option is specified. The output on stdout is captured in file zzzOut.txt and that on stderr is captured in file zzzErr.txt.

The amount of output displayed is controlled by the debug keyword.

The eq keyword can be used to test that the output by the run.

The output produced by the program execution is returned as the result of the "Assemble(%)" function.

Keep

To produce a named executable without running it, specify:

 keep=>"executable file name"

Emulator

To run the executable produced by "Assemble(%)" without the Intel emulator, which is used by default if it is present, specify:

 emulator=>0

eq

The eq keyword supplies the expected output from the execution of the assembled program. If the expected output is not obtained on stdout then we confess and stop further testing. Output on stderr is ignored for test purposes.

The point at which the wanted output diverges from the output actually got is displayed to assist debugging as in:

  Comparing wanted with got failed at line: 4, character: 22
  Start:
      k7: 0000 0000 0000 0001
      k6: 0000 0000 0000 0003
      k5: 0000 0000 0000 0007
      k4: 0000 0000 000
  Want ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1 0002
      k3: 0000 0000 0000 0006
      k2: 0000 0000 0000 000E
      k1: 0000 0000
  Got  ________________________________________________________________________________
  0 0002
      k3: 0000 0000 0000 0006
      k2: 0000 0000 0000 000E
      k1: 0000 0000

Debug

The debug keyword controls how much output is printed after each assemble and run.

  debug => 0

produces no output unless the eq keyword was specified and the actual output fails to match the expected output. If such a test fails we Carp::confess.

  debug => 1

shows all the output produces and conducts the test specified by the eq is present. If the test fails we Carp::confess.

  debug => 2

shows all the output produces and conducts the test specified by the eq is present. If the test fails we continue rather than calling Carp::confess.

Description

Generate X86 assembler code using Perl as a macro pre-processor.

Version "20210727".

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

Data

Layout data

SetLabel($l)

Set a label in the code section

     Parameter  Description
  1  $l         Label

Example:

    Mov rax, 1;
    Mov rdi, 1;
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSeven;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFour;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRax;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRax;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
  
    Bswap rax;
    PrintOutRegisterInHex rax;
  
    my $l = Label;
    Jmp $l;
  
    SetLabel $l;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    is_deeply Assemble, <<END;
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0002
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0001
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0300 0000 0000 0000
  END
  
    ok 8 == RegisterSize rax;
  

Ds(@d)

Layout bytes in memory and return their label

     Parameter  Description
  1  @d         Data to be laid out

Example:

    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;
  
    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:

    Comment "Print a string from memory";
    my $s = "Hello World";
  
    Mov rax, Rs($s);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov rdi, length $s;
    PrintOutMemory;
  
    ok Assemble =~ m(Hello World);
  
  
    my $q = Rs('abababab');  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov(rax, 1);
    Mov(rbx, 2);
    Mov(rcx, 3);
    Mov(rdx, 4);
    Mov(r8,  5);
    Lea r9,  "[rax+rbx]";
    PrintOutRegistersInHex;
  
    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;
  

Rutf8(@d)

Layout a utf8 encoded string as bytes in read only memory and return their label

     Parameter  Description
  1  @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

Example:

    my $s = Rb 0; Rb 1; Rw 2; Rd 3;  Rq 4;
  
    my $t = Db 0; Db 1; Dw 2; Dd 3;  Dq 4;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Vmovdqu8 xmm0, "[$s]";
    Vmovdqu8 xmm1, "[$t]";
    PrintOutRegisterInHex xmm0;
    PrintOutRegisterInHex xmm1;
    Sub rsp, 16;
  
    Mov rax, rsp;                                                                 # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
    Mov rdi, 16;
    Mov rsi, $s;
    CopyMemory(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
    PrintOutMemoryInHex;
  
    my $r = Assemble;
    ok $r =~ m(xmm0: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(xmm1: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
  

Dw(@words)

Layout words in the data segment and return their label

     Parameter  Description
  1  @words     Words to layout

Example:

    my $s = Rb 0; Rb 1; Rw 2; Rd 3;  Rq 4;
  
    my $t = Db 0; Db 1; Dw 2; Dd 3;  Dq 4;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Vmovdqu8 xmm0, "[$s]";
    Vmovdqu8 xmm1, "[$t]";
    PrintOutRegisterInHex xmm0;
    PrintOutRegisterInHex xmm1;
    Sub rsp, 16;
  
    Mov rax, rsp;                                                                 # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
    Mov rdi, 16;
    Mov rsi, $s;
    CopyMemory(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
    PrintOutMemoryInHex;
  
    my $r = Assemble;
    ok $r =~ m(xmm0: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(xmm1: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
  

Dd(@dwords)

Layout double words in the data segment and return their label

     Parameter  Description
  1  @dwords    Double words to layout

Example:

    my $s = Rb 0; Rb 1; Rw 2; Rd 3;  Rq 4;
  
    my $t = Db 0; Db 1; Dw 2; Dd 3;  Dq 4;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Vmovdqu8 xmm0, "[$s]";
    Vmovdqu8 xmm1, "[$t]";
    PrintOutRegisterInHex xmm0;
    PrintOutRegisterInHex xmm1;
    Sub rsp, 16;
  
    Mov rax, rsp;                                                                 # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
    Mov rdi, 16;
    Mov rsi, $s;
    CopyMemory(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
    PrintOutMemoryInHex;
  
    my $r = Assemble;
    ok $r =~ m(xmm0: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(xmm1: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
  

Dq(@qwords)

Layout quad words in the data segment and return their label

     Parameter  Description
  1  @qwords    Quad words to layout

Example:

    my $s = Rb 0; Rb 1; Rw 2; Rd 3;  Rq 4;
  
    my $t = Db 0; Db 1; Dw 2; Dd 3;  Dq 4;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Vmovdqu8 xmm0, "[$s]";
    Vmovdqu8 xmm1, "[$t]";
    PrintOutRegisterInHex xmm0;
    PrintOutRegisterInHex xmm1;
    Sub rsp, 16;
  
    Mov rax, rsp;                                                                 # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
    Mov rdi, 16;
    Mov rsi, $s;
    CopyMemory(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
    PrintOutMemoryInHex;
  
    my $r = Assemble;
    ok $r =~ m(xmm0: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(xmm1: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
  

Rb(@bytes)

Layout bytes in the data segment and return their label

     Parameter  Description
  1  @bytes     Bytes to layout

Example:

    my $s = Rb 0; Rb 1; Rw 2; Rd 3;  Rq 4;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $t = Db 0; Db 1; Dw 2; Dd 3;  Dq 4;
  
    Vmovdqu8 xmm0, "[$s]";
    Vmovdqu8 xmm1, "[$t]";
    PrintOutRegisterInHex xmm0;
    PrintOutRegisterInHex xmm1;
    Sub rsp, 16;
  
    Mov rax, rsp;                                                                 # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
    Mov rdi, 16;
    Mov rsi, $s;
    CopyMemory(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
    PrintOutMemoryInHex;
  
    my $r = Assemble;
    ok $r =~ m(xmm0: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(xmm1: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
  

Rw(@words)

Layout words in the data segment and return their label

     Parameter  Description
  1  @words     Words to layout

Example:

    my $s = Rb 0; Rb 1; Rw 2; Rd 3;  Rq 4;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $t = Db 0; Db 1; Dw 2; Dd 3;  Dq 4;
  
    Vmovdqu8 xmm0, "[$s]";
    Vmovdqu8 xmm1, "[$t]";
    PrintOutRegisterInHex xmm0;
    PrintOutRegisterInHex xmm1;
    Sub rsp, 16;
  
    Mov rax, rsp;                                                                 # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
    Mov rdi, 16;
    Mov rsi, $s;
    CopyMemory(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
    PrintOutMemoryInHex;
  
    my $r = Assemble;
    ok $r =~ m(xmm0: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(xmm1: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
  

Rd(@dwords)

Layout double words in the data segment and return their label

     Parameter  Description
  1  @dwords    Double words to layout

Example:

    my $s = Rb 0; Rb 1; Rw 2; Rd 3;  Rq 4;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $t = Db 0; Db 1; Dw 2; Dd 3;  Dq 4;
  
    Vmovdqu8 xmm0, "[$s]";
    Vmovdqu8 xmm1, "[$t]";
    PrintOutRegisterInHex xmm0;
    PrintOutRegisterInHex xmm1;
    Sub rsp, 16;
  
    Mov rax, rsp;                                                                 # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
    Mov rdi, 16;
    Mov rsi, $s;
    CopyMemory(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
    PrintOutMemoryInHex;
  
    my $r = Assemble;
    ok $r =~ m(xmm0: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(xmm1: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
  

Rq(@qwords)

Layout quad words in the data segment and return their label

     Parameter  Description
  1  @qwords    Quad words to layout

Example:

    my $s = Rb 0; Rb 1; Rw 2; Rd 3;  Rq 4;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    my $t = Db 0; Db 1; Dw 2; Dd 3;  Dq 4;
  
    Vmovdqu8 xmm0, "[$s]";
    Vmovdqu8 xmm1, "[$t]";
    PrintOutRegisterInHex xmm0;
    PrintOutRegisterInHex xmm1;
    Sub rsp, 16;
  
    Mov rax, rsp;                                                                 # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
    Mov rdi, 16;
    Mov rsi, $s;
    CopyMemory(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
    PrintOutMemoryInHex;
  
    my $r = Assemble;
    ok $r =~ m(xmm0: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(xmm1: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
  

Float32($float)

32 bit float

     Parameter  Description
  1  $float     Float

Float64($float)

64 bit float

     Parameter  Description
  1  $float     Float

Registers

Operations on registers

xmm(@r)

Add xmm to the front of a list of register expressions

     Parameter  Description
  1  @r         Register numbers

ymm(@r)

Add ymm to the front of a list of register expressions

     Parameter  Description
  1  @r         Register numbers

zmm(@r)

Add zmm to the front of a list of register expressions

     Parameter  Description
  1  @r         Register numbers

Save and Restore

Saving and restoring registers via the stack

SaveFirstFour(@keep)

Save the first 4 parameter registers making any parameter registers read only

     Parameter  Description
  1  @keep      Registers to mark as read only

Example:

    Mov rax, 1;
    Mov rdi, 1;
  
    SaveFirstFour;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSeven;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFour;
    PrintOutRegisterInHex rax, rdi;
  
  
    SaveFirstFour;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRax;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRax;
    PrintOutRegisterInHex rax, rdi;
  
  
    SaveFirstFour;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
  
    Bswap rax;
    PrintOutRegisterInHex rax;
  
    my $l = Label;
    Jmp $l;
    SetLabel $l;
  
    is_deeply Assemble, <<END;
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0002
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0001
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0300 0000 0000 0000
  END
  
    ok 8 == RegisterSize rax;
  

RestoreFirstFour()

Restore the first 4 parameter registers

Example:

    Mov rax, 1;
    Mov rdi, 1;
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSeven;
    PrintOutRegisterInHex rax, rdi;
  
    RestoreFirstFour;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRax;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRax;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
  
    Bswap rax;
    PrintOutRegisterInHex rax;
  
    my $l = Label;
    Jmp $l;
    SetLabel $l;
  
    is_deeply Assemble, <<END;
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0002
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0001
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0300 0000 0000 0000
  END
  
    ok 8 == RegisterSize rax;
  

RestoreFirstFourExceptRax()

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

Example:

    Mov rax, 1;
    Mov rdi, 1;
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSeven;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFour;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRax;
    PrintOutRegisterInHex rax, rdi;
  
    RestoreFirstFourExceptRax;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
  
    Bswap rax;
    PrintOutRegisterInHex rax;
  
    my $l = Label;
    Jmp $l;
    SetLabel $l;
  
    is_deeply Assemble, <<END;
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0002
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0001
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0300 0000 0000 0000
  END
  
    ok 8 == RegisterSize rax;
  

RestoreFirstFourExceptRaxAndRdi()

Restore the first 4 parameter registers except rax and rdi so we can return a pair of values

Example:

    Mov rax, 1;
    Mov rdi, 1;
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSeven;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFour;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRax;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRax;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
  
    RestoreFirstFourExceptRaxAndRdi;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax, rdi;
  
    Bswap rax;
    PrintOutRegisterInHex rax;
  
    my $l = Label;
    Jmp $l;
    SetLabel $l;
  
    is_deeply Assemble, <<END;
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0002
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0001
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0300 0000 0000 0000
  END
  
    ok 8 == RegisterSize rax;
  

SaveFirstSeven()

Save the first 7 parameter registers

Example:

    Mov rax, 1;
    Mov rdi, 1;
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
  
    SaveFirstSeven;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSeven;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFour;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
  
    SaveFirstSeven;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRax;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRax;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
  
    SaveFirstSeven;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
  
    Bswap rax;
    PrintOutRegisterInHex rax;
  
    my $l = Label;
    Jmp $l;
    SetLabel $l;
  
    is_deeply Assemble, <<END;
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0002
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0001
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0300 0000 0000 0000
  END
  
    ok 8 == RegisterSize rax;
  

RestoreFirstSeven()

Restore the first 7 parameter registers

Example:

    Mov rax, 1;
    Mov rdi, 1;
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
  
    RestoreFirstSeven;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFour;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRax;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRax;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
  
    Bswap rax;
    PrintOutRegisterInHex rax;
  
    my $l = Label;
    Jmp $l;
    SetLabel $l;
  
    is_deeply Assemble, <<END;
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0002
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0001
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0300 0000 0000 0000
  END
  
    ok 8 == RegisterSize rax;
  

RestoreFirstSevenExceptRax()

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

Example:

    Mov rax, 1;
    Mov rdi, 1;
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSeven;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFour;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
  
    RestoreFirstSevenExceptRax;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRax;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
  
    Bswap rax;
    PrintOutRegisterInHex rax;
  
    my $l = Label;
    Jmp $l;
    SetLabel $l;
  
    is_deeply Assemble, <<END;
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0002
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0001
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0300 0000 0000 0000
  END
  
    ok 8 == RegisterSize rax;
  

RestoreFirstSevenExceptRaxAndRdi()

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

Example:

    Mov rax, 1;
    Mov rdi, 1;
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSeven;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFour;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRax;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRax;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
  
    RestoreFirstSevenExceptRaxAndRdi;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
  
    Bswap rax;
    PrintOutRegisterInHex rax;
  
    my $l = Label;
    Jmp $l;
    SetLabel $l;
  
    is_deeply Assemble, <<END;
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0002
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0001
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0300 0000 0000 0000
  END
  
    ok 8 == RegisterSize rax;
  

ReorderSyscallRegisters(@registers)

Map the list of registers provided to the 64 bit system call sequence

     Parameter   Description
  1  @registers  Registers

Example:

    Mov rax, 1;  Mov rdi, 2;  Mov rsi,  3;  Mov rdx,  4;
    Mov r8,  8;  Mov r9,  9;  Mov r10, 10;  Mov r11, 11;
  
  
    ReorderSyscallRegisters   r8,r9;                                              # Reorder the registers for syscall  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
    PrintOutRegisterInHex rdi;
  
    UnReorderSyscallRegisters r8,r9;                                              # Unreorder the registers to recover their original values
    PrintOutRegisterInHex rax;
    PrintOutRegisterInHex rdi;
  
    ok Assemble =~ m(rax:.*08.*rdi:.*9.*rax:.*1.*rdi:.*2.*)s;
  

UnReorderSyscallRegisters(@registers)

Recover the initial values in registers that were reordered

     Parameter   Description
  1  @registers  Registers

Example:

    Mov rax, 1;  Mov rdi, 2;  Mov rsi,  3;  Mov rdx,  4;
    Mov r8,  8;  Mov r9,  9;  Mov r10, 10;  Mov r11, 11;
  
    ReorderSyscallRegisters   r8,r9;                                              # Reorder the registers for syscall
    PrintOutRegisterInHex rax;
    PrintOutRegisterInHex rdi;
  
  
    UnReorderSyscallRegisters r8,r9;                                              # Unreorder the registers to recover their original values  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
    PrintOutRegisterInHex rdi;
  
    ok Assemble =~ m(rax:.*08.*rdi:.*9.*rax:.*1.*rdi:.*2.*)s;
  

RegisterSize($r)

Return the size of a register

     Parameter  Description
  1  $r         Register

Example:

    Mov rax, 1;
    Mov rdi, 1;
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSeven;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFour;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRax;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRax;
    PrintOutRegisterInHex rax, rdi;
  
    SaveFirstFour;
    Mov rax, 2;
    Mov rdi, 2;
    SaveFirstSeven;
    Mov rax, 3;
    Mov rdi, 4;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstSevenExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
    RestoreFirstFourExceptRaxAndRdi;
    PrintOutRegisterInHex rax, rdi;
  
    Bswap rax;
    PrintOutRegisterInHex rax;
  
    my $l = Label;
    Jmp $l;
    SetLabel $l;
  
    is_deeply Assemble, <<END;
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0002
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0001
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0002
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0001
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0000 0000 0000 0003
     rdi: 0000 0000 0000 0004
     rax: 0300 0000 0000 0000
  END
  
  
    ok 8 == RegisterSize rax;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  

ClearRegisters(@registers)

Clear registers by setting them to zero

     Parameter   Description
  1  @registers  Registers

Example:

    Mov rax,1;
    Kmovq k0,  rax;
    Kaddb k0,  k0, k0;
    Kaddb k0,  k0, k0;
    Kaddb k0,  k0, k0;
    Kmovq rax, k0;
    PushR k0;
  
    ClearRegisters k0;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Kmovq k1, k0;
    PopR  k0;
    PrintOutRegisterInHex k0;
    PrintOutRegisterInHex k1;
  
    ok Assemble =~ m(k0: 0000 0000 0000 0008.*k1: 0000 0000 0000 0000)s;
  

SetMaskRegister($mask, $start, $length)

Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere

     Parameter  Description
  1  $mask      Mask register to set
  2  $start     Register containing start position or 0 for position 0
  3  $length    Register containing end position

Example:

    Mov rax, 8;
    Mov rsi, -1;
  
    Inc rsi; SetMaskRegister(k0, rax, rsi); PrintOutRegisterInHex k0;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Inc rsi; SetMaskRegister(k1, rax, rsi); PrintOutRegisterInHex k1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Inc rsi; SetMaskRegister(k2, rax, rsi); PrintOutRegisterInHex k2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Inc rsi; SetMaskRegister(k3, rax, rsi); PrintOutRegisterInHex k3;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Inc rsi; SetMaskRegister(k4, rax, rsi); PrintOutRegisterInHex k4;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Inc rsi; SetMaskRegister(k5, rax, rsi); PrintOutRegisterInHex k5;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Inc rsi; SetMaskRegister(k6, rax, rsi); PrintOutRegisterInHex k6;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Inc rsi; SetMaskRegister(k7, rax, rsi); PrintOutRegisterInHex k7;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    is_deeply Assemble, <<END;
      k0: 0000 0000 0000 0000
      k1: 0000 0000 0000 0100
      k2: 0000 0000 0000 0300
      k3: 0000 0000 0000 0700
      k4: 0000 0000 0000 0F00
      k5: 0000 0000 0000 1F00
      k6: 0000 0000 0000 3F00
      k7: 0000 0000 0000 7F00
  END
  

SetZF()

Set the zero flag

Example:

    SetZF;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutZF;
    ClearZF;
    PrintOutZF;
  
    SetZF;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutZF;
  
    SetZF;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutZF;
    ClearZF;
    PrintOutZF;
  
    ok Assemble =~ m(ZF=1.*ZF=0.*ZF=1.*ZF=1.*ZF=0)s;
  

ClearZF()

Clear the zero flag

Example:

    SetZF;
    PrintOutZF;
  
    ClearZF;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutZF;
    SetZF;
    PrintOutZF;
    SetZF;
    PrintOutZF;
  
    ClearZF;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutZF;
  
    ok Assemble =~ m(ZF=1.*ZF=0.*ZF=1.*ZF=1.*ZF=0)s;
  

Tracing

Trace the execution of a program

Trace()

Add tracing code

Tracking

Track the use of registers so that we do not accidently use unset registers or write into registers that are already in use.

Keep(@target)

Mark registers as in use so that they cannot be updated until we explicitly free them. Complain if the register is already in use.

     Parameter  Description
  1  @target    Registers to keep

KeepSet($target)

Confirm that the specified registers are in use

     Parameter  Description
  1  $target    Registers to keep

KeepPush(@target)

Push the current status of the specified registers and then mark them as free

     Parameter  Description
  1  @target    Registers to keep

KeepPop(@target)

Reset the status of the specified registers to the status quo ante the last push

     Parameter  Description
  1  @target    Registers to keep

KeepReturn(@target)

Pop the specified register and mark it as in use to effect a subroutine return with this register.

     Parameter  Description
  1  @target    Registers to return

KeepFree(@target)

Free registers so that they can be reused

     Parameter  Description
  1  @target    Registers to free

Mask

Operations on mask registers

LoadConstantIntoMaskRegister($reg, $value)

Load a constant into a mask register

     Parameter  Description
  1  $reg       Mask register to load
  2  $value     Constant to load

Example:

    Mov r14, 0;
    Kmovq k0, r14;
    KeepFree r14;
    Ktestq k0, k0;
    IfZ {PrintOutStringNL "0 & 0 == 0"};
    PrintOutZF;
  
  
    LoadConstantIntoMaskRegister k1, 1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Ktestq k1, k1;
    IfNz {PrintOutStringNL "1 & 1 != 0"};
    PrintOutZF;
  
  
    LoadConstantIntoMaskRegister k2, eval "0b".(('1'x4).('0'x4))x2;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    PrintOutRegisterInHex k0, k1, k2;
  
    Mov  r15, 0x89abcdef;
    Mov  r14, 0x01234567;
    Shl  r14, 32;
    Or r15, r14;
    Push r15;
    Push r15;
    KeepFree r15;
    PopEax;  PrintRaxInHex($stdout, 3); PrintOutNL; KeepFree rax;
  
    my $a = Vq('aaaa');
    $a->pop;
    $a->push;
    $a->outNL;
  
    PopEax;  PrintRaxInHex($stdout, 3); PrintOutNL; KeepFree rax;
  
    ok Assemble(debug => 0, eq => <<END);
  0 & 0 == 0
  ZF=1
  1 & 1 != 0
  ZF=0
      k0: 0000 0000 0000 0000
      k1: 0000 0000 0000 0001
      k2: 0000 0000 0000 F0F0
  89AB CDEF
  aaaa: 89AB CDEF 0123 4567
  0123 4567
  END
  

Structured Programming

Structured programming constructs

If($jump, $then, $else)

If

     Parameter  Description
  1  $jump      Jump op code of variable
  2  $then      Then - required
  3  $else      Else - optional

Example:

    Mov rax, 0;
    Test rax,rax;
    IfNz
     {PrintOutRegisterInHex rax;
     } sub
     {PrintOutRegisterInHex rbx;
     };
    KeepFree rax;
    Mov rax, 1;
    Test rax,rax;
    IfNz
     {PrintOutRegisterInHex rcx;
     } sub
     {PrintOutRegisterInHex rdx;
     };
  
    ok Assemble =~ m(rbx.*rcx)s;
  

Then($body)

Then body for an If statement

     Parameter  Description
  1  $body      Then body

Else($body)

Else body for an If statement

     Parameter  Description
  1  $body      Else body

IfEq($then, $else)

If equal execute the then body else the else body

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

IfNe($then, $else)

If not equal execute the then body else the else body

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

IfNz($then, $else)

If the zero is not set then execute the then body else the else body

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

IfZ($then, $else)

If the zero is set then execute the then body else the else body

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

IfLt($then, $else)

If less than execute the then body else the else body

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

IfLe($then, $else)

If less than or equal execute the then body else the else body

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

IfGt($then, $else)

If greater than execute the then body else the else body

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

IfGe($then, $else)

If greater than or equal execute the then body else the else body

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

Block($body)

Execute a block of code one with the option of jumping out of the block or restarting the block via the supplied labels.

     Parameter  Description
  1  $body      Body

Example:

    Mov rax, 0;
  
    Block  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {my ($start, $end) = @_;
      PrintOutRegisterInHex rax;
      Cmp rax, 3;
      IfGe {Jmp $end};
      Inc rax;
      PrintOutRegisterInHex rax
      Jmp $start;
     };
  
    ok Assemble(debug => 0, eq => <<END);
     rax: 0000 0000 0000 0000
     rax: 0000 0000 0000 0001
     rax: 0000 0000 0000 0002
     rax: 0000 0000 0000 0003
  END
  

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

For - iterate the body as long as register is less than limit incrementing by increment each time

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

Example:

    For  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {my ($start, $end, $next) = @_;
      Cmp rax, 3;
      IfGe {Jmp $end};
      PrintOutRegisterInHex rax;
     } rax, 16, 1;
  
    ok Assemble(debug => 0, eq => <<END);
     rax: 0000 0000 0000 0000
     rax: 0000 0000 0000 0001
     rax: 0000 0000 0000 0002
  END
  

ForIn($full, $last, $register, $limit, $increment)

For - iterate the full body as long as register plus increment is less than than limit incrementing by increment each time then increment the last body for the last non full block.

     Parameter   Description
  1  $full       Body for full block
  2  $last       Body for last block
  3  $register   Register
  4  $limit      Limit on loop
  5  $increment  Increment on each iteration

ForEver($body)

Iterate for ever

     Parameter  Description
  1  $body      Body to iterate

Macro($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.

Subroutine($body, %options)

Create a subroutine that can be called in assembler code

     Parameter  Description
  1  $body      Body
  2  %options   Options.

Nasm::X86::Sub::call($sub, @parameters)

Call a sub passing it some parameters

     Parameter    Description
  1  $sub         Subroutine descriptor
  2  @parameters  Parameter variables

cr($body, @registers)

Call a subroutine with a reordering of the registers.

     Parameter   Description
  1  $body       Code to execute with reordered registers
  2  @registers  Registers to reorder

Comment(@comment)

Insert a comment into the assembly code

     Parameter  Description
  1  @comment   Text of comment

Example:

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

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

DComment(@comment)

Insert a comment into the data segment

     Parameter  Description
  1  @comment   Text of comment

RComment(@comment)

Insert a comment into the read only data segment

     Parameter  Description
  1  @comment   Text of comment

Print

Print

PrintNL($channel)

Print a new line to stdout or stderr

     Parameter  Description
  1  $channel   Channel to write on

PrintErrNL()

Print a new line to stderr

PrintOutNL()

Print a new line to stderr

Example:

    my $q = Rs('abababab');
    Mov(rax, "[$q]");
    PrintOutString "rax: ";
    PrintOutRaxInHex;
  
    PrintOutNL;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Xor rax, rax;
    PrintOutString "rax: ";
    PrintOutRaxInHex;
  
    PrintOutNL;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    ok Assemble =~ m(rax: 6261 6261 6261 6261.*rax: 0000 0000 0000 0000)s;
  

PrintString($channel, @string)

Print a constant string to the specified channel

     Parameter  Description
  1  $channel   Channel
  2  @string    Strings

PrintErrString(@string)

Print a constant string to stderr.

     Parameter  Description
  1  @string    String

PrintOutString(@string)

Print a constant string to stdout.

     Parameter  Description
  1  @string    String

PrintErrStringNL(@string)

Print a constant string followed by a new line to stderr

     Parameter  Description
  1  @string    Strings

Example:

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

  
    ok Assemble(debug => 0, eq => <<END);
  Hello World
  Hello
  World
  END
  

PrintOutStringNL(@string)

Print a constant string followed by a new line to stdout

     Parameter  Description
  1  @string    Strings

Example:

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

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

    PrintErrStringNL "Hello World";
  
    ok Assemble(debug => 0, eq => <<END);
  Hello World
  Hello
  World
  END
  

PrintRaxInHex($channel, $end)

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

     Parameter  Description
  1  $channel   Channel
  2  $end       Optional end byte

PrintErrRaxInHex()

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

PrintOutRaxInHex()

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

Example:

    my $q = Rs('abababab');
    Mov(rax, "[$q]");
    PrintOutString "rax: ";
  
    PrintOutRaxInHex;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutNL;
    Xor rax, rax;
    PrintOutString "rax: ";
  
    PrintOutRaxInHex;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutNL;
  
    ok Assemble =~ m(rax: 6261 6261 6261 6261.*rax: 0000 0000 0000 0000)s;
  

PrintOutRaxInReverseInHex()

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

Example:

    Mov rax, 0x07654321;
    Shl rax, 32;
    Or  rax, 0x07654321;
    PushR rax;
  
    PrintOutRaxInHex;
    PrintOutNL;
  
    PrintOutRaxInReverseInHex;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutNL;
    KeepFree rax;
  
    Mov rax, rsp;
    Mov rdi, 8;
    PrintOutMemoryInHex;
    PrintOutNL;
    PopR rax;
    KeepFree rax, rdi;
  
    Mov rax, 4096;
    PushR rax;
    Mov rax, rsp;
    Mov rdi, 8;
    PrintOutMemoryInHex;
    PrintOutNL;
    PopR rax;
  
    is_deeply Assemble, <<END;
  0765 4321 0765 4321
  2143 6507 2143 6507
  2143 6507 2143 6507
  0010 0000 0000 0000
  END
  

PrintRegisterInHex($channel, @r)

Print the named registers as hex strings

     Parameter  Description
  1  $channel   Channel to print on
  2  @r         Names of the registers to print

PrintErrRegisterInHex(@r)

Print the named registers as hex strings on stderr

     Parameter  Description
  1  @r         Names of the registers to print

PrintOutRegisterInHex(@r)

Print the named registers as hex strings on stdout

     Parameter  Description
  1  @r         Names of the registers to print

Example:

    my $q = Rs(('a'..'p')x4);
    Mov r8,"[$q]";
  
    PrintOutRegisterInHex r8;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

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

PrintOutRegistersInHex()

Print the general purpose registers in hex

Example:

    my $q = Rs('abababab');
    Mov(rax, 1);
    Mov(rbx, 2);
    Mov(rcx, 3);
    Mov(rdx, 4);
    Mov(r8,  5);
    Lea r9,  "[rax+rbx]";
  
    PrintOutRegistersInHex;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    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;
  

PrintErrZF()

Print the zero flag without disturbing it on stderr

PrintOutZF()

Print the zero flag without disturbing it on stdout

Example:

    SetZF;
  
    PrintOutZF;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ClearZF;
  
    PrintOutZF;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    SetZF;
  
    PrintOutZF;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    SetZF;
  
    PrintOutZF;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ClearZF;
  
    PrintOutZF;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    ok Assemble =~ m(ZF=1.*ZF=0.*ZF=1.*ZF=1.*ZF=0)s;
  

Variables

Variable definitions and operations

Scopes

Each variable is contained in a scope in an effort to detect references to out of scope variables

Scope($name)

Create and stack a new scope and continue with it as the current scope

     Parameter  Description
  1  $name      Scope name

Example:

  if (1)                                                                              
  
   {my $start = Scope(start);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $s1    = Scope(s1);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $s2    = Scope(s2);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    is_deeply $s2->depth, 2;
    is_deeply $s2->name,  q(s2);
    ScopeEnd;
  
  
    my $t1    = Scope(t1);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $t2    = Scope(t2);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    is_deeply $t1->depth, 2;
    is_deeply $t1->name,  q(t1);
    is_deeply $t2->depth, 3;
    is_deeply $t2->name,  q(t2);
  
    ok  $s1->currentlyVisible;
    ok !$s2->currentlyVisible;
  
    ok  $s1->contains($t2);
    ok !$s2->contains($t2);
  
    ScopeEnd;
  
    is_deeply $s1->depth, 1;
    is_deeply $s1->name,  q(s1);
    ScopeEnd;
   }
  

ScopeEnd()

End the current scope and continue with the containing parent scope

Example:

  if (1)                                                                              
   {my $start = Scope(start);
    my $s1    = Scope(s1);
    my $s2    = Scope(s2);
    is_deeply $s2->depth, 2;
    is_deeply $s2->name,  q(s2);
  
    ScopeEnd;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $t1    = Scope(t1);
    my $t2    = Scope(t2);
    is_deeply $t1->depth, 2;
    is_deeply $t1->name,  q(t1);
    is_deeply $t2->depth, 3;
    is_deeply $t2->name,  q(t2);
  
    ok  $s1->currentlyVisible;
    ok !$s2->currentlyVisible;
  
    ok  $s1->contains($t2);
    ok !$s2->contains($t2);
  
  
    ScopeEnd;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    is_deeply $s1->depth, 1;
    is_deeply $s1->name,  q(s1);
  
    ScopeEnd;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

   }
  

Nasm::X86::Scope::contains($parent, $child)

Check that the named parent scope contains the specified child scope. If no child scope is supplied we use the current scope to check that the parent scope is currently visible

     Parameter  Description
  1  $parent    Parent scope
  2  $child     Child scope

Nasm::X86::Scope::currentlyVisible($scope)

Check that the named parent scope is currently visible

     Parameter  Description
  1  $scope     Scope to check for visibility

Definitions

Variable definitions

Variable($size, $name, $expr, %options)

Create a new variable with the specified size and name initialized via an expression

     Parameter  Description
  1  $size      Size as a power of 2
  2  $name      Name of variable
  3  $expr      Optional expression initializing variable
  4  %options   Options

Vb($name, $expr, %options)

Define a byte variable

     Parameter  Description
  1  $name      Name of variable
  2  $expr      Initializing expression
  3  %options   Options

Vw($name, $expr, %options)

Define a word variable

     Parameter  Description
  1  $name      Name of variable
  2  $expr      Initializing expression
  3  %options   Options

Vd($name, $expr, %options)

Define a double word variable

     Parameter  Description
  1  $name      Name of variable
  2  $expr      Initializing expression
  3  %options   Options

Vq($name, $expr, %options)

Define a quad variable

     Parameter  Description
  1  $name      Name of variable
  2  $expr      Initializing expression
  3  %options   Options

Cq($name, $expr, %options)

Define a quad constant

     Parameter  Description
  1  $name      Name of variable
  2  $expr      Initializing expression
  3  %options   Options

VxyzInit($var, @expr)

Initialize an xyz register from general purpose registers

     Parameter  Description
  1  $var       Variable
  2  @expr      Initializing general purpose registers or undef

Vx($name, @expr)

Define an xmm variable

     Parameter  Description
  1  $name      Name of variable
  2  @expr      Initializing expression

Vy($name, @expr)

Define an ymm variable

     Parameter  Description
  1  $name      Name of variable
  2  @expr      Initializing expression

Vz($name, @expr)

Define an zmm variable

     Parameter  Description
  1  $name      Name of variable
  2  @expr      Initializing expression

Vr($name, $size)

Define a reference variable

     Parameter  Description
  1  $name      Name of variable
  2  $size      Variable being referenced

Operations

Variable operations

Nasm::X86::Variable::address($left, $offset)

Get the address of a variable with an optional offset

     Parameter  Description
  1  $left      Left variable
  2  $offset    Optional offset

Nasm::X86::Variable::copy($left, $right)

Copy one variable into another

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::clone($var)

Clone a variable to create a new variable

     Parameter  Description
  1  $var       Variable to clone

Nasm::X86::Variable::copyAddress($left, $right)

Copy a reference to a variable

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::equals($op, $left, $right)

Equals operator

     Parameter  Description
  1  $op        Operator
  2  $left      Left variable
  3  $right     Right variable

Nasm::X86::Variable::assign($left, $op, $right)

Assign to the left hand side the value of the right hand side

     Parameter  Description
  1  $left      Left variable
  2  $op        Operator
  3  $right     Right variable

Nasm::X86::Variable::plusAssign($left, $right)

Implement plus and assign

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::minusAssign($left, $right)

Implement minus and assign

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::arithmetic($op, $name, $left, $right)

Return a variable containing the result of an arithmetic operation on the left hand and right hand side variables

     Parameter  Description
  1  $op        Operator
  2  $name      Operator name
  3  $left      Left variable
  4  $right     Right variable

Nasm::X86::Variable::add($left, $right)

Add the right hand variable to the left hand variable and return the result as a new variable

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::sub($left, $right)

Subtract the right hand variable from the left hand variable and return the result as a new variable

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::times($left, $right)

Multiply the left hand variable by the right hand variable and return the result as a new variable

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::division($op, $left, $right)

Return a variable containing the result or the remainder that occurs when the left hand side is divided by the right hand side

     Parameter  Description
  1  $op        Operator
  2  $left      Left variable
  3  $right     Right variable

Nasm::X86::Variable::divide($left, $right)

Divide the left hand variable by the right hand variable and return the result as a new variable

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::mod($left, $right)

Divide the left hand variable by the right hand variable and return the remainder as a new variable

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::boolean($sub, $op, $left, $right)

Combine the left hand variable with the right hand variable via a boolean operator

     Parameter  Description
  1  $sub       Operator
  2  $op        Operator name
  3  $left      Left variable
  4  $right     Right variable

Nasm::X86::Variable::eq($left, $right)

Check whether the left hand variable is equal to the right hand variable

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::ne($left, $right)

Check whether the left hand variable is not equal to the right hand variable

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::ge($left, $right)

Check whether the left hand variable is greater than or equal to the right hand variable

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::gt($left, $right)

Check whether the left hand variable is greater than the right hand variable

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::le($left, $right)

Check whether the left hand variable is less than or equal to the right hand variable

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::lt($left, $right)

Check whether the left hand variable is less than the right hand variable

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Print the values of variables or the memory addressed by them

Nasm::X86::Variable::dump($left, $channel, $newLine, $title1, $title2)

Dump the value of a variable to the specified channel adding an optional title and new line if requested

     Parameter  Description
  1  $left      Left variable
  2  $channel   Channel
  3  $newLine   New line required
  4  $title1    Optional leading title
  5  $title2    Optional trailing title

Example:

    my $a = Vq(a, 3); $a->outNL;
    my $b = Vq(b, 2); $b->outNL;
    my $c = $a +  $b; $c->outNL;
    my $d = $c -  $a; $d->outNL;
    my $e = $d == $b; $e->outNL;
    my $f = $d != $b; $f->outNL;
    my $g = $a *  $b; $g->outNL;
    my $h = $g /  $b; $h->outNL;
    my $i = $a %  $b; $i->outNL;
  
    If ($a == 3, sub{PrintOutStringNL "a == 3"});
    ++$a; $a->outNL;
    --$a; $a->outNL;
  
    ok Assemble(debug => 0, eq => <<END);
  a: 0000 0000 0000 0003
  b: 0000 0000 0000 0002
  (a add b): 0000 0000 0000 0005
  ((a add b) sub a): 0000 0000 0000 0002
  (((a add b) sub a) eq b): 0000 0000 0000 0001
  (((a add b) sub a) ne b): 0000 0000 0000 0000
  (a times b): 0000 0000 0000 0006
  ((a times b) / b): 0000 0000 0000 0003
  (a % b): 0000 0000 0000 0001
  a == 3
  a: 0000 0000 0000 0004
  a: 0000 0000 0000 0003
  END
  

Nasm::X86::Variable::err($left, $title1, $title2)

Dump the value of a variable on stderr

     Parameter  Description
  1  $left      Left variable
  2  $title1    Optional leading title
  3  $title2    Optional trailing title

Nasm::X86::Variable::out($left, $title1, $title2)

Dump the value of a variable on stdout

     Parameter  Description
  1  $left      Left variable
  2  $title1    Optional leading title
  3  $title2    Optional trailing title

Nasm::X86::Variable::errNL($left, $title1, $title2)

Dump the value of a variable on stderr and append a new line

     Parameter  Description
  1  $left      Left variable
  2  $title1    Optional leading title
  3  $title2    Optional trailing title

Nasm::X86::Variable::outNL($left, $title1, $title2)

Dump the value of a variable on stdout and append a new line

     Parameter  Description
  1  $left      Left variable
  2  $title1    Optional leading title
  3  $title2    Optional trailing title

Nasm::X86::Variable::debug($left)

Dump the value of a variable on stdout with an indication of where the dump came from

     Parameter  Description
  1  $left      Left variable

Nasm::X86::Variable::isRef($variable)

Check whether the specified variable is a reference to another variable

     Parameter  Description
  1  $variable  Variable

Nasm::X86::Variable::setReg($variable, $register, @registers)

Set the named registers from the content of the variable

     Parameter   Description
  1  $variable   Variable
  2  $register   Register to load
  3  @registers  Optional further registers to load

Nasm::X86::Variable::getReg($variable, $register, @registers)

Load the variable from the named registers

     Parameter   Description
  1  $variable   Variable
  2  $register   Register to load
  3  @registers  Optional further registers to load from

Nasm::X86::Variable::getConst($variable, $constant)

Load the variable from a constant in effect setting a variable to a specified value

     Parameter  Description
  1  $variable  Variable
  2  $constant  Constant to load

Nasm::X86::Variable::incDec($left, $op)

Increment or decrement a variable

     Parameter  Description
  1  $left      Left variable operator
  2  $op        Address of operator to perform inc or dec

Nasm::X86::Variable::inc($left)

Increment a variable

     Parameter  Description
  1  $left      Variable

Nasm::X86::Variable::dec($left)

Decrement a variable

     Parameter  Description
  1  $left      Variable

Nasm::X86::Variable::str($left)

The name of the variable

     Parameter  Description
  1  $left      Variable

Nasm::X86::Variable::min($left, $right)

Minimum of two variables

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Example:

    my $a = Vq("a", 1);
    my $b = Vq("b", 2);
    my $c = $a->min($b);
    my $d = $a->max($b);
    $a->outNL;
    $b->outNL;
    $c->outNL;
    $d->outNL;
  
    is_deeply Assemble,<<END;
  a: 0000 0000 0000 0001
  b: 0000 0000 0000 0002
  Minimum(a, b): 0000 0000 0000 0001
  Maximum(a, b): 0000 0000 0000 0002
  END
  

Nasm::X86::Variable::max($left, $right)

Maximum of two variables

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Example:

    my $a = Vq("a", 1);
    my $b = Vq("b", 2);
    my $c = $a->min($b);
    my $d = $a->max($b);
    $a->outNL;
    $b->outNL;
    $c->outNL;
    $d->outNL;
  
    is_deeply Assemble,<<END;
  a: 0000 0000 0000 0001
  b: 0000 0000 0000 0002
  Minimum(a, b): 0000 0000 0000 0001
  Maximum(a, b): 0000 0000 0000 0002
  END
  

Nasm::X86::Variable::and($left, $right)

And two variables

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::or($left, $right)

Or two variables

     Parameter  Description
  1  $left      Left variable
  2  $right     Right variable

Nasm::X86::Variable::setMask($start, $length, $mask)

Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere

     Parameter  Description
  1  $start     Variable containing start of mask
  2  $length    Variable containing length of mask
  3  $mask      Mask register

Example:

    my $start  = Vq("Start",  7);
    my $length = Vq("Length", 3);
    $start->setMask($length, k7);
    PrintOutRegisterInHex k7;
  
    is_deeply Assemble, <<END;
      k7: 0000 0000 0000 0380
  END
  
    my $z = Vq('zero', 0);
    my $o = Vq('one',  1);
    my $t = Vq('two',  2);
    $z->setMask($o,       k7); PrintOutRegisterInHex k7;
    $z->setMask($t,       k6); PrintOutRegisterInHex k6;
    $z->setMask($o+$t,    k5); PrintOutRegisterInHex k5;
    $o->setMask($o,       k4); PrintOutRegisterInHex k4;
    $o->setMask($t,       k3); PrintOutRegisterInHex k3;
    $o->setMask($o+$t,    k2); PrintOutRegisterInHex k2;
  
    $t->setMask($o,       k1); PrintOutRegisterInHex k1;
    $t->setMask($t,       k0); PrintOutRegisterInHex k0;
  
  
    ok Assemble(debug => 0, eq => <<END);
      k7: 0000 0000 0000 0001
      k6: 0000 0000 0000 0003
      k5: 0000 0000 0000 0007
      k4: 0000 0000 0000 0002
      k3: 0000 0000 0000 0006
      k2: 0000 0000 0000 000E
      k1: 0000 0000 0000 0004
      k0: 0000 0000 0000 000C
  END
  

Nasm::X86::Variable::setMaskFirst($length, $mask)

Set the first bits in the specified mask register

     Parameter  Description
  1  $length    Variable containing length to set
  2  $mask      Mask register

Nasm::X86::Variable::setMaskBit($length, $mask)

Set a bit in the specified mask register retaining the other bits

     Parameter  Description
  1  $length    Variable containing bit position to set
  2  $mask      Mask register

Nasm::X86::Variable::clearMaskBit($length, $mask)

Clear a bit in the specified mask register retaining the other bits

     Parameter  Description
  1  $length    Variable containing bit position to clear
  2  $mask      Mask register

Nasm::X86::Variable::setZmm($source, $zmm, $offset, $length)

Load bytes from the memory addressed by specified source variable into the numbered zmm register at the offset in the specified offset moving the number of bytes in the specified variable

     Parameter  Description
  1  $source    Variable containing the address of the source
  2  $zmm       Number of zmm to load
  3  $offset    Variable containing offset in zmm to move to
  4  $length    Variable containing length of move

Example:

    my $s = Rb(0..128);
    my $source = Vq(Source, $s);
  
    if (1)                                                                        # First block
     {my $offset = Vq(Offset, 7);
      my $length = Vq(Length, 3);
      $source->setZmm(0, $offset, $length);
     }
  
    if (1)                                                                        # Second block
     {my $offset = Vq(Offset, 33);
      my $length = Vq(Length, 12);
      $source->setZmm(0, $offset, $length);
     }
  
    PrintOutRegisterInHex zmm0;
  
    is_deeply Assemble, <<END;
    zmm0: 0000 0000 0000 0000   0000 0000 0000 0000   0000 000B 0A09 0807   0605 0403 0201 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0201   0000 0000 0000 0000
  END
  
    my $a = Vz a, Rb((map {"0x${_}0"} 0..9, 'a'..'f')x4);
    my $b = Vz b, Rb((map {"0x0${_}"} 0..9, 'a'..'f')x4);
  
     $a      ->loadZmm(0);                                                        # Show variable in zmm0
     $b      ->loadZmm(1);                                                        # Show variable in zmm1
  
    ($a + $b)->loadZmm(2);                                                        # Add bytes      and show in zmm2
    ($a - $b)->loadZmm(3);                                                        # Subtract bytes and show in zmm3
  
    PrintOutRegisterInHex "zmm$_" for 0..3;
  
    is_deeply Assemble, <<END;
    zmm0: F0E0 D0C0 B0A0 9080   7060 5040 3020 1000   F0E0 D0C0 B0A0 9080   7060 5040 3020 1000   F0E0 D0C0 B0A0 9080   7060 5040 3020 1000   F0E0 D0C0 B0A0 9080   7060 5040 3020 1000
    zmm1: 0F0E 0D0C 0B0A 0908   0706 0504 0302 0100   0F0E 0D0C 0B0A 0908   0706 0504 0302 0100   0F0E 0D0C 0B0A 0908   0706 0504 0302 0100   0F0E 0D0C 0B0A 0908   0706 0504 0302 0100
    zmm2: FFEE DDCC BBAA 9988   7766 5544 3322 1100   FFEE DDCC BBAA 9988   7766 5544 3322 1100   FFEE DDCC BBAA 9988   7766 5544 3322 1100   FFEE DDCC BBAA 9988   7766 5544 3322 1100
    zmm3: E1D2 C3B4 A596 8778   695A 4B3C 2D1E 0F00   E1D2 C3B4 A596 8778   695A 4B3C 2D1E 0F00   E1D2 C3B4 A596 8778   695A 4B3C 2D1E 0F00   E1D2 C3B4 A596 8778   695A 4B3C 2D1E 0F00
  END
  

Nasm::X86::Variable::loadZmm($source, $zmm)

Load bytes from the memory addressed by the specified source variable into the numbered zmm register.

     Parameter  Description
  1  $source    Variable containing the address of the source
  2  $zmm       Number of zmm to get

Nasm::X86::Variable::saveZmm2222($target, $zmm)

Save bytes into the memory addressed by the target variable from the numbered zmm register.

     Parameter  Description
  1  $target    Variable containing the address of the source
  2  $zmm       Number of zmm to put

getBwdqFromMm($size, $mm, $offset)

Get the numbered byte|word|double word|quad word from the numbered zmm register and return it in a variable

     Parameter  Description
  1  $size      Size of get
  2  $mm        Register
  3  $offset    Offset in bytes either as a constant or as a variable

getBFromXmm($xmm, $offset)

Get the byte from the numbered xmm register and return it in a variable

     Parameter  Description
  1  $xmm       Numbered xmm
  2  $offset    Offset in bytes

getWFromXmm($xmm, $offset)

Get the word from the numbered xmm register and return it in a variable

     Parameter  Description
  1  $xmm       Numbered xmm
  2  $offset    Offset in bytes

getDFromXmm($xmm, $offset)

Get the double word from the numbered xmm register and return it in a variable

     Parameter  Description
  1  $xmm       Numbered xmm
  2  $offset    Offset in bytes

getQFromXmm($xmm, $offset)

Get the quad word from the numbered xmm register and return it in a variable

     Parameter  Description
  1  $xmm       Numbered xmm
  2  $offset    Offset in bytes

getBFromZmm($zmm, $offset)

Get the byte from the numbered zmm register and return it in a variable

     Parameter  Description
  1  $zmm       Numbered zmm
  2  $offset    Offset in bytes

getWFromZmm($zmm, $offset)

Get the word from the numbered zmm register and return it in a variable

     Parameter  Description
  1  $zmm       Numbered zmm
  2  $offset    Offset in bytes

getDFromZmm($zmm, $offset)

Get the double word from the numbered zmm register and return it in a variable

     Parameter  Description
  1  $zmm       Numbered zmm
  2  $offset    Offset in bytes

Example:

    my $s = Rb(0..8);
    my $c = Vq("Content",   "[$s]");
       $c->putBIntoZmm(0,  4);
       $c->putWIntoZmm(0,  6);
       $c->putDIntoZmm(0, 10);
       $c->putQIntoZmm(0, 16);
    PrintOutRegisterInHex zmm0;
    getBFromZmm(0, 12)->outNL;
    getWFromZmm(0, 12)->outNL;
  
    getDFromZmm(0, 12)->outNL;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    getQFromZmm(0, 12)->outNL;
  
    is_deeply Assemble, <<END;
    zmm0: 0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0706 0504 0302 0100   0000 0302 0100 0000   0100 0000 0000 0000
  b at offset 12 in zmm0: 0000 0000 0000 0002
  w at offset 12 in zmm0: 0000 0000 0000 0302
  d at offset 12 in zmm0: 0000 0000 0000 0302
  q at offset 12 in zmm0: 0302 0100 0000 0302
  END
  

getQFromZmm($zmm, $offset)

Get the quad word from the numbered zmm register and return it in a variable

     Parameter  Description
  1  $zmm       Numbered zmm
  2  $offset    Offset in bytes

Nasm::X86::Variable::getBFromZmm($variable, $zmm, $offset)

Get the byte from the numbered zmm register and put it in a variable

     Parameter  Description
  1  $variable  Variable
  2  $zmm       Numbered zmm
  3  $offset    Offset in bytes

Nasm::X86::Variable::getWFromZmm($variable, $zmm, $offset)

Get the word from the numbered zmm register and put it in a variable

     Parameter  Description
  1  $variable  Variable
  2  $zmm       Numbered zmm
  3  $offset    Offset in bytes

Nasm::X86::Variable::getDFromZmm($variable, $zmm, $offset)

Get the double word from the numbered zmm register and put it in a variable

     Parameter  Description
  1  $variable  Variable
  2  $zmm       Numbered zmm
  3  $offset    Offset in bytes

Nasm::X86::Variable::getQFromZmm($variable, $zmm, $offset)

Get the quad word from the numbered zmm register and put it in a variable

     Parameter  Description
  1  $variable  Variable
  2  $zmm       Numbered zmm
  3  $offset    Offset in bytes

Nasm::X86::Variable::putBwdqIntoMm($content, $size, $mm, $offset)

Place the value of the content variable at the byte|word|double word|quad word in the numbered zmm register

     Parameter  Description
  1  $content   Variable with content
  2  $size      Size of put
  3  $mm        Numbered zmm
  4  $offset    Offset in bytes

Nasm::X86::Variable::putBIntoXmm($content, $xmm, $offset)

Place the value of the content variable at the byte in the numbered xmm register

     Parameter  Description
  1  $content   Variable with content
  2  $xmm       Numbered xmm
  3  $offset    Offset in bytes

Nasm::X86::Variable::putWIntoXmm($content, $xmm, $offset)

Place the value of the content variable at the word in the numbered xmm register

     Parameter  Description
  1  $content   Variable with content
  2  $xmm       Numbered xmm
  3  $offset    Offset in bytes

Nasm::X86::Variable::putDIntoXmm($content, $xmm, $offset)

Place the value of the content variable at the double word in the numbered xmm register

     Parameter  Description
  1  $content   Variable with content
  2  $xmm       Numbered xmm
  3  $offset    Offset in bytes

Nasm::X86::Variable::putQIntoXmm($content, $xmm, $offset)

Place the value of the content variable at the quad word in the numbered xmm register

     Parameter  Description
  1  $content   Variable with content
  2  $xmm       Numbered xmm
  3  $offset    Offset in bytes

Nasm::X86::Variable::putBIntoZmm($content, $zmm, $offset)

Place the value of the content variable at the byte in the numbered zmm register

     Parameter  Description
  1  $content   Variable with content
  2  $zmm       Numbered zmm
  3  $offset    Offset in bytes

Nasm::X86::Variable::putWIntoZmm($content, $zmm, $offset)

Place the value of the content variable at the word in the numbered zmm register

     Parameter  Description
  1  $content   Variable with content
  2  $zmm       Numbered zmm
  3  $offset    Offset in bytes

Nasm::X86::Variable::putDIntoZmm($content, $zmm, $offset)

Place the value of the content variable at the double word in the numbered zmm register

     Parameter  Description
  1  $content   Variable with content
  2  $zmm       Numbered zmm
  3  $offset    Offset in bytes

Example:

    my $s = Rb(0..8);
    my $c = Vq("Content",   "[$s]");
       $c->putBIntoZmm(0,  4);
       $c->putWIntoZmm(0,  6);
       $c->putDIntoZmm(0, 10);
       $c->putQIntoZmm(0, 16);
    PrintOutRegisterInHex zmm0;
    getBFromZmm(0, 12)->outNL;
    getWFromZmm(0, 12)->outNL;
    getDFromZmm(0, 12)->outNL;
    getQFromZmm(0, 12)->outNL;
  
    is_deeply Assemble, <<END;
    zmm0: 0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0706 0504 0302 0100   0000 0302 0100 0000   0100 0000 0000 0000
  b at offset 12 in zmm0: 0000 0000 0000 0002
  w at offset 12 in zmm0: 0000 0000 0000 0302
  d at offset 12 in zmm0: 0000 0000 0000 0302
  q at offset 12 in zmm0: 0302 0100 0000 0302
  END
  

Nasm::X86::Variable::putQIntoZmm($content, $zmm, $offset)

Place the value of the content variable at the quad word in the numbered zmm register

     Parameter  Description
  1  $content   Variable with content
  2  $zmm       Numbered zmm
  3  $offset    Offset in bytes

Broadcast

Broadcast from a variable into a zmm

Nasm::X86::Variable::zBroadCastD($variable, $zmm)

Broadcast a double word in a variable into the numbered zmm.

     Parameter  Description
  1  $variable  Variable containing value to broadcast
  2  $zmm       Numbered zmm to broadcast to

Stack

Push and pop variables to and from the stack

Nasm::X86::Variable::push($variable)

Push a variable onto the stack

     Parameter  Description
  1  $variable  Variable

Nasm::X86::Variable::pop($variable)

Pop a variable from the stack

     Parameter  Description
  1  $variable  Variable

Memory

Actions on memory described by variables

Nasm::X86::Variable::clearMemory($address, $size)

Clear the memory described in this variable

     Parameter  Description
  1  $address   Address of memory to clear
  2  $size      Size of the memory to clear

Nasm::X86::Variable::copyMemory($target, $source, $size)

Copy from one block of memory to another

     Parameter  Description
  1  $target    Address of target
  2  $source    Address of source
  3  $size      Length to copy

Nasm::X86::Variable::printMemoryInHexNL($address, $channel, $size)

Write the memory addressed by a variable to stdout or stderr

     Parameter  Description
  1  $address   Address of memory
  2  $channel   Channel to print on
  3  $size      Number of bytes to print

Nasm::X86::Variable::printErrMemoryInHexNL($address, $size)

Write the memory addressed by a variable to stderr

     Parameter  Description
  1  $address   Address of memory
  2  $size      Number of bytes to print

Nasm::X86::Variable::printOutMemoryInHexNL($address, $size)

Write the memory addressed by a variable to stdout

     Parameter  Description
  1  $address   Address of memory
  2  $size      Number of bytes to print

Nasm::X86::Variable::freeMemory($address, $size)

Free the memory addressed by this variable for the specified length

     Parameter  Description
  1  $address   Address of memory to free
  2  $size      Size of the memory to free

Example:

    my $N = Vq(size, 2048);
    my $q = Rs('a'..'p');
    AllocateMemory($N, my $address = Vq(address));
  
    Vmovdqu8 xmm0, "[$q]";
    $address->setReg(rax);
    Vmovdqu8 "[rax]", xmm0;
    Mov rdi, 16;
    PrintOutMemory;
    PrintOutNL;
  
    FreeMemory(address => $address, size=> $N);
  
    ok Assemble(eq => <<END);
  abcdefghijklmnop
  END
  

Nasm::X86::Variable::allocateMemory($size)

Allocate the specified amount of memory via mmap and return its address

     Parameter  Description
  1  $size      Size

Structured Programming with variables

Structured programming operations driven off variables.

Nasm::X86::Variable::for($limit, $body)

Iterate the body limit times.

     Parameter  Description
  1  $limit     Limit
  2  $body      Body

Example:

    Vq(limit,10)->for(sub
     {my ($i, $start, $next, $end) = @_;
      $i->outNL;
     });
  
    is_deeply Assemble, <<END;
  index: 0000 0000 0000 0000
  index: 0000 0000 0000 0001
  index: 0000 0000 0000 0002
  index: 0000 0000 0000 0003
  index: 0000 0000 0000 0004
  index: 0000 0000 0000 0005
  index: 0000 0000 0000 0006
  index: 0000 0000 0000 0007
  index: 0000 0000 0000 0008
  index: 0000 0000 0000 0009
  END
  

Stack

Manage data on the stack

Push, Pop, Peek

Generic versions of push, pop, peek

PopR(@r)

Pop registers from the stack

     Parameter  Description
  1  @r         Register

Example:

    Mov rax, 0x11111111;
    Mov rbx, 0x22222222;
    PushR my @save = (rax, rbx);
    Mov rax, 0x33333333;
  
    PopR @save;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
    PrintOutRegisterInHex rbx;
  
    is_deeply Assemble,<<END;
     rax: 0000 0000 1111 1111
     rbx: 0000 0000 2222 2222
  END
  

PopEax()

We cannot pop a double word from the stack in 64 bit long mode using pop so we improvise

Example:

    Mov r14, 0;
    Kmovq k0, r14;
    KeepFree r14;
    Ktestq k0, k0;
    IfZ {PrintOutStringNL "0 & 0 == 0"};
    PrintOutZF;
  
    LoadConstantIntoMaskRegister k1, 1;
    Ktestq k1, k1;
    IfNz {PrintOutStringNL "1 & 1 != 0"};
    PrintOutZF;
  
    LoadConstantIntoMaskRegister k2, eval "0b".(('1'x4).('0'x4))x2;
  
    PrintOutRegisterInHex k0, k1, k2;
  
    Mov  r15, 0x89abcdef;
    Mov  r14, 0x01234567;
    Shl  r14, 32;
    Or r15, r14;
    Push r15;
    Push r15;
    KeepFree r15;
  
    PopEax;  PrintRaxInHex($stdout, 3); PrintOutNL; KeepFree rax;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $a = Vq('aaaa');
    $a->pop;
    $a->push;
    $a->outNL;
  
  
    PopEax;  PrintRaxInHex($stdout, 3); PrintOutNL; KeepFree rax;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    ok Assemble(debug => 0, eq => <<END);
  0 & 0 == 0
  ZF=1
  1 & 1 != 0
  ZF=0
      k0: 0000 0000 0000 0000
      k1: 0000 0000 0000 0001
      k2: 0000 0000 0000 F0F0
  89AB CDEF
  aaaa: 89AB CDEF 0123 4567
  0123 4567
  END
  

PeekR($r)

Peek at register on stack

     Parameter  Description
  1  $r         Register

Declarations

Declare variables and structures

Structures

Declare a structure

Structure()

Create a structure addressed by a register

Nasm::X86::Structure::field($structure, $length, $comment)

Add a field of the specified length with an optional comment

     Parameter   Description
  1  $structure  Structure data descriptor
  2  $length     Length of data
  3  $comment    Optional comment

Nasm::X86::StructureField::addr($field, $register)

Address a field in a structure by either the default register or the named register

     Parameter  Description
  1  $field     Field
  2  $register  Optional address register else rax

All8Structure($N)

Create a structure consisting of 8 byte fields

     Parameter  Description
  1  $N         Number of variables required

Stack Frame

Declare local variables in a frame on the stack

LocalData()

Map local data

Nasm::X86::LocalData::start($local)

Start a local data area on the stack

     Parameter  Description
  1  $local     Local data descriptor

Nasm::X86::LocalData::free($local)

Free a local data area on the stack

     Parameter  Description
  1  $local     Local data descriptor

Nasm::X86::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

Nasm::X86::LocalVariable::stack($variable)

Address a local variable on the stack

     Parameter  Description
  1  $variable  Variable

Nasm::X86::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

AllocateAll8OnStack($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

Operating system

Interacting with the operating system.

Processes

Create and manage processes

Fork()

Fork

Example:

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

  
    Test rax,rax;
    IfNz                                                                          # Parent
     {Mov rbx, rax;
      WaitPid;
      PrintOutRegisterInHex rax;
      PrintOutRegisterInHex rbx;
      KeepFree rax;
      GetPid;                                                                     # Pid of parent as seen in parent
      Mov rcx,rax;
      PrintOutRegisterInHex rcx;
     }
    sub                                                                           # Child
     {Mov r8,rax;
      PrintOutRegisterInHex r8;
      KeepFree rax;
      GetPid;                                                                     # Child pid as seen in child
      Mov r9,rax;
      PrintOutRegisterInHex r9;
      KeepFree rax;
      GetPPid;                                                                    # Parent pid as seen in child
      Mov r10,rax;
      PrintOutRegisterInHex r10;
     };
  
    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;
     }
  

GetPid()

Get process identifier

Example:

    Fork;                                                                         # Fork
  
    Test rax,rax;
    IfNz                                                                          # Parent
     {Mov rbx, rax;
      WaitPid;
      PrintOutRegisterInHex rax;
      PrintOutRegisterInHex rbx;
      KeepFree rax;
  
      GetPid;                                                                     # Pid of parent as seen in parent  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Mov rcx,rax;
      PrintOutRegisterInHex rcx;
     }
    sub                                                                           # Child
     {Mov r8,rax;
      PrintOutRegisterInHex r8;
      KeepFree rax;
  
      GetPid;                                                                     # Child pid as seen in child  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Mov r9,rax;
      PrintOutRegisterInHex r9;
      KeepFree rax;
      GetPPid;                                                                    # Parent pid as seen in child
      Mov r10,rax;
      PrintOutRegisterInHex r10;
     };
  
    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;
     }
  

GetPidInHex()

Get process identifier in hex as 8 zero terminated bytes in rax

Example:

    GetPidInHex;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
  
    ok Assemble =~ m(rax: 00);
  

GetPPid()

Get parent process identifier

Example:

    Fork;                                                                         # Fork
  
    Test rax,rax;
    IfNz                                                                          # Parent
     {Mov rbx, rax;
      WaitPid;
      PrintOutRegisterInHex rax;
      PrintOutRegisterInHex rbx;
      KeepFree rax;
      GetPid;                                                                     # Pid of parent as seen in parent
      Mov rcx,rax;
      PrintOutRegisterInHex rcx;
     }
    sub                                                                           # Child
     {Mov r8,rax;
      PrintOutRegisterInHex r8;
      KeepFree rax;
      GetPid;                                                                     # Child pid as seen in child
      Mov r9,rax;
      PrintOutRegisterInHex r9;
      KeepFree rax;
  
      GetPPid;                                                                    # Parent pid as seen in child  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      Mov r10,rax;
      PrintOutRegisterInHex r10;
     };
  
    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;
     }
  

GetUid()

Get userid of current process

Example:

    GetUid;                                                                       # Userid  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
  
    my $r = Assemble;
    ok $r =~ m(rax:( 0000){3});
  

WaitPid()

Wait for the pid in rax to complete

Example:

    Fork;                                                                         # Fork
  
    Test rax,rax;
    IfNz                                                                          # Parent
     {Mov rbx, rax;
  
      WaitPid;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      PrintOutRegisterInHex rax;
      PrintOutRegisterInHex rbx;
      KeepFree rax;
      GetPid;                                                                     # Pid of parent as seen in parent
      Mov rcx,rax;
      PrintOutRegisterInHex rcx;
     }
    sub                                                                           # Child
     {Mov r8,rax;
      PrintOutRegisterInHex r8;
      KeepFree rax;
      GetPid;                                                                     # Child pid as seen in child
      Mov r9,rax;
      PrintOutRegisterInHex r9;
      KeepFree rax;
      GetPPid;                                                                    # Parent pid as seen in child
      Mov r10,rax;
      PrintOutRegisterInHex r10;
     };
  
    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;
     }
  

ReadTimeStampCounter()

Read the time stamp counter and return the time in nanoseconds in rax

Example:

    for(1..10)
  
     {ReadTimeStampCounter;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

      PrintOutRegisterInHex rax;
     }
  
    my @s = split /
/, Assemble;
    my @S = sort @s;
    is_deeply \@s, \@S;
  

Memory

Allocate and print memory

PrintMemoryInHex($channel)

Dump memory from the address in rax for the length in rdi on the specified channel. As this method prints in blocks of 8 up to 7 bytes will be missing from the end unless the length is a multiple of 8 .

     Parameter  Description
  1  $channel   Channel

PrintErrMemoryInHex()

Dump memory from the address in rax for the length in rdi on stderr

PrintOutMemoryInHex()

Dump memory from the address in rax for the length in rdi on stdout

Example:

    Mov rax, 0x07654321;
    Shl rax, 32;
    Or  rax, 0x07654321;
    PushR rax;
  
    PrintOutRaxInHex;
    PrintOutNL;
    PrintOutRaxInReverseInHex;
    PrintOutNL;
    KeepFree rax;
  
    Mov rax, rsp;
    Mov rdi, 8;
  
    PrintOutMemoryInHex;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutNL;
    PopR rax;
    KeepFree rax, rdi;
  
    Mov rax, 4096;
    PushR rax;
    Mov rax, rsp;
    Mov rdi, 8;
  
    PrintOutMemoryInHex;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutNL;
    PopR rax;
  
    is_deeply Assemble, <<END;
  0765 4321 0765 4321
  2143 6507 2143 6507
  2143 6507 2143 6507
  0010 0000 0000 0000
  END
  

PrintErrMemoryInHexNL()

Dump memory from the address in rax for the length in rdi and then print a new line

PrintOutMemoryInHexNL()

Dump memory from the address in rax for the length in rdi and then print a new line

Example:

    my $N = 256;
    my $s = Rb 0..$N-1;
    AllocateMemory(Cq(size, $N), my $a = Vq(address));
    CopyMemory(Vq(source, $s), Vq(size, $N), target => $a);
  
    AllocateMemory(Cq(size, $N), my $b = Vq(address));
    CopyMemory(source => $a, target => $b, Cq(size, $N));
  
    $b->setReg(rax);
    Mov rdi, $N;
  
    PrintOutMemoryInHexNL;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    ok Assemble(debug=>0, eq => <<END);
  0001 0203 0405 06070809 0A0B 0C0D 0E0F1011 1213 1415 16171819 1A1B 1C1D 1E1F2021 2223 2425 26272829 2A2B 2C2D 2E2F3031 3233 3435 36373839 3A3B 3C3D 3E3F4041 4243 4445 46474849 4A4B 4C4D 4E4F5051 5253 5455 56575859 5A5B 5C5D 5E5F6061 6263 6465 66676869 6A6B 6C6D 6E6F7071 7273 7475 76777879 7A7B 7C7D 7E7F8081 8283 8485 86878889 8A8B 8C8D 8E8F9091 9293 9495 96979899 9A9B 9C9D 9E9FA0A1 A2A3 A4A5 A6A7A8A9 AAAB ACAD AEAFB0B1 B2B3 B4B5 B6B7B8B9 BABB BCBD BEBFC0C1 C2C3 C4C5 C6C7C8C9 CACB CCCD CECFD0D1 D2D3 D4D5 D6D7D8D9 DADB DCDD DEDFE0E1 E2E3 E4E5 E6E7E8E9 EAEB ECED EEEFF0F1 F2F3 F4F5 F6F7F8F9 FAFB FCFD FEFF
  END
  

PrintMemory()

Print the memory addressed by rax for a length of rdi on the specified channel

Example:

    ReadFile(Vq(file, Rs($0)), (my $s = Vq(size)), my $a = Vq(address));          # Read file
    $a->setReg(rax);                                                              # Address of file in memory
    $s->setReg(rdi);                                                              # Length  of file in memory
    PrintOutMemory;                                                               # Print contents of memory to stdout
  
    my $r = Assemble;                                                             # Assemble and execute
    ok stringMd5Sum($r) eq fileMd5Sum($0);                                          # Output contains this file
  

PrintErrMemory()

Print the memory addressed by rax for a length of rdi on stderr

PrintOutMemory()

Print the memory addressed by rax for a length of rdi on stdout

Example:

    Comment "Print a string from memory";
    my $s = "Hello World";
    Mov rax, Rs($s);
    Mov rdi, length $s;
  
    PrintOutMemory;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    ok Assemble =~ m(Hello World);
  

PrintErrMemoryNL()

Print the memory addressed by rax for a length of rdi followed by a new line on stderr

PrintOutMemoryNL()

Print the memory addressed by rax for a length of rdi followed by a new line on stdout

AllocateMemory(@variables)

Allocate the specified amount of memory via mmap and return its address

     Parameter   Description
  1  @variables  Parameters

Example:

    my $N = Vq(size, 2048);
    my $q = Rs('a'..'p');
  
    AllocateMemory($N, my $address = Vq(address));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    Vmovdqu8 xmm0, "[$q]";
    $address->setReg(rax);
    Vmovdqu8 "[rax]", xmm0;
    Mov rdi, 16;
    PrintOutMemory;
    PrintOutNL;
  
    FreeMemory(address => $address, size=> $N);
  
    ok Assemble(eq => <<END);
  abcdefghijklmnop
  END
  
    my $N = Vq(size, 4096);                                                       # Size of the initial allocation which should be one or more pages
  
  
    AllocateMemory($N, my $A = Vq(address));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    ClearMemory($N, $A);
  
    $A->setReg(rax);
    $N->setReg(rdi);
    PrintOutMemoryInHexNL;
  
    FreeMemory($N, $A);
  
    ok Assemble(eq => <<END);
  0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  END
  
    my $N = 256;
    my $s = Rb 0..$N-1;
  
    AllocateMemory(Cq(size, $N), my $a = Vq(address));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    CopyMemory(Vq(source, $s), Vq(size, $N), target => $a);
  
  
    AllocateMemory(Cq(size, $N), my $b = Vq(address));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    CopyMemory(source => $a, target => $b, Cq(size, $N));
  
    $b->setReg(rax);
    Mov rdi, $N;
    PrintOutMemoryInHexNL;
  
    ok Assemble(debug=>0, eq => <<END);
  0001 0203 0405 06070809 0A0B 0C0D 0E0F1011 1213 1415 16171819 1A1B 1C1D 1E1F2021 2223 2425 26272829 2A2B 2C2D 2E2F3031 3233 3435 36373839 3A3B 3C3D 3E3F4041 4243 4445 46474849 4A4B 4C4D 4E4F5051 5253 5455 56575859 5A5B 5C5D 5E5F6061 6263 6465 66676869 6A6B 6C6D 6E6F7071 7273 7475 76777879 7A7B 7C7D 7E7F8081 8283 8485 86878889 8A8B 8C8D 8E8F9091 9293 9495 96979899 9A9B 9C9D 9E9FA0A1 A2A3 A4A5 A6A7A8A9 AAAB ACAD AEAFB0B1 B2B3 B4B5 B6B7B8B9 BABB BCBD BEBFC0C1 C2C3 C4C5 C6C7C8C9 CACB CCCD CECFD0D1 D2D3 D4D5 D6D7D8D9 DADB DCDD DEDFE0E1 E2E3 E4E5 E6E7E8E9 EAEB ECED EEEFF0F1 F2F3 F4F5 F6F7F8F9 FAFB FCFD FEFF
  END
  

FreeMemory(@variables)

Free memory

     Parameter   Description
  1  @variables  Variables

Example:

    my $N = Vq(size, 4096);                                                       # Size of the initial allocation which should be one or more pages
  
    AllocateMemory($N, my $A = Vq(address));
  
    ClearMemory($N, $A);
  
    $A->setReg(rax);
    $N->setReg(rdi);
    PrintOutMemoryInHexNL;
  
  
    FreeMemory($N, $A);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    ok Assemble(eq => <<END);
  0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  END
  

ClearMemory(@variables)

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

     Parameter   Description
  1  @variables  Variables

Example:

    my $N = Vq(size, 4096);                                                       # Size of the initial allocation which should be one or more pages
  
    AllocateMemory($N, my $A = Vq(address));
  
  
    ClearMemory($N, $A);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    $A->setReg(rax);
    $N->setReg(rdi);
    PrintOutMemoryInHexNL;
  
    FreeMemory($N, $A);
  
    ok Assemble(eq => <<END);
  0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  END
  

MaskMemory(@variables)

Write the specified byte into locations in the target mask that correspond to the locations in the source that contain the specified byte.

     Parameter   Description
  1  @variables  Variables

MaskMemoryInRange4(@variables)

Write the specified byte into locations in the target mask that correspond to the locations in the source that contain 4 bytes in the specified range.

     Parameter   Description
  1  @variables  Variables

CopyMemory(@variables)

Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi

     Parameter   Description
  1  @variables  Variables

Example:

    my $s = Rb 0; Rb 1; Rw 2; Rd 3;  Rq 4;
    my $t = Db 0; Db 1; Dw 2; Dd 3;  Dq 4;
  
    Vmovdqu8 xmm0, "[$s]";
    Vmovdqu8 xmm1, "[$t]";
    PrintOutRegisterInHex xmm0;
    PrintOutRegisterInHex xmm1;
    Sub rsp, 16;
  
    Mov rax, rsp;                                                                 # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
    Mov rdi, 16;
    Mov rsi, $s;
  
    CopyMemory(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutMemoryInHex;
  
    my $r = Assemble;
    ok $r =~ m(xmm0: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(xmm1: 0000 0000 0000 0004   0000 0003 0002 0100);
    ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
  
    my $N = 256;
    my $s = Rb 0..$N-1;
    AllocateMemory(Cq(size, $N), my $a = Vq(address));
  
    CopyMemory(Vq(source, $s), Vq(size, $N), target => $a);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    AllocateMemory(Cq(size, $N), my $b = Vq(address));
  
    CopyMemory(source => $a, target => $b, Cq(size, $N));  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    $b->setReg(rax);
    Mov rdi, $N;
    PrintOutMemoryInHexNL;
  
    ok Assemble(debug=>0, eq => <<END);
  0001 0203 0405 06070809 0A0B 0C0D 0E0F1011 1213 1415 16171819 1A1B 1C1D 1E1F2021 2223 2425 26272829 2A2B 2C2D 2E2F3031 3233 3435 36373839 3A3B 3C3D 3E3F4041 4243 4445 46474849 4A4B 4C4D 4E4F5051 5253 5455 56575859 5A5B 5C5D 5E5F6061 6263 6465 66676869 6A6B 6C6D 6E6F7071 7273 7475 76777879 7A7B 7C7D 7E7F8081 8283 8485 86878889 8A8B 8C8D 8E8F9091 9293 9495 96979899 9A9B 9C9D 9E9FA0A1 A2A3 A4A5 A6A7A8A9 AAAB ACAD AEAFB0B1 B2B3 B4B5 B6B7B8B9 BABB BCBD BEBFC0C1 C2C3 C4C5 C6C7C8C9 CACB CCCD CECFD0D1 D2D3 D4D5 D6D7D8D9 DADB DCDD DEDFE0E1 E2E3 E4E5 E6E7E8E9 EAEB ECED EEEFF0F1 F2F3 F4F5 F6F7F8F9 FAFB FCFD FEFF
  END
  

Files

Interact with the operating system via files.

OpenRead()

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

Example:

    Mov rax, Rs($0);                                                              # File to read
  
    OpenRead;                                                                     # Open file  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
    CloseFile;                                                                    # Close file
    PrintOutRegisterInHex rax;
    KeepFree rax, rdi;
  
    Mov rax, Rs(my $f = "zzzTemporaryFile.txt");                                  # File to write
    OpenWrite;                                                                    # Open file
    CloseFile;                                                                    # Close file
  
    is_deeply Assemble, <<END;                                                    # Channel  is now used for tracing
     rax: 0000 0000 0000 0004
     rax: 0000 0000 0000 0000
  END
    ok -e $f;                                                                     # Created file
    unlink $f;
  

OpenWrite()

Create the file named by the terminated string addressed by rax for write

Example:

    Mov rax, Rs($0);                                                              # File to read
    OpenRead;                                                                     # Open file
    PrintOutRegisterInHex rax;
    CloseFile;                                                                    # Close file
    PrintOutRegisterInHex rax;
    KeepFree rax, rdi;
  
    Mov rax, Rs(my $f = "zzzTemporaryFile.txt");                                  # File to write
  
    OpenWrite;                                                                    # Open file  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    CloseFile;                                                                    # Close file
  
    is_deeply Assemble, <<END;                                                    # Channel  is now used for tracing
     rax: 0000 0000 0000 0004
     rax: 0000 0000 0000 0000
  END
    ok -e $f;                                                                     # Created file
    unlink $f;
  

CloseFile()

Close the file whose descriptor is in rax

Example:

    Mov rax, Rs($0);                                                              # File to read
    OpenRead;                                                                     # Open file
    PrintOutRegisterInHex rax;
  
    CloseFile;                                                                    # Close file  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
    KeepFree rax, rdi;
  
    Mov rax, Rs(my $f = "zzzTemporaryFile.txt");                                  # File to write
    OpenWrite;                                                                    # Open file
  
    CloseFile;                                                                    # Close file  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    is_deeply Assemble, <<END;                                                    # Channel  is now used for tracing
     rax: 0000 0000 0000 0004
     rax: 0000 0000 0000 0000
  END
    ok -e $f;                                                                     # Created file
    unlink $f;
  

StatSize()

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

Example:

    Mov rax, Rs($0);                                                              # File to stat
  
    StatSize;                                                                     # Stat the file  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    PrintOutRegisterInHex rax;
  
    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(@variables)

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

     Parameter   Description
  1  @variables  Variables

Example:

    ReadFile(Vq(file, Rs($0)), (my $s = Vq(size)), my $a = Vq(address));          # Read file  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $a->setReg(rax);                                                              # Address of file in memory
    $s->setReg(rdi);                                                              # Length  of file in memory
    PrintOutMemory;                                                               # Print contents of memory to stdout
  
    my $r = Assemble;                                                             # Assemble and execute
    ok stringMd5Sum($r) eq fileMd5Sum($0);                                          # Output contains this file
  

executeFileViaBash(@variables)

Execute the file named in the byte string addressed by rax with bash

     Parameter   Description
  1  @variables  Variables

Example:

    my $s = CreateByteString;                                                     # Create a string
    $s->ql(<<END);                                                                # Write code to execute
  #!/usr/bin/bash
  whoami
  ls -la
  pwd
  END
    $s->write         (my $f = Vq('file', Rs("zzz.sh")));                         # Write code to a file
  
    executeFileViaBash($f);                                                       # Execute the file  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    unlinkFile        ($f);                                                       # Delete the file
  
    my $u = qx(whoami); chomp($u);
    ok Assemble(emulator=>0) =~ m($u);                                            # The Intel Software Development Emulator is way too slow on these operations.
  

unlinkFile(@variables)

Unlink the named file

     Parameter   Description
  1  @variables  Variables

Example:

    my $s = CreateByteString;                                                     # Create a string
    $s->ql(<<END);                                                                # Write code to execute
  #!/usr/bin/bash
  whoami
  ls -la
  pwd
  END
    $s->write         (my $f = Vq('file', Rs("zzz.sh")));                         # Write code to a file
    executeFileViaBash($f);                                                       # Execute the file
  
    unlinkFile        ($f);                                                       # Delete the file  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $u = qx(whoami); chomp($u);
    ok Assemble(emulator=>0) =~ m($u);                                            # The Intel Software Development Emulator is way too slow on these operations.
  

Hash functions

Hash functions

Hash()

Hash a string addressed by rax with length held in rdi and return the hash code in r15

Example:

    Mov rax, "[rbp+24]";
    Cstrlen;                                                                      # Length of string to hash
    Mov rdi, r15;
  
    Hash();                                                                       # Hash string  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    PrintOutRegisterInHex r15;
  
    my $e = Assemble keep=>'hash';                                                # Assemble to the specified file name
    ok qx($e "")  =~ m(r15: 0000 3F80 0000 3F80);                                 # Test well known hashes
    ok qx($e "a") =~ m(r15: 0000 3F80 C000 45B2);
  
  
    if (0)                                                                        # Hash various strings  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

     {my %r; my %f; my $count = 0;
      my $N = RegisterSize zmm0;
  
      if (1)                                                                      # Fixed blocks
       {for my $l(qw(a ab abc abcd), 'a a', 'a  a')
         {for my $i(1..$N)
           {my $t = $l x $i;
            last if $N < length $t;
            my $s = substr($t.(' ' x $N), 0, $N);
            next if $f{$s}++;
            my $r = qx($e "$s");
            say STDERR "$count  $r";
            if ($r =~ m(^.*r15:\s*(.*)$)m)
             {push $r{$1}->@*, $s;
              ++$count;
             }
           }
         }
       }
  
      if (1)                                                                      # Variable blocks
       {for my $l(qw(a ab abc abcd), '', 'a a', 'a  a')
         {for my $i(1..$N)
           {my $t = $l x $i;
            next if $f{$t}++;
            my $r = qx($e "$t");
            say STDERR "$count  $r";
            if ($r =~ m(^.*r15:\s*(.*)$)m)
             {push $r{$1}->@*, $t;
              ++$count;
             }
           }
         }
       }
      for my $r(keys %r)
       {delete $r{$r} if $r{$r}->@* < 2;
       }
  
      say STDERR dump(\%r);
      say STDERR "Keys hashed: ", $count;
      confess "Duplicates : ",  scalar keys(%r);
     }
  

Unicode

Convert utf8 to utf32

GetNextUtf8CharAsUtf32(@parameters)

Get the next utf8 encoded character from the addressed memory and return it as a utf32 char

     Parameter    Description
  1  @parameters  Parameters

ConvertUtf8ToUtf32(@parameters)

Convert a string of utf8 to an allocated block of utf32 and return its address and length.

     Parameter    Description
  1  @parameters  Parameters

Example:

    my @p = my ($out, $size, $fail) = (Vq(out), Vq(size), Vq('fail'));
    my $opens = Vq(opens);
    my $class = Vq(class);
  
    my $Chars = Rb(0x24, 0xc2, 0xa2, 0xc9, 0x91, 0xE2, 0x82, 0xAC, 0xF0, 0x90, 0x8D, 0x88);
    my $chars = Vq(chars, $Chars);
  
    GetNextUtf8CharAsUtf32 in=>$chars, @p;                                        # Dollar               UTF-8 Encoding: 0x24                UTF-32 Encoding: 0x00000024
    $out->out('out1 : ');     $size->outNL(' size : ');
  
    GetNextUtf8CharAsUtf32 in=>$chars+1, @p;                                      # Cents                UTF-8 Encoding: 0xC2 0xA2           UTF-32 Encoding: 0x000000a2
    $out->out('out2 : ');     $size->outNL(' size : ');
  
    GetNextUtf8CharAsUtf32 in=>$chars+3, @p;                                      # Alpha                UTF-8 Encoding: 0xC9 0x91           UTF-32 Encoding: 0x00000251
    $out->out('out3 : ');     $size->outNL(' size : ');
  
    GetNextUtf8CharAsUtf32 in=>$chars+5, @p;                                      # Euro                 UTF-8 Encoding: 0xE2 0x82 0xAC      UTF-32 Encoding: 0x000020AC
    $out->out('out4 : ');     $size->outNL(' size : ');
  
    GetNextUtf8CharAsUtf32 in=>$chars+8, @p;                                      # Gothic Letter Hwair  UTF-8 Encoding  0xF0 0x90 0x8D 0x88 UTF-32 Encoding: 0x00010348
    $out->out('out5 : ');     $size->outNL(' size : ');
  
    my $statement = qq(𝖺
 𝑎𝑠𝑠𝑖𝑔𝑛 【【𝖻 𝐩𝐥𝐮𝐬 𝖼】】
AAAAAAAA);                        # A sample sentence to parse
  
    my $s = Cq(statement, Rs($statement));
    my $l = Cq(size,  length($statement));
  
    AllocateMemory($l, my $address = Vq(address));                                # Allocate enough memory for a copy of the string
    CopyMemory(source => $s, target => $address, $l);
  
    GetNextUtf8CharAsUtf32 in=>$address, @p;
    $out->out('outA : ');     $size->outNL(' size : ');
  
    GetNextUtf8CharAsUtf32 in=>$address+4, @p;
    $out->out('outB : ');     $size->outNL(' size : ');
  
    GetNextUtf8CharAsUtf32 in=>$address+5, @p;
    $out->out('outC : ');     $size->outNL(' size : ');
  
    GetNextUtf8CharAsUtf32 in=>$address+30, @p;
    $out->out('outD : ');     $size->outNL(' size : ');
  
    GetNextUtf8CharAsUtf32 in=>$address+35, @p;
    $out->out('outE : ');     $size->outNL(' size : ');
  
    $address->printOutMemoryInHexNL($l);
                                                                                  # Single character classifications
    Cq('newLine', 0x0A)->putBIntoZmm(0, 0);                                       #r 0x0 - open bracket  #r 0x1 - close bracket
    Cq('newLine', 0x02)->putBIntoZmm(0, 3);                                       #r 0x2 - new line,     #r 0x3 - new line acting as a semi-colon
    Cq('space',   0x20)->putBIntoZmm(0, 4);
    Cq('space',   0x05)->putBIntoZmm(0, 7);                                       #r 0x5 - space
  
    my sub pu32($$)                                                               # Print some utf32 characters
     {my ($n, $m) = @_;                                                           # Variable: number of characters to print, variable: address of memory
      $n->for(sub
       {my ($index, $start, $next, $end) = @_;
        my $a = $m + $index * 4;
        $a->setReg(r15);
        KeepFree r15;
        Mov r15d, "[r15]";
        KeepFree r15;
        PrintOutRegisterInHex r15;
       });
     }
  
    if (1)                                                                        # Classify a utf32 string
     {my $a = Dd(0x0001d5ba, 0x00000020, 0x0001d44e, 0x0000000a, 0x0001d5bb, 0x0001d429);
      my $t = Cq('test', $a);
      my $s = Cq('size', 6);
  
      ClassifyCharacters4 address=>$t, size=>$s;
      PrintOutStringNL "Convert some utf8 to utf32";
      pu32($s, $t);
     }
  
  # circledLatinLetter               : assign             ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ
  # mathematicalBold                 : dyad lr 3          𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳𝚨𝚩𝚪𝚫𝚬𝚭𝚮𝚯𝚰𝚱𝚲𝚳𝚴𝚵𝚶𝚷𝚸𝚺𝚻𝚼𝚽𝚾𝚿𝛀𝛂𝛃𝛄𝛅𝛆𝛇𝛈𝛉𝛊𝛋𝛌𝛍𝛎𝛏𝛐𝛑𝛒𝛔𝛕𝛖𝛗𝛘𝛙𝛚𝟊𝟋
  # mathematicalBoldFraktur          :                    𝕬𝕭𝕮𝕯𝕰𝕱𝕲𝕳𝕴𝕵𝕶𝕷𝕸𝕹𝕺𝕻𝕼𝕽𝕾𝕿𝖀𝖁𝖂𝖃𝖄𝖅𝖆𝖇𝖈𝖉𝖊𝖋𝖌𝖍𝖎𝖏𝖐𝖑𝖒𝖓𝖔𝖕𝖖𝖗𝖘𝖙𝖚𝖛𝖜𝖝𝖞𝖟
  # mathematicalBoldItalic           : prefix             𝑨𝑩𝑪𝑫𝑬𝑭𝑮𝑯𝑰𝑱𝑲𝑳𝑴𝑵𝑶𝑷𝑸𝑹𝑺𝑻𝑼𝑽𝑾𝑿𝒀𝒁𝒂𝒃𝒄𝒅𝒆𝒇𝒈𝒉𝒊𝒋𝒌𝒍𝒎𝒏𝒐𝒑𝒒𝒓𝒔𝒕𝒖𝒗𝒘𝒙𝒚𝒛𝜜𝜝𝜞𝜟𝜠𝜡𝜢𝜣𝜤𝜥𝜦𝜧𝜨𝜩𝜪𝜫𝜬𝜮𝜯𝜰𝜱𝜲𝜳𝜴𝜶𝜷𝜸𝜹𝜺𝜻𝜼𝜽𝜾𝜿𝝀𝝁𝝂𝝃𝝄𝝅𝝆𝝈𝝉𝝊𝝋𝝌𝝍𝝎
  # mathematicalBoldScript           :                    𝓐𝓑𝓒𝓓𝓔𝓕𝓖𝓗𝓘𝓙𝓚𝓛𝓜𝓝𝓞𝓟𝓠𝓡𝓢𝓣𝓤𝓥𝓦𝓧𝓨𝓩𝓪𝓫𝓬𝓭𝓮𝓯𝓰𝓱𝓲𝓳𝓴𝓵𝓶𝓷𝓸𝓹𝓺𝓻𝓼𝓽𝓾𝓿𝔀𝔁𝔂𝔃
  # mathematicalDouble-struck        :                    𝔸𝔹𝔻𝔼𝔽𝔾𝕀𝕁𝕂𝕃𝕄𝕆𝕊𝕋𝕌𝕍𝕎𝕏𝕐𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫
  # mathematicalFraktur              :                    𝔄𝔅𝔇𝔈𝔉𝔊𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔𝔖𝔗𝔘𝔙𝔚𝔛𝔜𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷
  # mathematicalItalic               :                    𝐴𝐵𝐶𝐷𝐸𝐹𝐺𝐻𝐼𝐽𝐾𝐿𝑀𝑁𝑂𝑃𝑄𝑅𝑆𝑇𝑈𝑉𝑊𝑋𝑌𝑍𝑎𝑏𝑐𝑑𝑒𝑓𝑔𝑖𝑗𝑘𝑙𝑚𝑛𝑜𝑝𝑞𝑟𝑠𝑡𝑢𝑣𝑤𝑥𝑦𝑧𝛢𝛣𝛤𝛥𝛦𝛧𝛨𝛩𝛪𝛫𝛬𝛭𝛮𝛯𝛰𝛱𝛲𝛴𝛵𝛶𝛷𝛸𝛹𝛺𝛼𝛽𝛾𝛿𝜀𝜁𝜂𝜃𝜄𝜅𝜆𝜇𝜈𝜉𝜊𝜋𝜌𝜎𝜏𝜐𝜑𝜒𝜓𝜔
  # mathematicalMonospace            :                    𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣
  # mathematicalSans-serif           : variable           𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹𝖺𝖻𝖼𝖽𝖾𝖿𝗀𝗁𝗂𝗃𝗄𝗅𝗆𝗇𝗈𝗉𝗊𝗋𝗌𝗍𝗎𝗏𝗐𝗑𝗒𝗓
  # mathematicalSans-serifBold       :                    𝗔𝗕𝗖𝗗𝗘𝗙𝗚𝗛𝗜𝗝𝗞𝗟𝗠𝗡𝗢𝗣𝗤𝗥𝗦𝗧𝗨𝗩𝗪𝗫𝗬𝗭𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇𝝖𝝗𝝘𝝙𝝚𝝛𝝜𝝝𝝞𝝟𝝠𝝡𝝢𝝣𝝤𝝥𝝦𝝨𝝩𝝪𝝫𝝬𝝭𝝮𝝰𝝱𝝲𝝳𝝴𝝵𝝶𝝷𝝸𝝹𝝺𝝻𝝼𝝽𝝾𝝿𝞀𝞂𝞃𝞄𝞅𝞆𝞇𝞈
  # mathematicalSans-serifBoldItalic : postfix            𝘼𝘽𝘾𝘿𝙀𝙁𝙂𝙃𝙄𝙅𝙆𝙇𝙈𝙉𝙊𝙋𝙌𝙍𝙎𝙏𝙐𝙑𝙒𝙓𝙔𝙕𝙖𝙗𝙘𝙙𝙚𝙛𝙜𝙝𝙞𝙟𝙠𝙡𝙢𝙣𝙤𝙥𝙦𝙧𝙨𝙩𝙪𝙫𝙬𝙭𝙮𝙯𝞐𝞑𝞒𝞓𝞔𝞕𝞖𝞗𝞘𝞙𝞚𝞛𝞜𝞝𝞞𝞟𝞠𝞢𝞣𝞤𝞥𝞦𝞧𝞨𝞪𝞫𝞬𝞭𝞮𝞯𝞰𝞱𝞲𝞳𝞴𝞵𝞶𝞷𝞸𝞹𝞺𝞼𝞽𝞾𝞿𝟀𝟁𝟂
  # mathematicalSans-serifItalic     :                    𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘓𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻
  # mathematicalScript               :                    𝒜𝒞𝒟𝒢𝒥𝒦𝒩𝒪𝒫𝒬𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵𝒶𝒷𝒸𝒹𝒻𝒽𝒾𝒿𝓀𝓁𝓂𝓃𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏
  # negativeCircledLatinLetter       :                    🅐🅑🅒🅓🅔🅕🅖🅗🅘🅙🅚🅛🅜🅝🅞🅟🅠🅡🅢🅣🅤🅥🅦🅧🅨🅩
  # negativeSquaredLatinLetter       :                    🅰🅱🅲🅳🅴🅵🅶🅷🅸🅹🅺🅻🅼🅽🅾🅿🆀🆁🆂🆃🆄🆅🆆🆇🆈🆉
  # squaredLatinLetter               :                    🄰🄱🄲🄳🄴🄵🄶🄷🄸🄹🄺🄻🄼🄽🄾🄿🅀🅁🅂🅃🅄🅅🅆🅇🅈🅉🆥
  # semiColon                        : semicolon          ⟢
  
  # Delete following code when the following test is completed
    if (0)                                                                        # Convert utf8 test string to utf32
     {my @p = my ($u32, $size32, $count) = (Vq(u32), Vq(size32), Vq(count));
  
      ClassifyCharacters4 address=>$u32, size=>$count;
  
      PrintOutStringNL "Convert test statement - special characters";
      pu32($count, $u32);
  
      Cq('variable', 0x0)     ->putDIntoZmm(0,  0);                               # Range classifications
      Cq('variable', 0x06)    ->putBIntoZmm(0,  3);                               #r 0x6 - ascii
      Cq('variable', 0x01D5A0)->putDIntoZmm(0,  4);
      Cq('variable', 0x07)    ->putBIntoZmm(0,  7);                               #r 0x7 - variable
      Cq('variable', 0x01D434)->putDIntoZmm(0,  8);
      Cq('variable', 0x08)    ->putBIntoZmm(0, 11);                               #r 0x8 - assign
      Cq('variable', 0x01D400)->putDIntoZmm(0, 12);
      Cq('variable', 0x09)    ->putBIntoZmm(0, 15);                               #r 0x9 -
  
      Cq('variable', 0x7f)    ->putDIntoZmm(1,  0);
      Cq('variable', 0x06)    ->putBIntoZmm(1,  3);
      Cq('variable', 0x01D5D3)->putDIntoZmm(1,  4);
      Cq('variable', 0x07)    ->putBIntoZmm(1,  7);
      Cq('variable', 0x01D467)->putDIntoZmm(1,  8);
      Cq('variable', 0x08)    ->putBIntoZmm(1, 11);
      Cq('variable', 0x01D433)->putDIntoZmm(1, 12);
      Cq('variable', 0x09)    ->putBIntoZmm(1, 15);
  
      ClassifyInRange address=>$u32, size=>$count;
  
      PrintOutStringNL "Convert test statement - ranges";
      pu32($count, $u32);
  
      my $bl = Rd(0x10002045, 0x12002329, 0x1400276c, 0x16002770, 0x1c0027e6, 0x24002983, 0x26002987, 0x380029fc, 0x3a003008, 0x3e003010, 0x40003014, 0x4800ff3b, 0x4900ff3d, 0x4a00ff5b, 0x4b00ff5d, 0);
      my $bh = Rd(0x11002046, 0x1300232a, 0x1500276d, 0x1b002775, 0x230027ed, 0x25002984, 0x37002998, 0x390029fd, 0x3d00300b, 0x3f003011, 0x4700301b, 0x4800ff3b, 0x4900ff3d, 0x4a00ff5b, 0x4b00ff5d, 0);
  
      Vmovdqu8 zmm0, "[$bl]";
      Vmovdqu8 zmm1, "[$bh]";
      ClassifyWithInRange address=>$u32, size=>$count;
  
      PrintOutStringNL "Convert test statement - brackets";
      pu32($count, $u32);
  
      MatchBrackets address=>$u32, size=>$count, $opens, $fail;
  
      PrintOutStringNL "Convert test statement - bracket matching";
      pu32($count, $u32);
     }
  
    $address->clearMemory($l);
    $address->printOutMemoryInHexNL($l);
  
    ok Assemble(debug => 0, eq => <<END);
  out1 : 0000 0000 0000 0024 size : 0000 0000 0000 0001
  out2 : 0000 0000 0000 00A2 size : 0000 0000 0000 0002
  out3 : 0000 0000 0000 0251 size : 0000 0000 0000 0002
  out4 : 0000 0000 0000 20AC size : 0000 0000 0000 0003
  out5 : 0000 0000 0001 0348 size : 0000 0000 0000 0004
  outA : 0000 0000 0001 D5BA size : 0000 0000 0000 0004
  outB : 0000 0000 0000 000A size : 0000 0000 0000 0001
  outC : 0000 0000 0000 0020 size : 0000 0000 0000 0001
  outD : 0000 0000 0000 0020 size : 0000 0000 0000 0001
  outE : 0000 0000 0000 0010 size : 0000 0000 0000 0002
  F09D 96BA 0A20 F09D918E F09D 91A0 F09D91A0 F09D 9196 F09D9194 F09D 919B 20E38090 E380 90F0 9D96BB20 F09D 90A9 F09D90A5 F09D 90AE F09D90AC 20F0 9D96 BCE38091 E380 910A 4141
  Convert some utf8 to utf32
     r15: 0000 0000 0001 D5BA
     r15: 0000 0000 0500 0020
     r15: 0000 0000 0001 D44E
     r15: 0000 0000 0200 000A
     r15: 0000 0000 0001 D5BB
     r15: 0000 0000 0001 D429
  0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  END
  

ClassifyCharacters4(@parameters)

Classify the utf32 characters in a block of memory of specified length using the classification held in zmm0: zmm0 should be formatted in double words with each word having the classification in the highest 8 bits and the utf32 character so classified in the lower 21 bits. The classification bits are copied into the high unused) byte of each utf32 character in the block of memory.

     Parameter    Description
  1  @parameters  Parameters

ClassifyInRange(@parameters)

Character classification: classify the utf32 characters in a block of memory of specified length using a range specification held in zmm0, zmm1 formatted in double words with each word in zmm1 having the classification in the highest 8 bits and with zmm0 and zmm1 having the utf32 character at the start (zmm0) and end (zmm1) of each range in the lower 21 bits. The classification bits from the first matching range are copied into the high (unused) byte of each utf32 character in the block of memory.

     Parameter    Description
  1  @parameters  Parameters

ClassifyWithInRange(@parameters)

Bracket classification: Classify the utf32 characters in a block of memory of specified length using a range specification held in zmm0, zmm1 formatted in double words with the classification range in the highest 8 bits of zmm0 and zmm1 and the utf32 character at the start (zmm0) and end (zmm1) of each range in the lower 21 bits. The classification bits from the position within the first matching range are copied into the high (unused) byte of each utf32 character in the block of memory.

     Parameter    Description
  1  @parameters  Parameters

ClassifyWithInRangeAndSaveOffset(@parameters)

Alphabetic classification: classify the utf32 characters in a block of memory of specified length using a range specification held in zmm0, zmm1 formatted in double words with the classification code in the high byte of zmm1 and the offset of the first element in the range in the high byte of zmm0. The lowest 21 bits of each double word in zmm0 and zmm1 contain the utf32 characters marking the start and end of each range. The classification bits from zmm1 for the first matching range are copied into the high byte of each utf32 character in the block of memory. The offset in the range is copied into the lowest byte of each utf32 character in the block of memory. The middle two bytes are cleared. The net effect is to reduce 21 bits of utf32 to 16 bits.

     Parameter    Description
  1  @parameters  Parameters

MatchBrackets(@parameters)

Replace the low three bytes of a utf32 bracket character with 24 bits of offset to the matching opening or closing bracket. Opening brackets have even codes from 0x10 to 0x4e while the corresponding closing bracket has a code one higher.

     Parameter    Description
  1  @parameters  Parameters

PrintUtf32($n, $m)

Print the specified number of utf32 characters at the specified address

     Parameter  Description
  1  $n         Variable: number of characters to print
  2  $m         Variable: address of memory

Short Strings

Operations on Short Strings

LoadShortStringFromMemoryToZmm2($zmm)

Load the short string addressed by rax into the zmm register with the specified number

     Parameter  Description
  1  $zmm       Zmm register to load

LoadShortStringFromMemoryToZmm($zmm, $address)

Load the short string addressed by rax into the zmm register with the specified number

     Parameter  Description
  1  $zmm       Zmm register to load
  2  $address   Address of string in memory

Example:

    my $s = Rb(3, 0x01, 0x02, 0x03);
    my $t = Rb(7, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a);
  
  
    LoadShortStringFromMemoryToZmm 0, $s;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    LoadShortStringFromMemoryToZmm 1, $t;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    ConcatenateShortStrings(0, 1);
    PrintOutRegisterInHex xmm0;
    PrintOutRegisterInHex xmm1;
  
    my $r = Assemble;
    ok $r =~ m(xmm0: 0000 0000 000A 0908   0706 0504 0302 010A);
    ok $r =~ m(xmm1: 0000 0000 0000 0000   0A09 0807 0605 0407);
  

GetLengthOfShortString($reg, $zmm)

Get the length of the short string held in the numbered zmm register into the specified register

     Parameter  Description
  1  $reg       Register to hold length
  2  $zmm       Number of zmm register containing string

SetLengthOfShortString($zmm, $reg)

Set the length of the short string held in the numbered zmm register into the specified register

     Parameter  Description
  1  $zmm       Number of zmm register containing string
  2  $reg       Register to hold length

ConcatenateShortStrings($left, $right)

Concatenate the numbered source zmm containing a short string with the short string in the numbered target zmm.

     Parameter  Description
  1  $left      Target zmm
  2  $right     Source zmm

Byte Strings

Operations on Byte Strings

StringLength(@parameters)

Length of a zero terminated string

     Parameter    Description
  1  @parameters  Parameters

Example:

    StringLength(Vq(string, Rs("abcd")))->outNL;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Assemble(debug => 0, eq => <<END);
  size: 0000 0000 0000 0004
  END
  

CreateByteString(%options)

Create an relocatable string of bytes in an arena and returns its address in rax. Optionally add a chain header so that 64 byte blocks of memory can be freed and reused within the byte string.

     Parameter  Description
  1  %options   Free=>1 adds a free chain.

Example:

    my $a = CreateByteString;                                                     # Create a string  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $a->q('aa');
    $a->out;
    PrintOutNL;
    is_deeply Assemble, <<END;                                                    # Assemble and execute
  aa
  END
  
  
    my $a = CreateByteString;                                                     # Create a string  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $b = CreateByteString;                                                     # Create a string  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $a->q('aa');
    $b->q('bb');
    $a->out;
    PrintOutNL;
    $b->out;
    PrintOutNL;
    is_deeply Assemble, <<END;                                                    # Assemble and execute
  aa
  bb
  END
  
  
    my $a = CreateByteString;                                                     # Create a string  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $b = CreateByteString;                                                     # Create a string  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $a->q('aa');
    $a->q('AA');
    $a->out;
    PrintOutNL;
    is_deeply Assemble, <<END;                                                    # Assemble and execute
  aaAA
  END
  
  
    my $a = CreateByteString;                                                     # Create a string  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    my $b = CreateByteString;                                                     # Create a string  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $a->q('aa');
    $b->q('bb');
    $a->q('AA');
    $b->q('BB');
    $a->q('aa');
    $b->q('bb');
    $a->out;
    $b->out;
    PrintOutNL;
    is_deeply Assemble, <<END;                                                    # Assemble and execute
  aaAAaabbBBbb
  END
  
  
    my $a = CreateByteString;                                                     # Create a string  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $a->q('ab');
  
    my $b = CreateByteString;                                                     # Create target byte string  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    $b->append(source=>$a->bs);
    $b->append(source=>$a->bs);
    $a->append(source=>$b->bs);
    $b->append(source=>$a->bs);
    $a->append(source=>$b->bs);
    $b->append(source=>$a->bs);
    $b->append(source=>$a->bs);
    $b->append(source=>$a->bs);
    $b->append(source=>$a->bs);
  
  
    $a->out;   PrintOutNL;                                                        # Print byte string
    $b->out;   PrintOutNL;                                                        # Print byte string
    $a->length(my $sa = Vq(size)); $sa->outNL;
    $b->length(my $sb = Vq(size)); $sb->outNL;
    $a->clear;
    $a->length(my $sA = Vq(size)); $sA->outNL;
    $b->length(my $sB = Vq(size)); $sB->outNL;
  
    is_deeply Assemble, <<END;                                                    # Assemble and execute
  abababababababab
  ababababababababababababababababababababababababababababababababababababab
  size: 0000 0000 0000 0010
  size: 0000 0000 0000 004A
  size: 0000 0000 0000 0000
  size: 0000 0000 0000 004A
  END
  

Nasm::X86::ByteString::chain($byteString, $bs, $variable, @offsets)

Return a variable with the end point of a chain of double words in the byte string starting at the specified variable.

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  $bs          Byte string locator
  3  $variable    Start variable
  4  @offsets     Offsets chain

Example:

    my $format = Rd(map{4*$_+24} 0..64);
  
    my $b = CreateByteString;
    my $a = $b->allocBlock;
    Vmovdqu8 zmm31, "[$format]";
    $b->putBlock($b->bs, $a, 31);
    my $r = $b->chain($b->bs, Vq(start, 0x18), 4);       $r->outNL("chain1: ");
    my $s = $b->chain($b->bs, $r, 4);                    $s->outNL("chain2: ");
    my $t = $b->chain($b->bs, $s, 4);                    $t->outNL("chain3: ");
    my $A = $b->chain($b->bs, Vq(start, 0x18), 4, 4, 4); $A->outNL("chain4: ");           # Get a long chain
  
    $b->putChain($b->bs, Vq(start, 0x18), Vq(end, 0xff), 4, 4, 4);                # Put at the end of a long chain
  
    $b->dump;
  
    my $sub = Subroutine
     {my ($p) = @_;                                                               # Parameters
      If ($$p{c} == -1,
        sub {PrintOutStringNL "C is minus one"},
        sub {PrintOutStringNL "C is NOT minus one"},
       );
      If ($$p{d} == -1,
        sub {PrintOutStringNL "D is minus one"},
        sub {PrintOutStringNL "D is NOT minus one"},
       );
  
      my $C = $$p{c}->clone;
      $C->outNL;
  
      $$p{e} += 1;
      $$p{e}->outNL('E: ');
  
      $$p{f}->outNL('F1: ');
      $$p{f}++;
      $$p{f}->outNL('F2: ');
     } name=> 'aaa', in => {c => 3}, io => {d => 3, e => 3, f => 3};
  
    my $c = Cq(c, -1);
    my $d = Cq(d, -1);
    my $e = Vq(e,  1);
    my $f = Vq(f,  2);
  
    $sub->call($c, $d, $e, $f);
    $f->outNL('F3: ');
  
    ok Assemble(debug => 0, eq => <<END);
  chain1: 0000 0000 0000 001C
  chain2: 0000 0000 0000 0020
  chain3: 0000 0000 0000 0024
  chain4: 0000 0000 0000 0024
  Byte String
    Size: 0000 0000 0000 1000
    Used: 0000 0000 0000 0058
  0000: 0010 0000 0000 00005800 0000 0000 00000000 0000 0000 00001800 0000 1C00 00002000 0000 FF00 00002800 0000 2C00 00003000 0000 3400 00003800 0000 3C00 0000
  0040: 4000 0000 4400 00004800 0000 4C00 00005000 0000 5400 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  C is minus one
  D is minus one
  Clone of c: FFFF FFFF FFFF FFFF
  E: 0000 0000 0000 0002
  F1: 0000 0000 0000 0002
  F2: 0000 0000 0000 0003
  F3: 0000 0000 0000 0003
  END
  

Nasm::X86::ByteString::putChain($byteString, $bs, $start, $value, @offsets)

Write the double word in the specified variable to the double word location at the the specified offset in the specified byte string.

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  $bs          Byte string locator variable
  3  $start       Start variable
  4  $value       Value to put as a variable
  5  @offsets     Offsets chain

Nasm::X86::ByteString::length($byteString, @variables)

Get the length of a byte string

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  @variables   Variables

Nasm::X86::ByteString::makeReadOnly($byteString)

Make a byte string read only

     Parameter    Description
  1  $byteString  Byte string descriptor

Nasm::X86::ByteString::makeWriteable($byteString)

Make a byte string writable

     Parameter    Description
  1  $byteString  Byte string descriptor

Nasm::X86::ByteString::allocate($byteString, @variables)

Allocate the amount of space indicated in rdi in the byte string addressed by rax and return the offset of the allocation in the arena in rdi

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  @variables   Variables

Nasm::X86::ByteString::blockSize($byteString)

Size of a block

     Parameter    Description
  1  $byteString  Byte string

Nasm::X86::ByteString::allocZmmBlock($byteString, @variables)

Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable

     Parameter    Description
  1  $byteString  Byte string
  2  @variables   Variables

Nasm::X86::ByteString::allocBlock($byteString)

Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable

     Parameter    Description
  1  $byteString  Byte string

Example:

    my $a = CreateByteString; $a->dump;
    my $b1 = $a->allocBlock;  $a->dump;
    my $b2 = $a->allocBlock;  $a->dump;
    $a->freeBlock($b2);       $a->dump;
    $a->freeBlock($b1);       $a->dump;
  
    ok Assemble(debug => 0, eq => <<END);
  Byte String
    Size: 0000 0000 0000 1000
    Used: 0000 0000 0000 0018
  0000: 0010 0000 0000 00001800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  Byte String
    Size: 0000 0000 0000 1000
    Used: 0000 0000 0000 0058
  0000: 0010 0000 0000 00005800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  Byte String
    Size: 0000 0000 0000 1000
    Used: 0000 0000 0000 0098
  0000: 0010 0000 0000 00009800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  Byte String
    Size: 0000 0000 0000 1000
    Used: 0000 0000 0000 0098
  0000: 0010 0000 0000 00009800 0000 0000 00005800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  Byte String
    Size: 0000 0000 0000 1000
    Used: 0000 0000 0000 0098
  0000: 0010 0000 0000 00009800 0000 0000 00001800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 5800 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  END
  

Nasm::X86::ByteString::freeBlock($byteString, @variables)

Free a block in a byte string by placing it on the free chain

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  @variables   Variables

Example:

    my $a = CreateByteString; $a->dump;
    my $b1 = $a->allocBlock;  $a->dump;
    my $b2 = $a->allocBlock;  $a->dump;
    $a->freeBlock($b2);       $a->dump;
    $a->freeBlock($b1);       $a->dump;
  
    ok Assemble(debug => 0, eq => <<END);
  Byte String
    Size: 0000 0000 0000 1000
    Used: 0000 0000 0000 0018
  0000: 0010 0000 0000 00001800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  Byte String
    Size: 0000 0000 0000 1000
    Used: 0000 0000 0000 0058
  0000: 0010 0000 0000 00005800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  Byte String
    Size: 0000 0000 0000 1000
    Used: 0000 0000 0000 0098
  0000: 0010 0000 0000 00009800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  Byte String
    Size: 0000 0000 0000 1000
    Used: 0000 0000 0000 0098
  0000: 0010 0000 0000 00009800 0000 0000 00005800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  Byte String
    Size: 0000 0000 0000 1000
    Used: 0000 0000 0000 0098
  0000: 0010 0000 0000 00009800 0000 0000 00001800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 5800 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000
  END
  

Nasm::X86::ByteString::getBlock($byteString, $bsa, $block, $zmm)

Get the block with the specified offset in the specified block string and return it in the numbered zmm

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  $bsa         Byte string variable
  3  $block       Offset of the block as a variable
  4  $zmm         Number of zmm register to contain block

Nasm::X86::ByteString::putBlock($byteString, $bsa, $block, $zmm)

Write the numbered zmm to the block at the specified offset in the specified byte string

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  $bsa         Byte string variable
  3  $block       Block in byte string
  4  $zmm         Content variable

Nasm::X86::ByteString::m($byteString, @variables)

Append the content with length rdi addressed by rsi to the byte string addressed by rax

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  @variables   Variables

Nasm::X86::ByteString::q($byteString, $string)

Append a constant string to the byte string

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  $string      String

Nasm::X86::ByteString::ql($byteString, $const)

Append a quoted string containing new line characters to the byte string addressed by rax

     Parameter    Description
  1  $byteString  Byte string
  2  $const       Constant

Nasm::X86::ByteString::char($byteString, $char)

Append a character expressed as a decimal number to the byte string addressed by rax

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  $char        Number of character to be appended

Nasm::X86::ByteString::nl($byteString)

Append a new line to the byte string addressed by rax

     Parameter    Description
  1  $byteString  Byte string descriptor

Nasm::X86::ByteString::z($byteString)

Append a trailing zero to the byte string addressed by rax

     Parameter    Description
  1  $byteString  Byte string descriptor

Nasm::X86::ByteString::append($byteString, @variables)

Append one byte string to another

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  @variables   Variables

Nasm::X86::ByteString::clear($byteString)

Clear the byte string addressed by rax

     Parameter    Description
  1  $byteString  Byte string descriptor

Nasm::X86::ByteString::write($byteString, @variables)

Write the content in a byte string addressed by rax to a temporary file and replace the byte string content with the name of the temporary file

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  @variables   Variables

Nasm::X86::ByteString::read($byteString, @variables)

Read the named file (terminated with a zero byte) and place it into the named byte string.

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  @variables   Variables

Nasm::X86::ByteString::out($byteString)

Print the specified byte string addressed by rax on sysout

     Parameter    Description
  1  $byteString  Byte string descriptor

Nasm::X86::ByteString::dump($byteString, $depth)

Dump details of a byte string

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  $depth       Optional amount of memory to dump

Block Strings

Strings made from zmm sized blocks of text

Nasm::X86::ByteString::CreateBlockString($byteString)

Create a string from a doubly link linked list of 64 byte blocks linked via 4 byte offsets in the byte string addressed by rax and return its descriptor

     Parameter    Description
  1  $byteString  Byte string description

Nasm::X86::BlockString::address($blockString)

Address of a block string

     Parameter     Description
  1  $blockString  Block string descriptor

Nasm::X86::BlockString::allocBlock($blockString)

Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable

     Parameter     Description
  1  $blockString  Block string descriptor

Nasm::X86::BlockString::getBlockLength($blockString, $zmm)

Get the block length of the numbered zmm and return it in a variable

     Parameter     Description
  1  $blockString  Block string descriptor
  2  $zmm          Number of zmm register

Nasm::X86::BlockString::setBlockLengthInZmm($blockString, $length, $zmm)

Set the block length of the numbered zmm to the specified length

     Parameter     Description
  1  $blockString  Block string descriptor
  2  $length       Length as a variable
  3  $zmm          Number of zmm register

Nasm::X86::BlockString::getBlock($blockString, $bsa, $block, $zmm)

Get the block with the specified offset in the specified block string and return it in the numbered zmm

     Parameter     Description
  1  $blockString  Block string descriptor
  2  $bsa          Byte string variable
  3  $block        Offset of the block as a variable
  4  $zmm          Number of zmm register to contain block

Nasm::X86::BlockString::putBlock($blockString, $bsa, $block, $zmm)

Write the numbered zmm to the block at the specified offset in the specified byte string

     Parameter     Description
  1  $blockString  Block string descriptor
  2  $bsa          Byte string variable
  3  $block        Block in byte string
  4  $zmm          Content variable

Nasm::X86::BlockString::getNextAndPrevBlockOffsetFromZmm($blockString, $zmm)

Get the offsets of the next and previous blocks as variables from the specified zmm

     Parameter     Description
  1  $blockString  Block string descriptor
  2  $zmm          Zmm containing block

Nasm::X86::BlockString::putNextandPrevBlockOffsetIntoZmm($blockString, $zmm, $next, $prev)

Save next and prev offsets into a zmm representing a block

     Parameter     Description
  1  $blockString  Block string descriptor
  2  $zmm          Zmm containing block
  3  $next         Next offset as a variable
  4  $prev         Prev offset as a variable

Nasm::X86::BlockString::dump($blockString)

Dump a block string to sysout

     Parameter     Description
  1  $blockString  Block string descriptor

Nasm::X86::BlockString::len($blockString, $size)

Find the length of a block string

     Parameter     Description
  1  $blockString  Block string descriptor
  2  $size         Size variable

Nasm::X86::BlockString::concatenate($target, $source)

Concatenate two block strings by appending a copy of the source to the target block string.

     Parameter  Description
  1  $target    Target block string
  2  $source    Source block string

Nasm::X86::BlockString::insertChar($blockString, @variables)

Insert a character into a block string

     Parameter     Description
  1  $blockString  Block string
  2  @variables    Variables

Nasm::X86::BlockString::deleteChar($blockString, @variables)

Delete a character in a block string

     Parameter     Description
  1  $blockString  Block string
  2  @variables    Variables

Nasm::X86::BlockString::getCharacter($blockString, @variables)

Get a character from a block string

     Parameter     Description
  1  $blockString  Block string
  2  @variables    Variables

Nasm::X86::BlockString::append($blockString, @variables)

Append the specified content in memory to the specified block string

     Parameter     Description
  1  $blockString  Block string descriptor
  2  @variables    Variables

Nasm::X86::BlockString::clear($blockString)

Clear the block by freeing all but the first block

     Parameter     Description
  1  $blockString  Block string descriptor

Block Array

Array constructed as a tree of blocks in a byte string

Nasm::X86::ByteString::CreateBlockArray($byteString)

Create a block array in a byte string

     Parameter    Description
  1  $byteString  Byte string description

Nasm::X86::BlockArray::address($blockArray)

Address of a block string

     Parameter    Description
  1  $blockArray  Block array descriptor

Nasm::X86::BlockArray::allocBlock($blockArray)

Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable

     Parameter    Description
  1  $blockArray  Block array descriptor

Nasm::X86::BlockArray::dump($blockArray, @variables)

Dump a block array

     Parameter    Description
  1  $blockArray  Block array descriptor
  2  @variables   Variables

Nasm::X86::BlockArray::push($blockArray, @variables)

Push an element onto the array

     Parameter    Description
  1  $blockArray  Block array descriptor
  2  @variables   Variables

Nasm::X86::BlockArray::pop($blockArray, @variables)

Pop an element from an array

     Parameter    Description
  1  $blockArray  Block array descriptor
  2  @variables   Variables

Nasm::X86::BlockArray::get($blockArray, @variables)

Get an element from the array

     Parameter    Description
  1  $blockArray  Block array descriptor
  2  @variables   Variables

Nasm::X86::BlockArray::put($blockArray, @variables)

Put an element into an array as long as it is with in its limits established by pushing.

     Parameter    Description
  1  $blockArray  Block array descriptor
  2  @variables   Variables

Block Multi Way Tree

Multi Way Tree constructed as a tree of blocks in a byte string

Nasm::X86::ByteString::CreateBlockMultiWayTree($byteString)

Create a block multi way tree in a byte string

     Parameter    Description
  1  $byteString  Byte string description

Example:

    Mov r14, 0;
    Kmovq k0, r14;
    KeepFree r14;
    Ktestq k0, k0;
    IfZ {PrintOutStringNL "0 & 0 == 0"};
    PrintOutZF;
  
    LoadConstantIntoMaskRegister k1, 1;
    Ktestq k1, k1;
    IfNz {PrintOutStringNL "1 & 1 != 0"};
    PrintOutZF;
  
    LoadConstantIntoMaskRegister k2, eval "0b".(('1'x4).('0'x4))x2;
  
    PrintOutRegisterInHex k0, k1, k2;
  
    Mov  r15, 0x89abcdef;
    Mov  r14, 0x01234567;
    Shl  r14, 32;
    Or r15, r14;
    Push r15;
    Push r15;
    KeepFree r15;
    PopEax;  PrintRaxInHex($stdout, 3); PrintOutNL; KeepFree rax;
  
    my $a = Vq('aaaa');
    $a->pop;
    $a->push;
    $a->outNL;
  
    PopEax;  PrintRaxInHex($stdout, 3); PrintOutNL; KeepFree rax;
  
    ok Assemble(debug => 0, eq => <<END);
  0 & 0 == 0
  ZF=1
  1 & 1 != 0
  ZF=0
      k0: 0000 0000 0000 0000
      k1: 0000 0000 0000 0001
      k2: 0000 0000 0000 F0F0
  89AB CDEF
  aaaa: 89AB CDEF 0123 4567
  0123 4567
  END
  

Nasm::X86::BlockMultiWayTree::find($bmt, @variables)

Find a key in a tree and return its associated data

     Parameter   Description
  1  $bmt        Block multi way tree descriptor
  2  @variables  Variables

Nasm::X86::BlockMultiWayTree::insert($bmt, @variables)

Insert a (key, data) pair into the tree

     Parameter   Description
  1  $bmt        Block multi way tree descriptor
  2  @variables  Variables

Nasm::X86::BlockMultiWayTree::getKeysData($bmt, $offset, $zmmKeys, $zmmData)

Load the keys and data blocks for a node

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $offset    Offset as a variable
  3  $zmmKeys   Numbered zmm for keys
  4  $zmmData   Numbered data for keys

Nasm::X86::BlockMultiWayTree::putKeysData($bmt, $offset, $zmmKeys, $zmmData)

Save the key and data blocks for a node

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $offset    Offset as a variable
  3  $zmmKeys   Numbered zmm for keys
  4  $zmmData   Numbered data for keys

Nasm::X86::BlockMultiWayTree::getNode($bmt, $offset, $zmmNode)

Load the child nodes for a node

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $offset    Offset of nodes
  3  $zmmNode   Numbered zmm for keys

Nasm::X86::BlockMultiWayTree::getKeysDataNode($bmt, $offset, $zmmKeys, $zmmData, $zmmNode)

Load the keys, data and child nodes for a node

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $offset    Offset as a variable
  3  $zmmKeys   Numbered zmm for keys
  4  $zmmData   Numbered data for keys
  5  $zmmNode   Numbered numbered for keys

Nasm::X86::BlockMultiWayTree::putKeysDataNode($bmt, $offset, $zmmKeys, $zmmData, $zmmNode)

Save the keys, data and child nodes for a node

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $offset    Offset as a variable
  3  $zmmKeys   Numbered zmm for keys
  4  $zmmData   Numbered data for keys
  5  $zmmNode   Numbered numbered for keys

Nasm::X86::BlockMultiWayTree::getLengthInKeys($bmt, $zmm)

Get the length of the keys block in the numbered zmm and return it as a variable

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $zmm       Zmm number

Nasm::X86::BlockMultiWayTree::putLengthInKeys($bmt, $zmm, $length)

Get the length of the block in the numbered zmm from the specified variable

     Parameter  Description
  1  $bmt       Block multi way tree
  2  $zmm       Zmm number
  3  $length    Length variable

Nasm::X86::BlockMultiWayTree::getUpFromData($bmt, $zmm)

Get the up offset from the data block in the numbered zmm and return it as a variable

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $zmm       Zmm number

Nasm::X86::BlockMultiWayTree::putUpIntoData($bmt, $offset, $zmm)

Put the offset of the parent keys block expressed as a variable into the numbered zmm

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $offset    Variable containing up offset
  3  $zmm       Zmm number

Nasm::X86::BlockMultiWayTree::getLoop($bmt, $zmm)

Return the value of the loop field as a variable

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $zmm       Numbered zmm

Nasm::X86::BlockMultiWayTree::putLoop($bmt, $value, $zmm)

Set the value of the loop field from a variable

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $value     Variable containing offset of next loop entry
  3  $zmm       Numbered zmm

Nasm::X86::BlockMultiWayTree::leftOrRightMost($bmt, $dir, @variables)

Return the left most or right most node

     Parameter   Description
  1  $bmt        Block multi way tree descriptor
  2  $dir        Direction: left = 0 or right = 1
  3  @variables  Variables

Nasm::X86::BlockMultiWayTree::leftMost($bmt, @variables)

Return the left most node

     Parameter   Description
  1  $bmt        Block multi way tree descriptor
  2  @variables  Variables

Nasm::X86::BlockMultiWayTree::rightMost($bmt, @variables)

Return the right most node

     Parameter   Description
  1  $bmt        Block multi way tree descriptor
  2  @variables  Variables

Nasm::X86::BlockMultiWayTree::nodeFromData($bmt, $data, $node)

Load the the node block into the numbered zmm corresponding to the data block held in the numbered zmm.

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $data      Numbered zmm containing data
  3  $node      Numbered zmm to hold node block

Nasm::X86::BlockMultiWayTree::address($bmt)

Address of the byte string containing a block multi way tree

     Parameter  Description
  1  $bmt       Block multi way tree descriptor

Nasm::X86::BlockMultiWayTree::allocBlock($bmt, @variables)

Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable

     Parameter   Description
  1  $bmt        Block multi way tree descriptor
  2  @variables  Variables

Nasm::X86::BlockMultiWayTree::depth($bmt, @variables)

Return the depth of a node within a tree.

     Parameter   Description
  1  $bmt        Block multi way tree descriptor
  2  @variables  Variables

Nasm::X86::BlockMultiWayTree::iterator($b)

Iterate through a multi way tree

     Parameter  Description
  1  $b         Block multi way tree

Nasm::X86::BlockMultiWayTree::Iterator::next($iter)

Next element in the tree

     Parameter  Description
  1  $iter      Iterator

Nasm::X86::BlockMultiWayTree::by($b, $body)

Call the specified body with each (key, data) from the specified tree in order

     Parameter  Description
  1  $b         Block Multi Way Tree descriptor
  2  $body      Body

Assemble

Assemble generated code

CallC($sub, @parameters)

Call a C subroutine

     Parameter    Description
  1  $sub         Name of the sub to call
  2  @parameters  Parameters

Example:

    my $format = Rs "Hello %s
";
    my $data   = Rs "World";
  
    Extern qw(printf exit malloc strcpy); Link 'c';
  
  
    CallC 'malloc', length($format)+1;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov r15, rax;
  
    CallC 'strcpy', r15, $format;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    CallC 'printf', r15, $data;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    CallC 'exit', 0;  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    ok Assemble(eq => <<END);
  Hello World
  END
  

Extern(@externalReferences)

Name external references

     Parameter            Description
  1  @externalReferences  External references

Example:

    my $format = Rs "Hello %s
";
    my $data   = Rs "World";
  
  
    Extern qw(printf exit malloc strcpy); Link 'c';  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    CallC 'malloc', length($format)+1;
    Mov r15, rax;
    CallC 'strcpy', r15, $format;
    CallC 'printf', r15, $data;
    CallC 'exit', 0;
  
    ok Assemble(eq => <<END);
  Hello World
  END
  

Link(@libraries)

Libraries to link with

     Parameter   Description
  1  @libraries  External references

Example:

    my $format = Rs "Hello %s
";
    my $data   = Rs "World";
  
  
    Extern qw(printf exit malloc strcpy); Link 'c';  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  
    CallC 'malloc', length($format)+1;
    Mov r15, rax;
    CallC 'strcpy', r15, $format;
    CallC 'printf', r15, $data;
    CallC 'exit', 0;
  
    ok Assemble(eq => <<END);
  Hello World
  END
  

Start()

Initialize the assembler

Exit($c)

Exit with the specified return code or zero if no return code supplied. Assemble() automatically adds a call to Exit(0) if the last operation in the program is not a call to Exit.

     Parameter  Description
  1  $c         Return code

Assemble(%options)

Assemble the generated code

     Parameter  Description
  1  %options   Options

Example:

    PrintOutStringNL "Hello World";
    PrintOutStringNL "Hello
World";
    PrintErrStringNL "Hello World";
  
  
    ok Assemble(debug => 0, eq => <<END);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

  Hello World
  Hello
  World
  END
  

Hash Definitions

Nasm::X86 Definition

Iterator

Output fields

bs

Byte string definition

constant

Constant if true

count

Counter - number of node

data

Data at this position

depth

Lexical depth of scope

expr

Expression that initializes the variable

first

Variable addressing offset to first block of keys

free

Free chain offset

Offset of header block

key

Key at this position

keys

Offset of keys in header

label

Address in memory

laneSize

Size of the lanes in this variable

length

Offset of length in keys block

Location of links in bytes in zmm

loop

Offset of keys, data, node loop

maxKeys

Maximum number of keys

maxNodes

Maximum number of children per parent.

minKeys

Minimum number of keys

more

Iteration not yet finished

name

Name of the variable

next

Location of next offset in block in bytes

node

Current node within tree

number

Number of this scope

parent

Parent scope

pos

Current position within node

prev

Location of prev offset in block in bytes

purpose

Purpose of this variable

reference

Reference to another variable

saturate

Computations should saturate rather then wrap if true

signed

Elements of x|y|zmm registers are signed if true

size

Size field details

slots1

Number of slots in first block

slots2

Number of slots in second and subsequent blocks

structure

Structure details

tree

Tree we are iterating over

up

Offset of up in data block

used

Used field details

width

Width of a key or data slot

Attributes

The following is a list of all the attributes in this package. A method coded with the same name in your package will over ride the method of the same name in this package and thus provide your value for the attribute in place of the default value supplied for this attribute by this package.

Replaceable Attribute List

Pi32 Pi64

Pi32

Pi as a 32 bit float

Pi64

Pi as a 64 bit float

Private Methods

Label()

Create a unique label

Dbwdq($s, @d)

Layout data

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

Rbwdq($s, @d)

Layout data

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

hexTranslateTable()

Create/address a hex translate table and return its label

PrintOutRipInHex()

Print the instruction pointer in hex

PrintOutRflagsInHex()

Print the flags register in hex

PushRR(@r)

Push registers onto the stack without tracking

     Parameter  Description
  1  @r         Register

PushR(@r)

Push registers onto the stack

     Parameter  Description
  1  @r         Register

Example:

    Mov rax, 0x11111111;
    Mov rbx, 0x22222222;
  
    PushR my @save = (rax, rbx);  # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲

    Mov rax, 0x33333333;
    PopR @save;
    PrintOutRegisterInHex rax;
    PrintOutRegisterInHex rbx;
  
    is_deeply Assemble,<<END;
     rax: 0000 0000 1111 1111
     rbx: 0000 0000 2222 2222
  END
  

PopRR(@r)

Pop registers from the stack without tracking

     Parameter  Description
  1  @r         Register

ClassifyRange($recordOffsetInRange, @parameters)

Implementation of ClassifyInRange and ClassifyWithinRange

     Parameter             Description
  1  $recordOffsetInRange  Record offset in classification in high byte if 1 else in classification if 2
  2  @parameters           Parameters

Cstrlen()

Length of the C style string addressed by rax returning the length in r15

Nasm::X86::ByteString::updateSpace($byteString, @variables)

Make sure that the byte string addressed by rax has enough space to accommodate content of length rdi

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  @variables   Variables

Nasm::X86::ByteString::firstFreeBlock($byteString)

Create and load a variable with the first free block on the free block chain or zero if no such block in the given byte string

     Parameter    Description
  1  $byteString  Byte string address as a variable

Nasm::X86::ByteString::setFirstFreeBlock($byteString, $offset)

Set the first free block field from a variable

     Parameter    Description
  1  $byteString  Byte string descriptor
  2  $offset      First free block offset as a variable

Nasm::X86::BlockMultiWayTree::allocKeysDataNode($bmt, $K, $D, $N, @variables)

Allocate a keys/data/node block and place it in the numbered zmm registers

     Parameter   Description
  1  $bmt        Block multi way tree descriptor
  2  $K          Numbered zmm for keys
  3  $D          Numbered zmm for data
  4  $N          Numbered zmm for children
  5  @variables  Variables

Nasm::X86::BlockMultiWayTree::splitNode($bmt, $bs, $node, $key, @variables)

Split a node given its offset in a byte string retaining the key being inserted in the node split while putting the remainder to the left or right.

     Parameter   Description
  1  $bmt        Block multi way tree descriptor
  2  $bs         Backing byte string
  3  $node       Offset of node
  4  $key        Key
  5  @variables  Variables

Nasm::X86::BlockMultiWayTree::reParent($bmt, $bs, $PK, $PD, $PN, @variables)

Reparent the children of a node held in registers. The children are in the backing byte string not registers.

     Parameter   Description
  1  $bmt        Block multi way tree descriptor
  2  $bs         Backing byte string
  3  $PK         Numbered zmm key node
  4  $PD         Numbered zmm data node
  5  $PN         Numbered zmm child node
  6  @variables  Variables

Nasm::X86::BlockMultiWayTree::splitFullRoot($bmt, $bs)

Split a full root block held in 31..29 and place the left block in 28..26 and the right block in 25..23. The left and right blocks should have their loop offsets set so they can be inserted into the root.

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $bs        Byte string locator

Nasm::X86::BlockMultiWayTree::splitFullLeftNode($bmt, $bs)

Split a full left node block held in 28..26 whose parent is in 31..29 and place the new right block in 25..23. The parent is assumed to be not full. The loop and length fields are assumed to be authoritative and hence are preserved.

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $bs        Byte string locator

Example:

    my $Sk = Rd(17..28, 0, 0, 12,   0xFF);
    my $Sd = Rd(17..28, 0, 0, 0xDD, 0xEE);
    my $Sn = Rd(1..13,     0, 0,    0xCC);
  
    my $sk = Rd(1..14, 14,   0xA1);
    my $sd = Rd(1..14, 0xCC, 0xA2);
    my $sn = Rd(1..15,       0xA3);
  
    my $rk = Rd((0)x14, 14,   0xB1);
    my $rd = Rd((0)x14, 0xCC, 0xB2);
    my $rn = Rd((0)x15,       0xB3);
  
    my $b = CreateByteString;
    my $t = $b->CreateBlockMultiWayTree;
  
    Vmovdqu8 zmm31, "[$Sk]";
    Vmovdqu8 zmm30, "[$Sd]";
    Vmovdqu8 zmm29, "[$Sn]";
  
    Vmovdqu8 zmm28, "[$sk]";
    Vmovdqu8 zmm27, "[$sd]";
    Vmovdqu8 zmm26, "[$sn]";
  
    Vmovdqu8 zmm25, "[$rk]";
    Vmovdqu8 zmm24, "[$rd]";
    Vmovdqu8 zmm23, "[$rn]";
  
     $t->splitFullLeftNode($b->bs);
  
    PrintOutRegisterInHex reverse zmm(23..31);
  
    ok Assemble(debug => 0, eq => <<END);
   zmm31: 0000 00FF 0000 000D   0000 0000 0000 0000   0000 001C 0000 001B   0000 001A 0000 0019   0000 0018 0000 0017   0000 0016 0000 0015   0000 0014 0000 0013   0000 0012 0000 0011
   zmm30: 0000 00EE 0000 00DD   0000 0000 0000 0000   0000 001C 0000 001B   0000 001A 0000 0019   0000 0018 0000 0017   0000 0016 0000 0015   0000 0014 0000 0013   0000 0012 0000 0011
   zmm29: 0000 00CC 0000 0000   0000 0000 0000 000D   0000 000C 0000 000B   0000 000A 0000 0009   0000 0008 0000 0007   0000 0006 0000 0005   0000 0004 0000 0003   0000 0002 0000 0001
   zmm28: 0000 00A1 0000 0007   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0007   0000 0006 0000 0005   0000 0004 0000 0003   0000 0002 0000 0001
   zmm27: 0000 00A2 0000 00CC   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0007   0000 0006 0000 0005   0000 0004 0000 0003   0000 0002 0000 0001
   zmm26: 0000 00A3 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0007   0000 0006 0000 0005   0000 0004 0000 0003   0000 0002 0000 0001
   zmm25: 0000 00B1 0000 0006   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 000E 0000 000D   0000 000C 0000 000B   0000 000A 0000 0009
   zmm24: 0000 00B2 0000 00CC   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 000E 0000 000D   0000 000C 0000 000B   0000 000A 0000 0009
   zmm23: 0000 00B3 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 000E 0000 000D   0000 000C 0000 000B   0000 000A 0000 0009
  END
  

Nasm::X86::BlockMultiWayTree::splitFullRightNode($bmt, $bs)

Split a full right node block held in 25..23 whose parent is in 31..29 and place the new left block in 25..23. The loop and length fields are assumed to be authoritative and hence are preserved.

     Parameter  Description
  1  $bmt       Block multi way tree descriptor
  2  $bs        Byte string locator

Example:

    my $tk = Rd(1..12, 0, 0, 12,      0xC1);
    my $td = Rd(1..12, 0, 0,  0,      0xC2);
    my $tn = Rd(1, 0xBB, 3..13, 0, 0, 0xCC);
  
    my $lk = Rd(17..30, 14,   0xA1);
    my $ld = Rd(17..30, 0xCC, 0xA2);
    my $ln = Rd(17..31,       0xAA);
  
    my $rk = Rd(17..30, 14,   0xB1);
    my $rd = Rd(17..30, 0xCC, 0xB2);
    my $rn = Rd(17..31,       0xBB);
  
    my $b = CreateByteString;
    my $t = $b->CreateBlockMultiWayTree;
  
    Vmovdqu8 zmm31, "[$tk]";
    Vmovdqu8 zmm30, "[$td]";
    Vmovdqu8 zmm29, "[$tn]";
  
    Vmovdqu8 zmm28, "[$lk]";
    Vmovdqu8 zmm27, "[$ld]";
    Vmovdqu8 zmm26, "[$ln]";
  
    Vmovdqu8 zmm25, "[$rk]";
    Vmovdqu8 zmm24, "[$rd]";
    Vmovdqu8 zmm23, "[$rn]";
  
    $t->splitFullRightNode($b->bs);
  
    PrintOutRegisterInHex reverse zmm(23..31);
  
    ok Assemble(debug => 0, eq => <<END);
   zmm31: 0000 00C1 0000 000D   0000 0000 0000 000C   0000 000B 0000 000A   0000 0009 0000 0008   0000 0007 0000 0006   0000 0005 0000 0004   0000 0003 0000 0002   0000 0018 0000 0001
   zmm30: 0000 00C2 0000 0000   0000 0000 0000 000C   0000 000B 0000 000A   0000 0009 0000 0008   0000 0007 0000 0006   0000 0005 0000 0004   0000 0003 0000 0002   0000 0018 0000 0001
   zmm29: 0000 00CC 0000 0000   0000 000D 0000 000C   0000 000B 0000 000A   0000 0009 0000 0008   0000 0007 0000 0006   0000 0005 0000 0004   0000 0003 0000 00BB   0000 00AA 0000 0001
   zmm28: 0000 00A1 0000 0007   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0017   0000 0016 0000 0015   0000 0014 0000 0013   0000 0012 0000 0011
   zmm27: 0000 00A2 0000 00CC   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0017   0000 0016 0000 0015   0000 0014 0000 0013   0000 0012 0000 0011
   zmm26: 0000 00AA 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0017   0000 0016 0000 0015   0000 0014 0000 0013   0000 0012 0000 0011
   zmm25: 0000 00B1 0000 0006   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 001E 0000 001D   0000 001C 0000 001B   0000 001A 0000 0019
   zmm24: 0000 00B2 0000 00CC   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 001E 0000 001D   0000 001C 0000 001B   0000 001A 0000 0019
   zmm23: 0000 00BB 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 0000 0000 0000   0000 001E 0000 001D   0000 001C 0000 001B   0000 001A 0000 0019
  END
  

Nasm::X86::BlockMultiWayTree::findAndSplit($bmt, @variables)

Find a key in a tree which is known to contain at least one key splitting full nodes along the path to the key.

     Parameter   Description
  1  $bmt        Block multi way tree descriptor
  2  @variables  Variables

LocateIntelEmulator()

Locate the Intel Software Development Emulator

removeNonAsciiChars($string)

Return a copy of the specified string with all the non ascii characters removed

     Parameter  Description
  1  $string    String

totalBytesAssembled()

Total size in bytes of all files assembled during testing

Index

1 All8Structure - Create a structure consisting of 8 byte fields

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

3 AllocateMemory - Allocate the specified amount of memory via mmap and return its address

4 Assemble - Assemble the generated code

5 Block - Execute a block of code one with the option of jumping out of the block or restarting the block via the supplied labels.

6 CallC - Call a C subroutine

7 ClassifyCharacters4 - Classify the utf32 characters in a block of memory of specified length using the classification held in zmm0: zmm0 should be formatted in double words with each word having the classification in the highest 8 bits and the utf32 character so classified in the lower 21 bits.

8 ClassifyInRange - Character classification: classify the utf32 characters in a block of memory of specified length using a range specification held in zmm0, zmm1 formatted in double words with each word in zmm1 having the classification in the highest 8 bits and with zmm0 and zmm1 having the utf32 character at the start (zmm0) and end (zmm1) of each range in the lower 21 bits.

9 ClassifyRange - Implementation of ClassifyInRange and ClassifyWithinRange

10 ClassifyWithInRange - Bracket classification: Classify the utf32 characters in a block of memory of specified length using a range specification held in zmm0, zmm1 formatted in double words with the classification range in the highest 8 bits of zmm0 and zmm1 and the utf32 character at the start (zmm0) and end (zmm1) of each range in the lower 21 bits.

11 ClassifyWithInRangeAndSaveOffset - Alphabetic classification: classify the utf32 characters in a block of memory of specified length using a range specification held in zmm0, zmm1 formatted in double words with the classification code in the high byte of zmm1 and the offset of the first element in the range in the high byte of zmm0.

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

13 ClearRegisters - Clear registers by setting them to zero

14 ClearZF - Clear the zero flag

15 CloseFile - Close the file whose descriptor is in rax

16 Comment - Insert a comment into the assembly code

17 ConcatenateShortStrings - Concatenate the numbered source zmm containing a short string with the short string in the numbered target zmm.

18 ConvertUtf8ToUtf32 - Convert a string of utf8 to an allocated block of utf32 and return its address and length.

19 CopyMemory - Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi

20 Cq - Define a quad constant

21 cr - Call a subroutine with a reordering of the registers.

22 CreateByteString - Create an relocatable string of bytes in an arena and returns its address in rax.

23 Cstrlen - Length of the C style string addressed by rax returning the length in r15

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

25 Dbwdq - Layout data

26 DComment - Insert a comment into the data segment

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

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

29 Ds - Layout bytes in memory and return their label

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

31 Else - Else body for an If statement

32 executeFileViaBash - Execute the file named in the byte string addressed by rax with bash

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

34 Extern - Name external references

35 Float32 - 32 bit float

36 Float64 - 64 bit float

37 For - For - iterate the body as long as register is less than limit incrementing by increment each time

38 ForEver - Iterate for ever

39 ForIn - For - iterate the full body as long as register plus increment is less than than limit incrementing by increment each time then increment the last body for the last non full block.

40 Fork - Fork

41 FreeMemory - Free memory

42 getBFromXmm - Get the byte from the numbered xmm register and return it in a variable

43 getBFromZmm - Get the byte from the numbered zmm register and return it in a variable

44 getBwdqFromMm - Get the numbered byte|word|double word|quad word from the numbered zmm register and return it in a variable

45 getDFromXmm - Get the double word from the numbered xmm register and return it in a variable

46 getDFromZmm - Get the double word from the numbered zmm register and return it in a variable

47 GetLengthOfShortString - Get the length of the short string held in the numbered zmm register into the specified register

48 GetNextUtf8CharAsUtf32 - Get the next utf8 encoded character from the addressed memory and return it as a utf32 char

49 GetPid - Get process identifier

50 GetPidInHex - Get process identifier in hex as 8 zero terminated bytes in rax

51 GetPPid - Get parent process identifier

52 getQFromXmm - Get the quad word from the numbered xmm register and return it in a variable

53 getQFromZmm - Get the quad word from the numbered zmm register and return it in a variable

54 GetUid - Get userid of current process

55 getWFromXmm - Get the word from the numbered xmm register and return it in a variable

56 getWFromZmm - Get the word from the numbered zmm register and return it in a variable

57 Hash - Hash a string addressed by rax with length held in rdi and return the hash code in r15

58 hexTranslateTable - Create/address a hex translate table and return its label

59 If - If

60 IfEq - If equal execute the then body else the else body

61 IfGe - If greater than or equal execute the then body else the else body

62 IfGt - If greater than execute the then body else the else body

63 IfLe - If less than or equal execute the then body else the else body

64 IfLt - If less than execute the then body else the else body

65 IfNe - If not equal execute the then body else the else body

66 IfNz - If the zero is not set then execute the then body else the else body

67 IfZ - If the zero is set then execute the then body else the else body

68 Keep - Mark registers as in use so that they cannot be updated until we explicitly free them.

69 KeepFree - Free registers so that they can be reused

70 KeepPop - Reset the status of the specified registers to the status quo ante the last push

71 KeepPush - Push the current status of the specified registers and then mark them as free

72 KeepReturn - Pop the specified register and mark it as in use to effect a subroutine return with this register.

73 KeepSet - Confirm that the specified registers are in use

74 Label - Create a unique label

75 Link - Libraries to link with

76 LoadConstantIntoMaskRegister - Load a constant into a mask register

77 LoadShortStringFromMemoryToZmm - Load the short string addressed by rax into the zmm register with the specified number

78 LoadShortStringFromMemoryToZmm2 - Load the short string addressed by rax into the zmm register with the specified number

79 LocalData - Map local data

80 LocateIntelEmulator - Locate the Intel Software Development Emulator

81 Macro - 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

82 MaskMemory - Write the specified byte into locations in the target mask that correspond to the locations in the source that contain the specified byte.

83 MaskMemoryInRange4 - Write the specified byte into locations in the target mask that correspond to the locations in the source that contain 4 bytes in the specified range.

84 MatchBrackets - Replace the low three bytes of a utf32 bracket character with 24 bits of offset to the matching opening or closing bracket.

85 Nasm::X86::BlockArray::address - Address of a block string

86 Nasm::X86::BlockArray::allocBlock - Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable

87 Nasm::X86::BlockArray::dump - Dump a block array

88 Nasm::X86::BlockArray::get - Get an element from the array

89 Nasm::X86::BlockArray::pop - Pop an element from an array

90 Nasm::X86::BlockArray::push - Push an element onto the array

91 Nasm::X86::BlockArray::put - Put an element into an array as long as it is with in its limits established by pushing.

92 Nasm::X86::BlockMultiWayTree::address - Address of the byte string containing a block multi way tree

93 Nasm::X86::BlockMultiWayTree::allocBlock - Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable

94 Nasm::X86::BlockMultiWayTree::allocKeysDataNode - Allocate a keys/data/node block and place it in the numbered zmm registers

95 Nasm::X86::BlockMultiWayTree::by - Call the specified body with each (key, data) from the specified tree in order

96 Nasm::X86::BlockMultiWayTree::depth - Return the depth of a node within a tree.

97 Nasm::X86::BlockMultiWayTree::find - Find a key in a tree and return its associated data

98 Nasm::X86::BlockMultiWayTree::findAndSplit - Find a key in a tree which is known to contain at least one key splitting full nodes along the path to the key.

99 Nasm::X86::BlockMultiWayTree::getKeysData - Load the keys and data blocks for a node

100 Nasm::X86::BlockMultiWayTree::getKeysDataNode - Load the keys, data and child nodes for a node

101 Nasm::X86::BlockMultiWayTree::getLengthInKeys - Get the length of the keys block in the numbered zmm and return it as a variable

102 Nasm::X86::BlockMultiWayTree::getLoop - Return the value of the loop field as a variable

103 Nasm::X86::BlockMultiWayTree::getNode - Load the child nodes for a node

104 Nasm::X86::BlockMultiWayTree::getUpFromData - Get the up offset from the data block in the numbered zmm and return it as a variable

105 Nasm::X86::BlockMultiWayTree::insert - Insert a (key, data) pair into the tree

106 Nasm::X86::BlockMultiWayTree::iterator - Iterate through a multi way tree

107 Nasm::X86::BlockMultiWayTree::Iterator::next - Next element in the tree

108 Nasm::X86::BlockMultiWayTree::leftMost - Return the left most node

109 Nasm::X86::BlockMultiWayTree::leftOrRightMost - Return the left most or right most node

110 Nasm::X86::BlockMultiWayTree::nodeFromData - Load the the node block into the numbered zmm corresponding to the data block held in the numbered zmm.

111 Nasm::X86::BlockMultiWayTree::putKeysData - Save the key and data blocks for a node

112 Nasm::X86::BlockMultiWayTree::putKeysDataNode - Save the keys, data and child nodes for a node

113 Nasm::X86::BlockMultiWayTree::putLengthInKeys - Get the length of the block in the numbered zmm from the specified variable

114 Nasm::X86::BlockMultiWayTree::putLoop - Set the value of the loop field from a variable

115 Nasm::X86::BlockMultiWayTree::putUpIntoData - Put the offset of the parent keys block expressed as a variable into the numbered zmm

116 Nasm::X86::BlockMultiWayTree::reParent - Reparent the children of a node held in registers.

117 Nasm::X86::BlockMultiWayTree::rightMost - Return the right most node

118 Nasm::X86::BlockMultiWayTree::splitFullLeftNode - Split a full left node block held in 28.

119 Nasm::X86::BlockMultiWayTree::splitFullRightNode - Split a full right node block held in 25.

120 Nasm::X86::BlockMultiWayTree::splitFullRoot - Split a full root block held in 31.

121 Nasm::X86::BlockMultiWayTree::splitNode - Split a node given its offset in a byte string retaining the key being inserted in the node split while putting the remainder to the left or right.

122 Nasm::X86::BlockString::address - Address of a block string

123 Nasm::X86::BlockString::allocBlock - Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable

124 Nasm::X86::BlockString::append - Append the specified content in memory to the specified block string

125 Nasm::X86::BlockString::clear - Clear the block by freeing all but the first block

126 Nasm::X86::BlockString::concatenate - Concatenate two block strings by appending a copy of the source to the target block string.

127 Nasm::X86::BlockString::deleteChar - Delete a character in a block string

128 Nasm::X86::BlockString::dump - Dump a block string to sysout

129 Nasm::X86::BlockString::getBlock - Get the block with the specified offset in the specified block string and return it in the numbered zmm

130 Nasm::X86::BlockString::getBlockLength - Get the block length of the numbered zmm and return it in a variable

131 Nasm::X86::BlockString::getCharacter - Get a character from a block string

132 Nasm::X86::BlockString::getNextAndPrevBlockOffsetFromZmm - Get the offsets of the next and previous blocks as variables from the specified zmm

133 Nasm::X86::BlockString::insertChar - Insert a character into a block string

134 Nasm::X86::BlockString::len - Find the length of a block string

135 Nasm::X86::BlockString::putBlock - Write the numbered zmm to the block at the specified offset in the specified byte string

136 Nasm::X86::BlockString::putNextandPrevBlockOffsetIntoZmm - Save next and prev offsets into a zmm representing a block

137 Nasm::X86::BlockString::setBlockLengthInZmm - Set the block length of the numbered zmm to the specified length

138 Nasm::X86::ByteString::allocate - Allocate the amount of space indicated in rdi in the byte string addressed by rax and return the offset of the allocation in the arena in rdi

139 Nasm::X86::ByteString::allocBlock - Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable

140 Nasm::X86::ByteString::allocZmmBlock - Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable

141 Nasm::X86::ByteString::append - Append one byte string to another

142 Nasm::X86::ByteString::blockSize - Size of a block

143 Nasm::X86::ByteString::chain - Return a variable with the end point of a chain of double words in the byte string starting at the specified variable.

144 Nasm::X86::ByteString::char - Append a character expressed as a decimal number to the byte string addressed by rax

145 Nasm::X86::ByteString::clear - Clear the byte string addressed by rax

146 Nasm::X86::ByteString::CreateBlockArray - Create a block array in a byte string

147 Nasm::X86::ByteString::CreateBlockMultiWayTree - Create a block multi way tree in a byte string

148 Nasm::X86::ByteString::CreateBlockString - Create a string from a doubly link linked list of 64 byte blocks linked via 4 byte offsets in the byte string addressed by rax and return its descriptor

149 Nasm::X86::ByteString::dump - Dump details of a byte string

150 Nasm::X86::ByteString::firstFreeBlock - Create and load a variable with the first free block on the free block chain or zero if no such block in the given byte string

151 Nasm::X86::ByteString::freeBlock - Free a block in a byte string by placing it on the free chain

152 Nasm::X86::ByteString::getBlock - Get the block with the specified offset in the specified block string and return it in the numbered zmm

153 Nasm::X86::ByteString::length - Get the length of a byte string

154 Nasm::X86::ByteString::m - Append the content with length rdi addressed by rsi to the byte string addressed by rax

155 Nasm::X86::ByteString::makeReadOnly - Make a byte string read only

156 Nasm::X86::ByteString::makeWriteable - Make a byte string writable

157 Nasm::X86::ByteString::nl - Append a new line to the byte string addressed by rax

158 Nasm::X86::ByteString::out - Print the specified byte string addressed by rax on sysout

159 Nasm::X86::ByteString::putBlock - Write the numbered zmm to the block at the specified offset in the specified byte string

160 Nasm::X86::ByteString::putChain - Write the double word in the specified variable to the double word location at the the specified offset in the specified byte string.

161 Nasm::X86::ByteString::q - Append a constant string to the byte string

162 Nasm::X86::ByteString::ql - Append a quoted string containing new line characters to the byte string addressed by rax

163 Nasm::X86::ByteString::read - Read the named file (terminated with a zero byte) and place it into the named byte string.

164 Nasm::X86::ByteString::setFirstFreeBlock - Set the first free block field from a variable

165 Nasm::X86::ByteString::updateSpace - Make sure that the byte string addressed by rax has enough space to accommodate content of length rdi

166 Nasm::X86::ByteString::write - Write the content in a byte string addressed by rax to a temporary file and replace the byte string content with the name of the temporary file

167 Nasm::X86::ByteString::z - Append a trailing zero to the byte string addressed by rax

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

169 Nasm::X86::LocalData::free - Free a local data area on the stack

170 Nasm::X86::LocalData::start - Start a local data area on the stack

171 Nasm::X86::LocalData::variable - Add a local variable

172 Nasm::X86::LocalVariable::stack - Address a local variable on the stack

173 Nasm::X86::Scope::contains - Check that the named parent scope contains the specified child scope.

174 Nasm::X86::Scope::currentlyVisible - Check that the named parent scope is currently visible

175 Nasm::X86::Structure::field - Add a field of the specified length with an optional comment

176 Nasm::X86::StructureField::addr - Address a field in a structure by either the default register or the named register

177 Nasm::X86::Sub::call - Call a sub passing it some parameters

178 Nasm::X86::Variable::add - Add the right hand variable to the left hand variable and return the result as a new variable

179 Nasm::X86::Variable::address - Get the address of a variable with an optional offset

180 Nasm::X86::Variable::allocateMemory - Allocate the specified amount of memory via mmap and return its address

181 Nasm::X86::Variable::and - And two variables

182 Nasm::X86::Variable::arithmetic - Return a variable containing the result of an arithmetic operation on the left hand and right hand side variables

183 Nasm::X86::Variable::assign - Assign to the left hand side the value of the right hand side

184 Nasm::X86::Variable::boolean - Combine the left hand variable with the right hand variable via a boolean operator

185 Nasm::X86::Variable::clearMaskBit - Clear a bit in the specified mask register retaining the other bits

186 Nasm::X86::Variable::clearMemory - Clear the memory described in this variable

187 Nasm::X86::Variable::clone - Clone a variable to create a new variable

188 Nasm::X86::Variable::copy - Copy one variable into another

189 Nasm::X86::Variable::copyAddress - Copy a reference to a variable

190 Nasm::X86::Variable::copyMemory - Copy from one block of memory to another

191 Nasm::X86::Variable::debug - Dump the value of a variable on stdout with an indication of where the dump came from

192 Nasm::X86::Variable::dec - Decrement a variable

193 Nasm::X86::Variable::divide - Divide the left hand variable by the right hand variable and return the result as a new variable

194 Nasm::X86::Variable::division - Return a variable containing the result or the remainder that occurs when the left hand side is divided by the right hand side

195 Nasm::X86::Variable::dump - Dump the value of a variable to the specified channel adding an optional title and new line if requested

196 Nasm::X86::Variable::eq - Check whether the left hand variable is equal to the right hand variable

197 Nasm::X86::Variable::equals - Equals operator

198 Nasm::X86::Variable::err - Dump the value of a variable on stderr

199 Nasm::X86::Variable::errNL - Dump the value of a variable on stderr and append a new line

200 Nasm::X86::Variable::for - Iterate the body limit times.

201 Nasm::X86::Variable::freeMemory - Free the memory addressed by this variable for the specified length

202 Nasm::X86::Variable::ge - Check whether the left hand variable is greater than or equal to the right hand variable

203 Nasm::X86::Variable::getBFromZmm - Get the byte from the numbered zmm register and put it in a variable

204 Nasm::X86::Variable::getConst - Load the variable from a constant in effect setting a variable to a specified value

205 Nasm::X86::Variable::getDFromZmm - Get the double word from the numbered zmm register and put it in a variable

206 Nasm::X86::Variable::getQFromZmm - Get the quad word from the numbered zmm register and put it in a variable

207 Nasm::X86::Variable::getReg - Load the variable from the named registers

208 Nasm::X86::Variable::getWFromZmm - Get the word from the numbered zmm register and put it in a variable

209 Nasm::X86::Variable::gt - Check whether the left hand variable is greater than the right hand variable

210 Nasm::X86::Variable::inc - Increment a variable

211 Nasm::X86::Variable::incDec - Increment or decrement a variable

212 Nasm::X86::Variable::isRef - Check whether the specified variable is a reference to another variable

213 Nasm::X86::Variable::le - Check whether the left hand variable is less than or equal to the right hand variable

214 Nasm::X86::Variable::loadZmm - Load bytes from the memory addressed by the specified source variable into the numbered zmm register.

215 Nasm::X86::Variable::lt - Check whether the left hand variable is less than the right hand variable

216 Nasm::X86::Variable::max - Maximum of two variables

217 Nasm::X86::Variable::min - Minimum of two variables

218 Nasm::X86::Variable::minusAssign - Implement minus and assign

219 Nasm::X86::Variable::mod - Divide the left hand variable by the right hand variable and return the remainder as a new variable

220 Nasm::X86::Variable::ne - Check whether the left hand variable is not equal to the right hand variable

221 Nasm::X86::Variable::or - Or two variables

222 Nasm::X86::Variable::out - Dump the value of a variable on stdout

223 Nasm::X86::Variable::outNL - Dump the value of a variable on stdout and append a new line

224 Nasm::X86::Variable::plusAssign - Implement plus and assign

225 Nasm::X86::Variable::pop - Pop a variable from the stack

226 Nasm::X86::Variable::printErrMemoryInHexNL - Write the memory addressed by a variable to stderr

227 Nasm::X86::Variable::printMemoryInHexNL - Write the memory addressed by a variable to stdout or stderr

228 Nasm::X86::Variable::printOutMemoryInHexNL - Write the memory addressed by a variable to stdout

229 Nasm::X86::Variable::push - Push a variable onto the stack

230 Nasm::X86::Variable::putBIntoXmm - Place the value of the content variable at the byte in the numbered xmm register

231 Nasm::X86::Variable::putBIntoZmm - Place the value of the content variable at the byte in the numbered zmm register

232 Nasm::X86::Variable::putBwdqIntoMm - Place the value of the content variable at the byte|word|double word|quad word in the numbered zmm register

233 Nasm::X86::Variable::putDIntoXmm - Place the value of the content variable at the double word in the numbered xmm register

234 Nasm::X86::Variable::putDIntoZmm - Place the value of the content variable at the double word in the numbered zmm register

235 Nasm::X86::Variable::putQIntoXmm - Place the value of the content variable at the quad word in the numbered xmm register

236 Nasm::X86::Variable::putQIntoZmm - Place the value of the content variable at the quad word in the numbered zmm register

237 Nasm::X86::Variable::putWIntoXmm - Place the value of the content variable at the word in the numbered xmm register

238 Nasm::X86::Variable::putWIntoZmm - Place the value of the content variable at the word in the numbered zmm register

239 Nasm::X86::Variable::saveZmm2222 - Save bytes into the memory addressed by the target variable from the numbered zmm register.

240 Nasm::X86::Variable::setMask - Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere

241 Nasm::X86::Variable::setMaskBit - Set a bit in the specified mask register retaining the other bits

242 Nasm::X86::Variable::setMaskFirst - Set the first bits in the specified mask register

243 Nasm::X86::Variable::setReg - Set the named registers from the content of the variable

244 Nasm::X86::Variable::setZmm - Load bytes from the memory addressed by specified source variable into the numbered zmm register at the offset in the specified offset moving the number of bytes in the specified variable

245 Nasm::X86::Variable::str - The name of the variable

246 Nasm::X86::Variable::sub - Subtract the right hand variable from the left hand variable and return the result as a new variable

247 Nasm::X86::Variable::times - Multiply the left hand variable by the right hand variable and return the result as a new variable

248 Nasm::X86::Variable::zBroadCastD - Broadcast a double word in a variable into the numbered zmm.

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

250 OpenWrite - Create the file named by the terminated string addressed by rax for write

251 PeekR - Peek at register on stack

252 PopEax - We cannot pop a double word from the stack in 64 bit long mode using pop so we improvise

253 PopR - Pop registers from the stack

254 PopRR - Pop registers from the stack without tracking

255 PrintErrMemory - Print the memory addressed by rax for a length of rdi on stderr

256 PrintErrMemoryInHex - Dump memory from the address in rax for the length in rdi on stderr

257 PrintErrMemoryInHexNL - Dump memory from the address in rax for the length in rdi and then print a new line

258 PrintErrMemoryNL - Print the memory addressed by rax for a length of rdi followed by a new line on stderr

259 PrintErrNL - Print a new line to stderr

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

261 PrintErrRegisterInHex - Print the named registers as hex strings on stderr

262 PrintErrString - Print a constant string to stderr.

263 PrintErrStringNL - Print a constant string followed by a new line to stderr

264 PrintErrZF - Print the zero flag without disturbing it on stderr

265 PrintMemory - Print the memory addressed by rax for a length of rdi on the specified channel

266 PrintMemoryInHex - Dump memory from the address in rax for the length in rdi on the specified channel.

267 PrintNL - Print a new line to stdout or stderr

268 PrintOutMemory - Print the memory addressed by rax for a length of rdi on stdout

269 PrintOutMemoryInHex - Dump memory from the address in rax for the length in rdi on stdout

270 PrintOutMemoryInHexNL - Dump memory from the address in rax for the length in rdi and then print a new line

271 PrintOutMemoryNL - Print the memory addressed by rax for a length of rdi followed by a new line on stdout

272 PrintOutNL - Print a new line to stderr

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

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

275 PrintOutRegisterInHex - Print the named registers as hex strings on stdout

276 PrintOutRegistersInHex - Print the general purpose registers in hex

277 PrintOutRflagsInHex - Print the flags register in hex

278 PrintOutRipInHex - Print the instruction pointer in hex

279 PrintOutString - Print a constant string to stdout.

280 PrintOutStringNL - Print a constant string followed by a new line to stdout

281 PrintOutZF - Print the zero flag without disturbing it on stdout

282 PrintRaxInHex - Write the content of register rax in hexadecimal in big endian notation to the specified channel

283 PrintRegisterInHex - Print the named registers as hex strings

284 PrintString - Print a constant string to the specified channel

285 PrintUtf32 - Print the specified number of utf32 characters at the specified address

286 PushR - Push registers onto the stack

287 PushRR - Push registers onto the stack without tracking

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

289 Rbwdq - Layout data

290 RComment - Insert a comment into the read only data segment

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

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

293 ReadTimeStampCounter - Read the time stamp counter and return the time in nanoseconds in rax

294 RegisterSize - Return the size of a register

295 removeNonAsciiChars - Return a copy of the specified string with all the non ascii characters removed

296 ReorderSyscallRegisters - Map the list of registers provided to the 64 bit system call sequence

297 RestoreFirstFour - Restore the first 4 parameter registers

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

299 RestoreFirstFourExceptRaxAndRdi - Restore the first 4 parameter registers except rax and rdi so we can return a pair of values

300 RestoreFirstSeven - Restore the first 7 parameter registers

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

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

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

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

305 Rutf8 - Layout a utf8 encoded string as bytes in read only memory and return their label

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

307 SaveFirstFour - Save the first 4 parameter registers making any parameter registers read only

308 SaveFirstSeven - Save the first 7 parameter registers

309 Scope - Create and stack a new scope and continue with it as the current scope

310 ScopeEnd - End the current scope and continue with the containing parent scope

311 SetLabel - Set a label in the code section

312 SetLengthOfShortString - Set the length of the short string held in the numbered zmm register into the specified register

313 SetMaskRegister - Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere

314 SetZF - Set the zero flag

315 Start - Initialize the assembler

316 StatSize - Stat a file whose name is addressed by rax to get its size in rax

317 StringLength - Length of a zero terminated string

318 Structure - Create a structure addressed by a register

319 Subroutine - Create a subroutine that can be called in assembler code

320 Then - Then body for an If statement

321 totalBytesAssembled - Total size in bytes of all files assembled during testing

322 Trace - Add tracing code

323 unlinkFile - Unlink the named file

324 UnReorderSyscallRegisters - Recover the initial values in registers that were reordered

325 Variable - Create a new variable with the specified size and name initialized via an expression

326 Vb - Define a byte variable

327 Vd - Define a double word variable

328 Vq - Define a quad variable

329 Vr - Define a reference variable

330 Vw - Define a word variable

331 Vx - Define an xmm variable

332 VxyzInit - Initialize an xyz register from general purpose registers

333 Vy - Define an ymm variable

334 Vz - Define an zmm variable

335 WaitPid - Wait for the pid in rax to complete

336 xmm - Add xmm to the front of a list of register expressions

337 ymm - Add ymm to the front of a list of register expressions

338 zmm - Add zmm to the front of a list of register expressions

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.