Nasm::X86 - Generate X86 assembler code using Perl as a macro pre-processor.
Write and execute x64 Avx512 assembler code from perl using perl as a macro assembler. The generated code can be run under the Intel emulator to obtain execution trace and instruction counts.
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
With the print statements removed, the Intel Emulator indicates that 26 instructions were executed:
CALL_NEAR 1 ENTER 2 JMP 1 KMOVQ 1 MOV 5 POP 1 PUSH 3 SYSCALL 1 TZCNT 1 VMOVDQU8 1 VPBROADCASTB 1 VPCMPUB 8 *total 26
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 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 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
Arenas are resizeable, relocatable blocks of memory that hold other dynamic data structures. Arenas can be transferred between processes and relocated as needed as all addressing is relative to the start of the block of memory containing each arena.
Create two dynamic arenas, add some content to them, write each arena to stdout:
my $a = CreateArena; my $b = CreateArena; $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; aaAAaabbBBbb END
Create a dynamic string within an arena and add some content to it:
my $s = Rb(0..255); my $A = CreateArena; my $S = $A->CreateString; $S->append(V(source, $s), K(size, 256)); $S->len->outNL; $S->clear; $S->append(V(source, $s), K(size, 16)); $S->len->outNL; $S->dump; ok Assemble(debug => 0, eq => <<END); size: 0000 0000 0000 0100 size: 0000 0000 0000 0010 string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0010 zmm31: 0000 0018 0000 0018 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 000F 0E0D 0C0B 0A09 0807 0605 0403 0201 0010
END
Create a dynamic array within an arena, push some content on to it then pop it off again:
my $N = 15; my $A = CreateArena; my $a = $A->CreateArray; $a->push(V(element, $_)) for 1..$N; K(loop, $N)->for(sub {my ($start, $end, $next) = @_; my $l = $a->size; If $l == 0, Then {Jmp $end}; $a->pop(my $e = V(element)); $e->outNL; }); ok Assemble(debug => 0, eq => <<END); element: 0000 0000 0000 000F element: 0000 0000 0000 000E element: 0000 0000 0000 000D element: 0000 0000 0000 000C element: 0000 0000 0000 000B element: 0000 0000 0000 000A element: 0000 0000 0000 0009 element: 0000 0000 0000 0008 element: 0000 0000 0000 0007 element: 0000 0000 0000 0006 element: 0000 0000 0000 0005 element: 0000 0000 0000 0004 element: 0000 0000 0000 0003 element: 0000 0000 0000 0002 element: 0000 0000 0000 0001 END
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
Call a subroutine recursively and get a trace back showing the procedure calls and parameters passed to each call. Parameters are passed by reference not value.
my $d = V depth, 3; # Create a variable on the stack my $s = Subroutine {my ($p, $s) = @_; # Parameters, subroutine descriptor PrintOutTraceBack; my $d = $$p{depth}->copy($$p{depth} - 1); # Modify the variable referenced by the parameter If ($d > 0, Then {$s->call($d); # Recurse }); PrintOutTraceBack; } [qw(depth)], name => 'ref'; $s->call($d); # Call the subroutine ok Assemble(debug => 0, eq => <<END); Subroutine trace back, depth: 0000 0000 0000 0001 0000 0000 0000 0003 ref Subroutine trace back, depth: 0000 0000 0000 0002 0000 0000 0000 0002 ref 0000 0000 0000 0002 ref Subroutine trace back, depth: 0000 0000 0000 0003 0000 0000 0000 0001 ref 0000 0000 0000 0001 ref 0000 0000 0000 0001 ref Subroutine trace back, depth: 0000 0000 0000 0003 0000 0000 0000 0000 ref 0000 0000 0000 0000 ref 0000 0000 0000 0000 ref Subroutine trace back, depth: 0000 0000 0000 0002 0000 0000 0000 0000 ref 0000 0000 0000 0000 ref Subroutine trace back, depth: 0000 0000 0000 0001 0000 0000 0000 0000 ref
Quarks replace unique strings with unique numbers and in doing so unite all that is best and brightest in dynamic trees, arrays, strings and short strings, all written in X86 assembler, all generated by Perl:
my $N = 5; my $a = CreateArena; # Arena containing quarks my $Q = $a->CreateQuarks; # Quarks my $s = CreateShortString(0); # Short string used to load and unload quarks my $d = Rb(1..63); for my $i(1..$N) # Load a set of quarks {my $j = $i - 1; $s->load(K(address, $d), K(size, 4+$i)); my $q = $Q->quarkFromShortString($s); $q->outNL("New quark $j: "); # New quark, new number } PrintOutNL; for my $i(reverse 1..$N) # Reload a set of quarks {my $j = $i - 1; $s->load(K(address, $d), K(size, 4+$i)); my $q = $Q->quarkFromShortString($s); $q->outNL("Old quark $j: "); # Old quark, old number } PrintOutNL; for my $i(1..$N) # Dump quarks {my $j = $i - 1; $s->clear; $Q->shortStringFromQuark(K(quark, $j), $s); PrintOutString "Quark string $j: "; PrintOutRegisterInHex xmm0; } ok Assemble(debug => 0, trace => 0, eq => <<END); New quark 0: 0000 0000 0000 0000 New quark 1: 0000 0000 0000 0001 New quark 2: 0000 0000 0000 0002 New quark 3: 0000 0000 0000 0003 New quark 4: 0000 0000 0000 0004
Old quark 4: 0000 0000 0000 0004 Old quark 3: 0000 0000 0000 0003 Old quark 2: 0000 0000 0000 0002 Old quark 1: 0000 0000 0000 0001 Old quark 0: 0000 0000 0000 0000
Quark string 0: xmm0: 0000 0000 0000 0000 0000 0504 0302 0105 Quark string 1: xmm0: 0000 0000 0000 0000 0006 0504 0302 0106 Quark string 2: xmm0: 0000 0000 0000 0000 0706 0504 0302 0107 Quark string 3: xmm0: 0000 0000 0000 0008 0706 0504 0302 0108 Quark string 4: xmm0: 0000 0000 0000 0908 0706 0504 0302 0109 END
The Intel Software Development Emulator will be required if you do not have a computer with the avx512 instruction set and wish to execute code containing these instructions. For details see:
https://software.intel.com/content/dam/develop/external/us/en/documents/downloads/sde-external-8.63.0-2021-01-18-lin.tar.bz2
The Networkwide Assembler is required to assemble the code produced For full details see:
https://github.com/philiprbrenan/NasmX86/blob/main/.github/workflows/main.yml
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.
To produce a named executable without running it, specify:
keep=>"executable file name"
To run the executable produced by "Assemble(%)" without the Intel emulator, which is used by default if it is present, specify:
emulator=>0
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
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.
Generate X86 assembler code using Perl as a macro pre-processor.
Version "20210912".
The following sections describe the methods in each functional area of this module. For an alphabetic listing of all methods by name see Index.
Layout data
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; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ok Assemble(debug => 0, eq => <<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;
Layout bytes in memory and return their label.
Parameter Description 1 @d Data to be laid out
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;
Layout bytes in read only memory and return their label.
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;
Layout a utf8 encoded string as bytes in read only memory and return their label.
Layout bytes in the data segment and return their label.
Parameter Description 1 @bytes Bytes to layout
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);
Layout words in the data segment and return their label.
Parameter Description 1 @words Words to layout
Layout double words in the data segment and return their label.
Parameter Description 1 @dwords Double words to layout
Layout quad words in the data segment and return their label.
Parameter Description 1 @qwords Quad words to layout
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);
Operations on registers
Add xmm to the front of a list of register expressions.
Parameter Description 1 @r Register numbers
Add ymm to the front of a list of register expressions.
Add zmm to the front of a list of register expressions.
LoadZmm 0, 0..63; PrintOutRegisterInHex zmm 0; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 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 END
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
Add a new set of registers that are available.
Parameter Description 1 @reg Registers known to be available at the moment
Remove the current set of registers known to be free.
Check that a register is in fact a general purpose register.
Parameter Description 1 $reg Mask register to check
Check that a register is in fact a numbered general purpose register.
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.
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
Insert a one into the specified register at the point indicated by another register.
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
Load a numbered zmm with the specified bytes.
Parameter Description 1 $zmm Numbered zmm 2 @bytes Bytes
LoadZmm 0, 0..63; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutRegisterInHex zmm 0; 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 END
Saving and restoring registers via the stack
Save the first 4 parameter registers making any parameter registers read only.
Parameter Description 1 @keep Registers to mark as read only
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; ok Assemble(debug => 0, eq => <<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;
Restore the first 4 parameter registers.
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; ok Assemble(debug => 0, eq => <<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;
Restore the first 4 parameter registers except rax so it can return its value.
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; ok Assemble(debug => 0, eq => <<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;
Restore the first 4 parameter registers except rax and rdi so we can return a pair of values.
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; ok Assemble(debug => 0, eq => <<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;
Save the first 7 parameter registers.
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; ok Assemble(debug => 0, eq => <<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;
Restore the first 7 parameter registers.
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; ok Assemble(debug => 0, eq => <<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;
Restore the first 7 parameter registers except rax which is being used to return the result.
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; ok Assemble(debug => 0, eq => <<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;
Restore the first 7 parameter registers except rax and rdi which are being used to return the results.
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; ok Assemble(debug => 0, eq => <<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;
Map the list of registers provided to the 64 bit system call sequence.
Parameter Description 1 @registers Registers
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;
Recover the initial values in registers that were reordered.
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;
Return the size of a register.
Parameter Description 1 $r Register
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; ok Assemble(debug => 0, eq => <<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; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Clear registers by setting them to zero.
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;
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
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; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ok Assemble(debug => 0, eq => <<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
Set the zero flag.
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
Clear the zero flag.
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
Operations on mask registers
Check that a register is in fact a mask register.
Parameter Description 1 $mask Mask register to check
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
Mov r14, 0; Kmovq k0, 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; PopEax; PrintRaxInHex($stdout, 3); PrintOutNL; my $a = V('aaaa'); $a->pop; $a->push; $a->outNL; PopEax; PrintRaxInHex($stdout, 3); PrintOutNL; 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
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
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 constructs
If.
Parameter Description 1 $jump Jump op code of variable 2 $then Then - required 3 $else Else - optional
my $c = K(one,1); If ($c == 0, # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Then {PrintOutStringNL "1 == 0"; }, Else {PrintOutStringNL "1 != 0"; }); ok Assemble(debug => 0, eq => <<END); 1 != 0 END
Then block for an If statement.
Parameter Description 1 $block Then block
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 $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 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 block for an If statement.
Parameter Description 1 $block Else block
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 $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 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 if block for an If statement.
Parameter Description 1 $condition Condition 2 $then Then block 3 $else Else block
If equal execute the then block else the else block.
Parameter Description 1 $then Then - required 2 $else Else - optional
my $cmp = sub {my ($a, $b) = @_; for my $op(qw(eq ne lt le gt ge)) {Mov rax, $a; Cmp rax, $b; 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
If not equal execute the then block else the else block.
If the zero flag is not set then execute the then block else the else block.
Mov rax, 0; Test rax,rax; IfNz # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Then {PrintOutRegisterInHex rax; }, Else {PrintOutRegisterInHex rbx; }; Mov rax, 1; Test rax,rax; IfNz # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Then {PrintOutRegisterInHex rcx; }, Else {PrintOutRegisterInHex rdx; }; ok Assemble =~ m(rbx.*rcx)s;
If the zero flag is set then execute the then block else the else block.
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
If the carry flag is set then execute the then block else the else block.
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
If the carry flag is not set then execute the then block else the else block.
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
If less than execute the then block else the else block.
If less than or equal execute the then block else the else block.
If greater than execute the then block else the else block.
If greater than or equal execute the then block else the else block.
Pass block for an OrBlock.
Parameter Description 1 $block Block
Mov rax, 1; OrBlock {my ($pass, $end, $start) = @_; Cmp rax, 1; Je $pass; Cmp rax, 2; Je $pass; PrintOutStringNL "Fail"; } Pass # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($end, $pass, $start) = @_; PrintOutStringNL "Pass"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 }; ok Assemble(debug => 0, eq => <<END); Pass # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 END
Fail block for an AndBlock.
Mov rax, 1; Mov rdx, 2; AndBlock {my ($fail, $end, $start) = @_; Cmp rax, 1; Jne $fail; Cmp rdx, 2; Jne $fail; PrintOutStringNL "Pass"; } Fail # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($end, $fail, $start) = @_; PrintOutStringNL "Fail"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 }; ok Assemble(debug => 0, eq => <<END); Pass END
Short circuit and: execute a block of code to test conditions which, if all of them pass, allows the first block to continue successfully else if one of the conditions fails we execute the optional fail block.
Parameter Description 1 $test Block 2 $fail Optional failure block
Mov rax, 1; Mov rdx, 2; AndBlock # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($fail, $end, $start) = @_; Cmp rax, 1; Jne $fail; Cmp rdx, 2; Jne $fail; PrintOutStringNL "Pass"; } Fail {my ($end, $fail, $start) = @_; PrintOutStringNL "Fail"; }; ok Assemble(debug => 0, eq => <<END); Pass END
Short circuit or: execute a block of code to test conditions which, if one of them is met, leads on to the execution of the pass block, if all of the tests fail we continue withe the test block.
Parameter Description 1 $test Tests 2 $pass Optional block to execute on success
Mov rax, 1; OrBlock # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($pass, $end, $start) = @_; Cmp rax, 1; Je $pass; Cmp rax, 2; Je $pass; PrintOutStringNL "Fail"; } Pass {my ($end, $pass, $start) = @_; PrintOutStringNL "Pass"; }; ok Assemble(debug => 0, eq => <<END); Pass END
For - iterate the block as long as register is less than limit incrementing by increment each time. Nota Bene: The register is not explicitly set to zero as you might want to start at some other number.
Parameter Description 1 $block Block 2 $register Register 3 $limit Limit on loop 4 $increment Increment on each iteration
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
For - iterate the full block as long as register plus increment is less than than limit incrementing by increment each time then increment the last block for the last non full block.
Parameter Description 1 $full Block for full block 2 $last Block for last block 3 $register Register 4 $limitRegister Register containing upper limit of loop 5 $increment Increment on each iteration
Iterate for ever.
Parameter Description 1 $block Block to iterate
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 $block Block 2 %options Options.
Call a subroutine
Initialize a new stack frame. The first quad of each frame has the address of the name of the sub in the low dword, and the parameter count in the upper byte of the quad. This field is all zeroes in the initial frame.
Create a subroutine that can be called in assembler code.
Parameter Description 1 $block Block 2 $parameters [parameters names] 3 %options Options.
my $g = G g, 3; my $s = Subroutine # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($p, $s) = @_; $g->copy($g - 1); $g->outNL; If ($g > 0, Then {$s->call; }); } [], name => 'ref'; $s->call; ok Assemble(debug => 0, eq => <<END); g: 0000 0000 0000 0002 g: 0000 0000 0000 0001 g: 0000 0000 0000 0000 END my $g = G g, 2; my $u = Subroutine # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($p, $s) = @_; PrintOutTraceBack; $$p{g}->copy(K gg, 1); PrintOutTraceBack; } [qw(g)], name => 'uuuu'; my $t = Subroutine # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($p, $s) = @_; $u->call($$p{g}); } [qw(g)], name => 'tttt'; my $s = Subroutine # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($p, $s) = @_; $t->call($$p{g}); } [qw(g)], name => 'ssss'; $g->outNL; $s->call($g); $g->outNL; ok Assemble(debug => 0, eq => <<END); g: 0000 0000 0000 0002 Subroutine trace back, depth: 0000 0000 0000 0003 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 0000 0000 0000 0002 uuuu 0000 0000 0000 0002 tttt 0000 0000 0000 0002 ssss Subroutine trace back, depth: 0000 0000 0000 0003 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 0000 0000 0000 0001 uuuu 0000 0000 0000 0001 tttt 0000 0000 0000 0001 ssss g: 0000 0000 0000 0001 END my $r = G r, 2; my $u = Subroutine # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($p, $s) = @_; PrintOutTraceBack; $$p{u}->copy(K gg, 1); PrintOutTraceBack; } [qw(u)], name => 'uuuu'; my $t = Subroutine # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($p, $s) = @_; $u->call(u => $$p{t}); } [qw(t)], name => 'tttt'; my $s = Subroutine # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($p, $s) = @_; $t->call(t => $$p{s}); } [qw(s)], name => 'ssss'; $r->outNL; $s->call(s=>$r); $r->outNL; ok Assemble(debug => 0, eq => <<END); r: 0000 0000 0000 0002 Subroutine trace back, depth: 0000 0000 0000 0003 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 0000 0000 0000 0002 uuuu 0000 0000 0000 0002 tttt 0000 0000 0000 0002 ssss Subroutine trace back, depth: 0000 0000 0000 0003 # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 0000 0000 0000 0001 uuuu 0000 0000 0000 0001 tttt 0000 0000 0000 0001 ssss r: 0000 0000 0000 0001 END
Call a sub passing it some parameters.
Parameter Description 1 $sub Subroutine descriptor 2 @parameters Parameter variables
my $s = Subroutine {my ($p) = @_; $$p{in}->outNL; } [qw(in)], name => 'sss'; my $t = Subroutine {my ($p) = @_; $s->call($$p{in}); } [qw(in)], name => 'ttt'; my $c = Subroutine {my ($p) = @_; $t->via($$p{call}, $$p{in}); } [qw(call in)], name => 'ccc'; $c->call($t->V, V(in, 42)); ok Assemble(debug => 0, eq => <<END); in: 0000 0000 0000 002A END
Call a sub by reference passing it some parameters.
Parameter Description 1 $sub Subroutine descriptor 2 $ref Variable containing a reference to the sub 3 @parameters Parameter variables
Put the address of a subroutine into a stack variable so that it can be passed as a parameter.
Parameter Description 1 $sub Subroutine descriptor
Trace the call stack.
Parameter Description 1 $channel Channel to write on
Print sub routine track back on stderr.
Print sub routine track back on stdout.
my $d = V depth, 3; # Create a variable on the stack my $s = Subroutine {my ($p, $s) = @_; # Parameters, subroutine descriptor PrintOutTraceBack; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $d = $$p{depth}->copy($$p{depth} - 1); # Modify the variable referenced by the parameter If ($d > 0, Then {$s->call($d); # Recurse }); PrintOutTraceBack; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 } [qw(depth)], name => 'ref'; $s->call($d); # Call the subroutine ok Assemble(debug => 0, eq => <<END); Subroutine trace back, depth: 0000 0000 0000 0001 0000 0000 0000 0003 ref Subroutine trace back, depth: 0000 0000 0000 0002 0000 0000 0000 0002 ref 0000 0000 0000 0002 ref Subroutine trace back, depth: 0000 0000 0000 0003 0000 0000 0000 0001 ref 0000 0000 0000 0001 ref 0000 0000 0000 0001 ref Subroutine trace back, depth: 0000 0000 0000 0003 0000 0000 0000 0000 ref 0000 0000 0000 0000 ref 0000 0000 0000 0000 ref Subroutine trace back, depth: 0000 0000 0000 0002 0000 0000 0000 0000 ref 0000 0000 0000 0000 ref Subroutine trace back, depth: 0000 0000 0000 0001 0000 0000 0000 0000 ref END
Request a trace back followed by exit on a segv signal.
OnSegv(); # Request a trace back followed by exit on a segv signal. # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $t = Subroutine # Subroutine that will cause an error to occur to force a trace back to be printed {Mov r15, 0; Mov r15, "[r15]"; # Try to read an unmapped memory location } [qw(in)], name => 'sub that causes a segv'; # The name that will appear in the trace back $t->call(K(in, 42)); ok Assemble(debug => 0, keep2 => 'signal', emulator=>0, eq => <<END); # Cannot use the emulator because it does not understand signals Subroutine trace back, depth: 0000 0000 0000 0001 0000 0000 0000 002A sub that causes a segv END
Call a subroutine with a reordering of the registers.
Parameter Description 1 $block Code to execute with reordered registers 2 @registers Registers to reorder
Inserts comments into the generated assember code.
Insert a comment into the assembly code with a traceback showing how it was generated.
Parameter Description 1 @comment Text of comment
Insert a comment into the assembly code.
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);
Insert a comment into the data segment.
Insert a comment into the read only data segment.
Print
Print a new line to stdout or stderr.
Print a new line to stderr.
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;
Print a constant string to the specified channel.
Parameter Description 1 $channel Channel 2 @string Strings
Print a constant string to the specified channel followed by a new line.
Print a constant string to stderr.
Parameter Description 1 @string String
Print a constant string to stdout.
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;
Print one or more spaces to the specified channel.
Parameter Description 1 $channel Channel 2 $spaces Number of spaces if not one.
Print one or more spaces to stderr.
Parameter Description 1 $spaces Number of spaces if not one.
Print one or more spaces to stdout.
Print a constant string followed by a new line to stderr.
Parameter Description 1 @string Strings
PrintOutStringNL "Hello World"; PrintOutStringNL "Hello World"; PrintErrStringNL "Hello World"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ok Assemble(debug => 0, eq => <<END); Hello World Hello World END
Print a constant string followed by a new line to stdout.
PrintOutStringNL "Hello World"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutStringNL "Hello World"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintErrStringNL "Hello World"; ok Assemble(debug => 0, eq => <<END); Hello World Hello World 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
Write the content of register rax in hexadecimal in big endian notation to stderr.
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;
Write the content of register rax to stderr in hexadecimal in little endian notation.
Mov rax, 0x07654321; Shl rax, 32; Or rax, 0x07654321; PushR rax; PrintOutRaxInHex; PrintOutNL; PrintOutRaxInReverseInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutNL; Mov rax, rsp; Mov rdi, 8; PrintOutMemoryInHex; PrintOutNL; PopR rax; Mov rax, 4096; PushR rax; Mov rax, rsp; Mov rdi, 8; PrintOutMemoryInHex; PrintOutNL; PopR rax; ok Assemble(debug => 0, eq => <<END); 0765 4321 0765 4321 2143 6507 2143 6507 2143 6507 2143 6507 0010 0000 0000 0000 END
Print the named register as a hex strings.
Parameter Description 1 $channel Channel to print on 2 $r Register to print
Print the named registers as hex strings.
Parameter Description 1 $channel Channel to print on 2 @r Names of the registers to print
Print the named registers as hex strings on stderr.
Parameter Description 1 @r Names of the registers to print
Print the named registers as hex strings on stdout.
my $q = Rs(('a'..'p')x4); Mov r8,"[$q]"; PrintOutRegisterInHex r8; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ok Assemble(debug => 0, eq => <<END); r8: 6867 6665 6463 6261 END
Print the general purpose registers in hex.
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;
Print the zero flag without disturbing it on stderr.
Print the zero flag without disturbing it on stdout.
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
Print the utf 8 character addressed by rax to the specified channel. The character must be in little endian form.
Parameter Description 1 $channel Channel
Print the utf 8 character addressed by rax to stderr.
Print the utf 8 character addressed by rax to stdout.
my $u = Rd(convertUtf32ToUtf8LE(ord('α'))); Mov rax, $u; PrintOutUtf8Char; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutNL; ok Assemble(debug => 0, trace => 0, eq => <<END); α END
Parameter Description 1 $size Variable: number of characters to print 2 $address Variable: address of memory
Variable definitions and operations
Variable definitions
Create a new variable with the specified name initialized via an optional expression.
Parameter Description 1 $name Name of variable 2 $expr Optional expression initializing variable 3 %options Options
Define a global variable.
Parameter Description 1 $name Name of variable 2 $expr Initializing expression 3 %options Options
my $s = Subroutine {my ($p) = @_; $$p{v}->copy($$p{v} + $$p{k} + $$p{g} + 1); } [qw(v k g)], name => 'add'; my $v = V(v, 1); my $k = K(k, 2); my $g = G(g, 3); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $s->call($v, $k, $g); $v->outNL; ok Assemble(debug => 0, eq => <<END); v: 0000 0000 0000 0007 END my $g = G g, 0; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $s = Subroutine {my ($p) = @_; $$p{g}->copy(K value, 1); } [qw(g)], name => 'ref2'; my $t = Subroutine {my ($p) = @_; $s->call($$p{g}); } [qw(g)], name => 'ref'; $t->call($g); $g->outNL; ok Assemble(debug => 0, eq => <<END); g: 0000 0000 0000 0001 END
Define a constant variable.
my $s = Subroutine {my ($p) = @_; $$p{v}->copy($$p{v} + $$p{k} + $$p{g} + 1); } [qw(v k g)], name => 'add'; my $v = V(v, 1); my $k = K(k, 2); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $g = G(g, 3); $s->call($v, $k, $g); $v->outNL; ok Assemble(debug => 0, eq => <<END); v: 0000 0000 0000 0007 END my $g = G g, 0; my $s = Subroutine {my ($p) = @_; $$p{g}->copy(K value, 1); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 } [qw(g)], name => 'ref2'; my $t = Subroutine {my ($p) = @_; $s->call($$p{g}); } [qw(g)], name => 'ref'; $t->call($g); $g->outNL; ok Assemble(debug => 0, eq => <<END); g: 0000 0000 0000 0001 END 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 $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 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
Define a reference variable.
Parameter Description 1 $name Name of variable
Define a variable.
my $s = Subroutine {my ($p) = @_; $$p{v}->copy($$p{v} + $$p{k} + $$p{g} + 1); } [qw(v k g)], name => 'add'; my $v = V(v, 1); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $k = K(k, 2); my $g = G(g, 3); $s->call($v, $k, $g); $v->outNL; ok Assemble(debug => 0, eq => <<END); v: 0000 0000 0000 0007 END my $g = G g, 0; my $s = Subroutine {my ($p) = @_; $$p{g}->copy(K value, 1); } [qw(g)], name => 'ref2'; my $t = Subroutine {my ($p) = @_; $s->call($$p{g}); } [qw(g)], name => 'ref'; $t->call($g); $g->outNL; ok Assemble(debug => 0, eq => <<END); g: 0000 0000 0000 0001 END 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 $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 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
Print the values of variables or the memory addressed by them
Dump the value of a variable on stderr.
Parameter Description 1 $left Left variable 2 $title1 Optional leading title 3 $title2 Optional trailing title
Dump the value of a variable on stdout.
Dump the value of a variable on stderr and append a new line.
Dump the value of a variable on stdout and append a new line.
Dump the value of a variable on stdout with an indication of where the dump came from.
Parameter Description 1 $left Left variable
Variable operations
Get the address of a variable with an optional offset.
Parameter Description 1 $left Left variable 2 $offset Optional offset
Copy one variable into another.
Parameter Description 1 $left Left variable 2 $right Right variable 3 $Transfer Optional transfer register
my $s = Subroutine {my ($p) = @_; $$p{v}->copy($$p{v} + $$p{k} + $$p{g} + 1); } [qw(v k g)], name => 'add'; my $v = V(v, 1); my $k = K(k, 2); my $g = G(g, 3); $s->call($v, $k, $g); $v->outNL; ok Assemble(debug => 0, eq => <<END); v: 0000 0000 0000 0007 END my $g = G g, 0; my $s = Subroutine {my ($p) = @_; $$p{g}->copy(K value, 1); } [qw(g)], name => 'ref2'; my $t = Subroutine {my ($p) = @_; $s->call($$p{g}); } [qw(g)], name => 'ref'; $t->call($g); $g->outNL; ok Assemble(debug => 0, eq => <<END); g: 0000 0000 0000 0001 END
Copy a reference to a variable.
Copy the current state of the zero flag into a variable.
Parameter Description 1 $var Variable
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; ok Assemble(debug => 0, eq => <<END); zf: 0000 0000 0000 0001 zf: 0000 0000 0000 0000 zf: 0000 0000 0000 0000 zf: 0000 0000 0000 0001 END
Copy the opposite of the current state of the zero flag into a variable.
Equals operator.
Parameter Description 1 $op Operator 2 $left Left variable 3 $right Right variable
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
Implement plus and assign.
Parameter Description 1 $left Left variable 2 $right Right variable
Implement minus and assign.
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
Add the right hand variable to the left hand variable and return the result as a new variable.
Subtract the right hand variable from the left hand variable and return the result as a new variable.
Multiply the left hand variable by the right hand variable and return the result as a new variable.
Return a variable containing the result or the remainder that occurs when the left hand side is divided by the right hand side.
Divide the left hand variable by the right hand variable and return the result as a new variable.
Divide the left hand variable by the right hand variable and return the remainder as a new variable.
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
Combine the left hand variable with the right hand variable via a boolean operator and indicate the result by setting the zero flag if the result is true.
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
Check whether the left hand variable is equal to the right hand variable.
Check whether the left hand variable is not equal to the right hand variable.
Check whether the left hand variable is greater than or equal to the right hand variable.
Check whether the left hand variable is greater than the right hand variable.
Check whether the left hand variable is less than or equal to the right hand variable.
Check whether the left hand variable is less than the right hand variable.
Check whether the specified variable is a reference to another variable.
Parameter Description 1 $variable Variable
Set the named registers from the content of the variable.
Parameter Description 1 $variable Variable 2 $register Register to load
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
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 3 $transfer Optional transfer register
Parameter Description 1 $variable Variable 2 $constant Constant to load
Increment or decrement a variable.
Parameter Description 1 $left Left variable operator 2 $op Address of operator to perform inc or dec
Increment a variable.
Parameter Description 1 $left Variable
Decrement a variable.
The name of the variable.
Minimum of two variables.
Parameter Description 1 $left Left variable 2 $right Right variable or constant
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; ok Assemble(debug => 0, eq => <<END); a: 0000 0000 0000 0001 b: 0000 0000 0000 0002 min: 0000 0000 0000 0001 max: 0000 0000 0000 0002 END
Maximum of two variables.
And two variables.
Or two variables.
Parameter Description 1 $start Variable containing start of mask 2 $length Variable containing length of mask 3 $mask Mask register
my $start = V("Start", 7); my $length = V("Length", 3); $start->setMask($length, k7); PrintOutRegisterInHex k7; ok Assemble(debug => 0, eq => <<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
Set the first bits in the specified mask register.
Parameter Description 1 $length Variable containing length to set 2 $mask Mask register
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
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
Set a bit in the specified register retaining the other bits.
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
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; ok Assemble(debug => 0, eq => <<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
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
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
Put the specified register into the numbered zmm at the specified offset in the 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
Load the specified register from the numbered zmm at the quad offset specified as a constant number.
Parameter Description 1 $mm Mm register 2 $offset Offset in quads 3 $reg General purpose register to load
Save the specified register into the numbered zmm at the quad offset specified as a constant number.
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 5 $target Optional target variable - if none supplied we create a variable
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
Get the word from the numbered xmm register and return it in a variable.
Get the double word from the numbered xmm register and return it in a variable.
Get the quad word from the numbered xmm register and return it in a variable.
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
Get the word from the numbered zmm register and return it in a variable.
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
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; ok Assemble(debug => 0, eq => <<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
Get the quad word from the numbered zmm register and return it in a variable.
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
Get the word from the numbered zmm register and put it in a variable.
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
Get the quad word from the numbered zmm register and put it in a variable.
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
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
Place the value of the content variable at the word in the numbered xmm register.
Place the value of the content variable at the double word in the numbered xmm register.
Place the value of the content variable at the quad word in the numbered xmm register.
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
Place the value of the content variable at the word in the numbered zmm register.
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
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; ok Assemble(debug => 0, eq => <<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
Place the value of the content variable at the quad word in the numbered zmm register.
Broadcast from a variable into a 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
Push and pop variables to and from the stack
Push a variable onto the stack.
Pop a variable from the stack.
Actions on memory described by variables
Clear the memory described in this variable.
Parameter Description 1 $address Address of memory to clear 2 $size Size of the memory to clear
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
Write, in hexadecimal, 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
Write the memory addressed by a variable to stderr.
Parameter Description 1 $address Address of memory 2 $size Number of bytes to print
Write the memory addressed by a variable to stdout.
my $u = Rd(ord('𝝰'), ord('𝝱'), ord('𝝲'), ord('𝝳')); Mov rax, $u; my $address = V(address)->getReg(rax); $address->printOutMemoryInHexNL(K(size, 16)); ok Assemble(debug => 0, trace => 0, eq => <<END); 70D7 0100 71D7 010072D7 0100 73D7 0100 END my $v = V(var, 2); If $v == 0, Then {Mov rax, 0}, Ef {$v == 1} Then {Mov rax, 1}, Ef {$v == 2} Then {Mov rax, 2}, Else {Mov rax, 3}; PrintOutRegisterInHex rax; ok Assemble(debug => 0, trace => 0, eq => <<END); rax: 0000 0000 0000 0002 END
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
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(debug => 0, eq => <<END); abcdefghijklmnop END
Allocate the specified amount of memory via mmap and return its address.
Parameter Description 1 $size Size
Structured programming operations driven off variables.
Iterate the block limit times.
Parameter Description 1 $limit Limit 2 $block Block
V(limit,10)->for(sub {my ($i, $start, $next, $end) = @_; $i->outNL; }); ok Assemble(debug => 0, eq => <<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
Manage data on the stack
Generic versions of push, pop, peek
Pop registers from the stack. Use the last stored set if none explicitly supplied. Pops are done in reverse order to match the original pushing order.
Parameter Description 1 @r Register
Mov rax, 0x11111111; Mov rbx, 0x22222222; PushR my @save = (rax, rbx); Mov rax, 0x33333333; PopR; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutRegisterInHex rax; PrintOutRegisterInHex rbx; ok Assemble(debug => 0, eq => <<END); rax: 0000 0000 1111 1111 rbx: 0000 0000 2222 2222 END
We cannot pop a double word from the stack in 64 bit long mode using pop so we improvise.
Mov r14, 0; Kmovq k0, 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; PopEax; PrintRaxInHex($stdout, 3); PrintOutNL; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $a = V('aaaa'); $a->pop; $a->push; $a->outNL; PopEax; PrintRaxInHex($stdout, 3); PrintOutNL; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 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
Peek at register on stack.
Push several zmm registers.
Parameter Description 1 @Z Zmm register numbers
Pop zmm registers.
Push several Mask registers.
Parameter Description 1 @M Mask register numbers
Pop Mask registers.
Declare variables and structures
Declare a structure
Create a structure addressed by a register.
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
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
Create a structure consisting of 8 byte fields.
Parameter Description 1 $N Number of variables required
Declare local variables in a frame on the stack
Map local data.
Start a local data area on the stack.
Parameter Description 1 $local Local data descriptor
Free a local data area on the stack.
Add a local variable.
Parameter Description 1 $local Local data descriptor 2 $length Length of data 3 $comment Optional comment
Address a local variable on the stack.
Add some 8 byte local variables and return an array of variable definitions.
Parameter Description 1 $local Local data descriptor 2 @comments Optional comment
Create a local data descriptor consisting of the specified number of 8 byte local variables and return an array: (local data descriptor, variable definitions...).
Interacting with the operating system.
Create and manage processes
Fork.
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; }
Get process identifier.
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; }
Get process identifier in hex as 8 zero terminated bytes in rax.
GetPidInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutRegisterInHex rax; ok Assemble =~ m(rax: 00);
Get parent process identifier.
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; }
Get userid of current process.
GetUid; # Userid # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutRegisterInHex rax; my $r = Assemble; ok $r =~ m(rax:( 0000){3});
Wait for the pid in rax to complete.
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; }
Read the time stamp counter and return the time in nanoseconds in rax.
for(1..10) {ReadTimeStampCounter; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutRegisterInHex rax; } my @s = split / /, Assemble; my @S = sort @s; is_deeply \@s, \@S;
Allocate and print memory
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 .
Dump memory from the address in rax for the length in rdi on stderr.
Dump memory from the address in rax for the length in rdi on stdout.
Mov rax, 0x07654321; Shl rax, 32; Or rax, 0x07654321; PushR rax; PrintOutRaxInHex; PrintOutNL; PrintOutRaxInReverseInHex; PrintOutNL; Mov rax, rsp; Mov rdi, 8; PrintOutMemoryInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutNL; PopR rax; Mov rax, 4096; PushR rax; Mov rax, rsp; Mov rdi, 8; PrintOutMemoryInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutNL; PopR rax; ok Assemble(debug => 0, eq => <<END); 0765 4321 0765 4321 2143 6507 2143 6507 2143 6507 2143 6507 0010 0000 0000 0000 END
Dump memory from the address in rax for the length in rdi and then print a new line.
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
Print the memory addressed by rax for a length of rdi on the specified channel.
my $file = G(file, Rs($0)); my $size = G(size); my $address = G(address); ReadFile $file, $size, $address; # Read file $address->setReg(rax); # Address of file in memory $size ->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
Print the memory addressed by rax for a length of rdi on the specified channel followed by a new line.
Print the memory addressed by rax for a length of rdi on stderr.
Print the memory addressed by rax for a length of rdi on stdout.
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);
Print the memory addressed by rax for a length of rdi followed by a new line on stderr.
Print the memory addressed by rax for a length of rdi followed by a new line on stdout.
my $s = Rs("Hello World
Hello Skye"); Mov rax, $s; Cstrlen; Mov rdi, r15;
PrintOutMemoryNL; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ok Assemble(debug => 0, eq => <<END); Hello World Hello Skye END
Parameter Description 1 @variables Parameters
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(debug => 0, 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); Mov rdi, 128; PrintOutMemoryInHexNL; FreeMemory($N, $A); ok Assemble(debug => 1, 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 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
Free memory.
Parameter Description 1 @variables Variables
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); Mov rdi, 128; PrintOutMemoryInHexNL; FreeMemory($N, $A); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ok Assemble(debug => 1, 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 0000 END
Clear memory.
K(loop, 8+1)->for(sub {my ($index, $start, $next, $end) = @_; $index->setReg(r15); Push r15; }); Mov rax, rsp; Mov rdi, 8*9; PrintOutMemoryInHexNL; ClearMemory(K(size, 8*9), V(address, rax)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutMemoryInHexNL; ok Assemble(debug => 0, eq => <<END); 0800 0000 0000 00000700 0000 0000 00000600 0000 0000 00000500 0000 0000 00000400 0000 0000 00000300 0000 0000 00000200 0000 0000 00000100 0000 0000 00000000 0000 0000 0000 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 END 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); Mov rdi, 128; PrintOutMemoryInHexNL; FreeMemory($N, $A); ok Assemble(debug => 1, 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 0000 END
Write the specified byte into locations in the target mask that correspond to the locations in the source that contain the specified byte.
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.
Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi.
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
Interact with the operating system via files.
Open a file, whose name is addressed by rax, for read and return the file descriptor in rax.
Mov rax, Rs($0); # File to read OpenRead; # Open file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutRegisterInHex rax; CloseFile; # Close file PrintOutRegisterInHex rax; Mov rax, Rs(my $f = "zzzTemporaryFile.txt"); # File to write OpenWrite; # Open file CloseFile; # Close file ok Assemble(debug => 0, eq => <<END); rax: 0000 0000 0000 0003 rax: 0000 0000 0000 0000 END ok -e $f; # Created file unlink $f;
Create the file named by the terminated string addressed by rax for write.
Mov rax, Rs($0); # File to read OpenRead; # Open file PrintOutRegisterInHex rax; CloseFile; # Close file PrintOutRegisterInHex rax; Mov rax, Rs(my $f = "zzzTemporaryFile.txt"); # File to write OpenWrite; # Open file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 CloseFile; # Close file ok Assemble(debug => 0, eq => <<END); rax: 0000 0000 0000 0003 rax: 0000 0000 0000 0000 END ok -e $f; # Created file unlink $f;
Close the file whose descriptor is in rax.
Mov rax, Rs($0); # File to read OpenRead; # Open file PrintOutRegisterInHex rax; CloseFile; # Close file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutRegisterInHex rax; Mov rax, Rs(my $f = "zzzTemporaryFile.txt"); # File to write OpenWrite; # Open file CloseFile; # Close file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ok Assemble(debug => 0, eq => <<END); rax: 0000 0000 0000 0003 rax: 0000 0000 0000 0000 END ok -e $f; # Created file unlink $f;
Stat a file whose name is addressed by rax to get its size in rax.
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)); }
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.
my $file = G(file, Rs($0)); my $size = G(size); my $address = G(address); ReadFile $file, $size, $address; # Read file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $address->setReg(rax); # Address of file in memory $size ->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
Execute the file named in the arena addressed by rax with bash.
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.
Unlink the named file.
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 a string addressed by rax with length held in rdi and return the hash code in r15.
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); }
Convert utf8 to utf32
Get the next utf8 encoded character from the addressed memory and return it as a utf32 char.
Parameter Description 1 @parameters Parameters
Convert a string of utf8 to an allocated block of utf32 and return its address and length.
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, Rutf8($statement)); my $l = StringLength string => $s; 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 41414141 4141 4141 0000 END
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.
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.
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.
Operations on Short Strings
Create a description of a short string.
Parameter Description 1 $zmm Numbered zmm containing the string
my $s = CreateShortString(0); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $d = Rb(1..63); $s->load(K(address, $d), K(size, 9)); PrintOutRegisterInHex xmm0; $s->len->outNL; $s->setLength(K(size, 7)); PrintOutRegisterInHex xmm0; $s->append($s); PrintOutRegisterInHex ymm0; $s->appendByte(K(append,0xFF)); PrintOutRegisterInHex ymm0; ok Assemble(debug => 0, trace => 0, eq => <<END); xmm0: 0000 0000 0000 0908 0706 0504 0302 0109 size: 0000 0000 0000 0009 xmm0: 0000 0000 0000 0908 0706 0504 0302 0107 ymm0: 0000 0000 0000 0000 0000 0000 0000 0000 0007 0605 0403 0201 0706 0504 0302 010E ymm0: 0000 0000 0000 0000 0000 0000 0000 0000 FF07 0605 0403 0201 0706 0504 0302 010F END
Clear a short string.
Parameter Description 1 $string String
Load the variable addressed data with the variable length into the short string.
Parameter Description 1 $string String 2 $address Address 3 $length Length
my $s = CreateShortString(0); my $d = Rb(1..63); $s->load(K(address, $d), K(size, 9)); PrintOutRegisterInHex xmm0; $s->len->outNL; $s->setLength(K(size, 7)); PrintOutRegisterInHex xmm0; $s->append($s); PrintOutRegisterInHex ymm0; $s->appendByte(K(append,0xFF)); PrintOutRegisterInHex ymm0; ok Assemble(debug => 0, trace => 0, eq => <<END); xmm0: 0000 0000 0000 0908 0706 0504 0302 0109 size: 0000 0000 0000 0009 xmm0: 0000 0000 0000 0908 0706 0504 0302 0107 ymm0: 0000 0000 0000 0000 0000 0000 0000 0000 0007 0605 0403 0201 0706 0504 0302 010E ymm0: 0000 0000 0000 0000 0000 0000 0000 0000 FF07 0605 0403 0201 0706 0504 0302 010F END
Load the a short string with a constant string.
Parameter Description 1 $string Short string 2 $data String to load
Load the specified byte of each dword in the variable addressed data with the variable length into the short string.
Parameter Description 1 $string String 2 $byte Byte offset 0-3 3 $address Variable address 4 $length Variable length 5 $Offset Variable offset in short string at which to start
Return the length of a short string in a variable.
Set the length of the short string.
Parameter Description 1 $string String 2 $length Variable size
Append the lowest variable byte to the specified string.
Parameter Description 1 $string String 2 $char Variable byte
Append the right hand short string to the left hand short string.
Parameter Description 1 $left Target zmm 2 $right Source zmm
An arena is single extensible block of memory which contains other data structures such as strings, arrays, trees within it.
Length of a zero terminated string.
StringLength(V(string, Rs("abcd")))->outNL; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Assemble(debug => 0, eq => <<END); size: 0000 0000 0000 0004 END
Describe a relocatable arena.
Parameter Description 1 $bs Optional variable addressing the start of the arena
Create an relocatable arena and returns its address in rax. We 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.
my $a = CreateArena; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $a->q('aa'); $a->out; PrintOutNL; ok Assemble(debug => 0, eq => <<END); aa END my $a = CreateArena; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $b = CreateArena; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $a->q('aa'); $b->q('bb'); $a->out; PrintOutNL; $b->out; PrintOutNL; ok Assemble(debug => 0, eq => <<END); aa bb END my $a = CreateArena; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $b = CreateArena; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $a->q('aa'); $a->q('AA'); $a->out; PrintOutNL; ok Assemble(debug => 0, eq => <<END); aaAA END my $a = CreateArena; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $b = CreateArena; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $a->q('aa'); $b->q('bb'); $a->q('AA'); $b->q('BB'); $a->q('aa'); $b->q('bb'); $a->out; $b->out; PrintOutNL; ok Assemble(debug => 0, eq => <<END); aaAAaabbBBbb END my $a = CreateArena; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $a->q('ab'); my $b = CreateArena; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $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; ok Assemble(debug => 0, eq => <<END); abababababababab ababababababababababababababababababababababababababababababababababababab size: 0000 0000 0000 0010 size: 0000 0000 0000 004A size: 0000 0000 0000 0000 size: 0000 0000 0000 004A END
Get the length of an arena.
Parameter Description 1 $arena Arena descriptor 2 @variables Variables
Get the size of an arena.
Make an arena read only.
Parameter Description 1 $arena Arena descriptor
Make an arena writable.
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.
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
Parameter Description 1 $arena Arena 2 $bs Address of arena
my $a = CreateArena; $a->dump; my $b1 = $a->allocBlock($a->bs); $a->dump; my $b2 = $a->allocBlock($a->bs); $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
Append the content with length rdi addressed by rsi to the arena addressed by rax.
Append a constant string to the arena.
Parameter Description 1 $arena Arena descriptor 2 $string String
Append a quoted string containing new line characters to the arena addressed by rax.
Parameter Description 1 $arena Arena 2 $const Constant
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
Append a new line to the arena addressed by rax.
Append a trailing zero to the arena addressed by rax.
Append one arena to another.
Clear the arena addressed by rax.
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.
Read the named file (terminated with a zero byte) and place it into the named arena.
Print the specified arena addressed by rax on sysout.
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
Strings made from zmm sized blocks of text
Describe a string
Parameter Description 1 %options String options
Describe a string and optionally set its first block .
Parameter Description 1 $arena Arena description 2 %options {first=> offset of first block}
Parameter Description 1 $arena Arena description 2 %options Arena options
Create a string from a doubly link linked list of 64 byte blocks linked via 4 byte offsets in an arena and return its descriptor.
Parameter Description 1 $arena Arena description
Dump a string to sysout.
Parameter Description 1 $String String descriptor
Find the length of a string.
Parameter Description 1 $String String descriptor 2 $bs Optional arena address 3 $first Offset of first block
my $c = Rb(0..255); my $S = CreateArena; my $s = $S->CreateString; $s->append(source=>V(source, $c), V(size, 165)); $s->dump; $s->deleteChar(V(position, 0x44)); $s->dump; $s->len->outNL; ok Assemble(debug => 0, eq => <<END); string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0037 zmm31: 0000 0058 0000 0098 3635 3433 3231 302F 2E2D 2C2B 2A29 2827 2625 2423 2221 201F 1E1D 1C1B 1A19 1817 1615 1413 1211 100F 0E0D 0C0B 0A09 0807 0605 0403 0201 0037 Offset: 0000 0000 0000 0058 Length: 0000 0000 0000 0037 zmm31: 0000 0098 0000 0018 6D6C 6B6A 6968 6766 6564 6362 6160 5F5E 5D5C 5B5A 5958 5756 5554 5352 5150 4F4E 4D4C 4B4A 4948 4746 4544 4342 4140 3F3E 3D3C 3B3A 3938 3737 Offset: 0000 0000 0000 0098 Length: 0000 0000 0000 0037 zmm31: 0000 0018 0000 0058 A4A3 A2A1 A09F 9E9D 9C9B 9A99 9897 9695 9493 9291 908F 8E8D 8C8B 8A89 8887 8685 8483 8281 807F 7E7D 7C7B 7A79 7877 7675 7473 7271 706F 6E37 string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0037 zmm31: 0000 0058 0000 0098 3635 3433 3231 302F 2E2D 2C2B 2A29 2827 2625 2423 2221 201F 1E1D 1C1B 1A19 1817 1615 1413 1211 100F 0E0D 0C0B 0A09 0807 0605 0403 0201 0037 Offset: 0000 0000 0000 0058 Length: 0000 0000 0000 0036 zmm31: 0000 0098 0000 0018 186D 6C6B 6A69 6867 6665 6463 6261 605F 5E5D 5C5B 5A59 5857 5655 5453 5251 504F 4E4D 4C4B 4A49 4847 4645 4342 4140 3F3E 3D3C 3B3A 3938 3736 Offset: 0000 0000 0000 0098 Length: 0000 0000 0000 0037 zmm31: 0000 0018 0000 0058 A4A3 A2A1 A09F 9E9D 9C9B 9A99 9897 9695 9493 9291 908F 8E8D 8C8B 8A89 8887 8685 8483 8281 807F 7E7D 7C7B 7A79 7877 7675 7473 7271 706F 6E37 size: 0000 0000 0000 00A4 END
Concatenate two strings by appending a copy of the source to the target string.
Parameter Description 1 $target Target string 2 $source Source string
Insert a character into a string.
Parameter Description 1 $String String 2 @variables Variables
my $c = Rb(0..255); my $S = CreateArena; my $s = $S->CreateString; $s->append(source=>V(source, $c), K(size, 54)); $s->dump; $s->insertChar(V(character, 0x77), K(position, 4)); $s->dump; $s->insertChar(V(character, 0x88), K(position, 5)); $s->dump; $s->insertChar(V(character, 0x99), K(position, 6)); $s->dump; $s->insertChar(V(character, 0xAA), K(position, 7)); $s->dump; $s->insertChar(V(character, 0xBB), K(position, 8)); $s->dump; $s->insertChar(V(character, 0xCC), K(position, 9)); $s->dump; $s->insertChar(V(character, 0xDD), K(position, 10)); $s->dump; $s->insertChar(V(character, 0xEE), K(position, 11)); $s->dump; $s->insertChar(V(character, 0xFF), K(position, 12)); $s->dump; ok Assemble(debug => 0, eq => <<END); string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0036 zmm31: 0000 0018 0000 0018 0035 3433 3231 302F 2E2D 2C2B 2A29 2827 2625 2423 2221 201F 1E1D 1C1B 1A19 1817 1615 1413 1211 100F 0E0D 0C0B 0A09 0807 0605 0403 0201 0036 string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0037 zmm31: 0000 0018 0000 0018 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 7703 0201 0037 string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0005 zmm31: 0000 0058 0000 0058 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 7703 0201 0005 Offset: 0000 0000 0000 0058 Length: 0000 0000 0000 0033 zmm31: 0000 0018 0000 0018 0000 0018 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 8833 string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0005 zmm31: 0000 0058 0000 0058 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 7703 0201 0005 Offset: 0000 0000 0000 0058 Length: 0000 0000 0000 0034 zmm31: 0000 0018 0000 0018 0000 0035 3433 3231 302F 2E2D 2C2B 2A29 2827 2625 2423 2221 201F 1E1D 1C1B 1A19 1817 1615 1413 1211 100F 0E0D 0C0B 0A09 0807 0605 0499 8834 string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0005 zmm31: 0000 0058 0000 0058 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 7703 0201 0005 Offset: 0000 0000 0000 0058 Length: 0000 0000 0000 0035 zmm31: 0000 0018 0000 0018 0000 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 AA99 8835 string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0005 zmm31: 0000 0058 0000 0058 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 7703 0201 0005 Offset: 0000 0000 0000 0058 Length: 0000 0000 0000 0036 zmm31: 0000 0018 0000 0018 0035 3433 3231 302F 2E2D 2C2B 2A29 2827 2625 2423 2221 201F 1E1D 1C1B 1A19 1817 1615 1413 1211 100F 0E0D 0C0B 0A09 0807 0605 04BB AA99 8836 string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0005 zmm31: 0000 0058 0000 0058 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 7703 0201 0005 Offset: 0000 0000 0000 0058 Length: 0000 0000 0000 0037 zmm31: 0000 0018 0000 0018 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 CCBB AA99 8837 string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0005 zmm31: 0000 0058 0000 0058 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 7703 0201 0005 Offset: 0000 0000 0000 0058 Length: 0000 0000 0000 0005 zmm31: 0000 0098 0000 0098 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 CCBB AA99 8805 Offset: 0000 0000 0000 0098 Length: 0000 0000 0000 0033 zmm31: 0000 0018 0000 0018 0000 0018 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 DD33 string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0005 zmm31: 0000 0058 0000 0058 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 7703 0201 0005 Offset: 0000 0000 0000 0058 Length: 0000 0000 0000 0005 zmm31: 0000 0098 0000 0098 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 CCBB AA99 8805 Offset: 0000 0000 0000 0098 Length: 0000 0000 0000 0034 zmm31: 0000 0018 0000 0018 0000 0035 3433 3231 302F 2E2D 2C2B 2A29 2827 2625 2423 2221 201F 1E1D 1C1B 1A19 1817 1615 1413 1211 100F 0E0D 0C0B 0A09 0807 0605 04EE DD34 string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0005 zmm31: 0000 0058 0000 0058 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 7703 0201 0005 Offset: 0000 0000 0000 0058 Length: 0000 0000 0000 0005 zmm31: 0000 0098 0000 0098 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 CCBB AA99 8805 Offset: 0000 0000 0000 0098 Length: 0000 0000 0000 0035 zmm31: 0000 0018 0000 0018 0000 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 FFEE DD35 END
Delete a character in a string.
Get a character from a string.
Append the specified content in memory to the specified string.
Parameter Description 1 $String String descriptor 2 @variables Variables
Append the content of the specified short string.
Parameter Description 1 $string String descriptor 2 $short Short string
my $a = CreateArena; my $S = $a->CreateString; my $s = CreateShortString(0); my $d = Rb(1..63); $s->load(K(address, $d), K(size, 9)); $s->append($s); $S->appendShortString($s); $S->dump; ok Assemble(debug => 0, trace => 0, eq => <<END); string Dump Offset: 0000 0000 0000 0018 Length: 0000 0000 0000 0012 zmm31: 0000 0018 0000 0018 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0009 0807 0605 0403 0201 0908 0706 0504 0302 0112 END my $a = CreateArena; my $t = $a->CreateTree; my $s = CreateShortString(0); my $d = Rb(1..63); $s->load(K(address, $d), K(size, 9)); $t->insertShortString($s, K(data,42)); $t->dump; ok Assemble(debug => 0, trace => 0, eq => <<END); Tree at: 0000 0000 0000 0018 length: 0000 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 0000 0000 0000 0000 0000 0000 0002 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 0098 0000 0058 0001 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 0403 0201 index: 0000 0000 0000 0000 key: 0000 0000 0403 0201 data: 0000 0000 0000 0098 subTree Tree at: 0000 0000 0000 0098 length: 0000 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 0000 0000 0000 0000 0000 0000 0002 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 0118 0000 00D8 0001 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 0807 0605 index: 0000 0000 0000 0000 key: 0000 0000 0807 0605 data: 0000 0000 0000 0118 subTree Tree at: 0000 0000 0000 0118 length: 0000 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 0000 0000 0000 0000 0000 0000 0002 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 002A 0000 0158 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 0009 index: 0000 0000 0000 0000 key: 0000 0000 0000 0009 data: 0000 0000 0000 002A end end end END
Place as much as possible of the specified string into the specified short string.
Parameter Description 1 $string String descriptor 2 $short Short string descriptor 3 $first Optional offset to first block of string
Clear the block by freeing all but the first block.
Array constructed as a set of blocks in an arena
Describe a dynamic array held in an arena.
Parameter Description 1 %options Array description
Create a dynamic array held in an arena.
Reload the specified array description.
Parameter Description 1 $array Array descriptor 2 %options {first=>first block of array if not the existing first node; arena=>arena used by array if not the existing arena}
Dump a array.
Parameter Description 1 $Array Array descriptor 2 @variables Variables
Push an element onto the array.
my $c = Rb(0..255); my $A = CreateArena; my $a = $A->CreateArray; my $l = V(limit, 15); my $L = $l + 5; my sub put # Put a constant or a variable {my ($e) = @_; $a->push(element => (ref($e) ? $e : V($e, $e))); }; my sub get # Get a constant or a variable {my ($i) = @_; $a->get(index=>(my $v = ref($i) ? $i : K('index', $i)), my $e = V(element)); $v->out("index: ", " "); $e->outNL; }; $l->for(sub # Loop to the limit pushing {my ($index, $start, $next, $end) = @_; put($index+1); }); $l->for(sub # Loop to the limit getting {my ($index, $start, $next, $end) = @_; get($index); }); put(16); get(15); $L->for(sub {my ($index, $start, $next, $end) = @_; put($index+$l+2); }); $L->for(sub {my ($index, $start, $next, $end) = @_; get($index + $l + 1); }); if (1) {$a->put(my $i = V('index', 9), my $e = V(element, 0xFFF9)); get(9); } if (1) {$a->put(my $i = V('index', 19), my $e = V(element, 0xEEE9)); get(19); } ($l+$L+1)->for(sub {my ($i, $start, $next, $end) = @_; $a->pop(my $e = V(element)); $e->outNL; }); V(limit, 38)->for(sub # Push using a loop and reusing the freed space {my ($index, $start, $next, $end) = @_; $a->push(element=>$index*2); }); V(limit, 38)->for(sub # Push using a loop and reusing the freed space {my ($index, $start, $next, $end) = @_; $a->pop(my $e = V(element)); $e->outNL; }); $a->dump; ok Assemble(debug => 0, eq => <<END); index: 0000 0000 0000 0000 element: 0000 0000 0000 0001 index: 0000 0000 0000 0001 element: 0000 0000 0000 0002 index: 0000 0000 0000 0002 element: 0000 0000 0000 0003 index: 0000 0000 0000 0003 element: 0000 0000 0000 0004 index: 0000 0000 0000 0004 element: 0000 0000 0000 0005 index: 0000 0000 0000 0005 element: 0000 0000 0000 0006 index: 0000 0000 0000 0006 element: 0000 0000 0000 0007 index: 0000 0000 0000 0007 element: 0000 0000 0000 0008 index: 0000 0000 0000 0008 element: 0000 0000 0000 0009 index: 0000 0000 0000 0009 element: 0000 0000 0000 000A index: 0000 0000 0000 000A element: 0000 0000 0000 000B index: 0000 0000 0000 000B element: 0000 0000 0000 000C index: 0000 0000 0000 000C element: 0000 0000 0000 000D index: 0000 0000 0000 000D element: 0000 0000 0000 000E index: 0000 0000 0000 000E element: 0000 0000 0000 000F index: 0000 0000 0000 000F element: 0000 0000 0000 0010 index: 0000 0000 0000 0010 element: 0000 0000 0000 0011 index: 0000 0000 0000 0011 element: 0000 0000 0000 0012 index: 0000 0000 0000 0012 element: 0000 0000 0000 0013 index: 0000 0000 0000 0013 element: 0000 0000 0000 0014 index: 0000 0000 0000 0014 element: 0000 0000 0000 0015 index: 0000 0000 0000 0015 element: 0000 0000 0000 0016 index: 0000 0000 0000 0016 element: 0000 0000 0000 0017 index: 0000 0000 0000 0017 element: 0000 0000 0000 0018 index: 0000 0000 0000 0018 element: 0000 0000 0000 0019 index: 0000 0000 0000 0019 element: 0000 0000 0000 001A index: 0000 0000 0000 001A element: 0000 0000 0000 001B index: 0000 0000 0000 001B element: 0000 0000 0000 001C index: 0000 0000 0000 001C element: 0000 0000 0000 001D index: 0000 0000 0000 001D element: 0000 0000 0000 001E index: 0000 0000 0000 001E element: 0000 0000 0000 001F index: 0000 0000 0000 001F element: 0000 0000 0000 0020 index: 0000 0000 0000 0020 element: 0000 0000 0000 0021 index: 0000 0000 0000 0021 element: 0000 0000 0000 0022 index: 0000 0000 0000 0022 element: 0000 0000 0000 0023 index: 0000 0000 0000 0023 element: 0000 0000 0000 0024 index: 0000 0000 0000 0009 element: 0000 0000 0000 FFF9 index: 0000 0000 0000 0013 element: 0000 0000 0000 EEE9 element: 0000 0000 0000 0024 element: 0000 0000 0000 0023 element: 0000 0000 0000 0022 element: 0000 0000 0000 0021 element: 0000 0000 0000 0020 element: 0000 0000 0000 001F element: 0000 0000 0000 001E element: 0000 0000 0000 001D element: 0000 0000 0000 001C element: 0000 0000 0000 001B element: 0000 0000 0000 001A element: 0000 0000 0000 0019 element: 0000 0000 0000 0018 element: 0000 0000 0000 0017 element: 0000 0000 0000 0016 element: 0000 0000 0000 0015 element: 0000 0000 0000 EEE9 element: 0000 0000 0000 0013 element: 0000 0000 0000 0012 element: 0000 0000 0000 0011 element: 0000 0000 0000 0010 element: 0000 0000 0000 000F element: 0000 0000 0000 000E element: 0000 0000 0000 000D element: 0000 0000 0000 000C element: 0000 0000 0000 000B element: 0000 0000 0000 FFF9 element: 0000 0000 0000 0009 element: 0000 0000 0000 0008 element: 0000 0000 0000 0007 element: 0000 0000 0000 0006 element: 0000 0000 0000 0005 element: 0000 0000 0000 0004 element: 0000 0000 0000 0003 element: 0000 0000 0000 0002 element: 0000 0000 0000 0001 element: 0000 0000 0000 004A element: 0000 0000 0000 0048 element: 0000 0000 0000 0046 element: 0000 0000 0000 0044 element: 0000 0000 0000 0042 element: 0000 0000 0000 0040 element: 0000 0000 0000 003E element: 0000 0000 0000 003C element: 0000 0000 0000 003A element: 0000 0000 0000 0038 element: 0000 0000 0000 0036 element: 0000 0000 0000 0034 element: 0000 0000 0000 0032 element: 0000 0000 0000 0030 element: 0000 0000 0000 002E element: 0000 0000 0000 002C element: 0000 0000 0000 002A element: 0000 0000 0000 0028 element: 0000 0000 0000 0026 element: 0000 0000 0000 0024 element: 0000 0000 0000 0022 element: 0000 0000 0000 0020 element: 0000 0000 0000 001E element: 0000 0000 0000 001C element: 0000 0000 0000 001A element: 0000 0000 0000 0018 element: 0000 0000 0000 0016 element: 0000 0000 0000 0014 element: 0000 0000 0000 0012 element: 0000 0000 0000 0010 element: 0000 0000 0000 000E element: 0000 0000 0000 000C element: 0000 0000 0000 000A element: 0000 0000 0000 0008 element: 0000 0000 0000 0006 element: 0000 0000 0000 0004 element: 0000 0000 0000 0002 element: 0000 0000 0000 0000 array Size: 0000 0000 0000 0000 zmm31: 0000 001C 0000 001A 0000 0018 0000 0016 0000 0014 0000 0012 0000 0010 0000 000E 0000 000C 0000 000A 0000 0008 0000 0006 0000 0004 0000 0002 0000 0000 0000 0000 END my $c = Rb(0..255); my $A = CreateArena; my $a = $A->CreateArray; my sub put {my ($e) = @_; $a->push(element => V($e, $e)); }; my sub get {my ($i) = @_; # Parameters $a->get(my $v = V('index', $i), my $e = V(element)); $v->out; PrintOutString " "; $e->outNL; }; put($_) for 1..15; get(15); ok Assemble(debug => 2, eq => <<END); Index out of bounds on get from array, Index: 0000 0000 0000 000F Size: 0000 0000 0000 000F END
Pop an element from an array.
my $c = Rb(0..255); my $A = CreateArena; my $a = $A->CreateArray; my $l = V(limit, 15); my $L = $l + 5; my sub put # Put a constant or a variable {my ($e) = @_; $a->push(element => (ref($e) ? $e : V($e, $e))); }; my sub get # Get a constant or a variable {my ($i) = @_; $a->get(index=>(my $v = ref($i) ? $i : K('index', $i)), my $e = V(element)); $v->out("index: ", " "); $e->outNL; }; $l->for(sub # Loop to the limit pushing {my ($index, $start, $next, $end) = @_; put($index+1); }); $l->for(sub # Loop to the limit getting {my ($index, $start, $next, $end) = @_; get($index); }); put(16); get(15); $L->for(sub {my ($index, $start, $next, $end) = @_; put($index+$l+2); }); $L->for(sub {my ($index, $start, $next, $end) = @_; get($index + $l + 1); }); if (1) {$a->put(my $i = V('index', 9), my $e = V(element, 0xFFF9)); get(9); } if (1) {$a->put(my $i = V('index', 19), my $e = V(element, 0xEEE9)); get(19); } ($l+$L+1)->for(sub {my ($i, $start, $next, $end) = @_; $a->pop(my $e = V(element)); $e->outNL; }); V(limit, 38)->for(sub # Push using a loop and reusing the freed space {my ($index, $start, $next, $end) = @_; $a->push(element=>$index*2); }); V(limit, 38)->for(sub # Push using a loop and reusing the freed space {my ($index, $start, $next, $end) = @_; $a->pop(my $e = V(element)); $e->outNL; }); $a->dump; ok Assemble(debug => 0, eq => <<END); index: 0000 0000 0000 0000 element: 0000 0000 0000 0001 index: 0000 0000 0000 0001 element: 0000 0000 0000 0002 index: 0000 0000 0000 0002 element: 0000 0000 0000 0003 index: 0000 0000 0000 0003 element: 0000 0000 0000 0004 index: 0000 0000 0000 0004 element: 0000 0000 0000 0005 index: 0000 0000 0000 0005 element: 0000 0000 0000 0006 index: 0000 0000 0000 0006 element: 0000 0000 0000 0007 index: 0000 0000 0000 0007 element: 0000 0000 0000 0008 index: 0000 0000 0000 0008 element: 0000 0000 0000 0009 index: 0000 0000 0000 0009 element: 0000 0000 0000 000A index: 0000 0000 0000 000A element: 0000 0000 0000 000B index: 0000 0000 0000 000B element: 0000 0000 0000 000C index: 0000 0000 0000 000C element: 0000 0000 0000 000D index: 0000 0000 0000 000D element: 0000 0000 0000 000E index: 0000 0000 0000 000E element: 0000 0000 0000 000F index: 0000 0000 0000 000F element: 0000 0000 0000 0010 index: 0000 0000 0000 0010 element: 0000 0000 0000 0011 index: 0000 0000 0000 0011 element: 0000 0000 0000 0012 index: 0000 0000 0000 0012 element: 0000 0000 0000 0013 index: 0000 0000 0000 0013 element: 0000 0000 0000 0014 index: 0000 0000 0000 0014 element: 0000 0000 0000 0015 index: 0000 0000 0000 0015 element: 0000 0000 0000 0016 index: 0000 0000 0000 0016 element: 0000 0000 0000 0017 index: 0000 0000 0000 0017 element: 0000 0000 0000 0018 index: 0000 0000 0000 0018 element: 0000 0000 0000 0019 index: 0000 0000 0000 0019 element: 0000 0000 0000 001A index: 0000 0000 0000 001A element: 0000 0000 0000 001B index: 0000 0000 0000 001B element: 0000 0000 0000 001C index: 0000 0000 0000 001C element: 0000 0000 0000 001D index: 0000 0000 0000 001D element: 0000 0000 0000 001E index: 0000 0000 0000 001E element: 0000 0000 0000 001F index: 0000 0000 0000 001F element: 0000 0000 0000 0020 index: 0000 0000 0000 0020 element: 0000 0000 0000 0021 index: 0000 0000 0000 0021 element: 0000 0000 0000 0022 index: 0000 0000 0000 0022 element: 0000 0000 0000 0023 index: 0000 0000 0000 0023 element: 0000 0000 0000 0024 index: 0000 0000 0000 0009 element: 0000 0000 0000 FFF9 index: 0000 0000 0000 0013 element: 0000 0000 0000 EEE9 element: 0000 0000 0000 0024 element: 0000 0000 0000 0023 element: 0000 0000 0000 0022 element: 0000 0000 0000 0021 element: 0000 0000 0000 0020 element: 0000 0000 0000 001F element: 0000 0000 0000 001E element: 0000 0000 0000 001D element: 0000 0000 0000 001C element: 0000 0000 0000 001B element: 0000 0000 0000 001A element: 0000 0000 0000 0019 element: 0000 0000 0000 0018 element: 0000 0000 0000 0017 element: 0000 0000 0000 0016 element: 0000 0000 0000 0015 element: 0000 0000 0000 EEE9 element: 0000 0000 0000 0013 element: 0000 0000 0000 0012 element: 0000 0000 0000 0011 element: 0000 0000 0000 0010 element: 0000 0000 0000 000F element: 0000 0000 0000 000E element: 0000 0000 0000 000D element: 0000 0000 0000 000C element: 0000 0000 0000 000B element: 0000 0000 0000 FFF9 element: 0000 0000 0000 0009 element: 0000 0000 0000 0008 element: 0000 0000 0000 0007 element: 0000 0000 0000 0006 element: 0000 0000 0000 0005 element: 0000 0000 0000 0004 element: 0000 0000 0000 0003 element: 0000 0000 0000 0002 element: 0000 0000 0000 0001 element: 0000 0000 0000 004A element: 0000 0000 0000 0048 element: 0000 0000 0000 0046 element: 0000 0000 0000 0044 element: 0000 0000 0000 0042 element: 0000 0000 0000 0040 element: 0000 0000 0000 003E element: 0000 0000 0000 003C element: 0000 0000 0000 003A element: 0000 0000 0000 0038 element: 0000 0000 0000 0036 element: 0000 0000 0000 0034 element: 0000 0000 0000 0032 element: 0000 0000 0000 0030 element: 0000 0000 0000 002E element: 0000 0000 0000 002C element: 0000 0000 0000 002A element: 0000 0000 0000 0028 element: 0000 0000 0000 0026 element: 0000 0000 0000 0024 element: 0000 0000 0000 0022 element: 0000 0000 0000 0020 element: 0000 0000 0000 001E element: 0000 0000 0000 001C element: 0000 0000 0000 001A element: 0000 0000 0000 0018 element: 0000 0000 0000 0016 element: 0000 0000 0000 0014 element: 0000 0000 0000 0012 element: 0000 0000 0000 0010 element: 0000 0000 0000 000E element: 0000 0000 0000 000C element: 0000 0000 0000 000A element: 0000 0000 0000 0008 element: 0000 0000 0000 0006 element: 0000 0000 0000 0004 element: 0000 0000 0000 0002 element: 0000 0000 0000 0000 array Size: 0000 0000 0000 0000 zmm31: 0000 001C 0000 001A 0000 0018 0000 0016 0000 0014 0000 0012 0000 0010 0000 000E 0000 000C 0000 000A 0000 0008 0000 0006 0000 0004 0000 0002 0000 0000 0000 0000 END
Return the size of an array as a variable.
Parameter Description 1 $Array Array descriptor 2 $bs Optional arena address 3 $first Optional first block
Get an element from the array.
Put an element into an array as long as it is with in its limits established by pushing.
Tree constructed as sets of blocks in an arena.
Return a descriptor for a tree with the specified options
Parameter Description 1 %options Tree description options
Return a descriptor for a tree in the specified arena with the specified options
Parameter Description 1 $arena Arena descriptor 2 %options Options for tree
Create a tree in an arena.
Parameter Description 1 $arena Arena description 2 $bs Optional arena address
my $N = 12; my $b = CreateArena; my $t = $b->CreateTree; 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: '); my $D = V(depth); $iter->tree->depth($t->address, $iter->node, $D); $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 > 0, 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
Reload the specified tree description.
Parameter Description 1 $tree Tree descriptor 2 %options {first=>first node of tree if not the existing first node; arena=>arena used by tree if not the existing arena}
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 3 $bs Optional arena address 4 $first Optional start node
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
my $L = K(loop, 4); my $b = CreateArena; my $T = $b->CreateTree; my $t = $T->reload; $L->for(sub {my ($i, $start, $next, $end) = @_; $t->insertTreeAndReload($i); $t->first->outNL; }); $t->insert($L, $L*2); my $f = $T->reload; $L->for(sub {my ($i, $start, $next, $end) = @_; $f->findAndReload($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
Find the data at the end of a key chain held in a short string. Return a tree descriptor referencing the data located or marked as failed to find.
Parameter Description 1 $tree Tree descriptor 2 $string Short string
Return a variable containing the number of keys in the specified tree.
Parameter Description 1 $t Tree descriptor
my $b = CreateArena; my $t = $b->CreateTree; my $s = $t->size; $s->outNL; V(count, 24)->for(sub {my ($index, $start, $next, $end) = @_; my $k = $index + 1; my $d = $k + 0x100; $t->insert($k, $d); my $s = $t->size; $s->outNL; }); $t->getKeysDataNode($b->bs, $t->first, 31, 30, 29); PrintOutStringNL "Root"; $t->first->outNL('First: '); PrintOutRegisterInHex zmm31, zmm30, zmm29; $t->getKeysDataNode($b->bs, V(offset, 0xd8), 28,27,26); PrintOutStringNL "Left"; PrintOutRegisterInHex zmm28, zmm27, zmm26; $t->getKeysDataNode($b->bs, V(offset, 0x258), 28,27,26); PrintOutStringNL "Left"; PrintOutRegisterInHex zmm28, zmm27, zmm26; $t->getKeysDataNode($b->bs, V(offset, 0x198), 28,27,26); PrintOutStringNL "Left"; PrintOutRegisterInHex zmm28, zmm27, zmm26; ok Assemble(debug => 0, eq => <<END); size: 0000 0000 0000 0000 size: 0000 0000 0000 0001 size: 0000 0000 0000 0002 size: 0000 0000 0000 0003 size: 0000 0000 0000 0004 size: 0000 0000 0000 0005 size: 0000 0000 0000 0006 size: 0000 0000 0000 0007 size: 0000 0000 0000 0008 size: 0000 0000 0000 0009 size: 0000 0000 0000 000A size: 0000 0000 0000 000B size: 0000 0000 0000 000C size: 0000 0000 0000 000D size: 0000 0000 0000 000E size: 0000 0000 0000 000F size: 0000 0000 0000 0010 size: 0000 0000 0000 0011 size: 0000 0000 0000 0012 size: 0000 0000 0000 0013 size: 0000 0000 0000 0014 size: 0000 0000 0000 0015 size: 0000 0000 0000 0016 size: 0000 0000 0000 0017 size: 0000 0000 0000 0018 Root First: 0000 0000 0000 0018 zmm31: 0000 0058 0000 0002 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 0010 0000 0008 zmm30: 0000 0098 0000 0030 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 0110 0000 0108 zmm29: 0000 0018 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 0198 0000 0258 0000 00D8 Left zmm28: 0000 0118 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 0158 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0107 0000 0106 0000 0105 0000 0104 0000 0103 0000 0102 0000 0101 zmm26: 0000 00D8 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 0000 Left zmm28: 0000 0298 0000 0007 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 000F 0000 000E 0000 000D 0000 000C 0000 000B 0000 000A 0000 0009 zmm27: 0000 02D8 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 010F 0000 010E 0000 010D 0000 010C 0000 010B 0000 010A 0000 0109 zmm26: 0000 0258 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 0000 Left zmm28: 0000 01D8 0000 0008 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0018 0000 0017 0000 0016 0000 0015 0000 0014 0000 0013 0000 0012 0000 0011 zmm27: 0000 0218 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0118 0000 0117 0000 0116 0000 0115 0000 0114 0000 0113 0000 0112 0000 0111 zmm26: 0000 0198 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 0000 END
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
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
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
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: 0000 0000 0000 0018 key: 0000 0000 0000 0001 data: 0000 0000 0000 0098 depth: 0000 0000 0000 0001 Tree at: 0000 0000 0000 0098 key: 0000 0000 0000 0002 data: 0000 0000 0000 0004 depth: 0000 0000 0000 0001 END my $L = K(loop, 11); my $b = CreateArena; my $B = CreateArena; my $t = $b->CreateTree; my $T = $B->CreateTree; $L->for(sub {my ($i, $start, $next, $end) = @_; $t->insert($i+0x11, K(data, 0xFF)); $T->insert($i+0x22, K(data, 0xDD)); }); $b->dump; $B->dump; $t->print; $T->print; ok Assemble(debug => 0, eq => <<END); Arena Size: 0000 0000 0000 1000 Used: 0000 0000 0000 0098 0000: 0010 0000 0000 00009800 0000 0000 00000000 0000 0000 00001100 0000 1200 00001300 0000 1400 00001500 0000 1600 00001700 0000 1800 00001900 0000 1A00 0000 0040: 1B00 0000 0000 00000000 0000 0000 00000B00 0000 5800 0000FF00 0000 FF00 0000FF00 0000 FF00 0000FF00 0000 FF00 0000FF00 0000 FF00 0000FF00 0000 FF00 0000 0080: FF00 0000 0000 00000000 0000 0000 00001600 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 00002200 0000 2300 00002400 0000 2500 00002600 0000 2700 00002800 0000 2900 00002A00 0000 2B00 0000 0040: 2C00 0000 0000 00000000 0000 0000 00000B00 0000 5800 0000DD00 0000 DD00 0000DD00 0000 DD00 0000DD00 0000 DD00 0000DD00 0000 DD00 0000DD00 0000 DD00 0000 0080: DD00 0000 0000 00000000 0000 0000 00001600 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 Tree at: 0000 0000 0000 0018 key: 0000 0000 0000 0011 data: 0000 0000 0000 00FF depth: 0000 0000 0000 0001 key: 0000 0000 0000 0012 data: 0000 0000 0000 00FF depth: 0000 0000 0000 0001 key: 0000 0000 0000 0013 data: 0000 0000 0000 00FF depth: 0000 0000 0000 0001 key: 0000 0000 0000 0014 data: 0000 0000 0000 00FF depth: 0000 0000 0000 0001 key: 0000 0000 0000 0015 data: 0000 0000 0000 00FF depth: 0000 0000 0000 0001 key: 0000 0000 0000 0016 data: 0000 0000 0000 00FF depth: 0000 0000 0000 0001 key: 0000 0000 0000 0017 data: 0000 0000 0000 00FF depth: 0000 0000 0000 0001 key: 0000 0000 0000 0018 data: 0000 0000 0000 00FF depth: 0000 0000 0000 0001 key: 0000 0000 0000 0019 data: 0000 0000 0000 00FF depth: 0000 0000 0000 0001 key: 0000 0000 0000 001A data: 0000 0000 0000 00FF depth: 0000 0000 0000 0001 key: 0000 0000 0000 001B data: 0000 0000 0000 00FF depth: 0000 0000 0000 0001 Tree at: 0000 0000 0000 0018 key: 0000 0000 0000 0022 data: 0000 0000 0000 00DD depth: 0000 0000 0000 0001 key: 0000 0000 0000 0023 data: 0000 0000 0000 00DD depth: 0000 0000 0000 0001 key: 0000 0000 0000 0024 data: 0000 0000 0000 00DD depth: 0000 0000 0000 0001 key: 0000 0000 0000 0025 data: 0000 0000 0000 00DD depth: 0000 0000 0000 0001 key: 0000 0000 0000 0026 data: 0000 0000 0000 00DD depth: 0000 0000 0000 0001 key: 0000 0000 0000 0027 data: 0000 0000 0000 00DD depth: 0000 0000 0000 0001 key: 0000 0000 0000 0028 data: 0000 0000 0000 00DD depth: 0000 0000 0000 0001 key: 0000 0000 0000 0029 data: 0000 0000 0000 00DD depth: 0000 0000 0000 0001 key: 0000 0000 0000 002A data: 0000 0000 0000 00DD depth: 0000 0000 0000 0001 key: 0000 0000 0000 002B data: 0000 0000 0000 00DD depth: 0000 0000 0000 0001 key: 0000 0000 0000 002C data: 0000 0000 0000 00DD depth: 0000 0000 0000 0001 END
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.
Insert some data at the end of a chain of sub trees keyed by the contents of a short string.
Parameter Description 1 $tree Tree descriptor 2 $string Short string 3 $data Data as a dword
Return the offset of the left most or right most node.
Parameter Description 1 $t Tree descriptor 2 $dir Direction: left = 0 or right = 1 3 $bs Arena address 4 $node Start node 5 $offset Offset of located node
Return the offset of the left most node from the specified node.
Parameter Description 1 $t Tree descriptor 2 $bs Arena address 3 $node Start node 4 $offset Returned offset
Return the depth of a node within a tree.
Parameter Description 1 $t Tree descriptor 2 $bs Arena address 3 $node Node 4 $depth Return depth
Construct trees of trees.
Print a tree
Print a tree.
Parameter Description 1 $t Tree
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: 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 Tree at: 0000 0000 0000 0ED8 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 Tree at: 0000 0000 0000 0E58 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 Tree at: 0000 0000 0000 0DD8 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 Tree at: 0000 0000 0000 0D58 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 Tree at: 0000 0000 0000 0CD8 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 Tree at: 0000 0000 0000 0C58 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 Tree at: 0000 0000 0000 0BD8 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 Tree at: 0000 0000 0000 0B58 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 Tree at: 0000 0000 0000 0AD8 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 Tree at: 0000 0000 0000 0998 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 Tree at: 0000 0000 0000 0918 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 Tree at: 0000 0000 0000 0898 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 Tree at: 0000 0000 0000 0818 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 Tree at: 0000 0000 0000 06D8 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 Tree at: 0000 0000 0000 0658 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 Tree at: 0000 0000 0000 05D8 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 Tree at: 0000 0000 0000 0398 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 Tree at: 0000 0000 0000 0318 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 Tree at: 0000 0000 0000 0298 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 Tree at: 0000 0000 0000 0218 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 Tree at: 0000 0000 0000 0198 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 Tree at: 0000 0000 0000 0118 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: 0000 0000 0000 0098 END
Dump a tree and all its sub trees.
Parameter Description 1 $t Tree 2 $first Optional offset to first node 3 $bs Optional arena address
my $L = V(loop, 15); my $b = CreateArena; my $t = $b->CreateTree; $L->for(sub {my ($i, $start, $next, $end) = @_; If ($i % 2 == 0, Then {$t->insert ($i, $i); }, Else {$t->insertTree($i); }); }); $t->dump(); ok Assemble(debug => 0, eq => <<END); Tree at: 0000 0000 0000 0018 length: 0000 0000 0000 0001 0000 0018 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 0518 0000 0458 0000 0418 0000 001E 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 0218 0000 0058 0001 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 0007 index: 0000 0000 0000 0000 key: 0000 0000 0000 0007 data: 0000 0000 0000 0218 subTree Tree at: 0000 0000 0000 0218 length: 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 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 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0258 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 0000 end Tree at: 0000 0000 0000 0458 length: 0000 0000 0000 0007 0000 0458 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 0000 0000 04D8 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0006 0000 0198 0000 0004 0000 0118 0000 0002 0000 0098 0000 0000 0000 0498 002A 0007 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0006 0000 0005 0000 0004 0000 0003 0000 0002 0000 0001 0000 0000 index: 0000 0000 0000 0000 key: 0000 0000 0000 0000 data: 0000 0000 0000 0000 index: 0000 0000 0000 0001 key: 0000 0000 0000 0001 data: 0000 0000 0000 0098 subTree index: 0000 0000 0000 0002 key: 0000 0000 0000 0002 data: 0000 0000 0000 0002 index: 0000 0000 0000 0003 key: 0000 0000 0000 0003 data: 0000 0000 0000 0118 subTree index: 0000 0000 0000 0004 key: 0000 0000 0000 0004 data: 0000 0000 0000 0004 index: 0000 0000 0000 0005 key: 0000 0000 0000 0005 data: 0000 0000 0000 0198 subTree index: 0000 0000 0000 0006 key: 0000 0000 0000 0006 data: 0000 0000 0000 0006 Tree at: 0000 0000 0000 0098 length: 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 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 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 00D8 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 0000 end Tree at: 0000 0000 0000 0118 length: 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 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 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0158 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 0000 end Tree at: 0000 0000 0000 0198 length: 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 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 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 01D8 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 0000 end end Tree at: 0000 0000 0000 0518 length: 0000 0000 0000 0007 0000 0518 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 0000 0000 0598 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 000E 0000 0398 0000 000C 0000 0318 0000 000A 0000 0298 0000 0008 0000 0558 002A 0007 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 0000 0008 index: 0000 0000 0000 0000 key: 0000 0000 0000 0008 data: 0000 0000 0000 0008 index: 0000 0000 0000 0001 key: 0000 0000 0000 0009 data: 0000 0000 0000 0298 subTree index: 0000 0000 0000 0002 key: 0000 0000 0000 000A data: 0000 0000 0000 000A index: 0000 0000 0000 0003 key: 0000 0000 0000 000B data: 0000 0000 0000 0318 subTree index: 0000 0000 0000 0004 key: 0000 0000 0000 000C data: 0000 0000 0000 000C index: 0000 0000 0000 0005 key: 0000 0000 0000 000D data: 0000 0000 0000 0398 subTree index: 0000 0000 0000 0006 key: 0000 0000 0000 000E data: 0000 0000 0000 000E Tree at: 0000 0000 0000 0298 length: 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 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 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 02D8 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 0000 end Tree at: 0000 0000 0000 0318 length: 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 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 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0358 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 0000 end Tree at: 0000 0000 0000 0398 length: 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 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 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 03D8 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 0000 end end end END
Iterate through a tree non recursively
Iterate through a multi way tree starting either at the specified node or the first node of the specified tree.
Parameter Description 1 $t Tree 2 $bs Optional arena else the arena associated with the tree 3 $first Optionally the node to start at else the first node of the supplied tree will be used
Next element in the tree.
Parameter Description 1 $iter Iterator
Call the specified block with each (key, data) from the specified tree in order.
Parameter Description 1 $t Tree descriptor 2 $block Block to execute 3 $bs Arena address if not the one associated with the tree descriptor 4 $first First node offset if not the root of the tree provided
Quarks allow us to replace unique strings with unique numbers. We can translate either from a string to its associated number or from a number to its associated string or from a quark in one set of quarks to the corresponding quark with the same string in another set of quarks.
Return a descriptor for a set of quarks
Parameter Description 1 %options Options
Return a descriptor for a tree in the specified arena.
Create quarks in a specified arena.
Parameter Description 1 $arena Arena description optional arena address
my $N = 5; my $a = CreateArena; # Arena containing quarks my $Q = $a->CreateQuarks; # Quarks my $s = CreateShortString(0); # Short string used to load and unload quarks my $d = Rb(1..63); for my $i(1..$N) # Load a set of quarks {my $j = $i - 1; $s->load(K(address, $d), K(size, 4+$i)); my $q = $Q->quarkFromShortString($s); $q->outNL("New quark $j: "); # New quark, new number } PrintOutNL; for my $i(reverse 1..$N) # Reload a set of quarks {my $j = $i - 1; $s->load(K(address, $d), K(size, 4+$i)); my $q = $Q->quarkFromShortString($s); $q->outNL("Old quark $j: "); # Old quark, old number } PrintOutNL; for my $i(1..$N) # Dump quarks {my $j = $i - 1; $s->clear; $Q->shortStringFromQuark(K(quark, $j), $s); PrintOutString "Quark string $j: "; PrintOutRegisterInHex xmm0; } ok Assemble(debug => 0, trace => 0, eq => <<END); New quark 0: 0000 0000 0000 0000 New quark 1: 0000 0000 0000 0001 New quark 2: 0000 0000 0000 0002 New quark 3: 0000 0000 0000 0003 New quark 4: 0000 0000 0000 0004 Old quark 4: 0000 0000 0000 0004 Old quark 3: 0000 0000 0000 0003 Old quark 2: 0000 0000 0000 0002 Old quark 1: 0000 0000 0000 0001 Old quark 0: 0000 0000 0000 0000 Quark string 0: xmm0: 0000 0000 0000 0000 0000 0504 0302 0105 Quark string 1: xmm0: 0000 0000 0000 0000 0006 0504 0302 0106 Quark string 2: xmm0: 0000 0000 0000 0000 0706 0504 0302 0107 Quark string 3: xmm0: 0000 0000 0000 0008 0706 0504 0302 0108 Quark string 4: xmm0: 0000 0000 0000 0908 0706 0504 0302 0109 END my $N = 5; my $a = CreateArena; # Arena containing quarks my $Q1 = $a->CreateQuarks; # Quarks my $Q2 = $a->CreateQuarks; # Quarks my $s = CreateShortString(0); # Short string used to load and unload quarks my $d = Rb(1..63); for my $i(1..$N) # Load first set of quarks {my $j = $i - 1; $s->load(K(address, $d), K(size, 4+$i)); my $q = $Q1->quarkFromShortString($s); $q->outNL("Q1 $j: "); } PrintOutNL; for my $i(1..$N) # Load second set of quarks {my $j = $i - 1; $s->load(K(address, $d), K(size, 5+$i)); my $q = $Q2->quarkFromShortString($s); $q->outNL("Q2 $j: "); } PrintOutNL; $Q1->quarkToQuark(K(three,3), $Q1)->outNL; $Q1->quarkToQuark(K(three,3), $Q2)->outNL; $Q2->quarkToQuark(K(two, 2), $Q1)->outNL; $Q2->quarkToQuark(K(two, 2), $Q2)->outNL; ok Assemble(debug => 0, trace => 0, eq => <<END); Q1 0: 0000 0000 0000 0000 Q1 1: 0000 0000 0000 0001 Q1 2: 0000 0000 0000 0002 Q1 3: 0000 0000 0000 0003 Q1 4: 0000 0000 0000 0004 Q2 0: 0000 0000 0000 0000 Q2 1: 0000 0000 0000 0001 Q2 2: 0000 0000 0000 0002 Q2 3: 0000 0000 0000 0003 Q2 4: 0000 0000 0000 0004 found: 0000 0000 0000 0003 found: 0000 0000 0000 0002 found: 0000 0000 0000 0003 found: 0000 0000 0000 0002 END my $s = CreateShortString(0); # Short string used to load and unload quarks my $d = Rb(1..63); $s->loadDwordBytes(0, K(address, $d), K(size, 9)); PrintOutRegisterInHex xmm0; ok Assemble(debug => 0, trace => 0, eq => <<END); xmm0: 0000 0000 0000 211D 1915 110D 0905 0109 END
Reload the description of a set of quarks.
Parameter Description 1 $q Quarks 2 %options {arena=>arena to use; tree => first tree block; array => first array block}
Create a quark from a short string.
Parameter Description 1 $q Quarks 2 $string Short string
Locate (if possible) but do not create a quark from a short string. A quark of -1 is returned if there is no matching quark otherwise the number of the matching quark is returned in a variable.
Load a short string from the quark with the specified number. Returns a variable that is set to one if the quark was found else zero.
Parameter Description 1 $q Quarks 2 $number Variable quark number 3 $string Short string to load
Given a variable quark number in one set of quarks find the corresponding quark in another set of quarks and return it in a variable. No new quarks are created in this process. If the quark cannot be found in the first set we return -1, if it cannot be found in the second set we return -2 else the number of the matching quark.
Parameter Description 1 $Q First set of quarks 2 $number Variable quark number in first set 3 $q Second set of quarks
Create a quark from a subroutine definition.
Parameter Description 1 $q Quarks 2 $sub Subroutine definition 3 $String Optional overriding name as a short string
my $s1 = Subroutine {PrintOutStringNL "11111"; } [], name => 'test1'; my $s2 = Subroutine {PrintOutStringNL "22222"; } [], name => 'test2'; my $a = CreateArena; my $q = $a->CreateQuarks; my $n1 = $q->quarkFromSub($s1); my $s = CreateShortString(0); $s->loadConstantString("assign"); my $n2 = $q->quarkFromSub($s2, $s); my $S1 = $q->subFromQuark($n1); $s1->V->outNL; $S1 ->outNL(" sub: "); my $S2 = $q->subFromQuark($n2); $s2->V->outNL; $S2 ->outNL(" sub: "); $q->call($n1); $q->call($n2); ok Assemble(debug => 0, trace => 0, eq => <<END); call: 0000 0000 0040 1006 sub: 0000 0000 0040 1006 call: 0000 0000 0040 107A sub: 0000 0000 0040 107A 11111 22222 END
Get the offset of a subroutine as a variable from a set of quarks.
Parameter Description 1 $q Quarks 2 $number Variable subroutine number
Call a subroutine via its quark number. Return one in a variable if the subroutine was found and called else zero.
Dump a set of quarks identifying subroutines.
Parameter Description 1 $q Quarks
Assemble generated code
Call a C subroutine.
Parameter Description 1 $sub Name of the sub to call 2 @parameters Parameters
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
Name external references.
Parameter Description 1 @externalReferences External references
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
Libraries to link with.
Parameter Description 1 @libraries External references
Initialize the assembler.
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
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 the generated code.
PrintOutStringNL "Hello World"; PrintOutStringNL "Hello World"; PrintErrStringNL "Hello World"; ok Assemble(debug => 0, eq => <<END); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Hello World Hello World END
Quarks
Initial allocation
The arena containing the quarks
Hash of {argument name, argument variable}
Arena containing tree
Constant if true
Counter - number of node
Data at this position
Lexical depth
End label for this subroutine
Expression that initializes the variable
Variable addressing offset to first block of keys.
Variable indicating whether the last find was successful or not
Free chain offset
Global if true
Key at this position
Address in memory
Left split length
Maximum length in a block
Offset of length in keys block. The length field is a word - see: "MultiWayTree.svg"
Lexical level
Location of links in bytes in zmm
Offset of keys, data, node loop.
Maximum number of keys.
The maximum length of a short string
Iteration not yet finished
Name of the variable
Name of the sub as a string constant
Location of next offset in block in bytes
Current node within tree
Array mapping numbers to strings
Options
Parameters
Current position within node
Location of prev offset in block in bytes
Reference to another variable
Right split length
Size field offset
Number of slots in first block
Number of slots in second and subsequent blocks
POint at which to split a full block
Start label for this subroutine
A tree mapping strings to numbers
Variable indicating whether the last find found a sub tree
Tree we are iterating over
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 .
Total of 14 tree bits
Offset of up in data block.
Used field offset
Argument variables
Number of variables in subroutine
Width of a key or data slot.
The associated xmm register
The full name of the zmm register
The number of the zmm register containing the string
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.
Pi32 Pi64
Pi as a 32 bit float.
Pi as a 64 bit float.
Create a unique label or reuse the one supplied.
Parameter Description 1 {return "l".++$Labels unless @_; Generate a label
Layout data.
Parameter Description 1 $s Element size 2 @d Data to be laid out
Parameter Description 1 $sub Subroutine descriptor 2 $mode Mode 0 - direct call or 1 - indirect call 3 $label Label of sub 4 @parameters Parameter variables
Create/address a hex translate table and return its label.
Print the instruction pointer in hex.
Print the flags register in hex.
Print the specified number of utf32 characters at the specified address to the specified channel.
Parameter Description 1 $channel Channel 2 $size Variable: number of characters to print 3 $address Variable: address of memory
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
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 $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 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
Push registers onto the stack without tracking.
Push registers onto the stack.
Mov rax, 0x11111111; Mov rbx, 0x22222222; PushR my @save = (rax, rbx); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Mov rax, 0x33333333; PopR; PrintOutRegisterInHex rax; PrintOutRegisterInHex rbx; ok Assemble(debug => 0, eq => <<END); rax: 0000 0000 1111 1111 rbx: 0000 0000 2222 2222 END
Pop registers from the stack without tracking.
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
Length of the C style string addressed by rax returning the length in r15.
Hello Skye"); Mov rax, $s;
Cstrlen; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Mov rdi, r15; PrintOutMemoryNL; ok Assemble(debug => 0, eq => <<END); Hello World Hello Skye END
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
my $format = Rd(map{4*$_+24} 0..64); my $b = CreateArena; my $a = $b->allocBlock($b->bs); 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"}, ); $$p{c}->outNL; $$p{e} += 1; $$p{e}->outNL('E: '); $$p{f}->outNL('F1: '); $$p{f}++; $$p{f}->outNL('F2: '); } [qw(c d e f)], name=> 'aaa'; 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 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
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
Make sure that the arena addressed by rax has enough space to accommodate content of length rdi.
Size of a block.
Parameter Description 1 $arena 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
Set the first free block field from a variable.
Parameter Description 1 $arena Arena descriptor 2 $offset First free block offset as a variable
Free a block in an arena by placing it on the free chain.
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
Write the numbered zmm to the block at the specified offset in the specified arena.
Address of a string.
Parameter Description 1 $String String descriptor 2 $arena Arena address
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
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
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
Parameter Description 1 $String String descriptor 2 $bsa Arena variable 3 $block Block in arena 4 $zmm Content variable
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
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
Parameter Description 1 $Array Array descriptor
Parameter Description 1 $Array Array descriptor 2 $bs Arena address
Allocate a keys/data/node block and place it in the numbered zmm registers.
Parameter Description 1 $t Tree descriptor 2 $bs Arena address 3 $K Numbered zmm for keys 4 $D Numbered zmm for data 5 $N Numbered zmm for children
Split a non root node given its offset in an arena retaining the key being inserted in the node being 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
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
Transfer tree bits when splitting a full node.
Parameter Description 1 $t Tree descriptor 2 $parent Numbered parent zmm 3 $left Numbered left zmm 4 $right Numbered right zmm
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
Transfer tree bits when splitting a full left or right node.
Parameter Description 1 $t 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
Transfer tree bits when splitting a full left node.
Parameter Description 1 $t 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
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);
Transfer tree bits when splitting a full right node.
Parameter Description 1 $t 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
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 2 $bs Arena address
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
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.
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 my $tk = Rd(1, (0) x 13, 1, 0xC1); my $td = Rd(1, (0) x 14, 0xC2); my $tn = Rd(1, 0xAA, (0) x 13, 0xCC); my $lk = Rd(1..14, 14, 0xA1); my $ld = Rd(1..14, 0xCC, 0xA2); my $ln = Rd(1..15, 0xAA); my $rk = Rd((0)x14, 14, 0xB1); my $rd = Rd((0)x14, 0xCC, 0xB2); my $rn = Rd((0)x15, 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->splitFullLeftNode; PrintOutRegisterInHex reverse zmm(23..31); ok Assemble(debug => 0, eq => <<END); zmm31: 0000 00C1 0000 0002 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 0008 0000 0001 zmm30: 0000 00C2 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 0008 0000 0001 zmm29: 0000 00CC 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 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 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 00AA 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 00BB 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
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.
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
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 $bs Arena address 3 $first Start node 4 $key Key to find 5 $compare Last comparison result variable 6 $offset Offset of last node found 7 $index Index within last node found
Load the keys and data blocks for a node.
Parameter Description 1 $t Tree descriptor 2 $bs Arena address 3 $offset Offset as a variable 4 $zmmKeys Numbered zmm for keys 5 $zmmData Numbered data for keys 6 $work1 Optional first work register 7 $work2 Optional second work register
Save the key and data blocks for a node.
Load the keys, data and child nodes for a node.
Parameter Description 1 $t Tree descriptor 2 $bs Arena address 3 $offset Offset as a variable 4 $zmmKeys Numbered zmm for keys 5 $zmmData Numbered data for keys 6 $zmmNode Numbered numbered for keys 7 $work1 Optional first work register 8 $work2 Optional second work register
Save the keys, data and child nodes for a node.
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
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
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
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
Get the decompressed up offset from the data block in the numbered zmm and return it as a variable. The lowest 6 bits of an offset are always 0b011000. The up field becomes the count field for the root node which has no node above it. To differentiate between up and count, the lowest bit of the up field is set for offsets, and cleared for the count of the number of nodes in the tree held in the root node. Thus if this dword is set to zero it means that this is the count field for an empty tree.
Get the compressed up offset//count from the data block in the numbered zmm and return it as a variable.
Put the offset of the parent keys block expressed as a variable into the numbered zmm. Offsets always end in 0b01100 as long as only 64 byte allocations have been made in the arena. Offsets are indicated by setting the lowest bit in the dword containing the offset to 1.
Parameter Description 1 $t Tree descriptor 2 $offset Variable containing up offset 3 $zmm Zmm number 4 $transfer Transfer register
Get the number of keys in the tree. The number of keys in the tree is stored in the up field of the data block associated with the root. If the lowest bit in this field is set then the field is an offset, if it is clear then it is a count.
Increment the count field in the up field of the data block associate with the root node.
Decrement the count field in the up field of the data block associate with the root node.
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
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
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
Address of the arena containing a tree.
Parameter Description 1 $t Tree descriptor 2 $bs Variables
Set the Zero Flag to oppose the tree bit indexed by the specified variable 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 $position Variable holding index of position to test 3 $zmm Numbered zmm register holding the keys for a node in the tree
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
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
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
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.
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
Put the tree bits in the specified register into the numbered zmm.
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
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
Insert a one into the tree bits field in the numbered zmm at the specified point.
Locate the Intel Software Development Emulator.
Get the number of instructions executed from the emulator mix file.
Perform code optimizations.
Return a copy of the specified string with all the non ascii characters removed.
Total size in bytes of all files assembled during testing.
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 AndBlock - Short circuit and: execute a block of code to test conditions which, if all of them pass, allows the first block to continue successfully else if one of the conditions fails we execute the optional fail block.
5 Assemble - Assemble the generated code.
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.
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 ConvertUtf8ToUtf32 - Convert a string of utf8 to an allocated block of utf32 and return its address and length.
22 CopyMemory - Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi.
23 cr - Call a subroutine with a reordering of the registers.
24 CreateArena - Create an relocatable arena and returns its address in rax.
25 CreateShortString - Create a description of a short string.
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 DescribeArena - Describe a relocatable arena.
32 DescribeArray - Describe a dynamic array held in an arena.
33 DescribeQuarks - Return a descriptor for a set of quarks
34 DescribeString - Describe a string
35 DescribeTree - Return a descriptor for a tree with the specified options
36 Dq - Layout quad words in the data segment and return their label.
37 Ds - Layout bytes in memory and return their label.
38 Dw - Layout words in the data segment and return their label.
39 Ef - Else if block for an If statement.
40 Else - Else block for an If statement.
41 executeFileViaBash - Execute the file named in the arena addressed by rax with bash.
42 Exit - Exit with the specified return code or zero if no return code supplied.
43 Extern - Name external references.
44 Fail - Fail block for an AndBlock.
45 For - For - iterate the block as long as register is less than limit incrementing by increment each time.
46 ForEver - Iterate for ever.
47 ForIn - For - iterate the full block as long as register plus increment is less than than limit incrementing by increment each time then increment the last block for the last non full block.
48 Fork - Fork.
49 FreeMemory - Free memory.
50 G - Define a global variable.
51 getBFromXmm - Get the byte from the numbered xmm register and return it in a variable.
52 getBFromZmm - Get the byte from the numbered zmm register and return it in a variable.
53 getBwdqFromMm - Get the numbered byte|word|double word|quad word from the numbered zmm register and return it in a variable.
54 getDFromXmm - Get the double word from the numbered xmm register and return it in a variable.
55 getDFromZmm - Get the double word from the numbered zmm register and return it in a variable.
56 getInstructionCount - Get the number of instructions executed from the emulator mix file.
57 GetNextUtf8CharAsUtf32 - Get the next utf8 encoded character from the addressed memory and return it as a utf32 char.
58 GetPid - Get process identifier.
59 GetPidInHex - Get process identifier in hex as 8 zero terminated bytes in rax.
60 GetPPid - Get parent process identifier.
61 getQFromXmm - Get the quad word from the numbered xmm register and return it in a variable.
62 getQFromZmm - Get the quad word from the numbered zmm register and return it in a variable.
63 GetUid - Get userid of current process.
64 getWFromXmm - Get the word from the numbered xmm register and return it in a variable.
65 getWFromZmm - Get the word from the numbered zmm register and return it in a variable.
66 Hash - Hash a string addressed by rax with length held in rdi and return the hash code in r15.
67 hexTranslateTable - Create/address a hex translate table and return its label.
68 If - If.
69 IfC - If the carry flag is set then execute the then block else the else block.
70 IfEq - If equal execute the then block else the else block.
71 IfGe - If greater than or equal execute the then block else the else block.
72 IfGt - If greater than execute the then block else the else block.
73 IfLe - If less than or equal execute the then block else the else block.
74 IfLt - If less than execute the then block else the else block.
75 IfNc - If the carry flag is not set then execute the then block else the else block.
76 IfNe - If not equal execute the then block else the else block.
77 IfNz - If the zero flag is not set then execute the then block else the else block.
78 IfZ - If the zero flag is set then execute the then block else the else block.
79 InsertOneIntoRegisterAtPoint - Insert a one into the specified register at the point indicated by another register.
80 InsertZeroIntoRegisterAtPoint - Insert a zero into the specified register at the point indicated by another register.
81 K - Define a constant variable.
82 Label - Create a unique label or reuse the one supplied.
83 Link - Libraries to link with.
84 LoadBitsIntoMaskRegister - Load a bit string specification into a mask register.
85 LoadConstantIntoMaskRegister - Set a mask register equal to a constant.
86 loadFromZmm - Load the specified register from the offset located in the numbered zmm.
87 LoadRegFromMm - Load the specified register from the numbered zmm at the quad offset specified as a constant number.
88 LoadZmm - Load a numbered zmm with the specified bytes.
89 LocalData - Map local data.
90 LocateIntelEmulator - Locate the Intel Software Development Emulator.
91 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.
92 MaskMemory22 - Write the specified byte into locations in the target mask that correspond to the locations in the source that contain the specified byte.
93 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.
94 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.
95 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.
96 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.
97 Nasm::X86::Arena::append - Append one arena to another.
98 Nasm::X86::Arena::arenaSize - Get the size of an arena.
99 Nasm::X86::Arena::blockSize - Size of a block.
100 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.
101 Nasm::X86::Arena::char - Append a character expressed as a decimal number to the arena addressed by rax.
102 Nasm::X86::Arena::clear - Clear the arena addressed by rax.
103 Nasm::X86::Arena::CreateArray - Create a dynamic array held in an arena.
104 Nasm::X86::Arena::CreateQuarks - Create quarks in a specified arena.
105 Nasm::X86::Arena::CreateString - Create a string from a doubly link linked list of 64 byte blocks linked via 4 byte offsets in an arena and return its descriptor.
106 Nasm::X86::Arena::CreateTree - Create a tree in an arena.
107 Nasm::X86::Arena::DescribeArray - Describe a dynamic array held in an arena.
108 Nasm::X86::Arena::DescribeQuarks - Return a descriptor for a tree in the specified arena.
109 Nasm::X86::Arena::DescribeString - Describe a string and optionally set its first block .
110 Nasm::X86::Arena::DescribeString22 - Describe a string and optionally set its first block .
111 Nasm::X86::Arena::DescribeTree - Return a descriptor for a tree in the specified arena with the specified options
112 Nasm::X86::Arena::dump - Dump details of an arena.
113 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.
114 Nasm::X86::Arena::freeBlock - Free a block in an arena by placing it on the free chain.
115 Nasm::X86::Arena::getBlock - Get the block with the specified offset in the specified string and return it in the numbered zmm.
116 Nasm::X86::Arena::length - Get the length of an arena.
117 Nasm::X86::Arena::m - Append the content with length rdi addressed by rsi to the arena addressed by rax.
118 Nasm::X86::Arena::makeReadOnly - Make an arena read only.
119 Nasm::X86::Arena::makeWriteable - Make an arena writable.
120 Nasm::X86::Arena::nl - Append a new line to the arena addressed by rax.
121 Nasm::X86::Arena::out - Print the specified arena addressed by rax on sysout.
122 Nasm::X86::Arena::putBlock - Write the numbered zmm to the block at the specified offset in the specified arena.
123 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.
124 Nasm::X86::Arena::q - Append a constant string to the arena.
125 Nasm::X86::Arena::ql - Append a quoted string containing new line characters to the arena addressed by rax.
126 Nasm::X86::Arena::read - Read the named file (terminated with a zero byte) and place it into the named arena.
127 Nasm::X86::Arena::setFirstFreeBlock - Set the first free block field from a variable.
128 Nasm::X86::Arena::updateSpace - Make sure that the arena addressed by rax has enough space to accommodate content of length rdi.
129 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.
130 Nasm::X86::Arena::z - Append a trailing zero to the arena addressed by rax.
131 Nasm::X86::Array::address - Address of a string.
132 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.
133 Nasm::X86::Array::dump - Dump a array.
134 Nasm::X86::Array::get - Get an element from the array.
135 Nasm::X86::Array::pop - Pop an element from an array.
136 Nasm::X86::Array::push - Push an element onto the array.
137 Nasm::X86::Array::put - Put an element into an array as long as it is with in its limits established by pushing.
138 Nasm::X86::Array::reload - Reload the specified array description.
139 Nasm::X86::Array::size - Return the size of an array as a variable.
140 Nasm::X86::LocalData::allocate8 - Add some 8 byte local variables and return an array of variable definitions.
141 Nasm::X86::LocalData::free - Free a local data area on the stack.
142 Nasm::X86::LocalData::start - Start a local data area on the stack.
143 Nasm::X86::LocalData::variable - Add a local variable.
144 Nasm::X86::LocalVariable::stack - Address a local variable on the stack.
145 Nasm::X86::Quarks::call - Call a subroutine via its quark number.
146 Nasm::X86::Quarks::dumpSubs - Dump a set of quarks identifying subroutines.
147 Nasm::X86::Quarks::locateQuarkFromShortString - Locate (if possible) but do not create a quark from a short string.
148 Nasm::X86::Quarks::quarkFromShortString - Create a quark from a short string.
149 Nasm::X86::Quarks::quarkFromSub - Create a quark from a subroutine definition.
150 Nasm::X86::Quarks::quarkToQuark - Given a variable quark number in one set of quarks find the corresponding quark in another set of quarks and return it in a variable.
151 Nasm::X86::Quarks::reload - Reload the description of a set of quarks.
152 Nasm::X86::Quarks::shortStringFromQuark - Load a short string from the quark with the specified number.
153 Nasm::X86::Quarks::subFromQuark - Get the offset of a subroutine as a variable from a set of quarks.
154 Nasm::X86::ShortString::append - Append the right hand short string to the left hand short string.
155 Nasm::X86::ShortString::appendByte - Append the lowest variable byte to the specified string.
156 Nasm::X86::ShortString::clear - Clear a short string.
157 Nasm::X86::ShortString::len - Return the length of a short string in a variable.
158 Nasm::X86::ShortString::load - Load the variable addressed data with the variable length into the short string.
159 Nasm::X86::ShortString::loadConstantString - Load the a short string with a constant string.
160 Nasm::X86::ShortString::loadDwordBytes - Load the specified byte of each dword in the variable addressed data with the variable length into the short string.
161 Nasm::X86::ShortString::setLength - Set the length of the short string.
162 Nasm::X86::String::address - Address of a string.
163 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.
164 Nasm::X86::String::append - Append the specified content in memory to the specified string.
165 Nasm::X86::String::appendShortString - Append the content of the specified short string.
166 Nasm::X86::String::clear - Clear the block by freeing all but the first block.
167 Nasm::X86::String::concatenate - Concatenate two strings by appending a copy of the source to the target string.
168 Nasm::X86::String::deleteChar - Delete a character in a string.
169 Nasm::X86::String::dump - Dump a string to sysout.
170 Nasm::X86::String::getBlock - Get the block with the specified offset in the specified string and return it in the numbered zmm.
171 Nasm::X86::String::getBlockLength - Get the block length of the numbered zmm and return it in a variable.
172 Nasm::X86::String::getCharacter - Get a character from a string.
173 Nasm::X86::String::getNextAndPrevBlockOffsetFromZmm - Get the offsets of the next and previous blocks as variables from the specified zmm.
174 Nasm::X86::String::insertChar - Insert a character into a string.
175 Nasm::X86::String::len - Find the length of a string.
176 Nasm::X86::String::putBlock - Write the numbered zmm to the block at the specified offset in the specified arena.
177 Nasm::X86::String::putNextandPrevBlockOffsetIntoZmm - Save next and prev offsets into a zmm representing a block.
178 Nasm::X86::String::saveToShortString - Place as much as possible of the specified string into the specified short string.
179 Nasm::X86::String::setBlockLengthInZmm - Set the block length of the numbered zmm to the specified length.
180 Nasm::X86::Structure::field - Add a field of the specified length with an optional comment.
181 Nasm::X86::StructureField::addr - Address a field in a structure by either the default register or the named register.
182 Nasm::X86::Sub::call - Call a sub passing it some parameters.
183 Nasm::X86::Sub::callTo - Call a sub passing it some parameters.
184 Nasm::X86::Sub::V - Put the address of a subroutine into a stack variable so that it can be passed as a parameter.
185 Nasm::X86::Sub::via - Call a sub by reference passing it some parameters.
186 Nasm::X86::Tree::address - Address of the arena containing a tree.
187 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.
188 Nasm::X86::Tree::allocKeysDataNode - Allocate a keys/data/node block and place it in the numbered zmm registers.
189 Nasm::X86::Tree::by - Call the specified block with each (key, data) from the specified tree in order.
190 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.
191 Nasm::X86::Tree::decCountInData - Decrement the count field in the up field of the data block associate with the root node.
192 Nasm::X86::Tree::depth - Return the depth of a node within a tree.
193 Nasm::X86::Tree::dump - Dump a tree and all its sub trees.
194 Nasm::X86::Tree::expandTreeBitsWithOne - Insert a one into the tree bits field in the numbered zmm at the specified point.
195 Nasm::X86::Tree::expandTreeBitsWithZero - Insert a zero into the tree bits field in the numbered zmm at the specified point.
196 Nasm::X86::Tree::expandTreeBitsWithZeroOrOne - Insert a zero or one into the tree bits field in the numbered zmm at the specified point.
197 Nasm::X86::Tree::find - Find a key in a tree and test whether the found data is a sub tree.
198 Nasm::X86::Tree::findAndReload - Find a key in the specified tree and clone it is it is a sub tree.
199 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.
200 Nasm::X86::Tree::findShortString - Find the data at the end of a key chain held in a short string.
201 Nasm::X86::Tree::getCountFromData - Get the number of keys in the tree.
202 Nasm::X86::Tree::getKeysData - Load the keys and data blocks for a node.
203 Nasm::X86::Tree::getKeysDataNode - Load the keys, data and child nodes for a node.
204 Nasm::X86::Tree::getLengthInKeys - Get the length of the keys block in the numbered zmm and return it as a variable.
205 Nasm::X86::Tree::getLoop - Return the value of the loop field as a variable.
206 Nasm::X86::Tree::getTreeBits - Load the tree bits from the numbered zmm into the specified register.
207 Nasm::X86::Tree::getUpFromData - Get the decompressed up offset from the data block in the numbered zmm and return it as a variable.
208 Nasm::X86::Tree::getUpFromData11 - Get the up offset from the data block in the numbered zmm and return it as a variable.
209 Nasm::X86::Tree::getUpFromDataNM - Get the compressed up offset//count from the data block in the numbered zmm and return it as a variable.
210 Nasm::X86::Tree::incCountInData - Increment the count field in the up field of the data block associate with the root node.
211 Nasm::X86::Tree::insert - Insert a dword into into the specified tree at the specified key.
212 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.
213 Nasm::X86::Tree::insertShortString - Insert some data at the end of a chain of sub trees keyed by the contents of a short string.
214 Nasm::X86::Tree::insertTree - Insert a sub tree into the specified tree tree under the specified key.
215 Nasm::X86::Tree::insertTreeAndReload - Insert a new sub tree into the specified tree tree under the specified key and return a descriptor for it.
216 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.
217 Nasm::X86::Tree::iterator - Iterate through a multi way tree starting either at the specified node or the first node of the specified tree.
218 Nasm::X86::Tree::Iterator::next - Next element in the tree.
219 Nasm::X86::Tree::leftMost - Return the offset of the left most node from the specified node.
220 Nasm::X86::Tree::leftOrRightMost - Return the offset of the left most or right most node.
221 Nasm::X86::Tree::nodeFromData - Load the the node block into the numbered zmm corresponding to the data block held in the numbered zmm.
222 Nasm::X86::Tree::print - Print a tree.
223 Nasm::X86::Tree::putKeysData - Save the key and data blocks for a node.
224 Nasm::X86::Tree::putKeysDataNode - Save the keys, data and child nodes for a node.
225 Nasm::X86::Tree::putLengthInKeys - Get the length of the block in the numbered zmm from the specified variable.
226 Nasm::X86::Tree::putLoop - Set the value of the loop field from a variable.
227 Nasm::X86::Tree::putTreeBits - Put the tree bits in the specified register into the numbered zmm.
228 Nasm::X86::Tree::putUpIntoData - Put the offset of the parent keys block expressed as a variable into the numbered zmm.
229 Nasm::X86::Tree::putUpIntoData11 - Put the offset of the parent keys block expressed as a variable into the numbered zmm.
230 Nasm::X86::Tree::reload - Reload the specified tree description.
231 Nasm::X86::Tree::reParent - Reparent the children of a node held in registers.
232 Nasm::X86::Tree::rightMost - Return the offset of the left most node from the specified node.
233 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.
234 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.
235 Nasm::X86::Tree::size - Return a variable containing the number of keys in the specified tree.
236 Nasm::X86::Tree::splitFullLeftNode - Split a full left node block held in 28.
237 Nasm::X86::Tree::splitFullLeftOrRightNode - Split a full a full left node (held in 28.
238 Nasm::X86::Tree::splitFullRightNode - Split a full right node block held in 25.
239 Nasm::X86::Tree::splitFullRoot - Split a full root block held in 31.
240 Nasm::X86::Tree::splitNode - Split a non root node given its offset in an arena retaining the key being inserted in the node being split while putting the remainder to the left or right.
241 Nasm::X86::Tree::testTree - Set the Zero Flag to oppose the tree bit indexed by the specified variable 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.
242 Nasm::X86::Tree::transferTreeBitsFromLeft - Transfer tree bits when splitting a full left node.
243 Nasm::X86::Tree::transferTreeBitsFromLeftOrRight - Transfer tree bits when splitting a full left or right node.
244 Nasm::X86::Tree::transferTreeBitsFromParent - Transfer tree bits when splitting a full node.
245 Nasm::X86::Tree::transferTreeBitsFromRight - Transfer tree bits when splitting a full right node.
246 Nasm::X86::Variable::add - Add the right hand variable to the left hand variable and return the result as a new variable.
247 Nasm::X86::Variable::address - Get the address of a variable with an optional offset.
248 Nasm::X86::Variable::allocateMemory - Allocate the specified amount of memory via mmap and return its address.
249 Nasm::X86::Variable::and - And two variables.
250 Nasm::X86::Variable::arithmetic - Return a variable containing the result of an arithmetic operation on the left hand and right hand side variables.
251 Nasm::X86::Variable::assign - Assign to the left hand side the value of the right hand side.
252 Nasm::X86::Variable::boolean - Combine the left hand variable with the right hand variable via a boolean operator.
253 Nasm::X86::Variable::booleanC - Combine the left hand variable with the right hand variable via a boolean operator using a conditional move instruction.
254 Nasm::X86::Variable::booleanZF - Combine the left hand variable with the right hand variable via a boolean operator and indicate the result by setting the zero flag if the result is true.
255 Nasm::X86::Variable::clearBit - Clear a bit in the specified mask register retaining the other bits.
256 Nasm::X86::Variable::clearMaskBit - Clear a bit in the specified mask register retaining the other bits.
257 Nasm::X86::Variable::clearMemory - Clear the memory described in this variable.
258 Nasm::X86::Variable::copy - Copy one variable into another.
259 Nasm::X86::Variable::copyMemory - Copy from one block of memory to another.
260 Nasm::X86::Variable::copyRef - Copy a reference to a variable.
261 Nasm::X86::Variable::copyZF - Copy the current state of the zero flag into a variable.
262 Nasm::X86::Variable::copyZFInverted - Copy the opposite of the current state of the zero flag into a variable.
263 Nasm::X86::Variable::d - Dump the value of a variable on stderr and append a new line.
264 Nasm::X86::Variable::debug - Dump the value of a variable on stdout with an indication of where the dump came from.
265 Nasm::X86::Variable::dec - Decrement a variable.
266 Nasm::X86::Variable::divide - Divide the left hand variable by the right hand variable and return the result as a new variable.
267 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.
268 Nasm::X86::Variable::dump - Dump the value of a variable to the specified channel adding an optional title and new line if requested.
269 Nasm::X86::Variable::eq - Check whether the left hand variable is equal to the right hand variable.
270 Nasm::X86::Variable::equals - Equals operator.
271 Nasm::X86::Variable::err - Dump the value of a variable on stderr.
272 Nasm::X86::Variable::errNL - Dump the value of a variable on stderr and append a new line.
273 Nasm::X86::Variable::for - Iterate the block limit times.
274 Nasm::X86::Variable::freeMemory - Free the memory addressed by this variable for the specified length.
275 Nasm::X86::Variable::ge - Check whether the left hand variable is greater than or equal to the right hand variable.
276 Nasm::X86::Variable::getBFromZmm - Get the byte from the numbered zmm register and put it in a variable.
277 Nasm::X86::Variable::getConst - Load the variable from a constant in effect setting a variable to a specified value.
278 Nasm::X86::Variable::getConst22 - Load the variable from a constant in effect setting a variable to a specified value.
279 Nasm::X86::Variable::getDFromZmm - Get the double word from the numbered zmm register and put it in a variable.
280 Nasm::X86::Variable::getQFromZmm - Get the quad word from the numbered zmm register and put it in a variable.
281 Nasm::X86::Variable::getReg - Load the variable from the named registers.
282 Nasm::X86::Variable::getWFromZmm - Get the word from the numbered zmm register and put it in a variable.
283 Nasm::X86::Variable::gt - Check whether the left hand variable is greater than the right hand variable.
284 Nasm::X86::Variable::inc - Increment a variable.
285 Nasm::X86::Variable::incDec - Increment or decrement a variable.
286 Nasm::X86::Variable::isRef - Check whether the specified variable is a reference to another variable.
287 Nasm::X86::Variable::le - Check whether the left hand variable is less than or equal to the right hand variable.
288 Nasm::X86::Variable::loadZmm - Load bytes from the memory addressed by the specified source variable into the numbered zmm register.
289 Nasm::X86::Variable::lt - Check whether the left hand variable is less than the right hand variable.
290 Nasm::X86::Variable::max - Maximum of two variables.
291 Nasm::X86::Variable::min - Minimum of two variables.
292 Nasm::X86::Variable::minusAssign - Implement minus and assign.
293 Nasm::X86::Variable::mod - Divide the left hand variable by the right hand variable and return the remainder as a new variable.
294 Nasm::X86::Variable::ne - Check whether the left hand variable is not equal to the right hand variable.
295 Nasm::X86::Variable::or - Or two variables.
296 Nasm::X86::Variable::out - Dump the value of a variable on stdout.
297 Nasm::X86::Variable::outNL - Dump the value of a variable on stdout and append a new line.
298 Nasm::X86::Variable::plusAssign - Implement plus and assign.
299 Nasm::X86::Variable::pop - Pop a variable from the stack.
300 Nasm::X86::Variable::printErrMemoryInHexNL - Write the memory addressed by a variable to stderr.
301 Nasm::X86::Variable::printMemoryInHexNL - Write, in hexadecimal, the memory addressed by a variable to stdout or stderr.
302 Nasm::X86::Variable::printOutMemoryInHexNL - Write the memory addressed by a variable to stdout.
303 Nasm::X86::Variable::push - Push a variable onto the stack.
304 Nasm::X86::Variable::putBIntoXmm - Place the value of the content variable at the byte in the numbered xmm register.
305 Nasm::X86::Variable::putBIntoZmm - Place the value of the content variable at the byte in the numbered zmm register.
306 Nasm::X86::Variable::putBwdqIntoMm - Place the value of the content variable at the byte|word|double word|quad word in the numbered zmm register.
307 Nasm::X86::Variable::putDIntoXmm - Place the value of the content variable at the double word in the numbered xmm register.
308 Nasm::X86::Variable::putDIntoZmm - Place the value of the content variable at the double word in the numbered zmm register.
309 Nasm::X86::Variable::putQIntoXmm - Place the value of the content variable at the quad word in the numbered xmm register.
310 Nasm::X86::Variable::putQIntoZmm - Place the value of the content variable at the quad word in the numbered zmm register.
311 Nasm::X86::Variable::putWIntoXmm - Place the value of the content variable at the word in the numbered xmm register.
312 Nasm::X86::Variable::putWIntoZmm - Place the value of the content variable at the word in the numbered zmm register.
313 Nasm::X86::Variable::setBit - Set a bit in the specified register retaining the other bits.
314 Nasm::X86::Variable::setMask - Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere.
315 Nasm::X86::Variable::setMaskBit - Set a bit in the specified mask register retaining the other bits.
316 Nasm::X86::Variable::setMaskFirst - Set the first bits in the specified mask register.
317 Nasm::X86::Variable::setReg - Set the named registers from the content of the variable.
318 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.
319 Nasm::X86::Variable::str - The name of the variable.
320 Nasm::X86::Variable::sub - Subtract the right hand variable from the left hand variable and return the result as a new variable.
321 Nasm::X86::Variable::times - Multiply the left hand variable by the right hand variable and return the result as a new variable.
322 Nasm::X86::Variable::zBroadCastD - Broadcast a double word in a variable into the numbered zmm.
323 OnSegv - Request a trace back followed by exit on a segv signal.
324 OpenRead - Open a file, whose name is addressed by rax, for read and return the file descriptor in rax.
325 OpenWrite - Create the file named by the terminated string addressed by rax for write.
326 Optimize - Perform code optimizations.
327 OrBlock - Short circuit or: execute a block of code to test conditions which, if one of them is met, leads on to the execution of the pass block, if all of the tests fail we continue withe the test block.
328 Pass - Pass block for an OrBlock.
329 PeekR - Peek at register on stack.
330 PopEax - We cannot pop a double word from the stack in 64 bit long mode using pop so we improvise.
331 PopMask - Pop Mask registers.
332 PopR - Pop registers from the stack.
333 PopRR - Pop registers from the stack without tracking.
334 PopZmm - Pop zmm registers.
335 PrintErrMemory - Print the memory addressed by rax for a length of rdi on stderr.
336 PrintErrMemoryInHex - Dump memory from the address in rax for the length in rdi on stderr.
337 PrintErrMemoryInHexNL - Dump memory from the address in rax for the length in rdi and then print a new line.
338 PrintErrMemoryNL - Print the memory addressed by rax for a length of rdi followed by a new line on stderr.
339 PrintErrNL - Print a new line to stderr.
340 PrintErrRaxInHex - Write the content of register rax in hexadecimal in big endian notation to stderr.
341 PrintErrRegisterInHex - Print the named registers as hex strings on stderr.
342 PrintErrSpace - Print one or more spaces to stderr.
343 PrintErrString - Print a constant string to stderr.
344 PrintErrStringNL - Print a constant string followed by a new line to stderr.
345 PrintErrTraceBack - Print sub routine track back on stderr.
346 PrintErrUtf32 - Print the utf 8 character addressed by rax to stderr.
347 PrintErrUtf8Char - Print the utf 8 character addressed by rax to stderr.
348 PrintErrZF - Print the zero flag without disturbing it on stderr.
349 PrintMemory - Print the memory addressed by rax for a length of rdi on the specified channel.
350 PrintMemoryInHex - Dump memory from the address in rax for the length in rdi on the specified channel.
351 PrintMemoryNL - Print the memory addressed by rax for a length of rdi on the specified channel followed by a new line.
352 PrintNL - Print a new line to stdout or stderr.
353 PrintOneRegisterInHex - Print the named register as a hex strings.
354 PrintOutMemory - Print the memory addressed by rax for a length of rdi on stdout.
355 PrintOutMemoryInHex - Dump memory from the address in rax for the length in rdi on stdout.
356 PrintOutMemoryInHexNL - Dump memory from the address in rax for the length in rdi and then print a new line.
357 PrintOutMemoryNL - Print the memory addressed by rax for a length of rdi followed by a new line on stdout.
358 PrintOutNL - Print a new line to stderr.
359 PrintOutRaxInHex - Write the content of register rax in hexadecimal in big endian notation to stderr.
360 PrintOutRaxInReverseInHex - Write the content of register rax to stderr in hexadecimal in little endian notation.
361 PrintOutRegisterInHex - Print the named registers as hex strings on stdout.
362 PrintOutRegistersInHex - Print the general purpose registers in hex.
363 PrintOutRflagsInHex - Print the flags register in hex.
364 PrintOutRipInHex - Print the instruction pointer in hex.
365 PrintOutSpace - Print one or more spaces to stdout.
366 PrintOutString - Print a constant string to stdout.
367 PrintOutStringNL - Print a constant string followed by a new line to stdout.
368 PrintOutTraceBack - Print sub routine track back on stdout.
369 PrintOutUtf32 - Print the utf 8 character addressed by rax to stdout.
370 PrintOutUtf8Char - Print the utf 8 character addressed by rax to stdout.
371 PrintOutZF - Print the zero flag without disturbing it on stdout.
372 PrintRaxInHex - Write the content of register rax in hexadecimal in big endian notation to the specified channel.
373 PrintRegisterInHex - Print the named registers as hex strings.
374 PrintSpace - Print one or more spaces to the specified channel.
375 PrintString - Print a constant string to the specified channel.
376 PrintStringNL - Print a constant string to the specified channel followed by a new line.
377 PrintTraceBack - Trace the call stack.
378 PrintUtf32 - Print the specified number of utf32 characters at the specified address to the specified channel.
379 PrintUtf8Char - Print the utf 8 character addressed by rax to the specified channel.
380 PushMask - Push several Mask registers.
381 PushR - Push registers onto the stack.
382 PushRR - Push registers onto the stack without tracking.
383 PushZmm - Push several zmm registers.
384 putIntoZmm - Put the specified register into the numbered zmm at the specified offset in the zmm.
385 R - Define a reference variable.
386 Rb - Layout bytes in the data segment and return their label.
387 Rbwdq - Layout data.
388 RComment - Insert a comment into the read only data segment.
389 Rd - Layout double words in the data segment and return their label.
390 ReadFile - Read a file whose name is addressed by rax into memory.
391 ReadTimeStampCounter - Read the time stamp counter and return the time in nanoseconds in rax.
392 RegistersAvailable - Add a new set of registers that are available.
393 RegistersFree - Remove the current set of registers known to be free.
394 RegisterSize - Return the size of a register.
395 removeNonAsciiChars - Return a copy of the specified string with all the non ascii characters removed.
396 ReorderSyscallRegisters - Map the list of registers provided to the 64 bit system call sequence.
397 RestoreFirstFour - Restore the first 4 parameter registers.
398 RestoreFirstFourExceptRax - Restore the first 4 parameter registers except rax so it can return its value.
399 RestoreFirstFourExceptRaxAndRdi - Restore the first 4 parameter registers except rax and rdi so we can return a pair of values.
400 RestoreFirstSeven - Restore the first 7 parameter registers.
401 RestoreFirstSevenExceptRax - Restore the first 7 parameter registers except rax which is being used to return the result.
402 RestoreFirstSevenExceptRaxAndRdi - Restore the first 7 parameter registers except rax and rdi which are being used to return the results.
403 Rq - Layout quad words in the data segment and return their label.
404 Rs - Layout bytes in read only memory and return their label.
405 Rutf8 - Layout a utf8 encoded string as bytes in read only memory and return their label.
406 Rw - Layout words in the data segment and return their label.
407 SaveFirstFour - Save the first 4 parameter registers making any parameter registers read only.
408 SaveFirstSeven - Save the first 7 parameter registers.
409 SaveRegIntoMm - Save the specified register into the numbered zmm at the quad offset specified as a constant number.
410 SetLabel - Create (if necessary) and set a label in the code section returning the label so set.
411 SetMaskRegister - Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere.
412 SetZF - Set the zero flag.
413 Start - Initialize the assembler.
414 StatSize - Stat a file whose name is addressed by rax to get its size in rax.
415 StringLength - Length of a zero terminated string.
416 Structure - Create a structure addressed by a register.
417 Subroutine - Create a subroutine that can be called in assembler code.
418 SubroutineStartStack - Initialize a new stack frame.
419 Then - Then block for an If statement.
420 totalBytesAssembled - Total size in bytes of all files assembled during testing.
421 unlinkFile - Unlink the named file.
422 UnReorderSyscallRegisters - Recover the initial values in registers that were reordered.
423 V - Define a variable.
424 Variable - Create a new variable with the specified name initialized via an optional expression.
425 WaitPid - Wait for the pid in rax to complete.
426 xmm - Add xmm to the front of a list of register expressions.
427 ymm - Add ymm to the front of a list of register expressions.
428 zmm - Add zmm to the front of a list of register expressions.
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
philiprbrenan@gmail.com
http://www.appaapps.com
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.
To install Nasm::X86, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Nasm::X86
CPAN shell
perl -MCPAN -e shell install Nasm::X86
For more information on module installation, please visit the detailed CPAN module installation guide.