Looking for help!
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 perform 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 arena, add some content to it, write the arena to stdout:
my $a = CreateArena; # Create a string
my $b = CreateArena; # 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;
IfNz # Parent
Then
{Mov rbx, rax;
WaitPid;
GetPid; # Pid of parent as seen in parent
Mov rcx,rax;
PrintOutRegisterInHex rax, rbx, rcx;
},
Else # Child
{Mov r8,rax;
GetPid; # Child pid as seen in child
Mov r9,rax;
GetPPid; # Parent pid as seen in child
Mov r10,rax;
PrintOutRegisterInHex r8, r9, 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(V(file, Rs($0)), (my $s = V(size)), my $a = V(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
Create a multi way tree using SIMD instructions
Create a multiway tree as in Tree::Multi using Avx512 instructions and iterate through it:
my $N = 12;
my $b = CreateArena; # Resizable memory block
my $t = $b->CreateTree; # Multi way tree in memory block
K(count, $N)->for(sub # Add some entries to the tree
{my ($index, $start, $next, $end) = @_;
my $k = $index + 1;
$t->insert($k, $k + 0x100);
$t->insert($k + $N, $k + 0x200);
});
$t->by(sub # Iterate through the tree
{my ($iter, $end) = @_;
$iter->key ->out('key: ');
$iter->data->out(' data: ');
$iter->tree->depth($iter->node, my $D = V(depth));
$t->find($iter->key);
$t->found->out(' found: '); $t->data->out(' data: '); $D->outNL(' depth: ');
});
$t->find(K(key, 0xffff)); $t->found->outNL('Found: '); # Find some entries
$t->find(K(key, 0xd)); $t->found->outNL('Found: ');
If ($t->found,
Then
{$t->data->outNL("Data : ");
});
ok Assemble(debug => 0, eq => <<END);
key: 0000 0000 0000 0001 data: 0000 0000 0000 0101 found: 0000 0000 0000 0001 data: 0000 0000 0000 0101 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0002 data: 0000 0000 0000 0102 found: 0000 0000 0000 0001 data: 0000 0000 0000 0102 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0003 data: 0000 0000 0000 0103 found: 0000 0000 0000 0001 data: 0000 0000 0000 0103 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0004 data: 0000 0000 0000 0104 found: 0000 0000 0000 0001 data: 0000 0000 0000 0104 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0005 data: 0000 0000 0000 0105 found: 0000 0000 0000 0001 data: 0000 0000 0000 0105 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0006 data: 0000 0000 0000 0106 found: 0000 0000 0000 0001 data: 0000 0000 0000 0106 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0007 data: 0000 0000 0000 0107 found: 0000 0000 0000 0001 data: 0000 0000 0000 0107 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0008 data: 0000 0000 0000 0108 found: 0000 0000 0000 0001 data: 0000 0000 0000 0108 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0009 data: 0000 0000 0000 0109 found: 0000 0000 0000 0001 data: 0000 0000 0000 0109 depth: 0000 0000 0000 0002
key: 0000 0000 0000 000A data: 0000 0000 0000 010A found: 0000 0000 0000 0001 data: 0000 0000 0000 010A depth: 0000 0000 0000 0002
key: 0000 0000 0000 000B data: 0000 0000 0000 010B found: 0000 0000 0000 0001 data: 0000 0000 0000 010B depth: 0000 0000 0000 0002
key: 0000 0000 0000 000C data: 0000 0000 0000 010C found: 0000 0000 0000 0001 data: 0000 0000 0000 010C depth: 0000 0000 0000 0002
key: 0000 0000 0000 000D data: 0000 0000 0000 0201 found: 0000 0000 0000 0001 data: 0000 0000 0000 0201 depth: 0000 0000 0000 0001
key: 0000 0000 0000 000E data: 0000 0000 0000 0202 found: 0000 0000 0000 0001 data: 0000 0000 0000 0202 depth: 0000 0000 0000 0002
key: 0000 0000 0000 000F data: 0000 0000 0000 0203 found: 0000 0000 0000 0001 data: 0000 0000 0000 0203 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0010 data: 0000 0000 0000 0204 found: 0000 0000 0000 0001 data: 0000 0000 0000 0204 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0011 data: 0000 0000 0000 0205 found: 0000 0000 0000 0001 data: 0000 0000 0000 0205 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0012 data: 0000 0000 0000 0206 found: 0000 0000 0000 0001 data: 0000 0000 0000 0206 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0013 data: 0000 0000 0000 0207 found: 0000 0000 0000 0001 data: 0000 0000 0000 0207 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0014 data: 0000 0000 0000 0208 found: 0000 0000 0000 0001 data: 0000 0000 0000 0208 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0015 data: 0000 0000 0000 0209 found: 0000 0000 0000 0001 data: 0000 0000 0000 0209 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0016 data: 0000 0000 0000 020A found: 0000 0000 0000 0001 data: 0000 0000 0000 020A depth: 0000 0000 0000 0002
key: 0000 0000 0000 0017 data: 0000 0000 0000 020B found: 0000 0000 0000 0001 data: 0000 0000 0000 020B depth: 0000 0000 0000 0002
key: 0000 0000 0000 0018 data: 0000 0000 0000 020C found: 0000 0000 0000 0001 data: 0000 0000 0000 020C depth: 0000 0000 0000 0002
Found: 0000 0000 0000 0000
Found: 0000 0000 0000 0001
Data : 0000 0000 0000 0201
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:
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 "20210815".
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)
Create (if necessary) and set a label in the code section returning the label so set.
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;
Exit(0);
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(V(source, rsi), V(target, rax), V(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(V(source, rsi), V(target, rax), V(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(V(source, rsi), V(target, rax), V(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(V(source, rsi), V(target, rax), V(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(V(source, rsi), V(target, rax), V(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(V(source, rsi), V(target, rax), V(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(V(source, rsi), V(target, rax), V(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(V(source, rsi), V(target, rax), V(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);
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
Example:
LoadZmm 0, 0..63;
PrintOutRegisterInHex zmm 0; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply Assemble, <<END;
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
END
ChooseRegisters($number, @registers)
Choose the specified numbers of registers excluding those on the specified list
Parameter Description
1 $number Number of registers needed
2 @registers Registers not to choose
CheckGeneralPurposeRegister($reg)
Check that a register is in fact a general purpose register
Parameter Description
1 $reg Mask register to check
CheckNumberedGeneralPurposeRegister($reg)
Check that a register is in fact a numbered general purpose register
Parameter Description
1 $reg Mask register to check
InsertZeroIntoRegisterAtPoint($point, $in)
Insert a zero into the specified register at the point indicated by another register
Parameter Description
1 $point Register with a single 1 at the insertion point
2 $in Register to be inserted into.
Example:
Mov r15, 0x100; # Given a register with a single one in it indicating the desired position,
Mov r14, 0xFFDC; # Insert a zero into the register at that position shifting the bits above that position up left one to make space for the new zero.
Mov r13, 0xF03F;
PrintOutRegisterInHex r14, r15;
InsertZeroIntoRegisterAtPoint r15, r14; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex r14;
Or r14, r15; # Replace the inserted zero with a one
PrintOutRegisterInHex r14;
InsertOneIntoRegisterAtPoint r15, r13;
PrintOutRegisterInHex r13;
ok Assemble(debug => 0, eq => <<END);
r14: 0000 0000 0000 FFDC
r15: 0000 0000 0000 0100
r14: 0000 0000 0001 FEDC
r14: 0000 0000 0001 FFDC
r13: 0000 0000 0001 E13F
END
InsertOneIntoRegisterAtPoint($point, $in)
Insert a one into the specified register at the point indicated by another register
Parameter Description
1 $point Register with a single 1 at the insertion point
2 $in Register to be inserted into.
Example:
Mov r15, 0x100; # Given a register with a single one in it indicating the desired position,
Mov r14, 0xFFDC; # Insert a zero into the register at that position shifting the bits above that position up left one to make space for the new zero.
Mov r13, 0xF03F;
PrintOutRegisterInHex r14, r15;
InsertZeroIntoRegisterAtPoint r15, r14;
PrintOutRegisterInHex r14;
Or r14, r15; # Replace the inserted zero with a one
PrintOutRegisterInHex r14;
InsertOneIntoRegisterAtPoint r15, r13; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex r13;
ok Assemble(debug => 0, eq => <<END);
r14: 0000 0000 0000 FFDC
r15: 0000 0000 0000 0100
r14: 0000 0000 0001 FEDC
r14: 0000 0000 0001 FFDC
r13: 0000 0000 0001 E13F
END
LoadZmm($zmm, @bytes)
Load a numbered zmm with the specified bytes
Parameter Description
1 $zmm Numbered zmm
2 @bytes Bytes
Example:
LoadZmm 0, 0..63; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex zmm 0;
is_deeply Assemble, <<END;
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
END
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;
SetZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
IfZ Then {PrintOutStringNL "Zero"}, Else {PrintOutStringNL "NOT zero"};
ClearZF;
IfNz Then {PrintOutStringNL "NOT zero"}, Else {PrintOutStringNL "Zero"};
Mov r15, 5;
Shr r15, 1; IfC Then {PrintOutStringNL "Carry"} , Else {PrintOutStringNL "NO carry"};
Shr r15, 1; IfC Then {PrintOutStringNL "Carry"} , Else {PrintOutStringNL "NO carry"};
Shr r15, 1; IfNc Then {PrintOutStringNL "NO carry"}, Else {PrintOutStringNL "Carry"};
Shr r15, 1; IfNc Then {PrintOutStringNL "NO carry"}, Else {PrintOutStringNL "Carry"};
ok Assemble(debug=>0, eq => <<END);
ZF=1
ZF=0
ZF=1
ZF=1
ZF=0
Zero
NOT zero
Carry
NO carry
Carry
NO carry
END
ClearZF()
Clear the zero flag
Example:
SetZF;
PrintOutZF;
ClearZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutZF;
SetZF;
PrintOutZF;
SetZF;
PrintOutZF;
ClearZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutZF;
SetZF;
IfZ Then {PrintOutStringNL "Zero"}, Else {PrintOutStringNL "NOT zero"};
ClearZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
IfNz Then {PrintOutStringNL "NOT zero"}, Else {PrintOutStringNL "Zero"};
Mov r15, 5;
Shr r15, 1; IfC Then {PrintOutStringNL "Carry"} , Else {PrintOutStringNL "NO carry"};
Shr r15, 1; IfC Then {PrintOutStringNL "Carry"} , Else {PrintOutStringNL "NO carry"};
Shr r15, 1; IfNc Then {PrintOutStringNL "NO carry"}, Else {PrintOutStringNL "Carry"};
Shr r15, 1; IfNc Then {PrintOutStringNL "NO carry"}, Else {PrintOutStringNL "Carry"};
ok Assemble(debug=>0, eq => <<END);
ZF=1
ZF=0
ZF=1
ZF=1
ZF=0
Zero
NOT zero
Carry
NO carry
Carry
NO carry
END
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
CheckMaskRegister($mask)
Check that a register is in fact a mask register
Parameter Description
1 $mask Mask register to check
LoadConstantIntoMaskRegister($mask, $transfer, $value)
Set a mask register equal to a constant.
Parameter Description
1 $mask Mask register to load
2 $transfer Transfer register
3 $value Constant to load
Example:
Mov r14, 0;
Kmovq k0, r14;
KeepFree r14;
Ktestq k0, k0;
IfZ Then {PrintOutStringNL "0 & 0 == 0"};
PrintOutZF;
LoadConstantIntoMaskRegister k1, r13, 1; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Ktestq k1, k1;
IfNz Then {PrintOutStringNL "1 & 1 != 0"};
PrintOutZF;
LoadConstantIntoMaskRegister k2, r13, 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 = V('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
LoadBitsIntoMaskRegister($mask, $transfer, $prefix, @values)
Load a bit string specification into a mask register
Parameter Description
1 $mask Mask register to load
2 $transfer Transfer register
3 $prefix Prefix bits
4 @values +n 1 bits -n 0 bits
Example:
for (0..7)
{ClearRegisters "k$_";
K($_,$_)->setMaskBit("k$_");
PrintOutRegisterInHex "k$_";
}
ClearRegisters k7;
LoadBitsIntoMaskRegister(k7, r15, '1010', -4, +4, -2, +2, -1, +1, -1, +1); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex "k7";
ok Assemble(debug => 0, eq => <<END);
k0: 0000 0000 0000 0001
k1: 0000 0000 0000 0002
k2: 0000 0000 0000 0004
k3: 0000 0000 0000 0008
k4: 0000 0000 0000 0010
k5: 0000 0000 0000 0020
k6: 0000 0000 0000 0040
k7: 0000 0000 0000 0080
k7: 0000 0000 000A 0F35
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:
my $cmp = sub
{my ($a, $b) = @_;
for my $op(qw(eq ne lt le gt ge))
{Mov rax, $a;
Cmp rax, $b;
KeepFree rax;
my $Op = ucfirst $op;
eval qq(If$Op Then {PrintOutStringNL("$a $op $b")}, Else {PrintOutStringNL("$a NOT $op $b")}); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$@ and confess $@;
}
};
&$cmp(1,1);
&$cmp(1,2);
&$cmp(3,2);
Assemble(debug => 0, eq => <<END);
1 eq 1
1 NOT ne 1
1 NOT lt 1
1 le 1
1 NOT gt 1
1 ge 1
1 NOT eq 2
1 ne 2
1 lt 2
1 le 2
1 NOT gt 2
1 NOT ge 2
3 NOT eq 2
3 ne 2
3 NOT lt 2
3 NOT le 2
3 gt 2
3 ge 2
END
Then($body)
Then body for an If statement
Parameter Description
1 $body Then body
Example:
my $a = V(a, 3); $a->outNL;
my $b = K(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,
Then # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{PrintOutStringNL "a == 3"
},
Else
{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
Else($body)
Else body for an If statement
Parameter Description
1 $body Else body
Example:
my $a = V(a, 3); $a->outNL;
my $b = K(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,
Then
{PrintOutStringNL "a == 3"
},
Else # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{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
IfEq($then, $else)
If equal execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
Example:
my $cmp = sub
{my ($a, $b) = @_;
for my $op(qw(eq ne lt le gt ge))
{Mov rax, $a;
Cmp rax, $b;
KeepFree rax;
my $Op = ucfirst $op;
eval qq(If$Op Then {PrintOutStringNL("$a $op $b")}, Else {PrintOutStringNL("$a NOT $op $b")});
$@ and confess $@;
}
};
&$cmp(1,1);
&$cmp(1,2);
&$cmp(3,2);
Assemble(debug => 0, eq => <<END);
1 eq 1
1 NOT ne 1
1 NOT lt 1
1 le 1
1 NOT gt 1
1 ge 1
1 NOT eq 2
1 ne 2
1 lt 2
1 le 2
1 NOT gt 2
1 NOT ge 2
3 NOT eq 2
3 ne 2
3 NOT lt 2
3 NOT le 2
3 gt 2
3 ge 2
END
IfNe($then, $else)
If not equal execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
Example:
my $cmp = sub
{my ($a, $b) = @_;
for my $op(qw(eq ne lt le gt ge))
{Mov rax, $a;
Cmp rax, $b;
KeepFree rax;
my $Op = ucfirst $op;
eval qq(If$Op Then {PrintOutStringNL("$a $op $b")}, Else {PrintOutStringNL("$a NOT $op $b")});
$@ and confess $@;
}
};
&$cmp(1,1);
&$cmp(1,2);
&$cmp(3,2);
Assemble(debug => 0, eq => <<END);
1 eq 1
1 NOT ne 1
1 NOT lt 1
1 le 1
1 NOT gt 1
1 ge 1
1 NOT eq 2
1 ne 2
1 lt 2
1 le 2
1 NOT gt 2
1 NOT ge 2
3 NOT eq 2
3 ne 2
3 NOT lt 2
3 NOT le 2
3 gt 2
3 ge 2
END
IfNz($then, $else)
If the zero flag is not set then execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
Example:
Mov rax, 0;
Test rax,rax;
IfNz # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Then
{PrintOutRegisterInHex rax;
},
Else
{PrintOutRegisterInHex rbx;
};
KeepFree rax;
Mov rax, 1;
Test rax,rax;
IfNz # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Then
{PrintOutRegisterInHex rcx;
},
Else
{PrintOutRegisterInHex rdx;
};
ok Assemble =~ m(rbx.*rcx)s;
IfZ($then, $else)
If the zero flag is set then execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
Example:
SetZF;
PrintOutZF;
ClearZF;
PrintOutZF;
SetZF;
PrintOutZF;
SetZF;
PrintOutZF;
ClearZF;
PrintOutZF;
SetZF;
IfZ Then {PrintOutStringNL "Zero"}, Else {PrintOutStringNL "NOT zero"}; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ClearZF;
IfNz Then {PrintOutStringNL "NOT zero"}, Else {PrintOutStringNL "Zero"};
Mov r15, 5;
Shr r15, 1; IfC Then {PrintOutStringNL "Carry"} , Else {PrintOutStringNL "NO carry"};
Shr r15, 1; IfC Then {PrintOutStringNL "Carry"} , Else {PrintOutStringNL "NO carry"};
Shr r15, 1; IfNc Then {PrintOutStringNL "NO carry"}, Else {PrintOutStringNL "Carry"};
Shr r15, 1; IfNc Then {PrintOutStringNL "NO carry"}, Else {PrintOutStringNL "Carry"};
ok Assemble(debug=>0, eq => <<END);
ZF=1
ZF=0
ZF=1
ZF=1
ZF=0
Zero
NOT zero
Carry
NO carry
Carry
NO carry
END
IfC($then, $else)
If the carry flag is set then execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
Example:
SetZF;
PrintOutZF;
ClearZF;
PrintOutZF;
SetZF;
PrintOutZF;
SetZF;
PrintOutZF;
ClearZF;
PrintOutZF;
SetZF;
IfZ Then {PrintOutStringNL "Zero"}, Else {PrintOutStringNL "NOT zero"};
ClearZF;
IfNz Then {PrintOutStringNL "NOT zero"}, Else {PrintOutStringNL "Zero"};
Mov r15, 5;
Shr r15, 1; IfC Then {PrintOutStringNL "Carry"} , Else {PrintOutStringNL "NO carry"}; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Shr r15, 1; IfC Then {PrintOutStringNL "Carry"} , Else {PrintOutStringNL "NO carry"}; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Shr r15, 1; IfNc Then {PrintOutStringNL "NO carry"}, Else {PrintOutStringNL "Carry"};
Shr r15, 1; IfNc Then {PrintOutStringNL "NO carry"}, Else {PrintOutStringNL "Carry"};
ok Assemble(debug=>0, eq => <<END);
ZF=1
ZF=0
ZF=1
ZF=1
ZF=0
Zero
NOT zero
Carry
NO carry
Carry
NO carry
END
IfNc($then, $else)
If the carry flag is not set then execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
Example:
SetZF;
PrintOutZF;
ClearZF;
PrintOutZF;
SetZF;
PrintOutZF;
SetZF;
PrintOutZF;
ClearZF;
PrintOutZF;
SetZF;
IfZ Then {PrintOutStringNL "Zero"}, Else {PrintOutStringNL "NOT zero"};
ClearZF;
IfNz Then {PrintOutStringNL "NOT zero"}, Else {PrintOutStringNL "Zero"};
Mov r15, 5;
Shr r15, 1; IfC Then {PrintOutStringNL "Carry"} , Else {PrintOutStringNL "NO carry"};
Shr r15, 1; IfC Then {PrintOutStringNL "Carry"} , Else {PrintOutStringNL "NO carry"};
Shr r15, 1; IfNc Then {PrintOutStringNL "NO carry"}, Else {PrintOutStringNL "Carry"}; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Shr r15, 1; IfNc Then {PrintOutStringNL "NO carry"}, Else {PrintOutStringNL "Carry"}; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok Assemble(debug=>0, eq => <<END);
ZF=1
ZF=0
ZF=1
ZF=1
ZF=0
Zero
NOT zero
Carry
NO carry
Carry
NO carry
END
IfLt($then, $else)
If less than execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
Example:
my $cmp = sub
{my ($a, $b) = @_;
for my $op(qw(eq ne lt le gt ge))
{Mov rax, $a;
Cmp rax, $b;
KeepFree rax;
my $Op = ucfirst $op;
eval qq(If$Op Then {PrintOutStringNL("$a $op $b")}, Else {PrintOutStringNL("$a NOT $op $b")});
$@ and confess $@;
}
};
&$cmp(1,1);
&$cmp(1,2);
&$cmp(3,2);
Assemble(debug => 0, eq => <<END);
1 eq 1
1 NOT ne 1
1 NOT lt 1
1 le 1
1 NOT gt 1
1 ge 1
1 NOT eq 2
1 ne 2
1 lt 2
1 le 2
1 NOT gt 2
1 NOT ge 2
3 NOT eq 2
3 ne 2
3 NOT lt 2
3 NOT le 2
3 gt 2
3 ge 2
END
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
Example:
my $cmp = sub
{my ($a, $b) = @_;
for my $op(qw(eq ne lt le gt ge))
{Mov rax, $a;
Cmp rax, $b;
KeepFree rax;
my $Op = ucfirst $op;
eval qq(If$Op Then {PrintOutStringNL("$a $op $b")}, Else {PrintOutStringNL("$a NOT $op $b")});
$@ and confess $@;
}
};
&$cmp(1,1);
&$cmp(1,2);
&$cmp(3,2);
Assemble(debug => 0, eq => <<END);
1 eq 1
1 NOT ne 1
1 NOT lt 1
1 le 1
1 NOT gt 1
1 ge 1
1 NOT eq 2
1 ne 2
1 lt 2
1 le 2
1 NOT gt 2
1 NOT ge 2
3 NOT eq 2
3 ne 2
3 NOT lt 2
3 NOT le 2
3 gt 2
3 ge 2
END
IfGt($then, $else)
If greater than execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
Example:
my $cmp = sub
{my ($a, $b) = @_;
for my $op(qw(eq ne lt le gt ge))
{Mov rax, $a;
Cmp rax, $b;
KeepFree rax;
my $Op = ucfirst $op;
eval qq(If$Op Then {PrintOutStringNL("$a $op $b")}, Else {PrintOutStringNL("$a NOT $op $b")});
$@ and confess $@;
}
};
&$cmp(1,1);
&$cmp(1,2);
&$cmp(3,2);
Assemble(debug => 0, eq => <<END);
1 eq 1
1 NOT ne 1
1 NOT lt 1
1 le 1
1 NOT gt 1
1 ge 1
1 NOT eq 2
1 ne 2
1 lt 2
1 le 2
1 NOT gt 2
1 NOT ge 2
3 NOT eq 2
3 ne 2
3 NOT lt 2
3 NOT le 2
3 gt 2
3 ge 2
END
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
Example:
my $cmp = sub
{my ($a, $b) = @_;
for my $op(qw(eq ne lt le gt ge))
{Mov rax, $a;
Cmp rax, $b;
KeepFree rax;
my $Op = ucfirst $op;
eval qq(If$Op Then {PrintOutStringNL("$a $op $b")}, Else {PrintOutStringNL("$a NOT $op $b")});
$@ and confess $@;
}
};
&$cmp(1,1);
&$cmp(1,2);
&$cmp(3,2);
Assemble(debug => 0, eq => <<END);
1 eq 1
1 NOT ne 1
1 NOT lt 1
1 le 1
1 NOT gt 1
1 ge 1
1 NOT eq 2
1 ne 2
1 lt 2
1 le 2
1 NOT gt 2
1 NOT ge 2
3 NOT eq 2
3 ne 2
3 NOT lt 2
3 NOT le 2
3 gt 2
3 ge 2
END
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;
Jge $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;
Jge $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
CommentWithTraceBack(@comment)
Insert a comment into the assembly code with a traceback showing how it was generated
Parameter Description
1 @comment Text of comment
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;
Exit(0);
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
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
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;
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(debug=>0, eq => <<END);
r8: 6867 6665 6463 6261
END
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; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
SetZF;
IfZ Then {PrintOutStringNL "Zero"}, Else {PrintOutStringNL "NOT zero"};
ClearZF;
IfNz Then {PrintOutStringNL "NOT zero"}, Else {PrintOutStringNL "Zero"};
Mov r15, 5;
Shr r15, 1; IfC Then {PrintOutStringNL "Carry"} , Else {PrintOutStringNL "NO carry"};
Shr r15, 1; IfC Then {PrintOutStringNL "Carry"} , Else {PrintOutStringNL "NO carry"};
Shr r15, 1; IfNc Then {PrintOutStringNL "NO carry"}, Else {PrintOutStringNL "Carry"};
Shr r15, 1; IfNc Then {PrintOutStringNL "NO carry"}, Else {PrintOutStringNL "Carry"};
ok Assemble(debug=>0, eq => <<END);
ZF=1
ZF=0
ZF=1
ZF=1
ZF=0
Zero
NOT zero
Carry
NO carry
Carry
NO carry
END
Variables
Variable definitions and operations
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
V($name, $expr, %options)
Define a quad variable
Parameter Description
1 $name Name of variable
2 $expr Initializing expression
3 %options Options
Example:
my $a = V(a, 3); $a->outNL; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $b = K(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,
Then
{PrintOutStringNL "a == 3"
},
Else
{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
K($name, $expr, %options)
Define a quad constant
Parameter Description
1 $name Name of variable
2 $expr Initializing expression
3 %options Options
Example:
my $a = V(a, 3); $a->outNL;
my $b = K(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,
Then
{PrintOutStringNL "a == 3"
},
Else
{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
R($name, $size)
Define a reference variable
Parameter Description
1 $name Name of variable
2 $size Variable being referenced
Print variables
Print the values of variables or the memory addressed by them
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
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, $Transfer)
Copy one variable into another
Parameter Description
1 $left Left variable
2 $right Right variable
3 $Transfer Optional transfer register
Nasm::X86::Variable::copyAddress($left, $right, $Transfer)
Copy a reference to a variable
Parameter Description
1 $left Left variable
2 $right Right variable
3 $Transfer Optional transfer register
Nasm::X86::Variable::copyZF($var)
Copy the current state of the zero flag into a variable
Parameter Description
1 $var Variable
Example:
Mov r15, 1;
my $z = V(zf);
Cmp r15, 1; $z->copyZF; $z->outNL;
Cmp r15, 2; $z->copyZF; $z->outNL;
Cmp r15, 1; $z->copyZFInverted; $z->outNL;
Cmp r15, 2; $z->copyZFInverted; $z->outNL;
is_deeply Assemble(debug=>0), <<END;
zf: 0000 0000 0000 0001
zf: 0000 0000 0000 0000
zf: 0000 0000 0000 0000
zf: 0000 0000 0000 0001
END
Nasm::X86::Variable::copyZFInverted($var)
Copy the opposite of the current state of the zero flag into a variable
Parameter Description
1 $var Variable
Example:
Mov r15, 1;
my $z = V(zf);
Cmp r15, 1; $z->copyZF; $z->outNL;
Cmp r15, 2; $z->copyZF; $z->outNL;
Cmp r15, 1; $z->copyZFInverted; $z->outNL;
Cmp r15, 2; $z->copyZFInverted; $z->outNL;
is_deeply Assemble(debug=>0), <<END;
zf: 0000 0000 0000 0001
zf: 0000 0000 0000 0000
zf: 0000 0000 0000 0000
zf: 0000 0000 0000 0001
END
Nasm::X86::Variable::clone($var)
Clone a variable to create a new variable
Parameter Description
1 $var Variable to clone
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::booleanC($cmov, $op, $left, $right)
Combine the left hand variable with the right hand variable via a boolean operator using a conditional move instruction.
Parameter Description
1 $cmov Conditional move instruction name
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
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 = V("a", 1);
my $b = V("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 = V("a", 1);
my $b = V("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 = V("Start", 7);
my $length = V("Length", 3);
$start->setMask($length, k7);
PrintOutRegisterInHex k7;
is_deeply Assemble, <<END;
k7: 0000 0000 0000 0380
END
my $z = V('zero', 0);
my $o = V('one', 1);
my $t = V('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($index, $mask)
Set a bit in the specified mask register retaining the other bits
Parameter Description
1 $index Variable containing bit position to set
2 $mask Mask register
Nasm::X86::Variable::clearMaskBit($index, $mask)
Clear a bit in the specified mask register retaining the other bits
Parameter Description
1 $index Variable containing bit position to clear
2 $mask Mask register
Nasm::X86::Variable::setBit($index, $mask)
Set a bit in the specified register retaining the other bits
Parameter Description
1 $index Variable containing bit position to set
2 $mask Mask register
Nasm::X86::Variable::clearBit($index, $mask)
Clear a bit in the specified mask register retaining the other bits
Parameter Description
1 $index 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 = V(Source, $s);
if (1) # First block
{my $offset = V(Offset, 7);
my $length = V(Length, 3);
$source->setZmm(0, $offset, $length);
}
if (1) # Second block
{my $offset = V(Offset, 33);
my $length = V(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
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
loadFromZmm($register, $size, $zmm, $offset)
Load the specified register from the offset located in the numbered zmm.
Parameter Description
1 $register Register to load
2 $size "b|w|d|q" for size
3 $zmm Numbered zmm register to load from
4 $offset Constant offset in bytes
putIntoZmm($register, $size, $zmm, $offset)
Put the specified register into the numbered zmm at the from the offset located in the numbered zmm.
Parameter Description
1 $register Register to load
2 $size Bwdq for size
3 $zmm Numbered zmm register to load from
4 $offset Constant offset in bytes
getBwdqFromMm($size, $mm, $offset, $Transfer)
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 Mm register
3 $offset Offset in bytes either as a constant or as a variable
4 $Transfer Optional transfer register
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, $transfer)
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
3 $transfer Optional transfer register
Example:
my $s = Rb(0..8);
my $c = V("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, r15)->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, $transfer)
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
4 $transfer Transfer register
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, $Transfer)
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
5 $Transfer Optional transfer register
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, $transfer)
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
4 $transfer Optional transfer register
Example:
my $s = Rb(0..8);
my $c = V("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, r15)->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 = V(size, 2048);
my $q = Rs('a'..'p');
AllocateMemory($N, my $address = V(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:
V(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 Then {PrintOutStringNL "0 & 0 == 0"};
PrintOutZF;
LoadConstantIntoMaskRegister k1, r13, 1;
Ktestq k1, k1;
IfNz Then {PrintOutStringNL "1 & 1 != 0"};
PrintOutZF;
LoadConstantIntoMaskRegister k2, r13, 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 = V('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
Then
{Mov rbx, rax;
WaitPid;
GetPid; # Pid of parent as seen in parent
Mov rcx,rax;
PrintOutRegisterInHex rax, rbx, rcx;
},
Else # Child
{Mov r8,rax;
GetPid; # Child pid as seen in child
Mov r9,rax;
GetPPid; # Parent pid as seen in child
Mov r10,rax;
PrintOutRegisterInHex r8, r9, 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
Then
{Mov rbx, rax;
WaitPid;
GetPid; # Pid of parent as seen in parent # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov rcx,rax;
PrintOutRegisterInHex rax, rbx, rcx;
},
Else # Child
{Mov r8,rax;
GetPid; # Child pid as seen in child # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov r9,rax;
GetPPid; # Parent pid as seen in child
Mov r10,rax;
PrintOutRegisterInHex r8, r9, 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
Then
{Mov rbx, rax;
WaitPid;
GetPid; # Pid of parent as seen in parent
Mov rcx,rax;
PrintOutRegisterInHex rax, rbx, rcx;
},
Else # Child
{Mov r8,rax;
GetPid; # Child pid as seen in child
Mov r9,rax;
GetPPid; # Parent pid as seen in child # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov r10,rax;
PrintOutRegisterInHex r8, r9, 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
Then
{Mov rbx, rax;
WaitPid; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
GetPid; # Pid of parent as seen in parent
Mov rcx,rax;
PrintOutRegisterInHex rax, rbx, rcx;
},
Else # Child
{Mov r8,rax;
GetPid; # Child pid as seen in child
Mov r9,rax;
GetPPid; # Parent pid as seen in child
Mov r10,rax;
PrintOutRegisterInHex r8, r9, 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(K(size, $N), my $a = V(address));
CopyMemory(V(source, $s), V(size, $N), target => $a);
AllocateMemory(K(size, $N), my $b = V(address));
CopyMemory(source => $a, target => $b, K(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(V(file, Rs($0)), (my $s = V(size)), my $a = V(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; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Exit(0);
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 = V(size, 2048);
my $q = Rs('a'..'p');
AllocateMemory($N, my $address = V(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 = V(size, 4096); # Size of the initial allocation which should be one or more pages
AllocateMemory($N, my $A = V(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(K(size, $N), my $a = V(address)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
CopyMemory(V(source, $s), V(size, $N), target => $a);
AllocateMemory(K(size, $N), my $b = V(address)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
CopyMemory(source => $a, target => $b, K(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 = V(size, 4096); # Size of the initial allocation which should be one or more pages
AllocateMemory($N, my $A = V(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 = V(size, 4096); # Size of the initial allocation which should be one or more pages
AllocateMemory($N, my $A = V(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
MaskMemory22(@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_22(@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(V(source, rsi), V(target, rax), V(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(K(size, $N), my $a = V(address));
CopyMemory(V(source, $s), V(size, $N), target => $a); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
AllocateMemory(K(size, $N), my $b = V(address));
CopyMemory(source => $a, target => $b, K(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 0003
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 0003
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 0003
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(V(file, Rs($0)), (my $s = V(size)), my $a = V(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 arena addressed by rax with bash
Parameter Description
1 @variables Variables
Example:
my $s = CreateArena; # Create a string
$s->ql(<<END); # Write code to execute
#!/usr/bin/bash
whoami
ls -la
pwd
END
$s->write (my $f = V('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 = CreateArena; # Create a string
$s->ql(<<END); # Write code to execute
#!/usr/bin/bash
whoami
ls -la
pwd
END
$s->write (my $f = V('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) = (V(out), V(size), V('fail'));
my $Chars = Rb(0x24, 0xc2, 0xa2, 0xc9, 0x91, 0xE2, 0x82, 0xAC, 0xF0, 0x90, 0x8D, 0x88);
my $chars = V(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 = K(statement, Rs($statement));
my $l = K(size, length($statement));
AllocateMemory($l, my $address = V(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);
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
END
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
Short Strings
Operations on Short Strings
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
Arenas
An arena is single extensible block of memory which contains other data structures such as strings, arrays, trees within it.
StringLength(@parameters)
Length of a zero terminated string
Parameter Description
1 @parameters Parameters
Example:
StringLength(V(string, Rs("abcd")))->outNL; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Assemble(debug => 0, eq => <<END);
size: 0000 0000 0000 0004
END
CreateArena(%options)
Create an relocatable 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 arena.
Parameter Description
1 %options Free=>1 adds a free chain.
Example:
my $a = CreateArena; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$a->q('aa');
$a->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aa
END
my $a = CreateArena; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $b = CreateArena; # 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 = CreateArena; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $b = CreateArena; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$a->q('aa');
$a->q('AA');
$a->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aaAA
END
my $a = CreateArena; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $b = CreateArena; # 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 = CreateArena; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$a->q('ab');
my $b = CreateArena; # Create target arena # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$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 arena
$b->out; PrintOutNL; # Print arena
$a->length(my $sa = V(size)); $sa->outNL;
$b->length(my $sb = V(size)); $sb->outNL;
$a->clear;
$a->length(my $sA = V(size)); $sA->outNL;
$b->length(my $sB = V(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::Arena::length($arena, @variables)
Get the length of an arena
Parameter Description
1 $arena Arena descriptor
2 @variables Variables
Nasm::X86::Arena::makeReadOnly($arena)
Make an arena read only
Parameter Description
1 $arena Arena descriptor
Nasm::X86::Arena::makeWriteable($arena)
Make an arena writable
Parameter Description
1 $arena Arena descriptor
Nasm::X86::Arena::allocate($arena, @variables)
Allocate the amount of space indicated in rdi in the arena addressed by rax and return the offset of the allocation in the arena in rdi
Parameter Description
1 $arena Arena descriptor
2 @variables Variables
Nasm::X86::Arena::allocZmmBlock($arena, @variables)
Allocate a block to hold a zmm register in the specified arena and return the offset of the block in a variable
Parameter Description
1 $arena Arena
2 @variables Variables
Nasm::X86::Arena::allocBlock($arena)
Allocate a block to hold a zmm register in the specified arena and return the offset of the block in a variable
Parameter Description
1 $arena Arena
Example:
my $a = CreateArena; $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);
Arena
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
Arena
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
Arena
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
Arena
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
Arena
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::Arena::m($arena, @variables)
Append the content with length rdi addressed by rsi to the arena addressed by rax
Parameter Description
1 $arena Arena descriptor
2 @variables Variables
Nasm::X86::Arena::q($arena, $string)
Append a constant string to the arena
Parameter Description
1 $arena Arena descriptor
2 $string String
Nasm::X86::Arena::ql($arena, $const)
Append a quoted string containing new line characters to the arena addressed by rax
Parameter Description
1 $arena Arena
2 $const Constant
Nasm::X86::Arena::char($arena, $char)
Append a character expressed as a decimal number to the arena addressed by rax
Parameter Description
1 $arena Arena descriptor
2 $char Number of character to be appended
Nasm::X86::Arena::nl($arena)
Append a new line to the arena addressed by rax
Parameter Description
1 $arena Arena descriptor
Nasm::X86::Arena::z($arena)
Append a trailing zero to the arena addressed by rax
Parameter Description
1 $arena Arena descriptor
Nasm::X86::Arena::append($arena, @variables)
Append one arena to another
Parameter Description
1 $arena Arena descriptor
2 @variables Variables
Nasm::X86::Arena::clear($arena)
Clear the arena addressed by rax
Parameter Description
1 $arena Arena descriptor
Nasm::X86::Arena::write($arena, @variables)
Write the content in an arena addressed by rax to a temporary file and replace the arena content with the name of the temporary file
Parameter Description
1 $arena Arena descriptor
2 @variables Variables
Nasm::X86::Arena::read($arena, @variables)
Read the named file (terminated with a zero byte) and place it into the named arena.
Parameter Description
1 $arena Arena descriptor
2 @variables Variables
Nasm::X86::Arena::out($arena)
Print the specified arena addressed by rax on sysout
Parameter Description
1 $arena Arena descriptor
Nasm::X86::Arena::dump($arena, $depth)
Dump details of an arena
Parameter Description
1 $arena Arena descriptor
2 $depth Optional amount of memory to dump as the number of 64 byte blocks
String
Strings made from zmm sized blocks of text
Nasm::X86::Arena::CreateString($arena)
Create a string from a doubly link linked list of 64 byte blocks linked via 4 byte offsets in the arena addressed by rax and return its descriptor
Parameter Description
1 $arena Arena description
Nasm::X86::String::dump($String)
Dump a string to sysout
Parameter Description
1 $String String descriptor
Nasm::X86::String::len($String, $size)
Find the length of a string
Parameter Description
1 $String String descriptor
2 $size Size variable
Nasm::X86::String::concatenate($target, $source)
Concatenate two strings by appending a copy of the source to the target string.
Parameter Description
1 $target Target string
2 $source Source string
Nasm::X86::String::insertChar($String, @variables)
Insert a character into a string
Parameter Description
1 $String String
2 @variables Variables
Nasm::X86::String::deleteChar($String, @variables)
Delete a character in a string
Parameter Description
1 $String String
2 @variables Variables
Nasm::X86::String::getCharacter($String, @variables)
Get a character from a string
Parameter Description
1 $String String
2 @variables Variables
Nasm::X86::String::append($String, @variables)
Append the specified content in memory to the specified string
Parameter Description
1 $String String descriptor
2 @variables Variables
Nasm::X86::String::clear($String)
Clear the block by freeing all but the first block
Parameter Description
1 $String String descriptor
Array
Array constructed as a set of blocks in an arena
Nasm::X86::Arena::CreateArray($arena)
Create a array in an arena
Parameter Description
1 $arena Arena description
Nasm::X86::Array::dump($Array, @variables)
Dump a array
Parameter Description
1 $Array Array descriptor
2 @variables Variables
Nasm::X86::Array::push($Array, @variables)
Push an element onto the array
Parameter Description
1 $Array Array descriptor
2 @variables Variables
Nasm::X86::Array::pop($Array, @variables)
Pop an element from an array
Parameter Description
1 $Array Array descriptor
2 @variables Variables
Nasm::X86::Array::get($Array, @variables)
Get an element from the array
Parameter Description
1 $Array Array descriptor
2 @variables Variables
Nasm::X86::Array::put($Array, @variables)
Put an element into an array as long as it is with in its limits established by pushing.
Parameter Description
1 $Array Array descriptor
2 @variables Variables
Tree
Tree constructed as sets of blocks in an arena.
Nasm::X86::Arena::DescribeTree($arena)
Return a descriptor for a tree in the specified arena
Parameter Description
1 $arena Arena descriptor
Nasm::X86::Arena::CreateTree($arena)
Create a tree in an arena.
Parameter Description
1 $arena Arena description
Example:
my $N = 12;
my $b = CreateArena; # Resizable memory block
my $t = $b->CreateTree; # Multi way tree in memory block
K(count, $N)->for(sub # Add some entries to the tree
{my ($index, $start, $next, $end) = @_;
my $k = $index + 1;
$t->insert($k, $k + 0x100);
$t->insert($k + $N, $k + 0x200);
});
$t->by(sub # Iterate through the tree
{my ($iter, $end) = @_;
$iter->key ->out('key: ');
$iter->data->out(' data: ');
$iter->tree->depth($iter->node, my $D = V(depth));
$t->find($iter->key);
$t->found->out(' found: '); $t->data->out(' data: '); $D->outNL(' depth: ');
});
$t->find(K(key, 0xffff)); $t->found->outNL('Found: '); # Find some entries
$t->find(K(key, 0xd)); $t->found->outNL('Found: ');
If ($t->found,
Then
{$t->data->outNL("Data : ");
});
ok Assemble(debug => 0, eq => <<END);
key: 0000 0000 0000 0001 data: 0000 0000 0000 0101 found: 0000 0000 0000 0001 data: 0000 0000 0000 0101 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0002 data: 0000 0000 0000 0102 found: 0000 0000 0000 0001 data: 0000 0000 0000 0102 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0003 data: 0000 0000 0000 0103 found: 0000 0000 0000 0001 data: 0000 0000 0000 0103 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0004 data: 0000 0000 0000 0104 found: 0000 0000 0000 0001 data: 0000 0000 0000 0104 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0005 data: 0000 0000 0000 0105 found: 0000 0000 0000 0001 data: 0000 0000 0000 0105 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0006 data: 0000 0000 0000 0106 found: 0000 0000 0000 0001 data: 0000 0000 0000 0106 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0007 data: 0000 0000 0000 0107 found: 0000 0000 0000 0001 data: 0000 0000 0000 0107 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0008 data: 0000 0000 0000 0108 found: 0000 0000 0000 0001 data: 0000 0000 0000 0108 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0009 data: 0000 0000 0000 0109 found: 0000 0000 0000 0001 data: 0000 0000 0000 0109 depth: 0000 0000 0000 0002
key: 0000 0000 0000 000A data: 0000 0000 0000 010A found: 0000 0000 0000 0001 data: 0000 0000 0000 010A depth: 0000 0000 0000 0002
key: 0000 0000 0000 000B data: 0000 0000 0000 010B found: 0000 0000 0000 0001 data: 0000 0000 0000 010B depth: 0000 0000 0000 0002
key: 0000 0000 0000 000C data: 0000 0000 0000 010C found: 0000 0000 0000 0001 data: 0000 0000 0000 010C depth: 0000 0000 0000 0002
key: 0000 0000 0000 000D data: 0000 0000 0000 0201 found: 0000 0000 0000 0001 data: 0000 0000 0000 0201 depth: 0000 0000 0000 0001
key: 0000 0000 0000 000E data: 0000 0000 0000 0202 found: 0000 0000 0000 0001 data: 0000 0000 0000 0202 depth: 0000 0000 0000 0002
key: 0000 0000 0000 000F data: 0000 0000 0000 0203 found: 0000 0000 0000 0001 data: 0000 0000 0000 0203 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0010 data: 0000 0000 0000 0204 found: 0000 0000 0000 0001 data: 0000 0000 0000 0204 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0011 data: 0000 0000 0000 0205 found: 0000 0000 0000 0001 data: 0000 0000 0000 0205 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0012 data: 0000 0000 0000 0206 found: 0000 0000 0000 0001 data: 0000 0000 0000 0206 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0013 data: 0000 0000 0000 0207 found: 0000 0000 0000 0001 data: 0000 0000 0000 0207 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0014 data: 0000 0000 0000 0208 found: 0000 0000 0000 0001 data: 0000 0000 0000 0208 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0015 data: 0000 0000 0000 0209 found: 0000 0000 0000 0001 data: 0000 0000 0000 0209 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0016 data: 0000 0000 0000 020A found: 0000 0000 0000 0001 data: 0000 0000 0000 020A depth: 0000 0000 0000 0002
key: 0000 0000 0000 0017 data: 0000 0000 0000 020B found: 0000 0000 0000 0001 data: 0000 0000 0000 020B depth: 0000 0000 0000 0002
key: 0000 0000 0000 0018 data: 0000 0000 0000 020C found: 0000 0000 0000 0001 data: 0000 0000 0000 020C depth: 0000 0000 0000 0002
Found: 0000 0000 0000 0000
Found: 0000 0000 0000 0001
Data : 0000 0000 0000 0201
END
Nasm::X86::Tree::Clone($tree)
Clone the specified tree descriptions
Parameter Description
1 $tree Tree descriptor
Example:
my $L = K(loop, 4);
my $b = CreateArena;
my $T = $b->CreateTree;
my $t = $T->Clone;
$L->for(sub
{my ($i, $start, $next, $end) = @_;
$t->insertTreeAndClone($i);
$t->first->outNL;
});
$t->insert($L, $L*2);
my $f = $T->Clone;
$L->for(sub
{my ($i, $start, $next, $end) = @_;
$f->findAndClone($i);
$i->out('i: '); $f->found->out(' f: '); $f->data->out(' d: '); $f->subTree->outNL(' s: ');
});
$f->find($L);
$L->out('N: '); $f->found->out(' f: '); $f->data->out(' d: '); $f->subTree->outNL(' s: ');
ok Assemble(debug => 0, eq => <<END);
first: 0000 0000 0000 0098
first: 0000 0000 0000 0118
first: 0000 0000 0000 0198
first: 0000 0000 0000 0218
i: 0000 0000 0000 0000 f: 0000 0000 0000 0001 d: 0000 0000 0000 0098 s: 0000 0000 0000 0001
i: 0000 0000 0000 0001 f: 0000 0000 0000 0001 d: 0000 0000 0000 0118 s: 0000 0000 0000 0001
i: 0000 0000 0000 0002 f: 0000 0000 0000 0001 d: 0000 0000 0000 0198 s: 0000 0000 0000 0001
i: 0000 0000 0000 0003 f: 0000 0000 0000 0001 d: 0000 0000 0000 0218 s: 0000 0000 0000 0001
N: 0000 0000 0000 0004 f: 0000 0000 0000 0001 d: 0000 0000 0000 0008 s: 0000 0000 0000 0000
END
Nasm::X86::Tree::find($t, $key)
Find a key in a tree and test whether the found data is a sub tree. The results are held in the variables "found", "data", "subTree" addressed by the tree descriptor.
Parameter Description
1 $t Tree descriptor
2 $key Key field to search for
Nasm::X86::Tree::findAndClone($t, $key)
Find a key in the specified tree and clone it is it is a sub tree.
Parameter Description
1 $t Tree descriptor
2 $key Key as a dword
Example:
my $L = K(loop, 4);
my $b = CreateArena;
my $T = $b->CreateTree;
my $t = $T->Clone;
$L->for(sub
{my ($i, $start, $next, $end) = @_;
$t->insertTreeAndClone($i);
$t->first->outNL;
});
$t->insert($L, $L*2);
my $f = $T->Clone;
$L->for(sub
{my ($i, $start, $next, $end) = @_;
$f->findAndClone($i);
$i->out('i: '); $f->found->out(' f: '); $f->data->out(' d: '); $f->subTree->outNL(' s: ');
});
$f->find($L);
$L->out('N: '); $f->found->out(' f: '); $f->data->out(' d: '); $f->subTree->outNL(' s: ');
ok Assemble(debug => 0, eq => <<END);
first: 0000 0000 0000 0098
first: 0000 0000 0000 0118
first: 0000 0000 0000 0198
first: 0000 0000 0000 0218
i: 0000 0000 0000 0000 f: 0000 0000 0000 0001 d: 0000 0000 0000 0098 s: 0000 0000 0000 0001
i: 0000 0000 0000 0001 f: 0000 0000 0000 0001 d: 0000 0000 0000 0118 s: 0000 0000 0000 0001
i: 0000 0000 0000 0002 f: 0000 0000 0000 0001 d: 0000 0000 0000 0198 s: 0000 0000 0000 0001
i: 0000 0000 0000 0003 f: 0000 0000 0000 0001 d: 0000 0000 0000 0218 s: 0000 0000 0000 0001
N: 0000 0000 0000 0004 f: 0000 0000 0000 0001 d: 0000 0000 0000 0008 s: 0000 0000 0000 0000
END
Nasm::X86::Tree::insertDataOrTree($t, $tnd, $key, $data)
Insert either a key, data pair into the tree or create a sub tree at the specified key (if it does not already exist) and return the offset of the first block of the sub tree in the data variable.
Parameter Description
1 $t Tree descriptor
2 $tnd 0 - data or 1 - tree
3 $key Key as a dword
4 $data Data as a dword
Nasm::X86::Tree::insert($t, $key, $data)
Insert a dword into into the specified tree at the specified key.
Parameter Description
1 $t Tree descriptor
2 $key Key as a dword
3 $data Data as a dword
Nasm::X86::Tree::insertTree($t, $key, $subTree)
Insert a sub tree into the specified tree tree under the specified key. If no sub tree is supplied an empty one is provided gratis.
Parameter Description
1 $t Tree descriptor
2 $key Key as a dword
3 $subTree Sub tree to insert else an empty one will be added
Example:
my $b = CreateArena;
my $t = $b->CreateTree;
my $T = $b->CreateTree;
$T->insert (K(key, 2), K(data, 4));
$t->insertTree(K(key, 1), $T);
$t->print;
ok Assemble(debug => 0, eq => <<END);
Tree at: r15: 0000 0000 0000 0018
key: 0000 0000 0000 0001 data: 0000 0000 0000 0098 depth: 0000 0000 0000 0001
Tree at: r15: 0000 0000 0000 0098
key: 0000 0000 0000 0002 data: 0000 0000 0000 0004 depth: 0000 0000 0000 0001
END
Nasm::X86::Tree::insertTreeAndClone($t, $key)
Insert a new sub tree into the specified tree tree under the specified key and return a descriptor for it. If the tree already exists, return a descriptor for it.
Parameter Description
1 $t Tree descriptor
2 $key Key as a dword
Example:
my $L = K(loop, 4);
my $b = CreateArena;
my $T = $b->CreateTree;
my $t = $T->Clone;
$L->for(sub
{my ($i, $start, $next, $end) = @_;
$t->insertTreeAndClone($i);
$t->first->outNL;
});
$t->insert($L, $L*2);
my $f = $T->Clone;
$L->for(sub
{my ($i, $start, $next, $end) = @_;
$f->findAndClone($i);
$i->out('i: '); $f->found->out(' f: '); $f->data->out(' d: '); $f->subTree->outNL(' s: ');
});
$f->find($L);
$L->out('N: '); $f->found->out(' f: '); $f->data->out(' d: '); $f->subTree->outNL(' s: ');
ok Assemble(debug => 0, eq => <<END);
first: 0000 0000 0000 0098
first: 0000 0000 0000 0118
first: 0000 0000 0000 0198
first: 0000 0000 0000 0218
i: 0000 0000 0000 0000 f: 0000 0000 0000 0001 d: 0000 0000 0000 0098 s: 0000 0000 0000 0001
i: 0000 0000 0000 0001 f: 0000 0000 0000 0001 d: 0000 0000 0000 0118 s: 0000 0000 0000 0001
i: 0000 0000 0000 0002 f: 0000 0000 0000 0001 d: 0000 0000 0000 0198 s: 0000 0000 0000 0001
i: 0000 0000 0000 0003 f: 0000 0000 0000 0001 d: 0000 0000 0000 0218 s: 0000 0000 0000 0001
N: 0000 0000 0000 0004 f: 0000 0000 0000 0001 d: 0000 0000 0000 0008 s: 0000 0000 0000 0000
END
Nasm::X86::Tree::leftOrRightMost($t, $dir, @variables)
Return the left most or right most node
Parameter Description
1 $t Tree descriptor
2 $dir Direction: left = 0 or right = 1
3 @variables Variables
Nasm::X86::Tree::leftMost($t, @variables)
Return the left most node
Parameter Description
1 $t Tree descriptor
2 @variables Variables
Nasm::X86::Tree::rightMost($t, @variables)
Return the right most node
Parameter Description
1 $t Tree descriptor
2 @variables Variables
Nasm::X86::Tree::depth($t, @variables)
Return the depth of a node within a tree.
Parameter Description
1 $t Tree descriptor
2 @variables Variables
Sub trees
Construct trees of trees.
Print a tree
Nasm::X86::Tree::print($t)
Print a tree
Parameter Description
1 $t Tree
Example:
my $L = V(loop, 45);
my $b = CreateArena;
my $t = $b->CreateTree;
$L->for(sub
{my ($i, $start, $next, $end) = @_;
my $l = $L - $i;
If ($i % 2 == 0, sub
{$t->insert($i, $l);
$t->insertTree($l);
});
});
$t->print;
ok Assemble(debug => 0, eq => <<END);
Tree at: r15: 0000 0000 0000 0018
key: 0000 0000 0000 0000 data: 0000 0000 0000 002D depth: 0000 0000 0000 0002
key: 0000 0000 0000 0001 data: 0000 0000 0000 0ED8 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0002 data: 0000 0000 0000 002B depth: 0000 0000 0000 0002
key: 0000 0000 0000 0003 data: 0000 0000 0000 0E58 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0004 data: 0000 0000 0000 0029 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0005 data: 0000 0000 0000 0DD8 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0006 data: 0000 0000 0000 0027 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0007 data: 0000 0000 0000 0D58 depth: 0000 0000 0000 0001
key: 0000 0000 0000 0008 data: 0000 0000 0000 0025 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0009 data: 0000 0000 0000 0CD8 depth: 0000 0000 0000 0002
key: 0000 0000 0000 000A data: 0000 0000 0000 0023 depth: 0000 0000 0000 0002
key: 0000 0000 0000 000B data: 0000 0000 0000 0C58 depth: 0000 0000 0000 0002
key: 0000 0000 0000 000C data: 0000 0000 0000 0021 depth: 0000 0000 0000 0002
key: 0000 0000 0000 000D data: 0000 0000 0000 0BD8 depth: 0000 0000 0000 0002
key: 0000 0000 0000 000E data: 0000 0000 0000 001F depth: 0000 0000 0000 0001
key: 0000 0000 0000 000F data: 0000 0000 0000 0B58 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0010 data: 0000 0000 0000 001D depth: 0000 0000 0000 0002
key: 0000 0000 0000 0011 data: 0000 0000 0000 0AD8 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0012 data: 0000 0000 0000 001B depth: 0000 0000 0000 0002
key: 0000 0000 0000 0013 data: 0000 0000 0000 0998 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0014 data: 0000 0000 0000 0019 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0015 data: 0000 0000 0000 0918 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0016 data: 0000 0000 0000 0017 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0017 data: 0000 0000 0000 0898 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0018 data: 0000 0000 0000 0015 depth: 0000 0000 0000 0001
key: 0000 0000 0000 0019 data: 0000 0000 0000 0818 depth: 0000 0000 0000 0002
key: 0000 0000 0000 001A data: 0000 0000 0000 0013 depth: 0000 0000 0000 0002
key: 0000 0000 0000 001B data: 0000 0000 0000 06D8 depth: 0000 0000 0000 0002
key: 0000 0000 0000 001C data: 0000 0000 0000 0011 depth: 0000 0000 0000 0002
key: 0000 0000 0000 001D data: 0000 0000 0000 0658 depth: 0000 0000 0000 0002
key: 0000 0000 0000 001E data: 0000 0000 0000 000F depth: 0000 0000 0000 0002
key: 0000 0000 0000 001F data: 0000 0000 0000 05D8 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0020 data: 0000 0000 0000 000D depth: 0000 0000 0000 0002
key: 0000 0000 0000 0021 data: 0000 0000 0000 0398 depth: 0000 0000 0000 0001
key: 0000 0000 0000 0022 data: 0000 0000 0000 000B depth: 0000 0000 0000 0002
key: 0000 0000 0000 0023 data: 0000 0000 0000 0318 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0024 data: 0000 0000 0000 0009 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0025 data: 0000 0000 0000 0298 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0026 data: 0000 0000 0000 0007 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0027 data: 0000 0000 0000 0218 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0028 data: 0000 0000 0000 0005 depth: 0000 0000 0000 0002
key: 0000 0000 0000 0029 data: 0000 0000 0000 0198 depth: 0000 0000 0000 0002
key: 0000 0000 0000 002A data: 0000 0000 0000 0003 depth: 0000 0000 0000 0002
key: 0000 0000 0000 002B data: 0000 0000 0000 0118 depth: 0000 0000 0000 0002
key: 0000 0000 0000 002C data: 0000 0000 0000 0001 depth: 0000 0000 0000 0002
key: 0000 0000 0000 002D data: 0000 0000 0000 0098 depth: 0000 0000 0000 0002
Tree at: r15: 0000 0000 0000 0098
Tree at: r15: 0000 0000 0000 0118
Tree at: r15: 0000 0000 0000 0198
Tree at: r15: 0000 0000 0000 0218
Tree at: r15: 0000 0000 0000 0298
Tree at: r15: 0000 0000 0000 0318
Tree at: r15: 0000 0000 0000 0398
Tree at: r15: 0000 0000 0000 05D8
Tree at: r15: 0000 0000 0000 0658
Tree at: r15: 0000 0000 0000 06D8
Tree at: r15: 0000 0000 0000 0818
Tree at: r15: 0000 0000 0000 0898
Tree at: r15: 0000 0000 0000 0918
Tree at: r15: 0000 0000 0000 0998
Tree at: r15: 0000 0000 0000 0AD8
Tree at: r15: 0000 0000 0000 0B58
Tree at: r15: 0000 0000 0000 0BD8
Tree at: r15: 0000 0000 0000 0C58
Tree at: r15: 0000 0000 0000 0CD8
Tree at: r15: 0000 0000 0000 0D58
Tree at: r15: 0000 0000 0000 0DD8
Tree at: r15: 0000 0000 0000 0E58
Tree at: r15: 0000 0000 0000 0ED8
END
Iteration
Iterate through a tree non recursively
Nasm::X86::Tree::iterator($b)
Iterate through a multi way tree
Parameter Description
1 $b Tree
Nasm::X86::Tree::Iterator::next($iter)
Next element in the tree
Parameter Description
1 $iter Iterator
Nasm::X86::Tree::by($b, $body)
Call the specified body with each (key, data) from the specified tree in order
Parameter Description
1 $b 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
Example:
Comment "Print a string from memory";
my $s = "Hello World";
Mov rax, Rs($s);
Mov rdi, length $s;
PrintOutMemory;
Exit(0); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok Assemble =~ m(Hello World);
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
Arena definition.
constant
Constant if true
count
Counter - number of node
data
Data at this position
expr
Expression that initializes the variable
first
Variable addressing offset to first block of keys.
found
Variable indicating whether the last find was successful or not
free
Free chain offset
in
Input parameter list
io
References to parameters
key
Key at this position
label
Address in memory
leftLength
Left split length
length
Maximum length in a block
lengthOffset
Offset of length in keys block. The length field is a word - see: "MultiWayTree.svg"
links
Location of links in bytes in zmm
loop
Offset of keys, data, node loop.
maxKeys
Maximum 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
out
Output parameter list
pos
Current position within node
prev
Location of prev offset in block in bytes
recursive
Recursive sub routine - parameters will be passed on the stack and variables will be defined on the stack
reference
Reference to another variable
rightLength
Right split length
size
Size field details
slots1
Number of slots in first block
slots2
Number of slots in second and subsequent blocks
splittingKey
POint at which to split a full block
stack
Position on stack, undefined if not held on the stack
start
Start label for this subroutine
structure
Structure details
subTree
Variable indicating whether the last find found a sub tree
tree
Tree we are iterating over
treeBits
Offset of tree bits in keys block. The tree bits field is a word, each bit of which tells us whether the corresponding data element is the offset (or not) to a sub tree of this tree .
treeBitsMask
14 tree bits
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
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 = V(a, 3); $a->outNL;
my $b = K(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,
Then
{PrintOutStringNL "a == 3"
},
Else
{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
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
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
Cstrlen()
Length of the C style string addressed by rax returning the length in r15
Nasm::X86::Arena::chain($arena, $bs, $variable, @offsets)
Return a variable with the end point of a chain of double words in the arena starting at the specified variable.
Parameter Description
1 $arena Arena descriptor
2 $bs Arena locator
3 $variable Start variable
4 @offsets Offsets chain
Example:
my $format = Rd(map{4*$_+24} 0..64);
my $b = CreateArena;
my $a = $b->allocBlock;
Vmovdqu8 zmm31, "[$format]";
$b->putBlock($b->bs, $a, 31);
my $r = $b->chain($b->bs, V(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, V(start, 0x18), 4, 4, 4); $A->outNL("chain4: "); # Get a long chain
$b->putChain($b->bs, V(start, 0x18), V(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 => [qw(c)], io => [qw(d e f)];
my $c = K(c, -1);
my $d = K(d, -1);
my $e = V(e, 1);
my $f = V(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
Arena
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::Arena::putChain($arena, $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 arena.
Parameter Description
1 $arena Arena descriptor
2 $bs Arena locator variable
3 $start Start variable
4 $value Value to put as a variable
5 @offsets Offsets chain
Nasm::X86::Arena::updateSpace($arena, @variables)
Make sure that the arena addressed by rax has enough space to accommodate content of length rdi
Parameter Description
1 $arena Arena descriptor
2 @variables Variables
Nasm::X86::Arena::blockSize($arena)
Size of a block
Parameter Description
1 $arena Arena
Nasm::X86::Arena::firstFreeBlock($arena)
Create and load a variable with the first free block on the free block chain or zero if no such block in the given arena
Parameter Description
1 $arena Arena address as a variable
Nasm::X86::Arena::setFirstFreeBlock($arena, $offset)
Set the first free block field from a variable
Parameter Description
1 $arena Arena descriptor
2 $offset First free block offset as a variable
Nasm::X86::Arena::freeBlock($arena, @variables)
Free a block in an arena by placing it on the free chain
Parameter Description
1 $arena Arena descriptor
2 @variables Variables
Example:
my $a = CreateArena; $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);
Arena
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
Arena
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
Arena
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
Arena
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
Arena
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::Arena::getBlock($arena, $address, $block, $zmm, $work1, $work2)
Get the block with the specified offset in the specified string and return it in the numbered zmm
Parameter Description
1 $arena Arena descriptor
2 $address Arena address variable
3 $block Offset of the block as a variable
4 $zmm Number of zmm register to contain block
5 $work1 First optional work register
6 $work2 Second optional work register
Nasm::X86::Arena::putBlock($arena, $address, $block, $zmm, $work1, $work2)
Write the numbered zmm to the block at the specified offset in the specified arena
Parameter Description
1 $arena Arena descriptor
2 $address Arena address variable
3 $block Offset of the block as a variable
4 $zmm Number of zmm register to contain block
5 $work1 First optional work register
6 $work2 Second optional work register
Nasm::X86::String::address($String)
Address of a string
Parameter Description
1 $String String descriptor
Nasm::X86::String::allocBlock($String)
Allocate a block to hold a zmm register in the specified arena and return the offset of the block in a variable
Parameter Description
1 $String String descriptor
Nasm::X86::String::getBlockLength($String, $zmm)
Get the block length of the numbered zmm and return it in a variable
Parameter Description
1 $String String descriptor
2 $zmm Number of zmm register
Nasm::X86::String::setBlockLengthInZmm($String, $length, $zmm)
Set the block length of the numbered zmm to the specified length
Parameter Description
1 $String String descriptor
2 $length Length as a variable
3 $zmm Number of zmm register
Nasm::X86::String::getBlock($String, $bsa, $block, $zmm)
Get the block with the specified offset in the specified string and return it in the numbered zmm
Parameter Description
1 $String String descriptor
2 $bsa Arena variable
3 $block Offset of the block as a variable
4 $zmm Number of zmm register to contain block
Nasm::X86::String::putBlock($String, $bsa, $block, $zmm)
Write the numbered zmm to the block at the specified offset in the specified arena
Parameter Description
1 $String String descriptor
2 $bsa Arena variable
3 $block Block in arena
4 $zmm Content variable
Nasm::X86::String::getNextAndPrevBlockOffsetFromZmm($String, $zmm)
Get the offsets of the next and previous blocks as variables from the specified zmm
Parameter Description
1 $String String descriptor
2 $zmm Zmm containing block
Nasm::X86::String::putNextandPrevBlockOffsetIntoZmm($String, $zmm, $next, $prev)
Save next and prev offsets into a zmm representing a block
Parameter Description
1 $String String descriptor
2 $zmm Zmm containing block
3 $next Next offset as a variable
4 $prev Prev offset as a variable
Nasm::X86::Array::address($Array)
Address of a string
Parameter Description
1 $Array Array descriptor
Nasm::X86::Array::allocBlock($Array)
Allocate a block to hold a zmm register in the specified arena and return the offset of the block in a variable
Parameter Description
1 $Array Array descriptor
Nasm::X86::Tree::allocKeysDataNode($t, $K, $D, $N, @variables)
Allocate a keys/data/node block and place it in the numbered zmm registers
Parameter Description
1 $t 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::Tree::splitNode($t, $bs, $node, $key, @variables)
Split a node given its offset in an arena retaining the key being inserted in the node split while putting the remainder to the left or right.
Parameter Description
1 $t Tree descriptor
2 $bs Backing arena
3 $node Offset of node
4 $key Key
5 @variables Variables
Nasm::X86::Tree::reParent($t, $bs, $PK, $PD, $PN, @variables)
Reparent the children of a node held in registers. The children are in the backing arena not registers.
Parameter Description
1 $t Tree descriptor
2 $bs Backing arena
3 $PK Numbered zmm key node
4 $PD Numbered zmm data node
5 $PN Numbered zmm child node
6 @variables Variables
Nasm::X86::Tree::transferTreeBitsFromParent($b, $parent, $left, $right)
Transfer tree bits when splitting a full node.
Parameter Description
1 $b Tree descriptor
2 $parent Numbered parent zmm
3 $left Numbered left zmm
4 $right Numbered right zmm
Example:
my $B = Rb(0..63);
Vmovdqu8 zmm0, "[$B]";
loadFromZmm r15, w, zmm, 14;
my $b = CreateArena;
my $t = $b->CreateTree;
$t->getTreeBits(0, r14);
PrintOutRegisterInHex zmm0, r15, r14;
Mov r14, my $treeBits = 0xDCBA;
$t->putTreeBits(1, r14);
PrintOutRegisterInHex zmm1;
$t->transferTreeBitsFromParent(1, 2, 3);
PrintOutStringNL "Split:";
PrintOutRegisterInHex zmm1, zmm2, zmm3;
my $left = $treeBits & ((1<<$t->leftLength) - 1);
my $right = ($treeBits >> ($t->leftLength + 1)) & ((1<<$t->rightLength) - 1);
my $l = sprintf("%02X", $left);
my $r = sprintf("%02X", $right);
ok Assemble(debug => 0, eq => <<END);
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
r15: 0000 0000 0000 0F0E
r14: 0000 0000 0000 3B3A
zmm1: 0000 0000 DCBA 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
Split:
zmm1: 0000 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
zmm2: 0000 0000 00$l 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
zmm3: 0000 0000 00$r 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
END
Nasm::X86::Tree::transferTreeBitsFromLeftOrRight($b, $rnl, $point, $parent, $left, $right)
Transfer tree bits when splitting a full left or right node.
Parameter Description
1 $b Tree descriptor
2 $rnl 0 - left 1 - right
3 $point Register indicating point of left in parent
4 $parent Numbered parent zmm
5 $left Numbered left zmm
6 $right Numbered right zmm
Nasm::X86::Tree::transferTreeBitsFromLeft($b, $point, $parent, $left, $right)
Transfer tree bits when splitting a full left node
Parameter Description
1 $b Tree descriptor
2 $point Register indicating point of left in parent
3 $parent Numbered parent zmm
4 $left Numbered left zmm
5 $right Numbered right zmm
Example:
my $b = CreateArena;
my $t = $b->CreateTree;
my $lR = "110110";
my $lP = "1";
my $lL = "1110111";
my $p1 = "01010_110010";
my $p2 = "1";
my $epe = sprintf("%04X", eval "0b$p1$lP$p2");
my $ele = sprintf("%04X", eval "0b$lL" );
my $ere = sprintf("%04X", eval "0b$lR" );
my @expected;
for my $i(0..1)
{Mov r15, eval "0b$lR$lP$lL"; $t->putTreeBits(1+$i, r15);
Mov r15, eval "0b$p1$p2"; $t->putTreeBits(0, r15);
PrintOutRegisterInHex zmm 0, 1+$i;
Mov r15, 0b10;
$t->transferTreeBitsFromLeft (r15, 0, 1, 2) unless $i;
$t->transferTreeBitsFromRight(r15, 0, 1, 2) if $i;
PrintOutRegisterInHex zmm 0..2;
my $zzz = $i ? "zmm2" : "zmm1";
push @expected, <<END;
zmm0: 0000 0000 0565 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
$zzz: 0000 0000 36F7 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
zmm0: 0000 0000 $epe 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
zmm1: 0000 0000 $ele 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
zmm2: 0000 0000 $ere 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
END
}
ok Assemble(debug => 0, eq => join "", @expected);
Nasm::X86::Tree::transferTreeBitsFromRight($b, $point, $parent, $left, $right)
Transfer tree bits when splitting a full right node
Parameter Description
1 $b Tree descriptor
2 $point Register indicating point of right in parent
3 $parent Numbered parent zmm
4 $left Numbered left zmm
5 $right Numbered right zmm
Example:
my $b = CreateArena;
my $t = $b->CreateTree;
my $lR = "110110";
my $lP = "1";
my $lL = "1110111";
my $p1 = "01010_110010";
my $p2 = "1";
my $epe = sprintf("%04X", eval "0b$p1$lP$p2");
my $ele = sprintf("%04X", eval "0b$lL" );
my $ere = sprintf("%04X", eval "0b$lR" );
my @expected;
for my $i(0..1)
{Mov r15, eval "0b$lR$lP$lL"; $t->putTreeBits(1+$i, r15);
Mov r15, eval "0b$p1$p2"; $t->putTreeBits(0, r15);
PrintOutRegisterInHex zmm 0, 1+$i;
Mov r15, 0b10;
$t->transferTreeBitsFromLeft (r15, 0, 1, 2) unless $i;
$t->transferTreeBitsFromRight(r15, 0, 1, 2) if $i;
PrintOutRegisterInHex zmm 0..2;
my $zzz = $i ? "zmm2" : "zmm1";
push @expected, <<END;
zmm0: 0000 0000 0565 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
$zzz: 0000 0000 36F7 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
zmm0: 0000 0000 $epe 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
zmm1: 0000 0000 $ele 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
zmm2: 0000 0000 $ere 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
END
}
ok Assemble(debug => 0, eq => join "", @expected);
Nasm::X86::Tree::splitFullRoot($t)
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 $t Tree descriptor
Nasm::X86::Tree::splitFullLeftOrRightNode($t, $right)
Split a full a full left node (held in 28..26) or a full right node (held in 25..23) whose parent is in 31..29.
Parameter Description
1 $t Tree descriptor
2 $right 0 left or 1 right
Nasm::X86::Tree::splitFullLeftNode($t)
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 $t Tree descriptor
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 = CreateArena;
my $t = $b->CreateTree;
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;
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::Tree::splitFullRightNode($t)
Split a full right node block held in 25..23 whose parent is in 31..29 and place the new left block in 28..26. The loop and length fields are assumed to be authoritative and hence are preserved.
Parameter Description
1 $t Tree descriptor
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 = CreateArena;
my $t = $b->CreateTree;
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;
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::Tree::findAndSplit($t, @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 $t Tree descriptor
2 @variables Variables
Nasm::X86::Tree::getKeysData($t, $offset, $zmmKeys, $zmmData, $work1, $work2)
Load the keys and data blocks for a node
Parameter Description
1 $t Tree descriptor
2 $offset Offset as a variable
3 $zmmKeys Numbered zmm for keys
4 $zmmData Numbered data for keys
5 $work1 Optional first work register
6 $work2 Optional second work register
Nasm::X86::Tree::putKeysData($t, $offset, $zmmKeys, $zmmData, $work1, $work2)
Save the key and data blocks for a node
Parameter Description
1 $t Tree descriptor
2 $offset Offset as a variable
3 $zmmKeys Numbered zmm for keys
4 $zmmData Numbered data for keys
5 $work1 Optional first work register
6 $work2 Optional second work register
Nasm::X86::Tree::getKeysDataNode($t, $offset, $zmmKeys, $zmmData, $zmmNode, $work1, $work2)
Load the keys, data and child nodes for a node
Parameter Description
1 $t 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
6 $work1 Optional first work register
7 $work2 Optional second work register
Nasm::X86::Tree::putKeysDataNode($t, $offset, $zmmKeys, $zmmData, $zmmNode, $work1, $work2)
Save the keys, data and child nodes for a node
Parameter Description
1 $t 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
6 $work1 Optional first work register
7 $work2 Optional second work register
Nasm::X86::Tree::getLengthInKeys($t, $zmm)
Get the length of the keys block in the numbered zmm and return it as a variable
Parameter Description
1 $t Tree descriptor
2 $zmm Zmm number
Nasm::X86::Tree::putLengthInKeys($t, $zmm, $length)
Get the length of the block in the numbered zmm from the specified variable
Parameter Description
1 $t Tree
2 $zmm Zmm number
3 $length Length variable
Nasm::X86::Tree::getUpFromData($t, $zmm, $transfer)
Get the up offset from the data block in the numbered zmm and return it as a variable
Parameter Description
1 $t Tree descriptor
2 $zmm Zmm number
3 $transfer Transfer register
Nasm::X86::Tree::putUpIntoData($t, $offset, $zmm, $transfer)
Put the offset of the parent keys block expressed as a variable into the numbered zmm
Parameter Description
1 $t Tree descriptor
2 $offset Variable containing up offset
3 $zmm Zmm number
4 $transfer Optional transfer register
Nasm::X86::Tree::getLoop($t, $zmm, $transfer)
Return the value of the loop field as a variable
Parameter Description
1 $t Tree descriptor
2 $zmm Numbered zmm
3 $transfer Optional transfer register
Nasm::X86::Tree::putLoop($t, $value, $zmm, $transfer)
Set the value of the loop field from a variable
Parameter Description
1 $t Tree descriptor
2 $value Variable containing offset of next loop entry
3 $zmm Numbered zmm
4 $transfer Optional transfer register
Nasm::X86::Tree::nodeFromData($t, $data, $node)
Load the the node block into the numbered zmm corresponding to the data block held in the numbered zmm.
Parameter Description
1 $t Tree descriptor
2 $data Numbered zmm containing data
3 $node Numbered zmm to hold node block
Nasm::X86::Tree::address($t)
Address of the arena containing a tree
Parameter Description
1 $t Tree descriptor
Nasm::X86::Tree::allocBlock($t, @variables)
Allocate a block to hold a zmm register in the specified arena and return the offset of the block in a variable
Parameter Description
1 $t Tree descriptor
2 @variables Variables
Nasm::X86::Tree::isTree($t, $register, $zmm)
Set the Zero Flag to oppose the tree bit in the numbered zmm register holding the keys of a node to indicate whether the data element indicated by the specified register is an offset to a sub tree in the containing arena or not.
Parameter Description
1 $t Tree descriptor
2 $register Word register holding a bit shifted into the position to test
3 $zmm Numbered zmm register holding the keys for a node in the tree
Nasm::X86::Tree::setOrClearTree($t, $set, $register, $zmm)
Set or clear the tree bit in the numbered zmm register holding the keys of a node to indicate that the data element indicated by the specified register is an offset to a sub tree in the containing arena.
Parameter Description
1 $t Tree descriptor
2 $set Set if true else clear
3 $register Register holding a single one in the lowest 14 bits at the insertion point
4 $zmm Numbered zmm register holding the keys for a node in the tree
Nasm::X86::Tree::setTree($t, $register, $zmm)
Set the tree bit in the numbered zmm register holding the keys of a node to indicate that the data element indexed by the specified register is an offset to a sub tree in the containing arena.
Parameter Description
1 $t Tree descriptor
2 $register Register holding data element index 0..13
3 $zmm Numbered zmm register holding the keys for a node in the tree
Nasm::X86::Tree::clearTree($t, $register, $zmm)
Clear the tree bit in the numbered zmm register holding the keys of a node to indicate that the data element indexed by the specified register is an offset to a sub tree in the containing arena.
Parameter Description
1 $t Tree descriptor
2 $register Register holding data element index 0..13
3 $zmm Numbered zmm register holding the keys for a node in the tree
Nasm::X86::Tree::getTreeBits($t, $zmm, $register)
Load the tree bits from the numbered zmm into the specified register.
Parameter Description
1 $t Tree descriptor
2 $zmm Numbered zmm
3 $register Target register
Nasm::X86::Tree::putTreeBits($t, $zmm, $register)
Put the tree bits in the specified register into the numbered zmm.
Parameter Description
1 $t Tree descriptor
2 $zmm Numbered zmm
3 $register Target register
Nasm::X86::Tree::expandTreeBitsWithZeroOrOne($t, $onz, $zmm, $point)
Insert a zero or one into the tree bits field in the numbered zmm at the specified point
Parameter Description
1 $t Tree descriptor
2 $onz 0 - zero or 1 - one
3 $zmm Numbered zmm
4 $point Register indicating point
Nasm::X86::Tree::expandTreeBitsWithZero($t, $zmm, $point)
Insert a zero into the tree bits field in the numbered zmm at the specified point
Parameter Description
1 $t Tree descriptor
2 $zmm Numbered zmm
3 $point Register indicating point
Nasm::X86::Tree::expandTreeBitsWithOne($t, $zmm, $point)
Insert a one into the tree bits field in the numbered zmm at the specified point
Parameter Description
1 $t Tree descriptor
2 $zmm Numbered zmm
3 $point Register indicating point
LocateIntelEmulator()
Locate the Intel Software Development Emulator
getInstructionCount()
Get the number of instructions executed from the emulator mix file.
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 CheckGeneralPurposeRegister - Check that a register is in fact a general purpose register
8 CheckMaskRegister - Check that a register is in fact a mask register
9 CheckNumberedGeneralPurposeRegister - Check that a register is in fact a numbered general purpose register
10 ChooseRegisters - Choose the specified numbers of registers excluding those on the specified list
11 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.
12 ClassifyRange - Implementation of ClassifyInRange and ClassifyWithinRange
13 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.
14 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.
15 ClearMemory - Clear memory - the address of the memory is in rax, the length in rdi
16 ClearRegisters - Clear registers by setting them to zero
17 ClearZF - Clear the zero flag
18 CloseFile - Close the file whose descriptor is in rax
19 Comment - Insert a comment into the assembly code
20 CommentWithTraceBack - Insert a comment into the assembly code with a traceback showing how it was generated
21 ConcatenateShortStrings - Concatenate the numbered source zmm containing a short string with the short string in the numbered target zmm.
22 ConvertUtf8ToUtf32 - Convert a string of utf8 to an allocated block of utf32 and return its address and length.
23 CopyMemory - Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
24 cr - Call a subroutine with a reordering of the registers.
25 CreateArena - Create an relocatable arena and returns its address in rax.
26 Cstrlen - Length of the C style string addressed by rax returning the length in r15
27 Db - Layout bytes in the data segment and return their label
28 Dbwdq - Layout data
29 DComment - Insert a comment into the data segment
30 Dd - Layout double words in the data segment and return their label
31 Dq - Layout quad words in the data segment and return their label
32 Ds - Layout bytes in memory and return their label
33 Dw - Layout words in the data segment and return their label
34 Else - Else body for an If statement
35 executeFileViaBash - Execute the file named in the arena addressed by rax with bash
36 Exit - Exit with the specified return code or zero if no return code supplied.
37 Extern - Name external references
38 For - For - iterate the body as long as register is less than limit incrementing by increment each time
39 ForEver - Iterate for ever
40 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.
41 Fork - Fork
42 FreeMemory - Free memory
43 getBFromXmm - Get the byte from the numbered xmm register and return it in a variable
44 getBFromZmm - Get the byte from the numbered zmm register and return it in a variable
45 getBwdqFromMm - Get the numbered byte|word|double word|quad word from the numbered zmm register and return it in a variable
46 getDFromXmm - Get the double word from the numbered xmm register and return it in a variable
47 getDFromZmm - Get the double word from the numbered zmm register and return it in a variable
48 getInstructionCount - Get the number of instructions executed from the emulator mix file.
49 GetLengthOfShortString - Get the length of the short string held in the numbered zmm register into the specified register
50 GetNextUtf8CharAsUtf32 - Get the next utf8 encoded character from the addressed memory and return it as a utf32 char
51 GetPid - Get process identifier
52 GetPidInHex - Get process identifier in hex as 8 zero terminated bytes in rax
53 GetPPid - Get parent process identifier
54 getQFromXmm - Get the quad word from the numbered xmm register and return it in a variable
55 getQFromZmm - Get the quad word from the numbered zmm register and return it in a variable
56 GetUid - Get userid of current process
57 getWFromXmm - Get the word from the numbered xmm register and return it in a variable
58 getWFromZmm - Get the word from the numbered zmm register and return it in a variable
59 Hash - Hash a string addressed by rax with length held in rdi and return the hash code in r15
60 hexTranslateTable - Create/address a hex translate table and return its label
61 If - If
62 IfC - If the carry flag is set then execute the then body else the else body
63 IfEq - If equal execute the then body else the else body
64 IfGe - If greater than or equal execute the then body else the else body
65 IfGt - If greater than execute the then body else the else body
66 IfLe - If less than or equal execute the then body else the else body
67 IfLt - If less than execute the then body else the else body
68 IfNc - If the carry flag is not set then execute the then body else the else body
69 IfNe - If not equal execute the then body else the else body
70 IfNz - If the zero flag is not set then execute the then body else the else body
71 IfZ - If the zero flag is set then execute the then body else the else body
72 InsertOneIntoRegisterAtPoint - Insert a one into the specified register at the point indicated by another register
73 InsertZeroIntoRegisterAtPoint - Insert a zero into the specified register at the point indicated by another register
74 K - Define a quad constant
75 Keep - Mark registers as in use so that they cannot be updated until we explicitly free them.
76 KeepFree - Free registers so that they can be reused
77 KeepPop - Reset the status of the specified registers to the status quo ante the last push
78 KeepPush - Push the current status of the specified registers and then mark them as free
79 KeepReturn - Pop the specified register and mark it as in use to effect a subroutine return with this register.
80 KeepSet - Confirm that the specified registers are in use
81 Label - Create a unique label
82 Link - Libraries to link with
83 LoadBitsIntoMaskRegister - Load a bit string specification into a mask register
84 LoadConstantIntoMaskRegister - Set a mask register equal to a constant.
85 loadFromZmm - Load the specified register from the offset located in the numbered zmm.
86 LoadShortStringFromMemoryToZmm - Load the short string addressed by rax into the zmm register with the specified number
87 LoadZmm - Load a numbered zmm with the specified bytes
88 LocalData - Map local data
89 LocateIntelEmulator - Locate the Intel Software Development Emulator
90 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
91 MaskMemory22 - Write the specified byte into locations in the target mask that correspond to the locations in the source that contain the specified byte.
92 MaskMemoryInRange4_22 - 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.
93 Nasm::X86::Arena::allocate - Allocate the amount of space indicated in rdi in the arena addressed by rax and return the offset of the allocation in the arena in rdi
94 Nasm::X86::Arena::allocBlock - Allocate a block to hold a zmm register in the specified arena and return the offset of the block in a variable
95 Nasm::X86::Arena::allocZmmBlock - Allocate a block to hold a zmm register in the specified arena and return the offset of the block in a variable
96 Nasm::X86::Arena::append - Append one arena to another
97 Nasm::X86::Arena::blockSize - Size of a block
98 Nasm::X86::Arena::chain - Return a variable with the end point of a chain of double words in the arena starting at the specified variable.
99 Nasm::X86::Arena::char - Append a character expressed as a decimal number to the arena addressed by rax
100 Nasm::X86::Arena::clear - Clear the arena addressed by rax
101 Nasm::X86::Arena::CreateArray - Create a array in an arena
102 Nasm::X86::Arena::CreateString - Create a string from a doubly link linked list of 64 byte blocks linked via 4 byte offsets in the arena addressed by rax and return its descriptor
103 Nasm::X86::Arena::CreateTree - Create a tree in an arena.
104 Nasm::X86::Arena::DescribeTree - Return a descriptor for a tree in the specified arena
105 Nasm::X86::Arena::dump - Dump details of an arena
106 Nasm::X86::Arena::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 arena
107 Nasm::X86::Arena::freeBlock - Free a block in an arena by placing it on the free chain
108 Nasm::X86::Arena::getBlock - Get the block with the specified offset in the specified string and return it in the numbered zmm
109 Nasm::X86::Arena::length - Get the length of an arena
110 Nasm::X86::Arena::m - Append the content with length rdi addressed by rsi to the arena addressed by rax
111 Nasm::X86::Arena::makeReadOnly - Make an arena read only
112 Nasm::X86::Arena::makeWriteable - Make an arena writable
113 Nasm::X86::Arena::nl - Append a new line to the arena addressed by rax
114 Nasm::X86::Arena::out - Print the specified arena addressed by rax on sysout
115 Nasm::X86::Arena::putBlock - Write the numbered zmm to the block at the specified offset in the specified arena
116 Nasm::X86::Arena::putChain - Write the double word in the specified variable to the double word location at the the specified offset in the specified arena.
117 Nasm::X86::Arena::q - Append a constant string to the arena
118 Nasm::X86::Arena::ql - Append a quoted string containing new line characters to the arena addressed by rax
119 Nasm::X86::Arena::read - Read the named file (terminated with a zero byte) and place it into the named arena.
120 Nasm::X86::Arena::setFirstFreeBlock - Set the first free block field from a variable
121 Nasm::X86::Arena::updateSpace - Make sure that the arena addressed by rax has enough space to accommodate content of length rdi
122 Nasm::X86::Arena::write - Write the content in an arena addressed by rax to a temporary file and replace the arena content with the name of the temporary file
123 Nasm::X86::Arena::z - Append a trailing zero to the arena addressed by rax
124 Nasm::X86::Array::address - Address of a string
125 Nasm::X86::Array::allocBlock - Allocate a block to hold a zmm register in the specified arena and return the offset of the block in a variable
126 Nasm::X86::Array::dump - Dump a array
127 Nasm::X86::Array::get - Get an element from the array
128 Nasm::X86::Array::pop - Pop an element from an array
129 Nasm::X86::Array::push - Push an element onto the array
130 Nasm::X86::Array::put - Put an element into an array as long as it is with in its limits established by pushing.
131 Nasm::X86::LocalData::allocate8 - Add some 8 byte local variables and return an array of variable definitions
132 Nasm::X86::LocalData::free - Free a local data area on the stack
133 Nasm::X86::LocalData::start - Start a local data area on the stack
134 Nasm::X86::LocalData::variable - Add a local variable
135 Nasm::X86::LocalVariable::stack - Address a local variable on the stack
136 Nasm::X86::String::address - Address of a string
137 Nasm::X86::String::allocBlock - Allocate a block to hold a zmm register in the specified arena and return the offset of the block in a variable
138 Nasm::X86::String::append - Append the specified content in memory to the specified string
139 Nasm::X86::String::clear - Clear the block by freeing all but the first block
140 Nasm::X86::String::concatenate - Concatenate two strings by appending a copy of the source to the target string.
141 Nasm::X86::String::deleteChar - Delete a character in a string
142 Nasm::X86::String::dump - Dump a string to sysout
143 Nasm::X86::String::getBlock - Get the block with the specified offset in the specified string and return it in the numbered zmm
144 Nasm::X86::String::getBlockLength - Get the block length of the numbered zmm and return it in a variable
145 Nasm::X86::String::getCharacter - Get a character from a string
146 Nasm::X86::String::getNextAndPrevBlockOffsetFromZmm - Get the offsets of the next and previous blocks as variables from the specified zmm
147 Nasm::X86::String::insertChar - Insert a character into a string
148 Nasm::X86::String::len - Find the length of a string
149 Nasm::X86::String::putBlock - Write the numbered zmm to the block at the specified offset in the specified arena
150 Nasm::X86::String::putNextandPrevBlockOffsetIntoZmm - Save next and prev offsets into a zmm representing a block
151 Nasm::X86::String::setBlockLengthInZmm - Set the block length of the numbered zmm to the specified length
152 Nasm::X86::Structure::field - Add a field of the specified length with an optional comment
153 Nasm::X86::StructureField::addr - Address a field in a structure by either the default register or the named register
154 Nasm::X86::Sub::call - Call a sub passing it some parameters
155 Nasm::X86::Tree::address - Address of the arena containing a tree
156 Nasm::X86::Tree::allocBlock - Allocate a block to hold a zmm register in the specified arena and return the offset of the block in a variable
157 Nasm::X86::Tree::allocKeysDataNode - Allocate a keys/data/node block and place it in the numbered zmm registers
158 Nasm::X86::Tree::by - Call the specified body with each (key, data) from the specified tree in order
159 Nasm::X86::Tree::clearTree - Clear the tree bit in the numbered zmm register holding the keys of a node to indicate that the data element indexed by the specified register is an offset to a sub tree in the containing arena.
160 Nasm::X86::Tree::Clone - Clone the specified tree descriptions
161 Nasm::X86::Tree::depth - Return the depth of a node within a tree.
162 Nasm::X86::Tree::expandTreeBitsWithOne - Insert a one into the tree bits field in the numbered zmm at the specified point
163 Nasm::X86::Tree::expandTreeBitsWithZero - Insert a zero into the tree bits field in the numbered zmm at the specified point
164 Nasm::X86::Tree::expandTreeBitsWithZeroOrOne - Insert a zero or one into the tree bits field in the numbered zmm at the specified point
165 Nasm::X86::Tree::find - Find a key in a tree and test whether the found data is a sub tree.
166 Nasm::X86::Tree::findAndClone - Find a key in the specified tree and clone it is it is a sub tree.
167 Nasm::X86::Tree::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.
168 Nasm::X86::Tree::getKeysData - Load the keys and data blocks for a node
169 Nasm::X86::Tree::getKeysDataNode - Load the keys, data and child nodes for a node
170 Nasm::X86::Tree::getLengthInKeys - Get the length of the keys block in the numbered zmm and return it as a variable
171 Nasm::X86::Tree::getLoop - Return the value of the loop field as a variable
172 Nasm::X86::Tree::getTreeBits - Load the tree bits from the numbered zmm into the specified register.
173 Nasm::X86::Tree::getUpFromData - Get the up offset from the data block in the numbered zmm and return it as a variable
174 Nasm::X86::Tree::insert - Insert a dword into into the specified tree at the specified key.
175 Nasm::X86::Tree::insertDataOrTree - Insert either a key, data pair into the tree or create a sub tree at the specified key (if it does not already exist) and return the offset of the first block of the sub tree in the data variable.
176 Nasm::X86::Tree::insertTree - Insert a sub tree into the specified tree tree under the specified key.
177 Nasm::X86::Tree::insertTreeAndClone - Insert a new sub tree into the specified tree tree under the specified key and return a descriptor for it.
178 Nasm::X86::Tree::isTree - Set the Zero Flag to oppose the tree bit in the numbered zmm register holding the keys of a node to indicate whether the data element indicated by the specified register is an offset to a sub tree in the containing arena or not.
179 Nasm::X86::Tree::iterator - Iterate through a multi way tree
180 Nasm::X86::Tree::Iterator::next - Next element in the tree
181 Nasm::X86::Tree::leftMost - Return the left most node
182 Nasm::X86::Tree::leftOrRightMost - Return the left most or right most node
183 Nasm::X86::Tree::nodeFromData - Load the the node block into the numbered zmm corresponding to the data block held in the numbered zmm.
184 Nasm::X86::Tree::print - Print a tree
185 Nasm::X86::Tree::putKeysData - Save the key and data blocks for a node
186 Nasm::X86::Tree::putKeysDataNode - Save the keys, data and child nodes for a node
187 Nasm::X86::Tree::putLengthInKeys - Get the length of the block in the numbered zmm from the specified variable
188 Nasm::X86::Tree::putLoop - Set the value of the loop field from a variable
189 Nasm::X86::Tree::putTreeBits - Put the tree bits in the specified register into the numbered zmm.
190 Nasm::X86::Tree::putUpIntoData - Put the offset of the parent keys block expressed as a variable into the numbered zmm
191 Nasm::X86::Tree::reParent - Reparent the children of a node held in registers.
192 Nasm::X86::Tree::rightMost - Return the right most node
193 Nasm::X86::Tree::setOrClearTree - Set or clear the tree bit in the numbered zmm register holding the keys of a node to indicate that the data element indicated by the specified register is an offset to a sub tree in the containing arena.
194 Nasm::X86::Tree::setTree - Set the tree bit in the numbered zmm register holding the keys of a node to indicate that the data element indexed by the specified register is an offset to a sub tree in the containing arena.
195 Nasm::X86::Tree::splitFullLeftNode - Split a full left node block held in 28.
196 Nasm::X86::Tree::splitFullLeftOrRightNode - Split a full a full left node (held in 28.
197 Nasm::X86::Tree::splitFullRightNode - Split a full right node block held in 25.
198 Nasm::X86::Tree::splitFullRoot - Split a full root block held in 31.
199 Nasm::X86::Tree::splitNode - Split a node given its offset in an arena retaining the key being inserted in the node split while putting the remainder to the left or right.
200 Nasm::X86::Tree::transferTreeBitsFromLeft - Transfer tree bits when splitting a full left node
201 Nasm::X86::Tree::transferTreeBitsFromLeftOrRight - Transfer tree bits when splitting a full left or right node.
202 Nasm::X86::Tree::transferTreeBitsFromParent - Transfer tree bits when splitting a full node.
203 Nasm::X86::Tree::transferTreeBitsFromRight - Transfer tree bits when splitting a full right node
204 Nasm::X86::Variable::add - Add the right hand variable to the left hand variable and return the result as a new variable
205 Nasm::X86::Variable::address - Get the address of a variable with an optional offset
206 Nasm::X86::Variable::allocateMemory - Allocate the specified amount of memory via mmap and return its address
207 Nasm::X86::Variable::and - And two variables
208 Nasm::X86::Variable::arithmetic - Return a variable containing the result of an arithmetic operation on the left hand and right hand side variables
209 Nasm::X86::Variable::assign - Assign to the left hand side the value of the right hand side
210 Nasm::X86::Variable::boolean - Combine the left hand variable with the right hand variable via a boolean operator
211 Nasm::X86::Variable::booleanC - Combine the left hand variable with the right hand variable via a boolean operator using a conditional move instruction.
212 Nasm::X86::Variable::clearBit - Clear a bit in the specified mask register retaining the other bits
213 Nasm::X86::Variable::clearMaskBit - Clear a bit in the specified mask register retaining the other bits
214 Nasm::X86::Variable::clearMemory - Clear the memory described in this variable
215 Nasm::X86::Variable::clone - Clone a variable to create a new variable
216 Nasm::X86::Variable::copy - Copy one variable into another
217 Nasm::X86::Variable::copyAddress - Copy a reference to a variable
218 Nasm::X86::Variable::copyMemory - Copy from one block of memory to another
219 Nasm::X86::Variable::copyZF - Copy the current state of the zero flag into a variable
220 Nasm::X86::Variable::copyZFInverted - Copy the opposite of the current state of the zero flag into a variable
221 Nasm::X86::Variable::debug - Dump the value of a variable on stdout with an indication of where the dump came from
222 Nasm::X86::Variable::dec - Decrement a variable
223 Nasm::X86::Variable::divide - Divide the left hand variable by the right hand variable and return the result as a new variable
224 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
225 Nasm::X86::Variable::dump - Dump the value of a variable to the specified channel adding an optional title and new line if requested
226 Nasm::X86::Variable::eq - Check whether the left hand variable is equal to the right hand variable
227 Nasm::X86::Variable::equals - Equals operator
228 Nasm::X86::Variable::err - Dump the value of a variable on stderr
229 Nasm::X86::Variable::errNL - Dump the value of a variable on stderr and append a new line
230 Nasm::X86::Variable::for - Iterate the body limit times.
231 Nasm::X86::Variable::freeMemory - Free the memory addressed by this variable for the specified length
232 Nasm::X86::Variable::ge - Check whether the left hand variable is greater than or equal to the right hand variable
233 Nasm::X86::Variable::getBFromZmm - Get the byte from the numbered zmm register and put it in a variable
234 Nasm::X86::Variable::getConst - Load the variable from a constant in effect setting a variable to a specified value
235 Nasm::X86::Variable::getDFromZmm - Get the double word from the numbered zmm register and put it in a variable
236 Nasm::X86::Variable::getQFromZmm - Get the quad word from the numbered zmm register and put it in a variable
237 Nasm::X86::Variable::getReg - Load the variable from the named registers
238 Nasm::X86::Variable::getWFromZmm - Get the word from the numbered zmm register and put it in a variable
239 Nasm::X86::Variable::gt - Check whether the left hand variable is greater than the right hand variable
240 Nasm::X86::Variable::inc - Increment a variable
241 Nasm::X86::Variable::incDec - Increment or decrement a variable
242 Nasm::X86::Variable::isRef - Check whether the specified variable is a reference to another variable
243 Nasm::X86::Variable::le - Check whether the left hand variable is less than or equal to the right hand variable
244 Nasm::X86::Variable::loadZmm - Load bytes from the memory addressed by the specified source variable into the numbered zmm register.
245 Nasm::X86::Variable::lt - Check whether the left hand variable is less than the right hand variable
246 Nasm::X86::Variable::max - Maximum of two variables
247 Nasm::X86::Variable::min - Minimum of two variables
248 Nasm::X86::Variable::minusAssign - Implement minus and assign
249 Nasm::X86::Variable::mod - Divide the left hand variable by the right hand variable and return the remainder as a new variable
250 Nasm::X86::Variable::ne - Check whether the left hand variable is not equal to the right hand variable
251 Nasm::X86::Variable::or - Or two variables
252 Nasm::X86::Variable::out - Dump the value of a variable on stdout
253 Nasm::X86::Variable::outNL - Dump the value of a variable on stdout and append a new line
254 Nasm::X86::Variable::plusAssign - Implement plus and assign
255 Nasm::X86::Variable::pop - Pop a variable from the stack
256 Nasm::X86::Variable::printErrMemoryInHexNL - Write the memory addressed by a variable to stderr
257 Nasm::X86::Variable::printMemoryInHexNL - Write the memory addressed by a variable to stdout or stderr
258 Nasm::X86::Variable::printOutMemoryInHexNL - Write the memory addressed by a variable to stdout
259 Nasm::X86::Variable::push - Push a variable onto the stack
260 Nasm::X86::Variable::putBIntoXmm - Place the value of the content variable at the byte in the numbered xmm register
261 Nasm::X86::Variable::putBIntoZmm - Place the value of the content variable at the byte in the numbered zmm register
262 Nasm::X86::Variable::putBwdqIntoMm - Place the value of the content variable at the byte|word|double word|quad word in the numbered zmm register
263 Nasm::X86::Variable::putDIntoXmm - Place the value of the content variable at the double word in the numbered xmm register
264 Nasm::X86::Variable::putDIntoZmm - Place the value of the content variable at the double word in the numbered zmm register
265 Nasm::X86::Variable::putQIntoXmm - Place the value of the content variable at the quad word in the numbered xmm register
266 Nasm::X86::Variable::putQIntoZmm - Place the value of the content variable at the quad word in the numbered zmm register
267 Nasm::X86::Variable::putWIntoXmm - Place the value of the content variable at the word in the numbered xmm register
268 Nasm::X86::Variable::putWIntoZmm - Place the value of the content variable at the word in the numbered zmm register
269 Nasm::X86::Variable::setBit - Set a bit in the specified register retaining the other bits
270 Nasm::X86::Variable::setMask - Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere
271 Nasm::X86::Variable::setMaskBit - Set a bit in the specified mask register retaining the other bits
272 Nasm::X86::Variable::setMaskFirst - Set the first bits in the specified mask register
273 Nasm::X86::Variable::setReg - Set the named registers from the content of the variable
274 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
275 Nasm::X86::Variable::str - The name of the variable
276 Nasm::X86::Variable::sub - Subtract the right hand variable from the left hand variable and return the result as a new variable
277 Nasm::X86::Variable::times - Multiply the left hand variable by the right hand variable and return the result as a new variable
278 Nasm::X86::Variable::zBroadCastD - Broadcast a double word in a variable into the numbered zmm.
279 OpenRead - Open a file, whose name is addressed by rax, for read and return the file descriptor in rax
280 OpenWrite - Create the file named by the terminated string addressed by rax for write
281 PeekR - Peek at register on stack
282 PopEax - We cannot pop a double word from the stack in 64 bit long mode using pop so we improvise
283 PopR - Pop registers from the stack
284 PopRR - Pop registers from the stack without tracking
285 PrintErrMemory - Print the memory addressed by rax for a length of rdi on stderr
286 PrintErrMemoryInHex - Dump memory from the address in rax for the length in rdi on stderr
287 PrintErrMemoryInHexNL - Dump memory from the address in rax for the length in rdi and then print a new line
288 PrintErrMemoryNL - Print the memory addressed by rax for a length of rdi followed by a new line on stderr
289 PrintErrNL - Print a new line to stderr
290 PrintErrRaxInHex - Write the content of register rax in hexadecimal in big endian notation to stderr
291 PrintErrRegisterInHex - Print the named registers as hex strings on stderr
292 PrintErrString - Print a constant string to stderr.
293 PrintErrStringNL - Print a constant string followed by a new line to stderr
294 PrintErrZF - Print the zero flag without disturbing it on stderr
295 PrintMemory - Print the memory addressed by rax for a length of rdi on the specified channel
296 PrintMemoryInHex - Dump memory from the address in rax for the length in rdi on the specified channel.
297 PrintNL - Print a new line to stdout or stderr
298 PrintOutMemory - Print the memory addressed by rax for a length of rdi on stdout
299 PrintOutMemoryInHex - Dump memory from the address in rax for the length in rdi on stdout
300 PrintOutMemoryInHexNL - Dump memory from the address in rax for the length in rdi and then print a new line
301 PrintOutMemoryNL - Print the memory addressed by rax for a length of rdi followed by a new line on stdout
302 PrintOutNL - Print a new line to stderr
303 PrintOutRaxInHex - Write the content of register rax in hexadecimal in big endian notation to stderr
304 PrintOutRaxInReverseInHex - Write the content of register rax to stderr in hexadecimal in little endian notation
305 PrintOutRegisterInHex - Print the named registers as hex strings on stdout
306 PrintOutRegistersInHex - Print the general purpose registers in hex
307 PrintOutRflagsInHex - Print the flags register in hex
308 PrintOutRipInHex - Print the instruction pointer in hex
309 PrintOutString - Print a constant string to stdout.
310 PrintOutStringNL - Print a constant string followed by a new line to stdout
311 PrintOutZF - Print the zero flag without disturbing it on stdout
312 PrintRaxInHex - Write the content of register rax in hexadecimal in big endian notation to the specified channel
313 PrintRegisterInHex - Print the named registers as hex strings
314 PrintString - Print a constant string to the specified channel
315 PrintUtf32 - Print the specified number of utf32 characters at the specified address
316 PushR - Push registers onto the stack
317 PushRR - Push registers onto the stack without tracking
318 putIntoZmm - Put the specified register into the numbered zmm at the from the offset located in the numbered zmm.
319 R - Define a reference variable
320 Rb - Layout bytes in the data segment and return their label
321 Rbwdq - Layout data
322 RComment - Insert a comment into the read only data segment
323 Rd - Layout double words in the data segment and return their label
324 ReadFile - Read a file whose name is addressed by rax into memory.
325 ReadTimeStampCounter - Read the time stamp counter and return the time in nanoseconds in rax
326 RegisterSize - Return the size of a register
327 removeNonAsciiChars - Return a copy of the specified string with all the non ascii characters removed
328 ReorderSyscallRegisters - Map the list of registers provided to the 64 bit system call sequence
329 RestoreFirstFour - Restore the first 4 parameter registers
330 RestoreFirstFourExceptRax - Restore the first 4 parameter registers except rax so it can return its value
331 RestoreFirstFourExceptRaxAndRdi - Restore the first 4 parameter registers except rax and rdi so we can return a pair of values
332 RestoreFirstSeven - Restore the first 7 parameter registers
333 RestoreFirstSevenExceptRax - Restore the first 7 parameter registers except rax which is being used to return the result
334 RestoreFirstSevenExceptRaxAndRdi - Restore the first 7 parameter registers except rax and rdi which are being used to return the results
335 Rq - Layout quad words in the data segment and return their label
336 Rs - Layout bytes in read only memory and return their label
337 Rutf8 - Layout a utf8 encoded string as bytes in read only memory and return their label
338 Rw - Layout words in the data segment and return their label
339 SaveFirstFour - Save the first 4 parameter registers making any parameter registers read only
340 SaveFirstSeven - Save the first 7 parameter registers
341 SetLabel - Create (if necessary) and set a label in the code section returning the label so set.
342 SetLengthOfShortString - Set the length of the short string held in the numbered zmm register into the specified register
343 SetMaskRegister - Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere
344 SetZF - Set the zero flag
345 Start - Initialize the assembler
346 StatSize - Stat a file whose name is addressed by rax to get its size in rax
347 StringLength - Length of a zero terminated string
348 Structure - Create a structure addressed by a register
349 Subroutine - Create a subroutine that can be called in assembler code
350 Then - Then body for an If statement
351 totalBytesAssembled - Total size in bytes of all files assembled during testing
352 unlinkFile - Unlink the named file
353 UnReorderSyscallRegisters - Recover the initial values in registers that were reordered
354 V - Define a quad variable
355 Variable - Create a new variable with the specified size and name initialized via an expression
356 WaitPid - Wait for the pid in rax to complete
357 xmm - Add xmm to the front of a list of register expressions
358 ymm - Add ymm to the front of a list of register expressions
359 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
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.