Nasm::X86 - Generate X86 assembler code using Perl as a macro pre-processor.
Write and execute x64 instructions using Perl as a macro assembler as shown in the following examples.
Use avx512 instructions to do 64 comparisons in parallel:
my $P = "2F"; # Value to test for my $l = Rb 0; Rb $_ for 1..RegisterSize zmm0; # 0..63 Vmovdqu8 zmm0, "[$l]"; # Load data to test PrintOutRegisterInHex zmm0; Mov rax, "0x$P"; # Broadcast the value to be tested Vpbroadcastb zmm1, rax; PrintOutRegisterInHex zmm1; for my $c(0..7) # Each possible test {my $m = "k$c"; Vpcmpub $m, zmm1, zmm0, $c; PrintOutRegisterInHex $m; } Kmovq rax, k0; # Count the number of trailing zeros in k0 Tzcnt rax, rax; PrintOutRegisterInHex rax; is_deeply Assemble, <<END; # Assemble and test zmm0: 3F3E 3D3C 3B3A 3938 3736 3534 3332 3130 2F2E 2D2C 2B2A 2928 2726 2524 2322 2120 1F1E 1D1C 1B1A 1918 1716 1514 1312 1110 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100 zmm1: 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F k0: 0000 8000 0000 0000 k1: FFFF 0000 0000 0000 k2: FFFF 8000 0000 0000 k3: 0000 0000 0000 0000 k4: FFFF 7FFF FFFF FFFF k5: 0000 FFFF FFFF FFFF k6: 0000 7FFF FFFF FFFF k7: FFFF FFFF FFFF FFFF rax: 0000 0000 0000 002F END
Create a dynamic byte string, add some content to it, write the byte string to stdout:
my $a = CreateByteString; # Create a string my $b = CreateByteString; # Create a string $a->q('aa'); $b->q('bb'); $a->q('AA'); $b->q('BB'); $a->q('aa'); $b->q('bb'); $a->out; $b->out; PrintOutNL; is_deeply Assemble, <<END; # Assemble and execute aaAAaabbBBbb END
Start a child process and wait for it, printing out the process identifiers of each process involved:
Fork; # Fork Test rax,rax; If # Parent {Mov rbx, rax; WaitPid; PrintOutRegisterInHex rax; PrintOutRegisterInHex rbx; GetPid; # Pid of parent as seen in parent Mov rcx,rax; PrintOutRegisterInHex rcx; } sub # Child {Mov r8,rax; PrintOutRegisterInHex r8; GetPid; # Child pid as seen in child Mov r9,rax; PrintOutRegisterInHex r9; GetPPid; # Parent pid as seen in child Mov r10,rax; PrintOutRegisterInHex r10; }; my $r = Assemble; # r8: 0000 0000 0000 0000 #1 Return from fork as seen by child # r9: 0000 0000 0003 0C63 #2 Pid of child # r10: 0000 0000 0003 0C60 #3 Pid of parent from child # rax: 0000 0000 0003 0C63 #4 Return from fork as seen by parent # rbx: 0000 0000 0003 0C63 #5 Wait for child pid result # rcx: 0000 0000 0003 0C60 #6 Pid of parent
Read this file:
ReadFile(Vq(file, Rs($0)), (my $s = Vq(size)), my $a = Vq(address)); # Read file $a->setReg(rax); # Address of file in memory $s->setReg(rdi); # Length of file in memory PrintOutMemory; # Print contents of memory to stdout my $r = Assemble(1 => (my $f = temporaryFile)); # Assemble and execute ok fileMd5Sum($f) eq fileMd5Sum($0); # Output contains this file
Call 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
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 "20210728".
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
Set a label in the code section
Parameter Description 1 $l Label
Example:
Mov rax, 1; Mov rdi, 1; SaveFirstFour; Mov rax, 2; Mov rdi, 2; SaveFirstSeven; Mov rax, 3; Mov rdi, 4; PrintOutRegisterInHex rax, rdi; RestoreFirstSeven; PrintOutRegisterInHex rax, rdi; RestoreFirstFour; PrintOutRegisterInHex rax, rdi; SaveFirstFour; Mov rax, 2; Mov rdi, 2; SaveFirstSeven; Mov rax, 3; Mov rdi, 4; PrintOutRegisterInHex rax, rdi; RestoreFirstSevenExceptRax; PrintOutRegisterInHex rax, rdi; RestoreFirstFourExceptRax; PrintOutRegisterInHex rax, rdi; SaveFirstFour; Mov rax, 2; Mov rdi, 2; SaveFirstSeven; Mov rax, 3; Mov rdi, 4; PrintOutRegisterInHex rax, rdi; RestoreFirstSevenExceptRaxAndRdi; PrintOutRegisterInHex rax, rdi; RestoreFirstFourExceptRaxAndRdi; PrintOutRegisterInHex rax, rdi; Bswap rax; PrintOutRegisterInHex rax; my $l = Label; Jmp $l; SetLabel $l; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 is_deeply Assemble, <<END; rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0002 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0001 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0300 0000 0000 0000 END ok 8 == RegisterSize rax;
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; 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(Vq(source, rsi), Vq(target, rax), Vq(size, rdi)); PrintOutMemoryInHex; my $r = Assemble; ok $r =~ m(xmm0: 0000 0000 0000 0004 0000 0003 0002 0100); ok $r =~ m(xmm1: 0000 0000 0000 0004 0000 0003 0002 0100); ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
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(Vq(source, rsi), Vq(target, rax), Vq(size, rdi)); PrintOutMemoryInHex; my $r = Assemble; ok $r =~ m(xmm0: 0000 0000 0000 0004 0000 0003 0002 0100); ok $r =~ m(xmm1: 0000 0000 0000 0004 0000 0003 0002 0100); ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
32 bit float
Parameter Description 1 $float Float
64 bit float
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
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; is_deeply Assemble, <<END; rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0002 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0001 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0300 0000 0000 0000 END ok 8 == RegisterSize rax;
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; is_deeply Assemble, <<END; rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0002 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0001 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0300 0000 0000 0000 END ok 8 == RegisterSize rax;
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; is_deeply Assemble, <<END; rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0002 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0001 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0300 0000 0000 0000 END ok 8 == RegisterSize rax;
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; is_deeply Assemble, <<END; rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0002 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0001 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0300 0000 0000 0000 END ok 8 == RegisterSize rax;
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; is_deeply Assemble, <<END; rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0002 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0001 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0300 0000 0000 0000 END ok 8 == RegisterSize rax;
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; is_deeply Assemble, <<END; rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0002 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0001 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0300 0000 0000 0000 END ok 8 == RegisterSize rax;
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; is_deeply Assemble, <<END; rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0002 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0001 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0300 0000 0000 0000 END ok 8 == RegisterSize rax;
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; is_deeply Assemble, <<END; rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0002 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0001 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0300 0000 0000 0000 END ok 8 == RegisterSize rax;
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; is_deeply Assemble, <<END; rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0002 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0001 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0002 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0001 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0000 0000 0000 0003 rdi: 0000 0000 0000 0004 rax: 0300 0000 0000 0000 END ok 8 == RegisterSize rax; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
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; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 is_deeply Assemble, <<END; k0: 0000 0000 0000 0000 k1: 0000 0000 0000 0100 k2: 0000 0000 0000 0300 k3: 0000 0000 0000 0700 k4: 0000 0000 0000 0F00 k5: 0000 0000 0000 1F00 k6: 0000 0000 0000 3F00 k7: 0000 0000 0000 7F00 END
Set the zero flag
SetZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutZF; ClearZF; PrintOutZF; SetZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutZF; SetZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutZF; ClearZF; PrintOutZF; ok Assemble =~ m(ZF=1.*ZF=0.*ZF=1.*ZF=1.*ZF=0)s;
Clear the zero flag
SetZF; PrintOutZF; ClearZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutZF; SetZF; PrintOutZF; SetZF; PrintOutZF; ClearZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutZF; ok Assemble =~ m(ZF=1.*ZF=0.*ZF=1.*ZF=1.*ZF=0)s;
Trace the execution of a program
Add tracing code
Track the use of registers so that we do not accidently use unset registers or write into registers that are already in use.
Mark registers as in use so that they cannot be updated until we explicitly free them. Complain if the register is already in use.
Parameter Description 1 @target Registers to keep
Confirm that the specified registers are in use
Parameter Description 1 $target Registers to keep
Push the current status of the specified registers and then mark them as free
Reset the status of the specified registers to the status quo ante the last push
Pop the specified register and mark it as in use to effect a subroutine return with this register.
Parameter Description 1 @target Registers to return
Free registers so that they can be reused
Parameter Description 1 @target Registers to free
Operations on mask registers
Load a constant into a mask register
Parameter Description 1 $reg Mask register to load 2 $value Constant to load
Mov r14, 0; Kmovq k0, r14; KeepFree r14; Ktestq k0, k0; IfZ {PrintOutStringNL "0 & 0 == 0"}; PrintOutZF; LoadConstantIntoMaskRegister k1, 1; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Ktestq k1, k1; IfNz {PrintOutStringNL "1 & 1 != 0"}; PrintOutZF; LoadConstantIntoMaskRegister k2, eval "0b".(('1'x4).('0'x4))x2; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutRegisterInHex k0, k1, k2; Mov r15, 0x89abcdef; Mov r14, 0x01234567; Shl r14, 32; Or r15, r14; Push r15; Push r15; KeepFree r15; PopEax; PrintRaxInHex($stdout, 3); PrintOutNL; KeepFree rax; my $a = Vq('aaaa'); $a->pop; $a->push; $a->outNL; PopEax; PrintRaxInHex($stdout, 3); PrintOutNL; KeepFree rax; ok Assemble(debug => 0, eq => <<END); 0 & 0 == 0 ZF=1 1 & 1 != 0 ZF=0 k0: 0000 0000 0000 0000 k1: 0000 0000 0000 0001 k2: 0000 0000 0000 F0F0 89AB CDEF aaaa: 89AB CDEF 0123 4567 0123 4567 END
Structured programming constructs
If
Parameter Description 1 $jump Jump op code of variable 2 $then Then - required 3 $else Else - optional
Mov rax, 0; Test rax,rax; IfNz {PrintOutRegisterInHex rax; } sub {PrintOutRegisterInHex rbx; }; KeepFree rax; Mov rax, 1; Test rax,rax; IfNz {PrintOutRegisterInHex rcx; } sub {PrintOutRegisterInHex rdx; }; ok Assemble =~ m(rbx.*rcx)s;
Then body for an If statement
Parameter Description 1 $body Then body
Else body for an If statement
Parameter Description 1 $body Else body
If equal execute the then body else the else body
Parameter Description 1 $then Then - required 2 $else Else - optional
If not equal execute the then body else the else body
If the zero is not set then execute the then body else the else body
If the zero is set then execute the then body else the else body
If less than execute the then body else the else body
If less than or equal execute the then body else the else body
If greater than execute the then body else the else body
If greater than or equal execute the then body else the else body
Execute a block of code one with the option of jumping out of the block or restarting the block via the supplied labels.
Parameter Description 1 $body Body
Mov rax, 0; Block # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($start, $end) = @_; PrintOutRegisterInHex rax; Cmp rax, 3; IfGe {Jmp $end}; Inc rax; PrintOutRegisterInHex rax Jmp $start; }; ok Assemble(debug => 0, eq => <<END); rax: 0000 0000 0000 0000 rax: 0000 0000 0000 0001 rax: 0000 0000 0000 0002 rax: 0000 0000 0000 0003 END
For - iterate the body as long as register is less than limit incrementing by increment each time
Parameter Description 1 $body Body 2 $register Register 3 $limit Limit on loop 4 $increment Increment on each iteration
For # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 {my ($start, $end, $next) = @_; Cmp rax, 3; IfGe {Jmp $end}; PrintOutRegisterInHex rax; } rax, 16, 1; ok Assemble(debug => 0, eq => <<END); rax: 0000 0000 0000 0000 rax: 0000 0000 0000 0001 rax: 0000 0000 0000 0002 END
For - iterate the full body as long as register plus increment is less than than limit incrementing by increment each time then increment the last body for the last non full block.
Parameter Description 1 $full Body for full block 2 $last Body for last block 3 $register Register 4 $limit Limit on loop 5 $increment Increment on each iteration
Iterate for ever
Parameter Description 1 $body Body 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 $body Body 2 %options Options.
Create a subroutine that can be called in assembler code
Call a sub passing it some parameters
Parameter Description 1 $sub Subroutine descriptor 2 @parameters Parameter variables
Call a subroutine with a reordering of the registers.
Parameter Description 1 $body Code to execute with reordered registers 2 @registers Registers to reorder
Insert a comment into the assembly code
Parameter Description 1 @comment Text of comment
Comment "Print a string from memory"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $s = "Hello World"; Mov rax, Rs($s); Mov rdi, length $s; PrintOutMemory; 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
Parameter Description 1 $channel Channel to write on
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 stderr.
Parameter Description 1 @string String
Print a constant string 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; KeepFree rax; Mov rax, rsp; Mov rdi, 8; PrintOutMemoryInHex; PrintOutNL; PopR rax; KeepFree rax, rdi; Mov rax, 4096; PushR rax; Mov rax, rsp; Mov rdi, 8; PrintOutMemoryInHex; PrintOutNL; PopR rax; is_deeply Assemble, <<END; 0765 4321 0765 4321 2143 6507 2143 6507 2143 6507 2143 6507 0010 0000 0000 0000 END
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 =~ m(r8: 6867 6665 6463 6261)s;
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; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ok Assemble =~ m(ZF=1.*ZF=0.*ZF=1.*ZF=1.*ZF=0)s;
Variable definitions and operations
Each variable is contained in a scope in an effort to detect references to out of scope variables
Create and stack a new scope and continue with it as the current scope
Parameter Description 1 $name Scope name
if (1) {my $start = Scope(start); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $s1 = Scope(s1); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $s2 = Scope(s2); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 is_deeply $s2->depth, 2; is_deeply $s2->name, q(s2); ScopeEnd; my $t1 = Scope(t1); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $t2 = Scope(t2); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 is_deeply $t1->depth, 2; is_deeply $t1->name, q(t1); is_deeply $t2->depth, 3; is_deeply $t2->name, q(t2); ok $s1->currentlyVisible; ok !$s2->currentlyVisible; ok $s1->contains($t2); ok !$s2->contains($t2); ScopeEnd; is_deeply $s1->depth, 1; is_deeply $s1->name, q(s1); ScopeEnd; }
End the current scope and continue with the containing parent scope
if (1) {my $start = Scope(start); my $s1 = Scope(s1); my $s2 = Scope(s2); is_deeply $s2->depth, 2; is_deeply $s2->name, q(s2); ScopeEnd; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $t1 = Scope(t1); my $t2 = Scope(t2); is_deeply $t1->depth, 2; is_deeply $t1->name, q(t1); is_deeply $t2->depth, 3; is_deeply $t2->name, q(t2); ok $s1->currentlyVisible; ok !$s2->currentlyVisible; ok $s1->contains($t2); ok !$s2->contains($t2); ScopeEnd; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 is_deeply $s1->depth, 1; is_deeply $s1->name, q(s1); ScopeEnd; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 }
Check that the named parent scope contains the specified child scope. If no child scope is supplied we use the current scope to check that the parent scope is currently visible
Parameter Description 1 $parent Parent scope 2 $child Child scope
Check that the named parent scope is currently visible
Parameter Description 1 $scope Scope to check for visibility
Variable definitions
Create a new variable with the specified size and name initialized via an expression
Parameter Description 1 $size Size as a power of 2 2 $name Name of variable 3 $expr Optional expression initializing variable 4 %options Options
Define a byte variable
Parameter Description 1 $name Name of variable 2 $expr Initializing expression 3 %options Options
Define a word variable
Define a double word variable
Define a quad variable
Define a quad constant
Initialize an xyz register from general purpose registers
Parameter Description 1 $var Variable 2 @expr Initializing general purpose registers or undef
Define an xmm variable
Parameter Description 1 $name Name of variable 2 @expr Initializing expression
Define an ymm variable
Define an zmm variable
Define a reference variable
Parameter Description 1 $name Name of variable 2 $size Variable being referenced
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
Clone a variable to create a new variable
Parameter Description 1 $var Variable to clone
Copy a reference to 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
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
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
Print the values of variables or the memory addressed by them
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 = Vq(a, 3); $a->outNL; my $b = Vq(b, 2); $b->outNL; my $c = $a + $b; $c->outNL; my $d = $c - $a; $d->outNL; my $e = $d == $b; $e->outNL; my $f = $d != $b; $f->outNL; my $g = $a * $b; $g->outNL; my $h = $g / $b; $h->outNL; my $i = $a % $b; $i->outNL; If ($a == 3, sub{PrintOutStringNL "a == 3"}); ++$a; $a->outNL; --$a; $a->outNL; ok Assemble(debug => 0, eq => <<END); a: 0000 0000 0000 0003 b: 0000 0000 0000 0002 (a add b): 0000 0000 0000 0005 ((a add b) sub a): 0000 0000 0000 0002 (((a add b) sub a) eq b): 0000 0000 0000 0001 (((a add b) sub a) ne b): 0000 0000 0000 0000 (a times b): 0000 0000 0000 0006 ((a times b) / b): 0000 0000 0000 0003 (a % b): 0000 0000 0000 0001 a == 3 a: 0000 0000 0000 0004 a: 0000 0000 0000 0003 END
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
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 3 @registers Optional further registers 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
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
my $a = Vq("a", 1); my $b = Vq("b", 2); my $c = $a->min($b); my $d = $a->max($b); $a->outNL; $b->outNL; $c->outNL; $d->outNL; is_deeply Assemble,<<END; a: 0000 0000 0000 0001 b: 0000 0000 0000 0002 Minimum(a, b): 0000 0000 0000 0001 Maximum(a, b): 0000 0000 0000 0002 END
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 = Vq("Start", 7); my $length = Vq("Length", 3); $start->setMask($length, k7); PrintOutRegisterInHex k7; is_deeply Assemble, <<END; k7: 0000 0000 0000 0380 END my $z = Vq('zero', 0); my $o = Vq('one', 1); my $t = Vq('two', 2); $z->setMask($o, k7); PrintOutRegisterInHex k7; $z->setMask($t, k6); PrintOutRegisterInHex k6; $z->setMask($o+$t, k5); PrintOutRegisterInHex k5; $o->setMask($o, k4); PrintOutRegisterInHex k4; $o->setMask($t, k3); PrintOutRegisterInHex k3; $o->setMask($o+$t, k2); PrintOutRegisterInHex k2; $t->setMask($o, k1); PrintOutRegisterInHex k1; $t->setMask($t, k0); PrintOutRegisterInHex k0; ok Assemble(debug => 0, eq => <<END); k7: 0000 0000 0000 0001 k6: 0000 0000 0000 0003 k5: 0000 0000 0000 0007 k4: 0000 0000 0000 0002 k3: 0000 0000 0000 0006 k2: 0000 0000 0000 000E k1: 0000 0000 0000 0004 k0: 0000 0000 0000 000C END
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 $length 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 $length Variable containing bit position to clear 2 $mask Mask register
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 = Vq(Source, $s); if (1) # First block {my $offset = Vq(Offset, 7); my $length = Vq(Length, 3); $source->setZmm(0, $offset, $length); } if (1) # Second block {my $offset = Vq(Offset, 33); my $length = Vq(Length, 12); $source->setZmm(0, $offset, $length); } PrintOutRegisterInHex zmm0; is_deeply Assemble, <<END; zmm0: 0000 0000 0000 0000 0000 0000 0000 0000 0000 000B 0A09 0807 0605 0403 0201 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0201 0000 0000 0000 0000 END my $a = Vz a, Rb((map {"0x${_}0"} 0..9, 'a'..'f')x4); my $b = Vz b, Rb((map {"0x0${_}"} 0..9, 'a'..'f')x4); $a ->loadZmm(0); # Show variable in zmm0 $b ->loadZmm(1); # Show variable in zmm1 ($a + $b)->loadZmm(2); # Add bytes and show in zmm2 ($a - $b)->loadZmm(3); # Subtract bytes and show in zmm3 PrintOutRegisterInHex "zmm$_" for 0..3; is_deeply Assemble, <<END; zmm0: F0E0 D0C0 B0A0 9080 7060 5040 3020 1000 F0E0 D0C0 B0A0 9080 7060 5040 3020 1000 F0E0 D0C0 B0A0 9080 7060 5040 3020 1000 F0E0 D0C0 B0A0 9080 7060 5040 3020 1000 zmm1: 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100 zmm2: FFEE DDCC BBAA 9988 7766 5544 3322 1100 FFEE DDCC BBAA 9988 7766 5544 3322 1100 FFEE DDCC BBAA 9988 7766 5544 3322 1100 FFEE DDCC BBAA 9988 7766 5544 3322 1100 zmm3: E1D2 C3B4 A596 8778 695A 4B3C 2D1E 0F00 E1D2 C3B4 A596 8778 695A 4B3C 2D1E 0F00 E1D2 C3B4 A596 8778 695A 4B3C 2D1E 0F00 E1D2 C3B4 A596 8778 695A 4B3C 2D1E 0F00 END
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
Save bytes into the memory addressed by the target variable from the numbered zmm register.
Parameter Description 1 $target Variable containing the address of the source 2 $zmm Number of zmm to put
Get the numbered byte|word|double word|quad word from the numbered zmm register and return it in a variable
Parameter Description 1 $size Size of get 2 $mm Register 3 $offset Offset in bytes either as a constant or as a variable
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
my $s = Rb(0..8); my $c = Vq("Content", "[$s]"); $c->putBIntoZmm(0, 4); $c->putWIntoZmm(0, 6); $c->putDIntoZmm(0, 10); $c->putQIntoZmm(0, 16); PrintOutRegisterInHex zmm0; getBFromZmm(0, 12)->outNL; getWFromZmm(0, 12)->outNL; getDFromZmm(0, 12)->outNL; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 getQFromZmm(0, 12)->outNL; is_deeply Assemble, <<END; zmm0: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0706 0504 0302 0100 0000 0302 0100 0000 0100 0000 0000 0000 b at offset 12 in zmm0: 0000 0000 0000 0002 w at offset 12 in zmm0: 0000 0000 0000 0302 d at offset 12 in zmm0: 0000 0000 0000 0302 q at offset 12 in zmm0: 0302 0100 0000 0302 END
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
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
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
my $s = Rb(0..8); my $c = Vq("Content", "[$s]"); $c->putBIntoZmm(0, 4); $c->putWIntoZmm(0, 6); $c->putDIntoZmm(0, 10); $c->putQIntoZmm(0, 16); PrintOutRegisterInHex zmm0; getBFromZmm(0, 12)->outNL; getWFromZmm(0, 12)->outNL; getDFromZmm(0, 12)->outNL; getQFromZmm(0, 12)->outNL; is_deeply Assemble, <<END; zmm0: 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0706 0504 0302 0100 0000 0302 0100 0000 0100 0000 0000 0000 b at offset 12 in zmm0: 0000 0000 0000 0002 w at offset 12 in zmm0: 0000 0000 0000 0302 d at offset 12 in zmm0: 0000 0000 0000 0302 q at offset 12 in zmm0: 0302 0100 0000 0302 END
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 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
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 = Vq(size, 2048); my $q = Rs('a'..'p'); AllocateMemory($N, my $address = Vq(address)); Vmovdqu8 xmm0, "[$q]"; $address->setReg(rax); Vmovdqu8 "[rax]", xmm0; Mov rdi, 16; PrintOutMemory; PrintOutNL; FreeMemory(address => $address, size=> $N); ok Assemble(eq => <<END); abcdefghijklmnop END
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 body limit times.
Parameter Description 1 $limit Limit 2 $body Body
Vq(limit,10)->for(sub {my ($i, $start, $next, $end) = @_; $i->outNL; }); is_deeply Assemble, <<END; index: 0000 0000 0000 0000 index: 0000 0000 0000 0001 index: 0000 0000 0000 0002 index: 0000 0000 0000 0003 index: 0000 0000 0000 0004 index: 0000 0000 0000 0005 index: 0000 0000 0000 0006 index: 0000 0000 0000 0007 index: 0000 0000 0000 0008 index: 0000 0000 0000 0009 END
Manage data on the stack
Generic versions of push, pop, peek
Pop registers from the stack
Parameter Description 1 @r Register
Mov rax, 0x11111111; Mov rbx, 0x22222222; PushR my @save = (rax, rbx); Mov rax, 0x33333333; PopR @save; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutRegisterInHex rax; PrintOutRegisterInHex rbx; is_deeply Assemble,<<END; rax: 0000 0000 1111 1111 rbx: 0000 0000 2222 2222 END
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; KeepFree r14; Ktestq k0, k0; IfZ {PrintOutStringNL "0 & 0 == 0"}; PrintOutZF; LoadConstantIntoMaskRegister k1, 1; Ktestq k1, k1; IfNz {PrintOutStringNL "1 & 1 != 0"}; PrintOutZF; LoadConstantIntoMaskRegister k2, eval "0b".(('1'x4).('0'x4))x2; PrintOutRegisterInHex k0, k1, k2; Mov r15, 0x89abcdef; Mov r14, 0x01234567; Shl r14, 32; Or r15, r14; Push r15; Push r15; KeepFree r15; PopEax; PrintRaxInHex($stdout, 3); PrintOutNL; KeepFree rax; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $a = Vq('aaaa'); $a->pop; $a->push; $a->outNL; PopEax; PrintRaxInHex($stdout, 3); PrintOutNL; KeepFree rax; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ok Assemble(debug => 0, eq => <<END); 0 & 0 == 0 ZF=1 1 & 1 != 0 ZF=0 k0: 0000 0000 0000 0000 k1: 0000 0000 0000 0001 k2: 0000 0000 0000 F0F0 89AB CDEF aaaa: 89AB CDEF 0123 4567 0123 4567 END
Peek at register on stack
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 {Mov rbx, rax; WaitPid; PrintOutRegisterInHex rax; PrintOutRegisterInHex rbx; KeepFree rax; GetPid; # Pid of parent as seen in parent Mov rcx,rax; PrintOutRegisterInHex rcx; } sub # Child {Mov r8,rax; PrintOutRegisterInHex r8; KeepFree rax; GetPid; # Child pid as seen in child Mov r9,rax; PrintOutRegisterInHex r9; KeepFree rax; GetPPid; # Parent pid as seen in child Mov r10,rax; PrintOutRegisterInHex r10; }; my $r = Assemble; # r8: 0000 0000 0000 0000 #1 Return from fork as seen by child # r9: 0000 0000 0003 0C63 #2 Pid of child # r10: 0000 0000 0003 0C60 #3 Pid of parent from child # rax: 0000 0000 0003 0C63 #4 Return from fork as seen by parent # rbx: 0000 0000 0003 0C63 #5 Wait for child pid result # rcx: 0000 0000 0003 0C60 #6 Pid of parent if ($r =~ m(r8:( 0000){4}.*r9:(.*)\s{5,}r10:(.*)\s{5,}rax:(.*)\s{5,}rbx:(.*)\s{5,}rcx:(.*)\s{2,})s) {ok $2 eq $4; ok $2 eq $5; ok $3 eq $6; ok $2 gt $6; }
Get process identifier
Fork; # Fork Test rax,rax; IfNz # Parent {Mov rbx, rax; WaitPid; PrintOutRegisterInHex rax; PrintOutRegisterInHex rbx; KeepFree rax; GetPid; # Pid of parent as seen in parent # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Mov rcx,rax; PrintOutRegisterInHex rcx; } sub # Child {Mov r8,rax; PrintOutRegisterInHex r8; KeepFree rax; GetPid; # Child pid as seen in child # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Mov r9,rax; PrintOutRegisterInHex r9; KeepFree rax; GetPPid; # Parent pid as seen in child Mov r10,rax; PrintOutRegisterInHex r10; }; my $r = Assemble; # r8: 0000 0000 0000 0000 #1 Return from fork as seen by child # r9: 0000 0000 0003 0C63 #2 Pid of child # r10: 0000 0000 0003 0C60 #3 Pid of parent from child # rax: 0000 0000 0003 0C63 #4 Return from fork as seen by parent # rbx: 0000 0000 0003 0C63 #5 Wait for child pid result # rcx: 0000 0000 0003 0C60 #6 Pid of parent if ($r =~ m(r8:( 0000){4}.*r9:(.*)\s{5,}r10:(.*)\s{5,}rax:(.*)\s{5,}rbx:(.*)\s{5,}rcx:(.*)\s{2,})s) {ok $2 eq $4; ok $2 eq $5; ok $3 eq $6; ok $2 gt $6; }
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 {Mov rbx, rax; WaitPid; PrintOutRegisterInHex rax; PrintOutRegisterInHex rbx; KeepFree rax; GetPid; # Pid of parent as seen in parent Mov rcx,rax; PrintOutRegisterInHex rcx; } sub # Child {Mov r8,rax; PrintOutRegisterInHex r8; KeepFree rax; GetPid; # Child pid as seen in child Mov r9,rax; PrintOutRegisterInHex r9; KeepFree rax; GetPPid; # Parent pid as seen in child # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Mov r10,rax; PrintOutRegisterInHex r10; }; my $r = Assemble; # r8: 0000 0000 0000 0000 #1 Return from fork as seen by child # r9: 0000 0000 0003 0C63 #2 Pid of child # r10: 0000 0000 0003 0C60 #3 Pid of parent from child # rax: 0000 0000 0003 0C63 #4 Return from fork as seen by parent # rbx: 0000 0000 0003 0C63 #5 Wait for child pid result # rcx: 0000 0000 0003 0C60 #6 Pid of parent if ($r =~ m(r8:( 0000){4}.*r9:(.*)\s{5,}r10:(.*)\s{5,}rax:(.*)\s{5,}rbx:(.*)\s{5,}rcx:(.*)\s{2,})s) {ok $2 eq $4; ok $2 eq $5; ok $3 eq $6; ok $2 gt $6; }
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 {Mov rbx, rax; WaitPid; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutRegisterInHex rax; PrintOutRegisterInHex rbx; KeepFree rax; GetPid; # Pid of parent as seen in parent Mov rcx,rax; PrintOutRegisterInHex rcx; } sub # Child {Mov r8,rax; PrintOutRegisterInHex r8; KeepFree rax; GetPid; # Child pid as seen in child Mov r9,rax; PrintOutRegisterInHex r9; KeepFree rax; GetPPid; # Parent pid as seen in child Mov r10,rax; PrintOutRegisterInHex r10; }; my $r = Assemble; # r8: 0000 0000 0000 0000 #1 Return from fork as seen by child # r9: 0000 0000 0003 0C63 #2 Pid of child # r10: 0000 0000 0003 0C60 #3 Pid of parent from child # rax: 0000 0000 0003 0C63 #4 Return from fork as seen by parent # rbx: 0000 0000 0003 0C63 #5 Wait for child pid result # rcx: 0000 0000 0003 0C60 #6 Pid of parent if ($r =~ m(r8:( 0000){4}.*r9:(.*)\s{5,}r10:(.*)\s{5,}rax:(.*)\s{5,}rbx:(.*)\s{5,}rcx:(.*)\s{2,})s) {ok $2 eq $4; ok $2 eq $5; ok $3 eq $6; ok $2 gt $6; }
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 .
Parameter Description 1 $channel Channel
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; KeepFree rax; Mov rax, rsp; Mov rdi, 8; PrintOutMemoryInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutNL; PopR rax; KeepFree rax, rdi; Mov rax, 4096; PushR rax; Mov rax, rsp; Mov rdi, 8; PrintOutMemoryInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutNL; PopR rax; is_deeply Assemble, <<END; 0765 4321 0765 4321 2143 6507 2143 6507 2143 6507 2143 6507 0010 0000 0000 0000 END
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(Cq(size, $N), my $a = Vq(address)); CopyMemory(Vq(source, $s), Vq(size, $N), target => $a); AllocateMemory(Cq(size, $N), my $b = Vq(address)); CopyMemory(source => $a, target => $b, Cq(size, $N)); $b->setReg(rax); Mov rdi, $N; PrintOutMemoryInHexNL; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ok Assemble(debug=>0, eq => <<END); 0001 0203 0405 06070809 0A0B 0C0D 0E0F1011 1213 1415 16171819 1A1B 1C1D 1E1F2021 2223 2425 26272829 2A2B 2C2D 2E2F3031 3233 3435 36373839 3A3B 3C3D 3E3F4041 4243 4445 46474849 4A4B 4C4D 4E4F5051 5253 5455 56575859 5A5B 5C5D 5E5F6061 6263 6465 66676869 6A6B 6C6D 6E6F7071 7273 7475 76777879 7A7B 7C7D 7E7F8081 8283 8485 86878889 8A8B 8C8D 8E8F9091 9293 9495 96979899 9A9B 9C9D 9E9FA0A1 A2A3 A4A5 A6A7A8A9 AAAB ACAD AEAFB0B1 B2B3 B4B5 B6B7B8B9 BABB BCBD BEBFC0C1 C2C3 C4C5 C6C7C8C9 CACB CCCD CECFD0D1 D2D3 D4D5 D6D7D8D9 DADB DCDD DEDFE0E1 E2E3 E4E5 E6E7E8E9 EAEB ECED EEEFF0F1 F2F3 F4F5 F6F7F8F9 FAFB FCFD FEFF END
Print the memory addressed by rax for a length of rdi on the specified channel
ReadFile(Vq(file, Rs($0)), (my $s = Vq(size)), my $a = Vq(address)); # Read file $a->setReg(rax); # Address of file in memory $s->setReg(rdi); # Length of file in memory PrintOutMemory; # Print contents of memory to stdout my $r = Assemble; # Assemble and execute ok stringMd5Sum($r) eq fileMd5Sum($0); # Output contains this file
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; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 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
Parameter Description 1 @variables Parameters
my $N = Vq(size, 2048); my $q = Rs('a'..'p'); AllocateMemory($N, my $address = Vq(address)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Vmovdqu8 xmm0, "[$q]"; $address->setReg(rax); Vmovdqu8 "[rax]", xmm0; Mov rdi, 16; PrintOutMemory; PrintOutNL; FreeMemory(address => $address, size=> $N); ok Assemble(eq => <<END); abcdefghijklmnop END my $N = Vq(size, 4096); # Size of the initial allocation which should be one or more pages AllocateMemory($N, my $A = Vq(address)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ClearMemory($N, $A); $A->setReg(rax); $N->setReg(rdi); PrintOutMemoryInHexNL; FreeMemory($N, $A); ok Assemble(eq => <<END); 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 END my $N = 256; my $s = Rb 0..$N-1; AllocateMemory(Cq(size, $N), my $a = Vq(address)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 CopyMemory(Vq(source, $s), Vq(size, $N), target => $a); AllocateMemory(Cq(size, $N), my $b = Vq(address)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 CopyMemory(source => $a, target => $b, Cq(size, $N)); $b->setReg(rax); Mov rdi, $N; PrintOutMemoryInHexNL; ok Assemble(debug=>0, eq => <<END); 0001 0203 0405 06070809 0A0B 0C0D 0E0F1011 1213 1415 16171819 1A1B 1C1D 1E1F2021 2223 2425 26272829 2A2B 2C2D 2E2F3031 3233 3435 36373839 3A3B 3C3D 3E3F4041 4243 4445 46474849 4A4B 4C4D 4E4F5051 5253 5455 56575859 5A5B 5C5D 5E5F6061 6263 6465 66676869 6A6B 6C6D 6E6F7071 7273 7475 76777879 7A7B 7C7D 7E7F8081 8283 8485 86878889 8A8B 8C8D 8E8F9091 9293 9495 96979899 9A9B 9C9D 9E9FA0A1 A2A3 A4A5 A6A7A8A9 AAAB ACAD AEAFB0B1 B2B3 B4B5 B6B7B8B9 BABB BCBD BEBFC0C1 C2C3 C4C5 C6C7C8C9 CACB CCCD CECFD0D1 D2D3 D4D5 D6D7D8D9 DADB DCDD DEDFE0E1 E2E3 E4E5 E6E7E8E9 EAEB ECED EEEFF0F1 F2F3 F4F5 F6F7F8F9 FAFB FCFD FEFF END
Free memory
Parameter Description 1 @variables Variables
my $N = Vq(size, 4096); # Size of the initial allocation which should be one or more pages AllocateMemory($N, my $A = Vq(address)); ClearMemory($N, $A); $A->setReg(rax); $N->setReg(rdi); PrintOutMemoryInHexNL; FreeMemory($N, $A); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ok Assemble(eq => <<END); 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 END
Clear memory - the address of the memory is in rax, the length in rdi
my $N = Vq(size, 4096); # Size of the initial allocation which should be one or more pages AllocateMemory($N, my $A = Vq(address)); ClearMemory($N, $A); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $A->setReg(rax); $N->setReg(rdi); PrintOutMemoryInHexNL; FreeMemory($N, $A); ok Assemble(eq => <<END); 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 END
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(Vq(source, rsi), Vq(target, rax), Vq(size, rdi)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 PrintOutMemoryInHex; my $r = Assemble; ok $r =~ m(xmm0: 0000 0000 0000 0004 0000 0003 0002 0100); ok $r =~ m(xmm1: 0000 0000 0000 0004 0000 0003 0002 0100); ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000); my $N = 256; my $s = Rb 0..$N-1; AllocateMemory(Cq(size, $N), my $a = Vq(address)); CopyMemory(Vq(source, $s), Vq(size, $N), target => $a); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 AllocateMemory(Cq(size, $N), my $b = Vq(address)); CopyMemory(source => $a, target => $b, Cq(size, $N)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $b->setReg(rax); Mov rdi, $N; PrintOutMemoryInHexNL; ok Assemble(debug=>0, eq => <<END); 0001 0203 0405 06070809 0A0B 0C0D 0E0F1011 1213 1415 16171819 1A1B 1C1D 1E1F2021 2223 2425 26272829 2A2B 2C2D 2E2F3031 3233 3435 36373839 3A3B 3C3D 3E3F4041 4243 4445 46474849 4A4B 4C4D 4E4F5051 5253 5455 56575859 5A5B 5C5D 5E5F6061 6263 6465 66676869 6A6B 6C6D 6E6F7071 7273 7475 76777879 7A7B 7C7D 7E7F8081 8283 8485 86878889 8A8B 8C8D 8E8F9091 9293 9495 96979899 9A9B 9C9D 9E9FA0A1 A2A3 A4A5 A6A7A8A9 AAAB ACAD AEAFB0B1 B2B3 B4B5 B6B7B8B9 BABB BCBD BEBFC0C1 C2C3 C4C5 C6C7C8C9 CACB CCCD CECFD0D1 D2D3 D4D5 D6D7D8D9 DADB DCDD DEDFE0E1 E2E3 E4E5 E6E7E8E9 EAEB ECED EEEFF0F1 F2F3 F4F5 F6F7F8F9 FAFB FCFD FEFF END
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; KeepFree rax, rdi; Mov rax, Rs(my $f = "zzzTemporaryFile.txt"); # File to write OpenWrite; # Open file CloseFile; # Close file is_deeply Assemble, <<END; # Channel is now used for tracing rax: 0000 0000 0000 0004 rax: 0000 0000 0000 0000 END ok -e $f; # Created file unlink $f;
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; KeepFree rax, rdi; Mov rax, Rs(my $f = "zzzTemporaryFile.txt"); # File to write OpenWrite; # Open file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 CloseFile; # Close file is_deeply Assemble, <<END; # Channel is now used for tracing rax: 0000 0000 0000 0004 rax: 0000 0000 0000 0000 END ok -e $f; # Created file unlink $f;
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; KeepFree rax, rdi; Mov rax, Rs(my $f = "zzzTemporaryFile.txt"); # File to write OpenWrite; # Open file CloseFile; # Close file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 is_deeply Assemble, <<END; # Channel is now used for tracing rax: 0000 0000 0000 0004 rax: 0000 0000 0000 0000 END ok -e $f; # Created file unlink $f;
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
ReadFile(Vq(file, Rs($0)), (my $s = Vq(size)), my $a = Vq(address)); # Read file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $a->setReg(rax); # Address of file in memory $s->setReg(rdi); # Length of file in memory PrintOutMemory; # Print contents of memory to stdout my $r = Assemble; # Assemble and execute ok stringMd5Sum($r) eq fileMd5Sum($0); # Output contains this file
Execute the file named in the byte string addressed by rax with bash
my $s = CreateByteString; # Create a string $s->ql(<<END); # Write code to execute #!/usr/bin/bash whoami ls -la pwd END $s->write (my $f = Vq('file', Rs("zzz.sh"))); # Write code to a file executeFileViaBash($f); # Execute the file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 unlinkFile ($f); # Delete the file my $u = qx(whoami); chomp($u); ok Assemble(emulator=>0) =~ m($u); # The Intel Software Development Emulator is way too slow on these operations.
Unlink the named file
my $s = CreateByteString; # Create a string $s->ql(<<END); # Write code to execute #!/usr/bin/bash whoami ls -la pwd END $s->write (my $f = Vq('file', Rs("zzz.sh"))); # Write code to a file executeFileViaBash($f); # Execute the file unlinkFile ($f); # Delete the file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $u = qx(whoami); chomp($u); ok Assemble(emulator=>0) =~ m($u); # The Intel Software Development Emulator is way too slow on these operations.
Hash functions
Hash 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) = (Vq(out), Vq(size), Vq('fail')); my $opens = Vq(opens); my $class = Vq(class); my $Chars = Rb(0x24, 0xc2, 0xa2, 0xc9, 0x91, 0xE2, 0x82, 0xAC, 0xF0, 0x90, 0x8D, 0x88); my $chars = Vq(chars, $Chars); GetNextUtf8CharAsUtf32 in=>$chars, @p; # Dollar UTF-8 Encoding: 0x24 UTF-32 Encoding: 0x00000024 $out->out('out1 : '); $size->outNL(' size : '); GetNextUtf8CharAsUtf32 in=>$chars+1, @p; # Cents UTF-8 Encoding: 0xC2 0xA2 UTF-32 Encoding: 0x000000a2 $out->out('out2 : '); $size->outNL(' size : '); GetNextUtf8CharAsUtf32 in=>$chars+3, @p; # Alpha UTF-8 Encoding: 0xC9 0x91 UTF-32 Encoding: 0x00000251 $out->out('out3 : '); $size->outNL(' size : '); GetNextUtf8CharAsUtf32 in=>$chars+5, @p; # Euro UTF-8 Encoding: 0xE2 0x82 0xAC UTF-32 Encoding: 0x000020AC $out->out('out4 : '); $size->outNL(' size : '); GetNextUtf8CharAsUtf32 in=>$chars+8, @p; # Gothic Letter Hwair UTF-8 Encoding 0xF0 0x90 0x8D 0x88 UTF-32 Encoding: 0x00010348 $out->out('out5 : '); $size->outNL(' size : '); my $statement = qq(𝖺 𝑎𝑠𝑠𝑖𝑔𝑛 【【𝖻 𝐩𝐥𝐮𝐬 𝖼】】 AAAAAAAA); # A sample sentence to parse my $s = Cq(statement, Rs($statement)); my $l = Cq(size, length($statement)); AllocateMemory($l, my $address = Vq(address)); # Allocate enough memory for a copy of the string CopyMemory(source => $s, target => $address, $l); GetNextUtf8CharAsUtf32 in=>$address, @p; $out->out('outA : '); $size->outNL(' size : '); GetNextUtf8CharAsUtf32 in=>$address+4, @p; $out->out('outB : '); $size->outNL(' size : '); GetNextUtf8CharAsUtf32 in=>$address+5, @p; $out->out('outC : '); $size->outNL(' size : '); GetNextUtf8CharAsUtf32 in=>$address+30, @p; $out->out('outD : '); $size->outNL(' size : '); GetNextUtf8CharAsUtf32 in=>$address+35, @p; $out->out('outE : '); $size->outNL(' size : '); $address->printOutMemoryInHexNL($l); # Single character classifications Cq('newLine', 0x0A)->putBIntoZmm(0, 0); #r 0x0 - open bracket #r 0x1 - close bracket Cq('newLine', 0x02)->putBIntoZmm(0, 3); #r 0x2 - new line, #r 0x3 - new line acting as a semi-colon Cq('space', 0x20)->putBIntoZmm(0, 4); Cq('space', 0x05)->putBIntoZmm(0, 7); #r 0x5 - space my sub pu32($$) # Print some utf32 characters {my ($n, $m) = @_; # Variable: number of characters to print, variable: address of memory $n->for(sub {my ($index, $start, $next, $end) = @_; my $a = $m + $index * 4; $a->setReg(r15); KeepFree r15; Mov r15d, "[r15]"; KeepFree r15; PrintOutRegisterInHex r15; }); } if (1) # Classify a utf32 string {my $a = Dd(0x0001d5ba, 0x00000020, 0x0001d44e, 0x0000000a, 0x0001d5bb, 0x0001d429); my $t = Cq('test', $a); my $s = Cq('size', 6); ClassifyCharacters4 address=>$t, size=>$s; PrintOutStringNL "Convert some utf8 to utf32"; pu32($s, $t); } # circledLatinLetter : assign ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ # mathematicalBold : dyad lr 3 𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳𝚨𝚩𝚪𝚫𝚬𝚭𝚮𝚯𝚰𝚱𝚲𝚳𝚴𝚵𝚶𝚷𝚸𝚺𝚻𝚼𝚽𝚾𝚿𝛀𝛂𝛃𝛄𝛅𝛆𝛇𝛈𝛉𝛊𝛋𝛌𝛍𝛎𝛏𝛐𝛑𝛒𝛔𝛕𝛖𝛗𝛘𝛙𝛚𝟊𝟋 # mathematicalBoldFraktur : 𝕬𝕭𝕮𝕯𝕰𝕱𝕲𝕳𝕴𝕵𝕶𝕷𝕸𝕹𝕺𝕻𝕼𝕽𝕾𝕿𝖀𝖁𝖂𝖃𝖄𝖅𝖆𝖇𝖈𝖉𝖊𝖋𝖌𝖍𝖎𝖏𝖐𝖑𝖒𝖓𝖔𝖕𝖖𝖗𝖘𝖙𝖚𝖛𝖜𝖝𝖞𝖟 # mathematicalBoldItalic : prefix 𝑨𝑩𝑪𝑫𝑬𝑭𝑮𝑯𝑰𝑱𝑲𝑳𝑴𝑵𝑶𝑷𝑸𝑹𝑺𝑻𝑼𝑽𝑾𝑿𝒀𝒁𝒂𝒃𝒄𝒅𝒆𝒇𝒈𝒉𝒊𝒋𝒌𝒍𝒎𝒏𝒐𝒑𝒒𝒓𝒔𝒕𝒖𝒗𝒘𝒙𝒚𝒛𝜜𝜝𝜞𝜟𝜠𝜡𝜢𝜣𝜤𝜥𝜦𝜧𝜨𝜩𝜪𝜫𝜬𝜮𝜯𝜰𝜱𝜲𝜳𝜴𝜶𝜷𝜸𝜹𝜺𝜻𝜼𝜽𝜾𝜿𝝀𝝁𝝂𝝃𝝄𝝅𝝆𝝈𝝉𝝊𝝋𝝌𝝍𝝎 # mathematicalBoldScript : 𝓐𝓑𝓒𝓓𝓔𝓕𝓖𝓗𝓘𝓙𝓚𝓛𝓜𝓝𝓞𝓟𝓠𝓡𝓢𝓣𝓤𝓥𝓦𝓧𝓨𝓩𝓪𝓫𝓬𝓭𝓮𝓯𝓰𝓱𝓲𝓳𝓴𝓵𝓶𝓷𝓸𝓹𝓺𝓻𝓼𝓽𝓾𝓿𝔀𝔁𝔂𝔃 # mathematicalDouble-struck : 𝔸𝔹𝔻𝔼𝔽𝔾𝕀𝕁𝕂𝕃𝕄𝕆𝕊𝕋𝕌𝕍𝕎𝕏𝕐𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫 # mathematicalFraktur : 𝔄𝔅𝔇𝔈𝔉𝔊𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔𝔖𝔗𝔘𝔙𝔚𝔛𝔜𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷 # mathematicalItalic : 𝐴𝐵𝐶𝐷𝐸𝐹𝐺𝐻𝐼𝐽𝐾𝐿𝑀𝑁𝑂𝑃𝑄𝑅𝑆𝑇𝑈𝑉𝑊𝑋𝑌𝑍𝑎𝑏𝑐𝑑𝑒𝑓𝑔𝑖𝑗𝑘𝑙𝑚𝑛𝑜𝑝𝑞𝑟𝑠𝑡𝑢𝑣𝑤𝑥𝑦𝑧𝛢𝛣𝛤𝛥𝛦𝛧𝛨𝛩𝛪𝛫𝛬𝛭𝛮𝛯𝛰𝛱𝛲𝛴𝛵𝛶𝛷𝛸𝛹𝛺𝛼𝛽𝛾𝛿𝜀𝜁𝜂𝜃𝜄𝜅𝜆𝜇𝜈𝜉𝜊𝜋𝜌𝜎𝜏𝜐𝜑𝜒𝜓𝜔 # mathematicalMonospace : 𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣 # mathematicalSans-serif : variable 𝖠𝖡𝖢𝖣𝖤𝖥𝖦𝖧𝖨𝖩𝖪𝖫𝖬𝖭𝖮𝖯𝖰𝖱𝖲𝖳𝖴𝖵𝖶𝖷𝖸𝖹𝖺𝖻𝖼𝖽𝖾𝖿𝗀𝗁𝗂𝗃𝗄𝗅𝗆𝗇𝗈𝗉𝗊𝗋𝗌𝗍𝗎𝗏𝗐𝗑𝗒𝗓 # mathematicalSans-serifBold : 𝗔𝗕𝗖𝗗𝗘𝗙𝗚𝗛𝗜𝗝𝗞𝗟𝗠𝗡𝗢𝗣𝗤𝗥𝗦𝗧𝗨𝗩𝗪𝗫𝗬𝗭𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇𝝖𝝗𝝘𝝙𝝚𝝛𝝜𝝝𝝞𝝟𝝠𝝡𝝢𝝣𝝤𝝥𝝦𝝨𝝩𝝪𝝫𝝬𝝭𝝮𝝰𝝱𝝲𝝳𝝴𝝵𝝶𝝷𝝸𝝹𝝺𝝻𝝼𝝽𝝾𝝿𝞀𝞂𝞃𝞄𝞅𝞆𝞇𝞈 # mathematicalSans-serifBoldItalic : postfix 𝘼𝘽𝘾𝘿𝙀𝙁𝙂𝙃𝙄𝙅𝙆𝙇𝙈𝙉𝙊𝙋𝙌𝙍𝙎𝙏𝙐𝙑𝙒𝙓𝙔𝙕𝙖𝙗𝙘𝙙𝙚𝙛𝙜𝙝𝙞𝙟𝙠𝙡𝙢𝙣𝙤𝙥𝙦𝙧𝙨𝙩𝙪𝙫𝙬𝙭𝙮𝙯𝞐𝞑𝞒𝞓𝞔𝞕𝞖𝞗𝞘𝞙𝞚𝞛𝞜𝞝𝞞𝞟𝞠𝞢𝞣𝞤𝞥𝞦𝞧𝞨𝞪𝞫𝞬𝞭𝞮𝞯𝞰𝞱𝞲𝞳𝞴𝞵𝞶𝞷𝞸𝞹𝞺𝞼𝞽𝞾𝞿𝟀𝟁𝟂 # mathematicalSans-serifItalic : 𝘈𝘉𝘊𝘋𝘌𝘍𝘎𝘏𝘐𝘑𝘒𝘓𝘔𝘕𝘖𝘗𝘘𝘙𝘚𝘛𝘜𝘝𝘞𝘟𝘠𝘡𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻 # mathematicalScript : 𝒜𝒞𝒟𝒢𝒥𝒦𝒩𝒪𝒫𝒬𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵𝒶𝒷𝒸𝒹𝒻𝒽𝒾𝒿𝓀𝓁𝓂𝓃𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏 # negativeCircledLatinLetter : 🅐🅑🅒🅓🅔🅕🅖🅗🅘🅙🅚🅛🅜🅝🅞🅟🅠🅡🅢🅣🅤🅥🅦🅧🅨🅩 # negativeSquaredLatinLetter : 🅰🅱🅲🅳🅴🅵🅶🅷🅸🅹🅺🅻🅼🅽🅾🅿🆀🆁🆂🆃🆄🆅🆆🆇🆈🆉 # squaredLatinLetter : 🄰🄱🄲🄳🄴🄵🄶🄷🄸🄹🄺🄻🄼🄽🄾🄿🅀🅁🅂🅃🅄🅅🅆🅇🅈🅉🆥 # semiColon : semicolon ⟢ # Delete following code when the following test is completed if (0) # Convert utf8 test string to utf32 {my @p = my ($u32, $size32, $count) = (Vq(u32), Vq(size32), Vq(count)); ClassifyCharacters4 address=>$u32, size=>$count; PrintOutStringNL "Convert test statement - special characters"; pu32($count, $u32); Cq('variable', 0x0) ->putDIntoZmm(0, 0); # Range classifications Cq('variable', 0x06) ->putBIntoZmm(0, 3); #r 0x6 - ascii Cq('variable', 0x01D5A0)->putDIntoZmm(0, 4); Cq('variable', 0x07) ->putBIntoZmm(0, 7); #r 0x7 - variable Cq('variable', 0x01D434)->putDIntoZmm(0, 8); Cq('variable', 0x08) ->putBIntoZmm(0, 11); #r 0x8 - assign Cq('variable', 0x01D400)->putDIntoZmm(0, 12); Cq('variable', 0x09) ->putBIntoZmm(0, 15); #r 0x9 - Cq('variable', 0x7f) ->putDIntoZmm(1, 0); Cq('variable', 0x06) ->putBIntoZmm(1, 3); Cq('variable', 0x01D5D3)->putDIntoZmm(1, 4); Cq('variable', 0x07) ->putBIntoZmm(1, 7); Cq('variable', 0x01D467)->putDIntoZmm(1, 8); Cq('variable', 0x08) ->putBIntoZmm(1, 11); Cq('variable', 0x01D433)->putDIntoZmm(1, 12); Cq('variable', 0x09) ->putBIntoZmm(1, 15); ClassifyInRange address=>$u32, size=>$count; PrintOutStringNL "Convert test statement - ranges"; pu32($count, $u32); my $bl = Rd(0x10002045, 0x12002329, 0x1400276c, 0x16002770, 0x1c0027e6, 0x24002983, 0x26002987, 0x380029fc, 0x3a003008, 0x3e003010, 0x40003014, 0x4800ff3b, 0x4900ff3d, 0x4a00ff5b, 0x4b00ff5d, 0); my $bh = Rd(0x11002046, 0x1300232a, 0x1500276d, 0x1b002775, 0x230027ed, 0x25002984, 0x37002998, 0x390029fd, 0x3d00300b, 0x3f003011, 0x4700301b, 0x4800ff3b, 0x4900ff3d, 0x4a00ff5b, 0x4b00ff5d, 0); Vmovdqu8 zmm0, "[$bl]"; Vmovdqu8 zmm1, "[$bh]"; ClassifyWithInRange address=>$u32, size=>$count; PrintOutStringNL "Convert test statement - brackets"; pu32($count, $u32); MatchBrackets address=>$u32, size=>$count, $opens, $fail; PrintOutStringNL "Convert test statement - bracket matching"; pu32($count, $u32); } $address->clearMemory($l); $address->printOutMemoryInHexNL($l); ok Assemble(debug => 0, eq => <<END); out1 : 0000 0000 0000 0024 size : 0000 0000 0000 0001 out2 : 0000 0000 0000 00A2 size : 0000 0000 0000 0002 out3 : 0000 0000 0000 0251 size : 0000 0000 0000 0002 out4 : 0000 0000 0000 20AC size : 0000 0000 0000 0003 out5 : 0000 0000 0001 0348 size : 0000 0000 0000 0004 outA : 0000 0000 0001 D5BA size : 0000 0000 0000 0004 outB : 0000 0000 0000 000A size : 0000 0000 0000 0001 outC : 0000 0000 0000 0020 size : 0000 0000 0000 0001 outD : 0000 0000 0000 0020 size : 0000 0000 0000 0001 outE : 0000 0000 0000 0010 size : 0000 0000 0000 0002 F09D 96BA 0A20 F09D918E F09D 91A0 F09D91A0 F09D 9196 F09D9194 F09D 919B 20E38090 E380 90F0 9D96BB20 F09D 90A9 F09D90A5 F09D 90AE F09D90AC 20F0 9D96 BCE38091 E380 910A 4141 Convert some utf8 to utf32 r15: 0000 0000 0001 D5BA r15: 0000 0000 0500 0020 r15: 0000 0000 0001 D44E r15: 0000 0000 0200 000A r15: 0000 0000 0001 D5BB r15: 0000 0000 0001 D429 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 END
Classify the utf32 characters in a block of memory of specified length using the classification held in zmm0: zmm0 should be formatted in double words with each word having the classification in the highest 8 bits and the utf32 character so classified in the lower 21 bits. The classification bits are copied into the high unused) byte of each utf32 character in the block of memory.
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.
Replace the low three bytes of a utf32 bracket character with 24 bits of offset to the matching opening or closing bracket. Opening brackets have even codes from 0x10 to 0x4e while the corresponding closing bracket has a code one higher.
Print the specified number of utf32 characters at the specified address
Parameter Description 1 $n Variable: number of characters to print 2 $m Variable: address of memory
Operations on Short Strings
Load the short string addressed by rax into the zmm register with the specified number
Parameter Description 1 $zmm Zmm register to load
Parameter Description 1 $zmm Zmm register to load 2 $address Address of string in memory
my $s = Rb(3, 0x01, 0x02, 0x03); my $t = Rb(7, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a); LoadShortStringFromMemoryToZmm 0, $s; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 LoadShortStringFromMemoryToZmm 1, $t; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 ConcatenateShortStrings(0, 1); PrintOutRegisterInHex xmm0; PrintOutRegisterInHex xmm1; my $r = Assemble; ok $r =~ m(xmm0: 0000 0000 000A 0908 0706 0504 0302 010A); ok $r =~ m(xmm1: 0000 0000 0000 0000 0A09 0807 0605 0407);
Get the length of the short string held in the numbered zmm register into the specified register
Parameter Description 1 $reg Register to hold length 2 $zmm Number of zmm register containing string
Set the length of the short string held in the numbered zmm register into the specified register
Parameter Description 1 $zmm Number of zmm register containing string 2 $reg Register to hold length
Concatenate the numbered source zmm containing a short string with the short string in the numbered target zmm.
Parameter Description 1 $left Target zmm 2 $right Source zmm
Operations on Byte Strings
Length of a zero terminated string
StringLength(Vq(string, Rs("abcd")))->outNL; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Assemble(debug => 0, eq => <<END); size: 0000 0000 0000 0004 END
Create an relocatable string of bytes in an arena and returns its address in rax. Optionally add a chain header so that 64 byte blocks of memory can be freed and reused within the byte string.
Parameter Description 1 %options Free=>1 adds a free chain.
my $a = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $a->q('aa'); $a->out; PrintOutNL; is_deeply Assemble, <<END; # Assemble and execute aa END my $a = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $b = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $a->q('aa'); $b->q('bb'); $a->out; PrintOutNL; $b->out; PrintOutNL; is_deeply Assemble, <<END; # Assemble and execute aa bb END my $a = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $b = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $a->q('aa'); $a->q('AA'); $a->out; PrintOutNL; is_deeply Assemble, <<END; # Assemble and execute aaAA END my $a = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 my $b = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $a->q('aa'); $b->q('bb'); $a->q('AA'); $b->q('BB'); $a->q('aa'); $b->q('bb'); $a->out; $b->out; PrintOutNL; is_deeply Assemble, <<END; # Assemble and execute aaAAaabbBBbb END my $a = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $a->q('ab'); my $b = CreateByteString; # Create target byte string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 $b->append(source=>$a->bs); $b->append(source=>$a->bs); $a->append(source=>$b->bs); $b->append(source=>$a->bs); $a->append(source=>$b->bs); $b->append(source=>$a->bs); $b->append(source=>$a->bs); $b->append(source=>$a->bs); $b->append(source=>$a->bs); $a->out; PrintOutNL; # Print byte string $b->out; PrintOutNL; # Print byte string $a->length(my $sa = Vq(size)); $sa->outNL; $b->length(my $sb = Vq(size)); $sb->outNL; $a->clear; $a->length(my $sA = Vq(size)); $sA->outNL; $b->length(my $sB = Vq(size)); $sB->outNL; is_deeply Assemble, <<END; # Assemble and execute abababababababab ababababababababababababababababababababababababababababababababababababab size: 0000 0000 0000 0010 size: 0000 0000 0000 004A size: 0000 0000 0000 0000 size: 0000 0000 0000 004A END
Return a variable with the end point of a chain of double words in the byte string starting at the specified variable.
Parameter Description 1 $byteString Byte string descriptor 2 $bs Byte string locator 3 $variable Start variable 4 @offsets Offsets chain
my $format = Rd(map{4*$_+24} 0..64); my $b = CreateByteString; my $a = $b->allocBlock; Vmovdqu8 zmm31, "[$format]"; $b->putBlock($b->bs, $a, 31); my $r = $b->chain($b->bs, Vq(start, 0x18), 4); $r->outNL("chain1: "); my $s = $b->chain($b->bs, $r, 4); $s->outNL("chain2: "); my $t = $b->chain($b->bs, $s, 4); $t->outNL("chain3: "); my $A = $b->chain($b->bs, Vq(start, 0x18), 4, 4, 4); $A->outNL("chain4: "); # Get a long chain $b->putChain($b->bs, Vq(start, 0x18), Vq(end, 0xff), 4, 4, 4); # Put at the end of a long chain $b->dump; my $sub = Subroutine {my ($p) = @_; # Parameters If ($$p{c} == -1, sub {PrintOutStringNL "C is minus one"}, sub {PrintOutStringNL "C is NOT minus one"}, ); If ($$p{d} == -1, sub {PrintOutStringNL "D is minus one"}, sub {PrintOutStringNL "D is NOT minus one"}, ); my $C = $$p{c}->clone; $C->outNL; $$p{e} += 1; $$p{e}->outNL('E: '); $$p{f}->outNL('F1: '); $$p{f}++; $$p{f}->outNL('F2: '); } name=> 'aaa', in => {c => 3}, io => {d => 3, e => 3, f => 3}; my $c = Cq(c, -1); my $d = Cq(d, -1); my $e = Vq(e, 1); my $f = Vq(f, 2); $sub->call($c, $d, $e, $f); $f->outNL('F3: '); ok Assemble(debug => 0, eq => <<END); chain1: 0000 0000 0000 001C chain2: 0000 0000 0000 0020 chain3: 0000 0000 0000 0024 chain4: 0000 0000 0000 0024 Byte String Size: 0000 0000 0000 1000 Used: 0000 0000 0000 0058 0000: 0010 0000 0000 00005800 0000 0000 00000000 0000 0000 00001800 0000 1C00 00002000 0000 FF00 00002800 0000 2C00 00003000 0000 3400 00003800 0000 3C00 0000 0040: 4000 0000 4400 00004800 0000 4C00 00005000 0000 5400 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 C is minus one D is minus one Clone of c: FFFF FFFF FFFF FFFF E: 0000 0000 0000 0002 F1: 0000 0000 0000 0002 F2: 0000 0000 0000 0003 F3: 0000 0000 0000 0003 END
Write the double word in the specified variable to the double word location at the the specified offset in the specified byte string.
Parameter Description 1 $byteString Byte string descriptor 2 $bs Byte string locator variable 3 $start Start variable 4 $value Value to put as a variable 5 @offsets Offsets chain
Get the length of a byte string
Parameter Description 1 $byteString Byte string descriptor 2 @variables Variables
Make a byte string read only
Parameter Description 1 $byteString Byte string descriptor
Make a byte string writable
Allocate the amount of space indicated in rdi in the byte string addressed by rax and return the offset of the allocation in the arena in rdi
Size of a block
Parameter Description 1 $byteString Byte string
Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable
Parameter Description 1 $byteString Byte string 2 @variables Variables
my $a = CreateByteString; $a->dump; my $b1 = $a->allocBlock; $a->dump; my $b2 = $a->allocBlock; $a->dump; $a->freeBlock($b2); $a->dump; $a->freeBlock($b1); $a->dump; ok Assemble(debug => 0, eq => <<END); Byte String Size: 0000 0000 0000 1000 Used: 0000 0000 0000 0018 0000: 0010 0000 0000 00001800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 Byte String Size: 0000 0000 0000 1000 Used: 0000 0000 0000 0058 0000: 0010 0000 0000 00005800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 Byte String Size: 0000 0000 0000 1000 Used: 0000 0000 0000 0098 0000: 0010 0000 0000 00009800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 Byte String Size: 0000 0000 0000 1000 Used: 0000 0000 0000 0098 0000: 0010 0000 0000 00009800 0000 0000 00005800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 Byte String Size: 0000 0000 0000 1000 Used: 0000 0000 0000 0098 0000: 0010 0000 0000 00009800 0000 0000 00001800 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 0040: 0000 0000 0000 00000000 0000 0000 00000000 0000 5800 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 0080: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 00C0: 0000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 00000000 0000 0000 0000 END
Free a block in a byte string by placing it on the free chain
Get the block with the specified offset in the specified block string and return it in the numbered zmm
Parameter Description 1 $byteString Byte string descriptor 2 $bsa Byte string variable 3 $block Offset of the block as a variable 4 $zmm Number of zmm register to contain block
Write the numbered zmm to the block at the specified offset in the specified byte string
Parameter Description 1 $byteString Byte string descriptor 2 $bsa Byte string variable 3 $block Block in byte string 4 $zmm Content variable
Append the content with length rdi addressed by rsi to the byte string addressed by rax
Append a constant string to the byte string
Parameter Description 1 $byteString Byte string descriptor 2 $string String
Append a quoted string containing new line characters to the byte string addressed by rax
Parameter Description 1 $byteString Byte string 2 $const Constant
Append a character expressed as a decimal number to the byte string addressed by rax
Parameter Description 1 $byteString Byte string descriptor 2 $char Number of character to be appended
Append a new line to the byte string addressed by rax
Append a trailing zero to the byte string addressed by rax
Append one byte string to another
Clear the byte string addressed by rax
Write the content in a byte string addressed by rax to a temporary file and replace the byte string content with the name of the temporary file
Read the named file (terminated with a zero byte) and place it into the named byte string.
Print the specified byte string addressed by rax on sysout
Dump details of a byte string
Parameter Description 1 $byteString Byte string descriptor 2 $depth Optional amount of memory to dump
Strings made from zmm sized blocks of text
Create a string from a doubly link linked list of 64 byte blocks linked via 4 byte offsets in the byte string addressed by rax and return its descriptor
Parameter Description 1 $byteString Byte string description
Address of a block string
Parameter Description 1 $blockString Block string descriptor
Get the block length of the numbered zmm and return it in a variable
Parameter Description 1 $blockString Block string descriptor 2 $zmm Number of zmm register
Set the block length of the numbered zmm to the specified length
Parameter Description 1 $blockString Block string descriptor 2 $length Length as a variable 3 $zmm Number of zmm register
Parameter Description 1 $blockString Block string descriptor 2 $bsa Byte string variable 3 $block Offset of the block as a variable 4 $zmm Number of zmm register to contain block
Parameter Description 1 $blockString Block string descriptor 2 $bsa Byte string variable 3 $block Block in byte string 4 $zmm Content variable
Get the offsets of the next and previous blocks as variables from the specified zmm
Parameter Description 1 $blockString Block string descriptor 2 $zmm Zmm containing block
Save next and prev offsets into a zmm representing a block
Parameter Description 1 $blockString Block string descriptor 2 $zmm Zmm containing block 3 $next Next offset as a variable 4 $prev Prev offset as a variable
Dump a block string to sysout
Find the length of a block string
Parameter Description 1 $blockString Block string descriptor 2 $size Size variable
Concatenate two block strings by appending a copy of the source to the target block string.
Parameter Description 1 $target Target block string 2 $source Source block string
Insert a character into a block string
Parameter Description 1 $blockString Block string 2 @variables Variables
Delete a character in a block string
Get a character from a block string
Append the specified content in memory to the specified block string
Parameter Description 1 $blockString Block string descriptor 2 @variables Variables
Clear the block by freeing all but the first block
Array constructed as a tree of blocks in a byte string
Create a block array in a byte string
Parameter Description 1 $blockArray Block array descriptor
Dump a block array
Parameter Description 1 $blockArray Block array descriptor 2 @variables Variables
Push an element onto the array
Pop an element from an array
Get an element from the array
Put an element into an array as long as it is with in its limits established by pushing.
Multi Way Tree constructed as a tree of blocks in a byte string
Create a block multi way tree in a byte string
Mov r14, 0; Kmovq k0, r14; KeepFree r14; Ktestq k0, k0; IfZ {PrintOutStringNL "0 & 0 == 0"}; PrintOutZF; LoadConstantIntoMaskRegister k1, 1; Ktestq k1, k1; IfNz {PrintOutStringNL "1 & 1 != 0"}; PrintOutZF; LoadConstantIntoMaskRegister k2, eval "0b".(('1'x4).('0'x4))x2; PrintOutRegisterInHex k0, k1, k2; Mov r15, 0x89abcdef; Mov r14, 0x01234567; Shl r14, 32; Or r15, r14; Push r15; Push r15; KeepFree r15; PopEax; PrintRaxInHex($stdout, 3); PrintOutNL; KeepFree rax; my $a = Vq('aaaa'); $a->pop; $a->push; $a->outNL; PopEax; PrintRaxInHex($stdout, 3); PrintOutNL; KeepFree rax; ok Assemble(debug => 0, eq => <<END); 0 & 0 == 0 ZF=1 1 & 1 != 0 ZF=0 k0: 0000 0000 0000 0000 k1: 0000 0000 0000 0001 k2: 0000 0000 0000 F0F0 89AB CDEF aaaa: 89AB CDEF 0123 4567 0123 4567 END
Find a key in a tree and return its associated data
Parameter Description 1 $bmt Block multi way tree descriptor 2 @variables Variables
Insert a (key, data) pair into the tree
Load the keys and data blocks for a node
Parameter Description 1 $bmt Block multi way tree descriptor 2 $offset Offset as a variable 3 $zmmKeys Numbered zmm for keys 4 $zmmData Numbered data for keys
Save the key and data blocks for a node
Load the child nodes for a node
Parameter Description 1 $bmt Block multi way tree descriptor 2 $offset Offset of nodes 3 $zmmNode Numbered zmm for keys
Load the keys, data and child nodes for a node
Parameter Description 1 $bmt Block multi way tree descriptor 2 $offset Offset as a variable 3 $zmmKeys Numbered zmm for keys 4 $zmmData Numbered data for keys 5 $zmmNode Numbered numbered for keys
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 $bmt Block multi way tree descriptor 2 $zmm Zmm number
Get the length of the block in the numbered zmm from the specified variable
Parameter Description 1 $bmt Block multi way tree 2 $zmm Zmm number 3 $length Length variable
Get the up offset 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
Parameter Description 1 $bmt Block multi way tree descriptor 2 $offset Variable containing up offset 3 $zmm Zmm number
Return the value of the loop field as a variable
Parameter Description 1 $bmt Block multi way tree descriptor 2 $zmm Numbered zmm
Set the value of the loop field from a variable
Parameter Description 1 $bmt Block multi way tree descriptor 2 $value Variable containing offset of next loop entry 3 $zmm Numbered zmm
Return the left most or right most node
Parameter Description 1 $bmt Block multi way tree descriptor 2 $dir Direction: left = 0 or right = 1 3 @variables Variables
Return the left most node
Return the right most node
Load the the node block into the numbered zmm corresponding to the data block held in the numbered zmm.
Parameter Description 1 $bmt Block multi way tree descriptor 2 $data Numbered zmm containing data 3 $node Numbered zmm to hold node block
Address of the byte string containing a block multi way tree
Parameter Description 1 $bmt Block multi way tree descriptor
Return the depth of a node within a tree.
Iterate through a multi way tree
Parameter Description 1 $b Block multi way tree
Next element in the tree
Parameter Description 1 $iter Iterator
Call the specified body with each (key, data) from the specified tree in order
Parameter Description 1 $b Block Multi Way Tree descriptor 2 $body Body
Assemble 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
Assemble the generated code
Parameter Description 1 %options Options
PrintOutStringNL "Hello World"; PrintOutStringNL "Hello World"; PrintErrStringNL "Hello World"; ok Assemble(debug => 0, eq => <<END); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Hello World Hello World END
Iterator
Byte string definition
Constant if true
Counter - number of node
Data at this position
Lexical depth of scope
Expression that initializes the variable
Variable addressing offset to first block of keys
Free chain offset
Offset of header block
Key at this position
Offset of keys in header
Address in memory
Size of the lanes in this variable
Offset of length in keys block
Location of links in bytes in zmm
Offset of keys, data, node loop
Maximum number of keys
Maximum number of children per parent.
Minimum number of keys
Iteration not yet finished
Name of the variable
Location of next offset in block in bytes
Current node within tree
Number of this scope
Parent scope
Current position within node
Location of prev offset in block in bytes
Purpose of this variable
Reference to another variable
Computations should saturate rather then wrap if true
Elements of x|y|zmm registers are signed if true
Size field details
Number of slots in first block
Number of slots in second and subsequent blocks
Structure details
Tree we are iterating over
Offset of up in data block
Used field details
Width of a key or data slot
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
Parameter Description 1 $s Element size 2 @d Data to be laid out
Create/address a hex translate table and return its label
Print the instruction pointer in hex
Print the flags register in hex
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 @save; PrintOutRegisterInHex rax; PrintOutRegisterInHex rbx; is_deeply Assemble,<<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
Make sure that the byte string addressed by rax has enough space to accommodate content of length rdi
Create and load a variable with the first free block on the free block chain or zero if no such block in the given byte string
Parameter Description 1 $byteString Byte string address as a variable
Set the first free block field from a variable
Parameter Description 1 $byteString Byte string descriptor 2 $offset First free block offset as a variable
Allocate a keys/data/node block and place it in the numbered zmm registers
Parameter Description 1 $bmt Block multi way tree descriptor 2 $K Numbered zmm for keys 3 $D Numbered zmm for data 4 $N Numbered zmm for children 5 @variables Variables
Split a node given its offset in a byte string retaining the key being inserted in the node split while putting the remainder to the left or right.
Parameter Description 1 $bmt Block multi way tree descriptor 2 $bs Backing byte string 3 $node Offset of node 4 $key Key 5 @variables Variables
Reparent the children of a node held in registers. The children are in the backing byte string not registers.
Parameter Description 1 $bmt Block multi way tree descriptor 2 $bs Backing byte string 3 $PK Numbered zmm key node 4 $PD Numbered zmm data node 5 $PN Numbered zmm child node 6 @variables Variables
Split a full root block held in 31..29 and place the left block in 28..26 and the right block in 25..23. The left and right blocks should have their loop offsets set so they can be inserted into the root.
Parameter Description 1 $bmt Block multi way tree descriptor 2 $bs Byte string locator
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 = CreateByteString; my $t = $b->CreateBlockMultiWayTree; Vmovdqu8 zmm31, "[$Sk]"; Vmovdqu8 zmm30, "[$Sd]"; Vmovdqu8 zmm29, "[$Sn]"; Vmovdqu8 zmm28, "[$sk]"; Vmovdqu8 zmm27, "[$sd]"; Vmovdqu8 zmm26, "[$sn]"; Vmovdqu8 zmm25, "[$rk]"; Vmovdqu8 zmm24, "[$rd]"; Vmovdqu8 zmm23, "[$rn]"; $t->splitFullLeftNode($b->bs); PrintOutRegisterInHex reverse zmm(23..31); ok Assemble(debug => 0, eq => <<END); zmm31: 0000 00FF 0000 000D 0000 0000 0000 0000 0000 001C 0000 001B 0000 001A 0000 0019 0000 0018 0000 0017 0000 0016 0000 0015 0000 0014 0000 0013 0000 0012 0000 0011 zmm30: 0000 00EE 0000 00DD 0000 0000 0000 0000 0000 001C 0000 001B 0000 001A 0000 0019 0000 0018 0000 0017 0000 0016 0000 0015 0000 0014 0000 0013 0000 0012 0000 0011 zmm29: 0000 00CC 0000 0000 0000 0000 0000 000D 0000 000C 0000 000B 0000 000A 0000 0009 0000 0008 0000 0007 0000 0006 0000 0005 0000 0004 0000 0003 0000 0002 0000 0001 zmm28: 0000 00A1 0000 0007 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0007 0000 0006 0000 0005 0000 0004 0000 0003 0000 0002 0000 0001 zmm27: 0000 00A2 0000 00CC 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0007 0000 0006 0000 0005 0000 0004 0000 0003 0000 0002 0000 0001 zmm26: 0000 00A3 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0007 0000 0006 0000 0005 0000 0004 0000 0003 0000 0002 0000 0001 zmm25: 0000 00B1 0000 0006 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 000E 0000 000D 0000 000C 0000 000B 0000 000A 0000 0009 zmm24: 0000 00B2 0000 00CC 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 000E 0000 000D 0000 000C 0000 000B 0000 000A 0000 0009 zmm23: 0000 00B3 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 000E 0000 000D 0000 000C 0000 000B 0000 000A 0000 0009 END
Split a full right node block held in 25..23 whose parent is in 31..29 and place the new left block in 25..23. The loop and length fields are assumed to be authoritative and hence are preserved.
my $tk = Rd(1..12, 0, 0, 12, 0xC1); my $td = Rd(1..12, 0, 0, 0, 0xC2); my $tn = Rd(1, 0xBB, 3..13, 0, 0, 0xCC); my $lk = Rd(17..30, 14, 0xA1); my $ld = Rd(17..30, 0xCC, 0xA2); my $ln = Rd(17..31, 0xAA); my $rk = Rd(17..30, 14, 0xB1); my $rd = Rd(17..30, 0xCC, 0xB2); my $rn = Rd(17..31, 0xBB); my $b = CreateByteString; my $t = $b->CreateBlockMultiWayTree; Vmovdqu8 zmm31, "[$tk]"; Vmovdqu8 zmm30, "[$td]"; Vmovdqu8 zmm29, "[$tn]"; Vmovdqu8 zmm28, "[$lk]"; Vmovdqu8 zmm27, "[$ld]"; Vmovdqu8 zmm26, "[$ln]"; Vmovdqu8 zmm25, "[$rk]"; Vmovdqu8 zmm24, "[$rd]"; Vmovdqu8 zmm23, "[$rn]"; $t->splitFullRightNode($b->bs); PrintOutRegisterInHex reverse zmm(23..31); ok Assemble(debug => 0, eq => <<END); zmm31: 0000 00C1 0000 000D 0000 0000 0000 000C 0000 000B 0000 000A 0000 0009 0000 0008 0000 0007 0000 0006 0000 0005 0000 0004 0000 0003 0000 0002 0000 0018 0000 0001 zmm30: 0000 00C2 0000 0000 0000 0000 0000 000C 0000 000B 0000 000A 0000 0009 0000 0008 0000 0007 0000 0006 0000 0005 0000 0004 0000 0003 0000 0002 0000 0018 0000 0001 zmm29: 0000 00CC 0000 0000 0000 000D 0000 000C 0000 000B 0000 000A 0000 0009 0000 0008 0000 0007 0000 0006 0000 0005 0000 0004 0000 0003 0000 00BB 0000 00AA 0000 0001 zmm28: 0000 00A1 0000 0007 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0017 0000 0016 0000 0015 0000 0014 0000 0013 0000 0012 0000 0011 zmm27: 0000 00A2 0000 00CC 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0017 0000 0016 0000 0015 0000 0014 0000 0013 0000 0012 0000 0011 zmm26: 0000 00AA 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0017 0000 0016 0000 0015 0000 0014 0000 0013 0000 0012 0000 0011 zmm25: 0000 00B1 0000 0006 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 001E 0000 001D 0000 001C 0000 001B 0000 001A 0000 0019 zmm24: 0000 00B2 0000 00CC 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 001E 0000 001D 0000 001C 0000 001B 0000 001A 0000 0019 zmm23: 0000 00BB 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 001E 0000 001D 0000 001C 0000 001B 0000 001A 0000 0019 END
Find a key in a tree which is known to contain at least one key splitting full nodes along the path to the key.
Locate the Intel Software Development Emulator
Return a copy of the specified string with all the non ascii characters removed
Parameter Description 1 $string String
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 Assemble - Assemble the generated code
5 Block - Execute a block of code one with the option of jumping out of the block or restarting the block via the supplied labels.
6 CallC - Call a C subroutine
7 ClassifyCharacters4 - Classify the utf32 characters in a block of memory of specified length using the classification held in zmm0: zmm0 should be formatted in double words with each word having the classification in the highest 8 bits and the utf32 character so classified in the lower 21 bits.
8 ClassifyInRange - Character classification: classify the utf32 characters in a block of memory of specified length using a range specification held in zmm0, zmm1 formatted in double words with each word in zmm1 having the classification in the highest 8 bits and with zmm0 and zmm1 having the utf32 character at the start (zmm0) and end (zmm1) of each range in the lower 21 bits.
9 ClassifyRange - Implementation of ClassifyInRange and ClassifyWithinRange
10 ClassifyWithInRange - Bracket classification: Classify the utf32 characters in a block of memory of specified length using a range specification held in zmm0, zmm1 formatted in double words with the classification range in the highest 8 bits of zmm0 and zmm1 and the utf32 character at the start (zmm0) and end (zmm1) of each range in the lower 21 bits.
11 ClassifyWithInRangeAndSaveOffset - Alphabetic classification: classify the utf32 characters in a block of memory of specified length using a range specification held in zmm0, zmm1 formatted in double words with the classification code in the high byte of zmm1 and the offset of the first element in the range in the high byte of zmm0.
12 ClearMemory - Clear memory - the address of the memory is in rax, the length in rdi
13 ClearRegisters - Clear registers by setting them to zero
14 ClearZF - Clear the zero flag
15 CloseFile - Close the file whose descriptor is in rax
16 Comment - Insert a comment into the assembly code
17 ConcatenateShortStrings - Concatenate the numbered source zmm containing a short string with the short string in the numbered target zmm.
18 ConvertUtf8ToUtf32 - Convert a string of utf8 to an allocated block of utf32 and return its address and length.
19 CopyMemory - Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
20 Cq - Define a quad constant
21 cr - Call a subroutine with a reordering of the registers.
22 CreateByteString - Create an relocatable string of bytes in an arena and returns its address in rax.
23 Cstrlen - Length of the C style string addressed by rax returning the length in r15
24 Db - Layout bytes in the data segment and return their label
25 Dbwdq - Layout data
26 DComment - Insert a comment into the data segment
27 Dd - Layout double words in the data segment and return their label
28 Dq - Layout quad words in the data segment and return their label
29 Ds - Layout bytes in memory and return their label
30 Dw - Layout words in the data segment and return their label
31 Else - Else body for an If statement
32 executeFileViaBash - Execute the file named in the byte string addressed by rax with bash
33 Exit - Exit with the specified return code or zero if no return code supplied.
34 Extern - Name external references
35 Float32 - 32 bit float
36 Float64 - 64 bit float
37 For - For - iterate the body as long as register is less than limit incrementing by increment each time
38 ForEver - Iterate for ever
39 ForIn - For - iterate the full body as long as register plus increment is less than than limit incrementing by increment each time then increment the last body for the last non full block.
40 Fork - Fork
41 FreeMemory - Free memory
42 getBFromXmm - Get the byte from the numbered xmm register and return it in a variable
43 getBFromZmm - Get the byte from the numbered zmm register and return it in a variable
44 getBwdqFromMm - Get the numbered byte|word|double word|quad word from the numbered zmm register and return it in a variable
45 getDFromXmm - Get the double word from the numbered xmm register and return it in a variable
46 getDFromZmm - Get the double word from the numbered zmm register and return it in a variable
47 GetLengthOfShortString - Get the length of the short string held in the numbered zmm register into the specified register
48 GetNextUtf8CharAsUtf32 - Get the next utf8 encoded character from the addressed memory and return it as a utf32 char
49 GetPid - Get process identifier
50 GetPidInHex - Get process identifier in hex as 8 zero terminated bytes in rax
51 GetPPid - Get parent process identifier
52 getQFromXmm - Get the quad word from the numbered xmm register and return it in a variable
53 getQFromZmm - Get the quad word from the numbered zmm register and return it in a variable
54 GetUid - Get userid of current process
55 getWFromXmm - Get the word from the numbered xmm register and return it in a variable
56 getWFromZmm - Get the word from the numbered zmm register and return it in a variable
57 Hash - Hash a string addressed by rax with length held in rdi and return the hash code in r15
58 hexTranslateTable - Create/address a hex translate table and return its label
59 If - If
60 IfEq - If equal execute the then body else the else body
61 IfGe - If greater than or equal execute the then body else the else body
62 IfGt - If greater than execute the then body else the else body
63 IfLe - If less than or equal execute the then body else the else body
64 IfLt - If less than execute the then body else the else body
65 IfNe - If not equal execute the then body else the else body
66 IfNz - If the zero is not set then execute the then body else the else body
67 IfZ - If the zero is set then execute the then body else the else body
68 Keep - Mark registers as in use so that they cannot be updated until we explicitly free them.
69 KeepFree - Free registers so that they can be reused
70 KeepPop - Reset the status of the specified registers to the status quo ante the last push
71 KeepPush - Push the current status of the specified registers and then mark them as free
72 KeepReturn - Pop the specified register and mark it as in use to effect a subroutine return with this register.
73 KeepSet - Confirm that the specified registers are in use
74 Label - Create a unique label
75 Link - Libraries to link with
76 LoadConstantIntoMaskRegister - Load a constant into a mask register
77 LoadShortStringFromMemoryToZmm - Load the short string addressed by rax into the zmm register with the specified number
78 LoadShortStringFromMemoryToZmm2 - Load the short string addressed by rax into the zmm register with the specified number
79 LocalData - Map local data
80 LocateIntelEmulator - Locate the Intel Software Development Emulator
81 Macro - Create a sub with optional parameters name=> the name of the subroutine so it can be reused rather than regenerated, comment=> a comment describing the sub
82 MaskMemory - Write the specified byte into locations in the target mask that correspond to the locations in the source that contain the specified byte.
83 MaskMemoryInRange4 - Write the specified byte into locations in the target mask that correspond to the locations in the source that contain 4 bytes in the specified range.
84 MatchBrackets - Replace the low three bytes of a utf32 bracket character with 24 bits of offset to the matching opening or closing bracket.
85 Nasm::X86::BlockArray::address - Address of a block string
86 Nasm::X86::BlockArray::allocBlock - Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable
87 Nasm::X86::BlockArray::dump - Dump a block array
88 Nasm::X86::BlockArray::get - Get an element from the array
89 Nasm::X86::BlockArray::pop - Pop an element from an array
90 Nasm::X86::BlockArray::push - Push an element onto the array
91 Nasm::X86::BlockArray::put - Put an element into an array as long as it is with in its limits established by pushing.
92 Nasm::X86::BlockMultiWayTree::address - Address of the byte string containing a block multi way tree
93 Nasm::X86::BlockMultiWayTree::allocBlock - Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable
94 Nasm::X86::BlockMultiWayTree::allocKeysDataNode - Allocate a keys/data/node block and place it in the numbered zmm registers
95 Nasm::X86::BlockMultiWayTree::by - Call the specified body with each (key, data) from the specified tree in order
96 Nasm::X86::BlockMultiWayTree::depth - Return the depth of a node within a tree.
97 Nasm::X86::BlockMultiWayTree::find - Find a key in a tree and return its associated data
98 Nasm::X86::BlockMultiWayTree::findAndSplit - Find a key in a tree which is known to contain at least one key splitting full nodes along the path to the key.
99 Nasm::X86::BlockMultiWayTree::getKeysData - Load the keys and data blocks for a node
100 Nasm::X86::BlockMultiWayTree::getKeysDataNode - Load the keys, data and child nodes for a node
101 Nasm::X86::BlockMultiWayTree::getLengthInKeys - Get the length of the keys block in the numbered zmm and return it as a variable
102 Nasm::X86::BlockMultiWayTree::getLoop - Return the value of the loop field as a variable
103 Nasm::X86::BlockMultiWayTree::getNode - Load the child nodes for a node
104 Nasm::X86::BlockMultiWayTree::getUpFromData - Get the up offset from the data block in the numbered zmm and return it as a variable
105 Nasm::X86::BlockMultiWayTree::insert - Insert a (key, data) pair into the tree
106 Nasm::X86::BlockMultiWayTree::iterator - Iterate through a multi way tree
107 Nasm::X86::BlockMultiWayTree::Iterator::next - Next element in the tree
108 Nasm::X86::BlockMultiWayTree::leftMost - Return the left most node
109 Nasm::X86::BlockMultiWayTree::leftOrRightMost - Return the left most or right most node
110 Nasm::X86::BlockMultiWayTree::nodeFromData - Load the the node block into the numbered zmm corresponding to the data block held in the numbered zmm.
111 Nasm::X86::BlockMultiWayTree::putKeysData - Save the key and data blocks for a node
112 Nasm::X86::BlockMultiWayTree::putKeysDataNode - Save the keys, data and child nodes for a node
113 Nasm::X86::BlockMultiWayTree::putLengthInKeys - Get the length of the block in the numbered zmm from the specified variable
114 Nasm::X86::BlockMultiWayTree::putLoop - Set the value of the loop field from a variable
115 Nasm::X86::BlockMultiWayTree::putUpIntoData - Put the offset of the parent keys block expressed as a variable into the numbered zmm
116 Nasm::X86::BlockMultiWayTree::reParent - Reparent the children of a node held in registers.
117 Nasm::X86::BlockMultiWayTree::rightMost - Return the right most node
118 Nasm::X86::BlockMultiWayTree::splitFullLeftNode - Split a full left node block held in 28.
119 Nasm::X86::BlockMultiWayTree::splitFullRightNode - Split a full right node block held in 25.
120 Nasm::X86::BlockMultiWayTree::splitFullRoot - Split a full root block held in 31.
121 Nasm::X86::BlockMultiWayTree::splitNode - Split a node given its offset in a byte string retaining the key being inserted in the node split while putting the remainder to the left or right.
122 Nasm::X86::BlockString::address - Address of a block string
123 Nasm::X86::BlockString::allocBlock - Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable
124 Nasm::X86::BlockString::append - Append the specified content in memory to the specified block string
125 Nasm::X86::BlockString::clear - Clear the block by freeing all but the first block
126 Nasm::X86::BlockString::concatenate - Concatenate two block strings by appending a copy of the source to the target block string.
127 Nasm::X86::BlockString::deleteChar - Delete a character in a block string
128 Nasm::X86::BlockString::dump - Dump a block string to sysout
129 Nasm::X86::BlockString::getBlock - Get the block with the specified offset in the specified block string and return it in the numbered zmm
130 Nasm::X86::BlockString::getBlockLength - Get the block length of the numbered zmm and return it in a variable
131 Nasm::X86::BlockString::getCharacter - Get a character from a block string
132 Nasm::X86::BlockString::getNextAndPrevBlockOffsetFromZmm - Get the offsets of the next and previous blocks as variables from the specified zmm
133 Nasm::X86::BlockString::insertChar - Insert a character into a block string
134 Nasm::X86::BlockString::len - Find the length of a block string
135 Nasm::X86::BlockString::putBlock - Write the numbered zmm to the block at the specified offset in the specified byte string
136 Nasm::X86::BlockString::putNextandPrevBlockOffsetIntoZmm - Save next and prev offsets into a zmm representing a block
137 Nasm::X86::BlockString::setBlockLengthInZmm - Set the block length of the numbered zmm to the specified length
138 Nasm::X86::ByteString::allocate - Allocate the amount of space indicated in rdi in the byte string addressed by rax and return the offset of the allocation in the arena in rdi
139 Nasm::X86::ByteString::allocBlock - Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable
140 Nasm::X86::ByteString::allocZmmBlock - Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable
141 Nasm::X86::ByteString::append - Append one byte string to another
142 Nasm::X86::ByteString::blockSize - Size of a block
143 Nasm::X86::ByteString::chain - Return a variable with the end point of a chain of double words in the byte string starting at the specified variable.
144 Nasm::X86::ByteString::char - Append a character expressed as a decimal number to the byte string addressed by rax
145 Nasm::X86::ByteString::clear - Clear the byte string addressed by rax
146 Nasm::X86::ByteString::CreateBlockArray - Create a block array in a byte string
147 Nasm::X86::ByteString::CreateBlockMultiWayTree - Create a block multi way tree in a byte string
148 Nasm::X86::ByteString::CreateBlockString - Create a string from a doubly link linked list of 64 byte blocks linked via 4 byte offsets in the byte string addressed by rax and return its descriptor
149 Nasm::X86::ByteString::dump - Dump details of a byte string
150 Nasm::X86::ByteString::firstFreeBlock - Create and load a variable with the first free block on the free block chain or zero if no such block in the given byte string
151 Nasm::X86::ByteString::freeBlock - Free a block in a byte string by placing it on the free chain
152 Nasm::X86::ByteString::getBlock - Get the block with the specified offset in the specified block string and return it in the numbered zmm
153 Nasm::X86::ByteString::length - Get the length of a byte string
154 Nasm::X86::ByteString::m - Append the content with length rdi addressed by rsi to the byte string addressed by rax
155 Nasm::X86::ByteString::makeReadOnly - Make a byte string read only
156 Nasm::X86::ByteString::makeWriteable - Make a byte string writable
157 Nasm::X86::ByteString::nl - Append a new line to the byte string addressed by rax
158 Nasm::X86::ByteString::out - Print the specified byte string addressed by rax on sysout
159 Nasm::X86::ByteString::putBlock - Write the numbered zmm to the block at the specified offset in the specified byte string
160 Nasm::X86::ByteString::putChain - Write the double word in the specified variable to the double word location at the the specified offset in the specified byte string.
161 Nasm::X86::ByteString::q - Append a constant string to the byte string
162 Nasm::X86::ByteString::ql - Append a quoted string containing new line characters to the byte string addressed by rax
163 Nasm::X86::ByteString::read - Read the named file (terminated with a zero byte) and place it into the named byte string.
164 Nasm::X86::ByteString::setFirstFreeBlock - Set the first free block field from a variable
165 Nasm::X86::ByteString::updateSpace - Make sure that the byte string addressed by rax has enough space to accommodate content of length rdi
166 Nasm::X86::ByteString::write - Write the content in a byte string addressed by rax to a temporary file and replace the byte string content with the name of the temporary file
167 Nasm::X86::ByteString::z - Append a trailing zero to the byte string addressed by rax
168 Nasm::X86::LocalData::allocate8 - Add some 8 byte local variables and return an array of variable definitions
169 Nasm::X86::LocalData::free - Free a local data area on the stack
170 Nasm::X86::LocalData::start - Start a local data area on the stack
171 Nasm::X86::LocalData::variable - Add a local variable
172 Nasm::X86::LocalVariable::stack - Address a local variable on the stack
173 Nasm::X86::Scope::contains - Check that the named parent scope contains the specified child scope.
174 Nasm::X86::Scope::currentlyVisible - Check that the named parent scope is currently visible
175 Nasm::X86::Structure::field - Add a field of the specified length with an optional comment
176 Nasm::X86::StructureField::addr - Address a field in a structure by either the default register or the named register
177 Nasm::X86::Sub::call - Call a sub passing it some parameters
178 Nasm::X86::Variable::add - Add the right hand variable to the left hand variable and return the result as a new variable
179 Nasm::X86::Variable::address - Get the address of a variable with an optional offset
180 Nasm::X86::Variable::allocateMemory - Allocate the specified amount of memory via mmap and return its address
181 Nasm::X86::Variable::and - And two variables
182 Nasm::X86::Variable::arithmetic - Return a variable containing the result of an arithmetic operation on the left hand and right hand side variables
183 Nasm::X86::Variable::assign - Assign to the left hand side the value of the right hand side
184 Nasm::X86::Variable::boolean - Combine the left hand variable with the right hand variable via a boolean operator
185 Nasm::X86::Variable::clearMaskBit - Clear a bit in the specified mask register retaining the other bits
186 Nasm::X86::Variable::clearMemory - Clear the memory described in this variable
187 Nasm::X86::Variable::clone - Clone a variable to create a new variable
188 Nasm::X86::Variable::copy - Copy one variable into another
189 Nasm::X86::Variable::copyAddress - Copy a reference to a variable
190 Nasm::X86::Variable::copyMemory - Copy from one block of memory to another
191 Nasm::X86::Variable::debug - Dump the value of a variable on stdout with an indication of where the dump came from
192 Nasm::X86::Variable::dec - Decrement a variable
193 Nasm::X86::Variable::divide - Divide the left hand variable by the right hand variable and return the result as a new variable
194 Nasm::X86::Variable::division - Return a variable containing the result or the remainder that occurs when the left hand side is divided by the right hand side
195 Nasm::X86::Variable::dump - Dump the value of a variable to the specified channel adding an optional title and new line if requested
196 Nasm::X86::Variable::eq - Check whether the left hand variable is equal to the right hand variable
197 Nasm::X86::Variable::equals - Equals operator
198 Nasm::X86::Variable::err - Dump the value of a variable on stderr
199 Nasm::X86::Variable::errNL - Dump the value of a variable on stderr and append a new line
200 Nasm::X86::Variable::for - Iterate the body limit times.
201 Nasm::X86::Variable::freeMemory - Free the memory addressed by this variable for the specified length
202 Nasm::X86::Variable::ge - Check whether the left hand variable is greater than or equal to the right hand variable
203 Nasm::X86::Variable::getBFromZmm - Get the byte from the numbered zmm register and put it in a variable
204 Nasm::X86::Variable::getConst - Load the variable from a constant in effect setting a variable to a specified value
205 Nasm::X86::Variable::getDFromZmm - Get the double word from the numbered zmm register and put it in a variable
206 Nasm::X86::Variable::getQFromZmm - Get the quad word from the numbered zmm register and put it in a variable
207 Nasm::X86::Variable::getReg - Load the variable from the named registers
208 Nasm::X86::Variable::getWFromZmm - Get the word from the numbered zmm register and put it in a variable
209 Nasm::X86::Variable::gt - Check whether the left hand variable is greater than the right hand variable
210 Nasm::X86::Variable::inc - Increment a variable
211 Nasm::X86::Variable::incDec - Increment or decrement a variable
212 Nasm::X86::Variable::isRef - Check whether the specified variable is a reference to another variable
213 Nasm::X86::Variable::le - Check whether the left hand variable is less than or equal to the right hand variable
214 Nasm::X86::Variable::loadZmm - Load bytes from the memory addressed by the specified source variable into the numbered zmm register.
215 Nasm::X86::Variable::lt - Check whether the left hand variable is less than the right hand variable
216 Nasm::X86::Variable::max - Maximum of two variables
217 Nasm::X86::Variable::min - Minimum of two variables
218 Nasm::X86::Variable::minusAssign - Implement minus and assign
219 Nasm::X86::Variable::mod - Divide the left hand variable by the right hand variable and return the remainder as a new variable
220 Nasm::X86::Variable::ne - Check whether the left hand variable is not equal to the right hand variable
221 Nasm::X86::Variable::or - Or two variables
222 Nasm::X86::Variable::out - Dump the value of a variable on stdout
223 Nasm::X86::Variable::outNL - Dump the value of a variable on stdout and append a new line
224 Nasm::X86::Variable::plusAssign - Implement plus and assign
225 Nasm::X86::Variable::pop - Pop a variable from the stack
226 Nasm::X86::Variable::printErrMemoryInHexNL - Write the memory addressed by a variable to stderr
227 Nasm::X86::Variable::printMemoryInHexNL - Write the memory addressed by a variable to stdout or stderr
228 Nasm::X86::Variable::printOutMemoryInHexNL - Write the memory addressed by a variable to stdout
229 Nasm::X86::Variable::push - Push a variable onto the stack
230 Nasm::X86::Variable::putBIntoXmm - Place the value of the content variable at the byte in the numbered xmm register
231 Nasm::X86::Variable::putBIntoZmm - Place the value of the content variable at the byte in the numbered zmm register
232 Nasm::X86::Variable::putBwdqIntoMm - Place the value of the content variable at the byte|word|double word|quad word in the numbered zmm register
233 Nasm::X86::Variable::putDIntoXmm - Place the value of the content variable at the double word in the numbered xmm register
234 Nasm::X86::Variable::putDIntoZmm - Place the value of the content variable at the double word in the numbered zmm register
235 Nasm::X86::Variable::putQIntoXmm - Place the value of the content variable at the quad word in the numbered xmm register
236 Nasm::X86::Variable::putQIntoZmm - Place the value of the content variable at the quad word in the numbered zmm register
237 Nasm::X86::Variable::putWIntoXmm - Place the value of the content variable at the word in the numbered xmm register
238 Nasm::X86::Variable::putWIntoZmm - Place the value of the content variable at the word in the numbered zmm register
239 Nasm::X86::Variable::saveZmm2222 - Save bytes into the memory addressed by the target variable from the numbered zmm register.
240 Nasm::X86::Variable::setMask - Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere
241 Nasm::X86::Variable::setMaskBit - Set a bit in the specified mask register retaining the other bits
242 Nasm::X86::Variable::setMaskFirst - Set the first bits in the specified mask register
243 Nasm::X86::Variable::setReg - Set the named registers from the content of the variable
244 Nasm::X86::Variable::setZmm - Load bytes from the memory addressed by specified source variable into the numbered zmm register at the offset in the specified offset moving the number of bytes in the specified variable
245 Nasm::X86::Variable::str - The name of the variable
246 Nasm::X86::Variable::sub - Subtract the right hand variable from the left hand variable and return the result as a new variable
247 Nasm::X86::Variable::times - Multiply the left hand variable by the right hand variable and return the result as a new variable
248 Nasm::X86::Variable::zBroadCastD - Broadcast a double word in a variable into the numbered zmm.
249 OpenRead - Open a file, whose name is addressed by rax, for read and return the file descriptor in rax
250 OpenWrite - Create the file named by the terminated string addressed by rax for write
251 PeekR - Peek at register on stack
252 PopEax - We cannot pop a double word from the stack in 64 bit long mode using pop so we improvise
253 PopR - Pop registers from the stack
254 PopRR - Pop registers from the stack without tracking
255 PrintErrMemory - Print the memory addressed by rax for a length of rdi on stderr
256 PrintErrMemoryInHex - Dump memory from the address in rax for the length in rdi on stderr
257 PrintErrMemoryInHexNL - Dump memory from the address in rax for the length in rdi and then print a new line
258 PrintErrMemoryNL - Print the memory addressed by rax for a length of rdi followed by a new line on stderr
259 PrintErrNL - Print a new line to stderr
260 PrintErrRaxInHex - Write the content of register rax in hexadecimal in big endian notation to stderr
261 PrintErrRegisterInHex - Print the named registers as hex strings on stderr
262 PrintErrString - Print a constant string to stderr.
263 PrintErrStringNL - Print a constant string followed by a new line to stderr
264 PrintErrZF - Print the zero flag without disturbing it on stderr
265 PrintMemory - Print the memory addressed by rax for a length of rdi on the specified channel
266 PrintMemoryInHex - Dump memory from the address in rax for the length in rdi on the specified channel.
267 PrintNL - Print a new line to stdout or stderr
268 PrintOutMemory - Print the memory addressed by rax for a length of rdi on stdout
269 PrintOutMemoryInHex - Dump memory from the address in rax for the length in rdi on stdout
270 PrintOutMemoryInHexNL - Dump memory from the address in rax for the length in rdi and then print a new line
271 PrintOutMemoryNL - Print the memory addressed by rax for a length of rdi followed by a new line on stdout
272 PrintOutNL - Print a new line to stderr
273 PrintOutRaxInHex - Write the content of register rax in hexadecimal in big endian notation to stderr
274 PrintOutRaxInReverseInHex - Write the content of register rax to stderr in hexadecimal in little endian notation
275 PrintOutRegisterInHex - Print the named registers as hex strings on stdout
276 PrintOutRegistersInHex - Print the general purpose registers in hex
277 PrintOutRflagsInHex - Print the flags register in hex
278 PrintOutRipInHex - Print the instruction pointer in hex
279 PrintOutString - Print a constant string to stdout.
280 PrintOutStringNL - Print a constant string followed by a new line to stdout
281 PrintOutZF - Print the zero flag without disturbing it on stdout
282 PrintRaxInHex - Write the content of register rax in hexadecimal in big endian notation to the specified channel
283 PrintRegisterInHex - Print the named registers as hex strings
284 PrintString - Print a constant string to the specified channel
285 PrintUtf32 - Print the specified number of utf32 characters at the specified address
286 PushR - Push registers onto the stack
287 PushRR - Push registers onto the stack without tracking
288 Rb - Layout bytes in the data segment and return their label
289 Rbwdq - Layout data
290 RComment - Insert a comment into the read only data segment
291 Rd - Layout double words in the data segment and return their label
292 ReadFile - Read a file whose name is addressed by rax into memory.
293 ReadTimeStampCounter - Read the time stamp counter and return the time in nanoseconds in rax
294 RegisterSize - Return the size of a register
295 removeNonAsciiChars - Return a copy of the specified string with all the non ascii characters removed
296 ReorderSyscallRegisters - Map the list of registers provided to the 64 bit system call sequence
297 RestoreFirstFour - Restore the first 4 parameter registers
298 RestoreFirstFourExceptRax - Restore the first 4 parameter registers except rax so it can return its value
299 RestoreFirstFourExceptRaxAndRdi - Restore the first 4 parameter registers except rax and rdi so we can return a pair of values
300 RestoreFirstSeven - Restore the first 7 parameter registers
301 RestoreFirstSevenExceptRax - Restore the first 7 parameter registers except rax which is being used to return the result
302 RestoreFirstSevenExceptRaxAndRdi - Restore the first 7 parameter registers except rax and rdi which are being used to return the results
303 Rq - Layout quad words in the data segment and return their label
304 Rs - Layout bytes in read only memory and return their label
305 Rutf8 - Layout a utf8 encoded string as bytes in read only memory and return their label
306 Rw - Layout words in the data segment and return their label
307 SaveFirstFour - Save the first 4 parameter registers making any parameter registers read only
308 SaveFirstSeven - Save the first 7 parameter registers
309 Scope - Create and stack a new scope and continue with it as the current scope
310 ScopeEnd - End the current scope and continue with the containing parent scope
311 SetLabel - Set a label in the code section
312 SetLengthOfShortString - Set the length of the short string held in the numbered zmm register into the specified register
313 SetMaskRegister - Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere
314 SetZF - Set the zero flag
315 Start - Initialize the assembler
316 StatSize - Stat a file whose name is addressed by rax to get its size in rax
317 StringLength - Length of a zero terminated string
318 Structure - Create a structure addressed by a register
319 Subroutine - Create a subroutine that can be called in assembler code
320 Then - Then body for an If statement
321 totalBytesAssembled - Total size in bytes of all files assembled during testing
322 Trace - Add tracing code
323 unlinkFile - Unlink the named file
324 UnReorderSyscallRegisters - Recover the initial values in registers that were reordered
325 Variable - Create a new variable with the specified size and name initialized via an expression
326 Vb - Define a byte variable
327 Vd - Define a double word variable
328 Vq - Define a quad variable
329 Vr - Define a reference variable
330 Vw - Define a word variable
331 Vx - Define an xmm variable
332 VxyzInit - Initialize an xyz register from general purpose registers
333 Vy - Define an ymm variable
334 Vz - Define an zmm variable
335 WaitPid - Wait for the pid in rax to complete
336 xmm - Add xmm to the front of a list of register expressions
337 ymm - Add ymm to the front of a list of register expressions
338 zmm - Add zmm to the front of a list of register expressions
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.