Looking for help!
Name
Nasm::X86 - Generate X86 assembler code using Perl as a macro pre-processor.
Synopsis
Write and execute x64 instructions using perl as a macro assembler as shown in the following examples.
Avx512 instructions
Use avx512 instructions to do 64 comparisons in parallel:
my $P = "2F"; # Value to test for
my $l = Rb 0; Rb $_ for 1..RegisterSize zmm0; # 0..63
Vmovdqu8 zmm0, "[$l]"; # Load data to test
PrintOutRegisterInHex zmm0;
Mov rax, "0x$P"; # Broadcast the value to be tested
Vpbroadcastb zmm1, rax;
PrintOutRegisterInHex zmm1;
for my $c(0..7) # Each possible test
{my $m = "k$c";
Vpcmpub $m, zmm1, zmm0, $c;
PrintOutRegisterInHex $m;
}
Kmovq rax, k0; # Count the number of trailing zeros in k0
Tzcnt rax, rax;
PrintOutRegisterInHex rax;
is_deeply Assemble, <<END; # Assemble and test
zmm0: 3F3E 3D3C 3B3A 3938 3736 3534 3332 3130 2F2E 2D2C 2B2A 2928 2726 2524 2322 2120 1F1E 1D1C 1B1A 1918 1716 1514 1312 1110 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100
zmm1: 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F 2F2F
k0: 0000 8000 0000 0000
k1: FFFF 0000 0000 0000
k2: FFFF 8000 0000 0000
k3: 0000 0000 0000 0000
k4: FFFF 7FFF FFFF FFFF
k5: 0000 FFFF FFFF FFFF
k6: 0000 7FFF FFFF FFFF
k7: FFFF FFFF FFFF FFFF
rax: 0000 0000 0000 00$P
END
Dynamic string held in an arena
Create a dynamic byte string, add some content to it, write the byte string to stdout:
my $a = CreateByteString; # Create a string
my $b = CreateByteString; # Create a string
$a->q('aa');
$b->q('bb');
$a->q('AA');
$b->q('BB');
$a->q('aa');
$b->q('bb');
$a->out;
$b->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aaAAaabbBBbb
END
Process management
Start a child process and wait for it, printing out the process identifiers of each process involved:
Fork; # Fork
Test rax,rax;
If # Parent
{Mov rbx, rax;
WaitPid;
PrintOutRegisterInHex rax;
PrintOutRegisterInHex rbx;
GetPid; # Pid of parent as seen in parent
Mov rcx,rax;
PrintOutRegisterInHex rcx;
}
sub # Child
{Mov r8,rax;
PrintOutRegisterInHex r8;
GetPid; # Child pid as seen in child
Mov r9,rax;
PrintOutRegisterInHex r9;
GetPPid; # Parent pid as seen in child
Mov r10,rax;
PrintOutRegisterInHex r10;
};
my $r = Assemble;
# r8: 0000 0000 0000 0000 #1 Return from fork as seen by child
# r9: 0000 0000 0003 0C63 #2 Pid of child
# r10: 0000 0000 0003 0C60 #3 Pid of parent from child
# rax: 0000 0000 0003 0C63 #4 Return from fork as seen by parent
# rbx: 0000 0000 0003 0C63 #5 Wait for child pid result
# rcx: 0000 0000 0003 0C60 #6 Pid of parent
Read a file
Read this file:
Mov rax, Rs($0); # File to read
ReadFile; # Read file
PrintOutMemory; # Print memory
my $r = Assemble; # Assemble and execute
ok index($r, readFile($0)) > -1; # Output contains this file
Installation
The Intel Software Development Emulator will be required if you do not have a computer with the avx512 instruction set and wish to execute code containing these instructions. For details see:
The Networkwide Assembler is required to assemble the code produced For full details see:
https://github.com/philiprbrenan/NasmX86/blob/main/.github/workflows/main.yml
Execution Options
The Assemble(%options) function takes the following keywords to control assembly and execution of the assembled code:
To produce a named executable without running it, specify:
keep=>"executable file name"
To run the executable produced by Assemble(%options) without the Intel emulator, which is used by default if it is present, specify:
emulator=>0
Description
Generate X86 assembler code using Perl as a macro pre-processor.
Version "20210519".
The following sections describe the methods in each functional area of this module. For an alphabetic listing of all methods by name see Index.
Data
Layout data
SetLabel($l)
Set a label in the code section
Parameter Description
1 $l Label
Example:
Mov rax, 1;
Mov rdi, 1;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSeven;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFour;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRax;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRax;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
Bswap rax;
PrintOutRegisterInHex rax;
my $l = Label;
Jmp $l;
SetLabel $l; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0002
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0001
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0300 0000 0000 0000
END
ok 8 == RegisterSize rax;
Ds(@d)
Layout bytes in memory and return their label
Parameter Description
1 @d Data to be laid out
Example:
my $q = Rs('a'..'z');
Mov rax, Ds('0'x64); # Output area # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Vmovdqu32(xmm0, "[$q]"); # Load
Vprolq (xmm0, xmm0, 32); # Rotate double words in quad words
Vmovdqu32("[rax]", xmm0); # Save
Mov rdi, 16;
PrintOutMemory;
ok Assemble =~ m(efghabcdmnopijkl)s;
Rs(@d)
Layout bytes in read only memory and return their label
Parameter Description
1 @d Data to be laid out
Example:
Comment "Print a string from memory";
my $s = "Hello World";
Mov rax, Rs($s); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov rdi, length $s;
PrintOutMemory;
ok Assemble =~ m(Hello World);
my $q = Rs('abababab'); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov(rax, 1);
Mov(rbx, 2);
Mov(rcx, 3);
Mov(rdx, 4);
Mov(r8, 5);
Lea r9, "[rax+rbx]";
PrintOutRegistersInHex;
my $r = Assemble;
ok $r =~ m( r8: 0000 0000 0000 0005.* r9: 0000 0000 0000 0003.*rax: 0000 0000 0000 0001)s;
ok $r =~ m(rbx: 0000 0000 0000 0002.*rcx: 0000 0000 0000 0003.*rdx: 0000 0000 0000 0004)s;
Db(@bytes)
Layout bytes in the data segment and return their label
Parameter Description
1 @bytes Bytes to layout
Example:
my $s = Rb 0; Rb 1; Rw 2; Rd 3; Rq 4;
my $t = Db 0; Db 1; Dw 2; Dd 3; Dq 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Vmovdqu8 xmm0, "[$s]";
Vmovdqu8 xmm1, "[$t]";
PrintOutRegisterInHex xmm0;
PrintOutRegisterInHex xmm1;
Sub rsp, 16;
Mov rax, rsp; # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
Mov rdi, 16;
Mov rsi, $s;
CopyMemory->call(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
PrintOutMemoryInHex;
my $r = Assemble;
ok $r =~ m(xmm0: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(xmm1: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
Dw(@words)
Layout words in the data segment and return their label
Parameter Description
1 @words Words to layout
Example:
my $s = Rb 0; Rb 1; Rw 2; Rd 3; Rq 4;
my $t = Db 0; Db 1; Dw 2; Dd 3; Dq 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Vmovdqu8 xmm0, "[$s]";
Vmovdqu8 xmm1, "[$t]";
PrintOutRegisterInHex xmm0;
PrintOutRegisterInHex xmm1;
Sub rsp, 16;
Mov rax, rsp; # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
Mov rdi, 16;
Mov rsi, $s;
CopyMemory->call(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
PrintOutMemoryInHex;
my $r = Assemble;
ok $r =~ m(xmm0: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(xmm1: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
Dd(@dwords)
Layout double words in the data segment and return their label
Parameter Description
1 @dwords Double words to layout
Example:
my $s = Rb 0; Rb 1; Rw 2; Rd 3; Rq 4;
my $t = Db 0; Db 1; Dw 2; Dd 3; Dq 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Vmovdqu8 xmm0, "[$s]";
Vmovdqu8 xmm1, "[$t]";
PrintOutRegisterInHex xmm0;
PrintOutRegisterInHex xmm1;
Sub rsp, 16;
Mov rax, rsp; # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
Mov rdi, 16;
Mov rsi, $s;
CopyMemory->call(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
PrintOutMemoryInHex;
my $r = Assemble;
ok $r =~ m(xmm0: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(xmm1: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
Dq(@qwords)
Layout quad words in the data segment and return their label
Parameter Description
1 @qwords Quad words to layout
Example:
my $s = Rb 0; Rb 1; Rw 2; Rd 3; Rq 4;
my $t = Db 0; Db 1; Dw 2; Dd 3; Dq 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Vmovdqu8 xmm0, "[$s]";
Vmovdqu8 xmm1, "[$t]";
PrintOutRegisterInHex xmm0;
PrintOutRegisterInHex xmm1;
Sub rsp, 16;
Mov rax, rsp; # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
Mov rdi, 16;
Mov rsi, $s;
CopyMemory->call(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
PrintOutMemoryInHex;
my $r = Assemble;
ok $r =~ m(xmm0: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(xmm1: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
Rb(@bytes)
Layout bytes in the data segment and return their label
Parameter Description
1 @bytes Bytes to layout
Example:
my $s = Rb 0; Rb 1; Rw 2; Rd 3; Rq 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $t = Db 0; Db 1; Dw 2; Dd 3; Dq 4;
Vmovdqu8 xmm0, "[$s]";
Vmovdqu8 xmm1, "[$t]";
PrintOutRegisterInHex xmm0;
PrintOutRegisterInHex xmm1;
Sub rsp, 16;
Mov rax, rsp; # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
Mov rdi, 16;
Mov rsi, $s;
CopyMemory->call(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
PrintOutMemoryInHex;
my $r = Assemble;
ok $r =~ m(xmm0: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(xmm1: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
Rw(@words)
Layout words in the data segment and return their label
Parameter Description
1 @words Words to layout
Example:
my $s = Rb 0; Rb 1; Rw 2; Rd 3; Rq 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $t = Db 0; Db 1; Dw 2; Dd 3; Dq 4;
Vmovdqu8 xmm0, "[$s]";
Vmovdqu8 xmm1, "[$t]";
PrintOutRegisterInHex xmm0;
PrintOutRegisterInHex xmm1;
Sub rsp, 16;
Mov rax, rsp; # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
Mov rdi, 16;
Mov rsi, $s;
CopyMemory->call(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
PrintOutMemoryInHex;
my $r = Assemble;
ok $r =~ m(xmm0: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(xmm1: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
Rd(@dwords)
Layout double words in the data segment and return their label
Parameter Description
1 @dwords Double words to layout
Example:
my $s = Rb 0; Rb 1; Rw 2; Rd 3; Rq 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $t = Db 0; Db 1; Dw 2; Dd 3; Dq 4;
Vmovdqu8 xmm0, "[$s]";
Vmovdqu8 xmm1, "[$t]";
PrintOutRegisterInHex xmm0;
PrintOutRegisterInHex xmm1;
Sub rsp, 16;
Mov rax, rsp; # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
Mov rdi, 16;
Mov rsi, $s;
CopyMemory->call(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
PrintOutMemoryInHex;
my $r = Assemble;
ok $r =~ m(xmm0: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(xmm1: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
Rq(@qwords)
Layout quad words in the data segment and return their label
Parameter Description
1 @qwords Quad words to layout
Example:
my $s = Rb 0; Rb 1; Rw 2; Rd 3; Rq 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $t = Db 0; Db 1; Dw 2; Dd 3; Dq 4;
Vmovdqu8 xmm0, "[$s]";
Vmovdqu8 xmm1, "[$t]";
PrintOutRegisterInHex xmm0;
PrintOutRegisterInHex xmm1;
Sub rsp, 16;
Mov rax, rsp; # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
Mov rdi, 16;
Mov rsi, $s;
CopyMemory->call(Vq(source, rsi), Vq(target, rax), Vq(size, rdi));
PrintOutMemoryInHex;
my $r = Assemble;
ok $r =~ m(xmm0: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(xmm1: 0000 0000 0000 0004 0000 0003 0002 0100);
ok $r =~ m(0001 0200 0300 00000400 0000 0000 0000);
Float32($float)
32 bit float
Parameter Description
1 $float Float
Float64($float)
64 bit float
Parameter Description
1 $float Float
Registers
Operations on registers
Save and Restore
Saving and restoring registers via the stack
SaveFirstFour(@keep)
Save the first 4 parameter registers making any parameter registers read only
Parameter Description
1 @keep Registers to mark as read only
Example:
Mov rax, 1;
Mov rdi, 1;
SaveFirstFour; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSeven;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFour;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRax;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRax;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
Bswap rax;
PrintOutRegisterInHex rax;
my $l = Label;
Jmp $l;
SetLabel $l;
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0002
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0001
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0300 0000 0000 0000
END
ok 8 == RegisterSize rax;
RestoreFirstFour()
Restore the first 4 parameter registers
Example:
Mov rax, 1;
Mov rdi, 1;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSeven;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFour; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRax;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRax;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
Bswap rax;
PrintOutRegisterInHex rax;
my $l = Label;
Jmp $l;
SetLabel $l;
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0002
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0001
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0300 0000 0000 0000
END
ok 8 == RegisterSize rax;
RestoreFirstFourExceptRax()
Restore the first 4 parameter registers except rax so it can return its value
Example:
Mov rax, 1;
Mov rdi, 1;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSeven;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFour;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRax;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRax; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
Bswap rax;
PrintOutRegisterInHex rax;
my $l = Label;
Jmp $l;
SetLabel $l;
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0002
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0001
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0300 0000 0000 0000
END
ok 8 == RegisterSize rax;
RestoreFirstFourExceptRaxAndRdi()
Restore the first 4 parameter registers except rax and rdi so we can return a pair of values
Example:
Mov rax, 1;
Mov rdi, 1;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSeven;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFour;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRax;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRax;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRaxAndRdi; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax, rdi;
Bswap rax;
PrintOutRegisterInHex rax;
my $l = Label;
Jmp $l;
SetLabel $l;
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0002
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0001
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0300 0000 0000 0000
END
ok 8 == RegisterSize rax;
SaveFirstSeven()
Save the first 7 parameter registers
Example:
Mov rax, 1;
Mov rdi, 1;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSeven;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFour;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRax;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRax;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
Bswap rax;
PrintOutRegisterInHex rax;
my $l = Label;
Jmp $l;
SetLabel $l;
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0002
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0001
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0300 0000 0000 0000
END
ok 8 == RegisterSize rax;
RestoreFirstSeven()
Restore the first 7 parameter registers
Example:
Mov rax, 1;
Mov rdi, 1;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSeven; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax, rdi;
RestoreFirstFour;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRax;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRax;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
Bswap rax;
PrintOutRegisterInHex rax;
my $l = Label;
Jmp $l;
SetLabel $l;
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0002
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0001
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0300 0000 0000 0000
END
ok 8 == RegisterSize rax;
RestoreFirstSevenExceptRax()
Restore the first 7 parameter registers except rax which is being used to return the result
Example:
Mov rax, 1;
Mov rdi, 1;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSeven;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFour;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRax; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRax;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
Bswap rax;
PrintOutRegisterInHex rax;
my $l = Label;
Jmp $l;
SetLabel $l;
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0002
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0001
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0300 0000 0000 0000
END
ok 8 == RegisterSize rax;
RestoreFirstSevenExceptRaxAndRdi()
Restore the first 7 parameter registers except rax and rdi which are being used to return the results
Example:
Mov rax, 1;
Mov rdi, 1;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSeven;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFour;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRax;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRax;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRaxAndRdi; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
Bswap rax;
PrintOutRegisterInHex rax;
my $l = Label;
Jmp $l;
SetLabel $l;
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0002
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0001
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0300 0000 0000 0000
END
ok 8 == RegisterSize rax;
ReorderSyscallRegisters(@registers)
Map the list of registers provided to the 64 bit system call sequence
Parameter Description
1 @registers Registers
Example:
Mov rax, 1; Mov rdi, 2; Mov rsi, 3; Mov rdx, 4;
Mov r8, 8; Mov r9, 9; Mov r10, 10; Mov r11, 11;
ReorderSyscallRegisters r8,r9; # Reorder the registers for syscall # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
PrintOutRegisterInHex rdi;
UnReorderSyscallRegisters r8,r9; # Unreorder the registers to recover their original values
PrintOutRegisterInHex rax;
PrintOutRegisterInHex rdi;
ok Assemble =~ m(rax:.*08.*rdi:.*9.*rax:.*1.*rdi:.*2.*)s;
UnReorderSyscallRegisters(@registers)
Recover the initial values in registers that were reordered
Parameter Description
1 @registers Registers
Example:
Mov rax, 1; Mov rdi, 2; Mov rsi, 3; Mov rdx, 4;
Mov r8, 8; Mov r9, 9; Mov r10, 10; Mov r11, 11;
ReorderSyscallRegisters r8,r9; # Reorder the registers for syscall
PrintOutRegisterInHex rax;
PrintOutRegisterInHex rdi;
UnReorderSyscallRegisters r8,r9; # Unreorder the registers to recover their original values # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
PrintOutRegisterInHex rdi;
ok Assemble =~ m(rax:.*08.*rdi:.*9.*rax:.*1.*rdi:.*2.*)s;
ReorderXmmRegisters(@registers) = map {"xmm$_"} @_;)
Map the list of xmm registers provided to 0-31
Parameter Description
1 @registers) = map {"xmm$_"} @_; Registers
Example:
my $t = GenTree(2,2); # Tree description
$t->node->(); # Root
Movdqa xmm1, xmm0; # Root is in xmm1
if (1) # New left node
{$t->node->(); # Node in xmm0
Movdqa xmm2, xmm0; # Left is in xmm2
cxr {$t->insertLeft->()} 1,2; # Insert left under root
cxr {$t->dump->("Left")} 2; # Left node after insertion
}
if (1) # New right node in xmm0
{$t->node->();
Movdqa xmm3, xmm0; # Right is in xmm3
cxr {$t->insertRight->()} 1,3; # Insert left under root
cxr {$t->dump->("Right")} 3; # Right node after insertion
}
cxr
{$t->dump->("Root"); # Root node after insertions
$t->isRoot->();
IfNz {PrintOutStringNL "root"} sub {PrintOutStringNL "NOT root"};
} 1;
PushRR xmm0; # Dump underlying byte string
PopRR rdi, rax;
$t->byteString->dump;
Exit; # Return to operating system
is_deeply Assemble, <<END; # Test tree so produced
Left
ArenaTreeNode at: 0000 0000 0000 00B0
up: 0000 0000 0000 0010
left: 0000 0000 0000 0000
right: 0000 0000 0000 0000
Right
ArenaTreeNode at: 0000 0000 0000 0150
up: 0000 0000 0000 0010
left: 0000 0000 0000 0000
right: 0000 0000 0000 0000
Root
ArenaTreeNode at: 0000 0000 0000 0010
up: 0000 0000 0000 0000
left: 0000 0000 0000 00B0
right: 0000 0000 0000 0150
root
Byte String
Size: 0000 0000 0000 1000
Used: 0000 0000 0000 01E0
END
UnReorderXmmRegisters(@registers)
Recover the initial values in the xmm registers that were reordered
Parameter Description
1 @registers Registers
Example:
my $t = GenTree(2,2); # Tree description
$t->node->(); # Root
Movdqa xmm1, xmm0; # Root is in xmm1
if (1) # New left node
{$t->node->(); # Node in xmm0
Movdqa xmm2, xmm0; # Left is in xmm2
cxr {$t->insertLeft->()} 1,2; # Insert left under root
cxr {$t->dump->("Left")} 2; # Left node after insertion
}
if (1) # New right node in xmm0
{$t->node->();
Movdqa xmm3, xmm0; # Right is in xmm3
cxr {$t->insertRight->()} 1,3; # Insert left under root
cxr {$t->dump->("Right")} 3; # Right node after insertion
}
cxr
{$t->dump->("Root"); # Root node after insertions
$t->isRoot->();
IfNz {PrintOutStringNL "root"} sub {PrintOutStringNL "NOT root"};
} 1;
PushRR xmm0; # Dump underlying byte string
PopRR rdi, rax;
$t->byteString->dump;
Exit; # Return to operating system
is_deeply Assemble, <<END; # Test tree so produced
Left
ArenaTreeNode at: 0000 0000 0000 00B0
up: 0000 0000 0000 0010
left: 0000 0000 0000 0000
right: 0000 0000 0000 0000
Right
ArenaTreeNode at: 0000 0000 0000 0150
up: 0000 0000 0000 0010
left: 0000 0000 0000 0000
right: 0000 0000 0000 0000
Root
ArenaTreeNode at: 0000 0000 0000 0010
up: 0000 0000 0000 0000
left: 0000 0000 0000 00B0
right: 0000 0000 0000 0150
root
Byte String
Size: 0000 0000 0000 1000
Used: 0000 0000 0000 01E0
END
RegisterSize($r)
Return the size of a register
Parameter Description
1 $r Register
Example:
Mov rax, 1;
Mov rdi, 1;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSeven;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFour;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRax;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRax;
PrintOutRegisterInHex rax, rdi;
SaveFirstFour;
Mov rax, 2;
Mov rdi, 2;
SaveFirstSeven;
Mov rax, 3;
Mov rdi, 4;
PrintOutRegisterInHex rax, rdi;
RestoreFirstSevenExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
RestoreFirstFourExceptRaxAndRdi;
PrintOutRegisterInHex rax, rdi;
Bswap rax;
PrintOutRegisterInHex rax;
my $l = Label;
Jmp $l;
SetLabel $l;
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0002
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0001
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0002
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0001
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0000 0000 0000 0003
rdi: 0000 0000 0000 0004
rax: 0300 0000 0000 0000
END
ok 8 == RegisterSize rax; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ClearRegisters(@registers)
Clear registers by setting them to zero
Parameter Description
1 @registers Registers
Example:
Mov rax,1;
Kmovq k0, rax;
Kaddb k0, k0, k0;
Kaddb k0, k0, k0;
Kaddb k0, k0, k0;
Kmovq rax, k0;
PushR k0;
ClearRegisters k0; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Kmovq k1, k0;
PopR k0;
PrintOutRegisterInHex k0;
PrintOutRegisterInHex k1;
ok Assemble =~ m(k0: 0000 0000 0000 0008.*k1: 0000 0000 0000 0000)s;
SetRegisterToMinusOne($register)
Set the specified register to -1
Parameter Description
1 $register Register to set
Example:
SetRegisterToMinusOne rax; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
ok Assemble =~ m(rax: FFFF FFFF FFFF FFFF);
SetMaskRegister($mask, $start, $length)
Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere
Parameter Description
1 $mask Mask register to set
2 $start Register containing start position or 0 for position 0
3 $length Register containing end position
Example:
Mov rax, 8;
Mov rsi, -1;
Inc rsi; SetMaskRegister(k0, rax, rsi); PrintOutRegisterInHex k0; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Inc rsi; SetMaskRegister(k1, rax, rsi); PrintOutRegisterInHex k1; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Inc rsi; SetMaskRegister(k2, rax, rsi); PrintOutRegisterInHex k2; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Inc rsi; SetMaskRegister(k3, rax, rsi); PrintOutRegisterInHex k3; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Inc rsi; SetMaskRegister(k4, rax, rsi); PrintOutRegisterInHex k4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Inc rsi; SetMaskRegister(k5, rax, rsi); PrintOutRegisterInHex k5; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Inc rsi; SetMaskRegister(k6, rax, rsi); PrintOutRegisterInHex k6; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Inc rsi; SetMaskRegister(k7, rax, rsi); PrintOutRegisterInHex k7; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply Assemble, <<END;
k0: 0000 0000 0000 0000
k1: 0000 0000 0000 0100
k2: 0000 0000 0000 0300
k3: 0000 0000 0000 0700
k4: 0000 0000 0000 0F00
k5: 0000 0000 0000 1F00
k6: 0000 0000 0000 3F00
k7: 0000 0000 0000 7F00
END
SetZF()
Set the zero flag
Example:
SetZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutZF;
ClearZF;
PrintOutZF;
SetZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutZF;
SetZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutZF;
ClearZF;
PrintOutZF;
ok Assemble =~ m(ZF=1.*ZF=0.*ZF=1.*ZF=1.*ZF=0)s;
ClearZF()
Clear the zero flag
Example:
SetZF;
PrintOutZF;
ClearZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutZF;
SetZF;
PrintOutZF;
SetZF;
PrintOutZF;
ClearZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutZF;
ok Assemble =~ m(ZF=1.*ZF=0.*ZF=1.*ZF=1.*ZF=0)s;
Tracking
Track the use of registers so that we do not accidently use unset registers or write into registers that are already in use.
Keep(@target)
Mark free registers so that they are not updated until we Free them or complain if the register is already in use.
Parameter Description
1 @target Registers to keep
KeepSet($target)
Confirm that the specified registers are in use
Parameter Description
1 $target Registers to keep
KeepPush(@target)
Push the current status of the specified registers and then mark them as free
Parameter Description
1 @target Registers to keep
KeepPop(@target)
Reset the status of the specified registers to the status quo ante the last push
Parameter Description
1 @target Registers to keep
KeepReturn(@target)
Pop the specified register and mark it as in use to effect a subroutine return with this register.
Parameter Description
1 @target Registers to return
KeepFree(@target)
Free registers so that they can be reused
Parameter Description
1 @target Registers to free
Arithmetic
Arithmetic operations on registers
Copy($target, $source)
Copy the source to the target register
Parameter Description
1 $target Target register
2 $source Source expression
Example:
my $s = Rb(13, 1..13);
my $t = Rb(1..64);
my $source = rax; # Address to load from
my $start = rsi; # Start position in the zmm register
my $length = rdi; # Length of copy
Copy $source, $s; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
LoadShortStringFromMemoryToZmm 0, $s; # Load a sample string
KeepFree $source;
PrintOutRegisterInHex xmm0;
LoadZmmFromMemory 0, Increment(GetLengthOfShortString($start, 0)), Copy($length, 1), Copy($source, $t); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex xmm0;
LoadZmmFromMemory 0, $start, $length, $source;
PrintOutRegisterInHex xmm0;
KeepFree $length;
LoadZmmFromMemory 0, $start, Minus($length, Copy(r13, 56), $start), $source; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
SetLengthOfShortString 0, sil; # Set current length of zmm0
PrintOutRegisterInHex xmm0, zmm0;
is_deeply Assemble, <<END;
xmm0: 0000 0D0C 0B0A 0908 0706 0504 0302 010D
xmm0: 0001 0D0C 0B0A 0908 0706 0504 0302 010D
xmm0: 0201 0D0C 0B0A 0908 0706 0504 0302 010D
xmm0: 0201 0D0C 0B0A 0908 0706 0504 0302 0138
zmm0: 0000 0000 0000 0000 2A29 2827 2625 2423 2221 201F 1E1D 1C1B 1A19 1817 1615 1413 1211 100F 0E0D 0C0B 0A09 0807 0605 0403 0201 0D0C 0B0A 0908 0706 0504 0302 0138
END
MaximumOfTwoRegisters($result, $first, $second)
Return in the specified register the value in the second register if it is greater than the value in the first register
Parameter Description
1 $result Result register
2 $first First register
3 $second Second register
Example:
Mov rax, 1;
Mov rdi, 2;
PrintOutRegisterInHex MaximumOfTwoRegisters r15, rax, rdi; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex MinimumOfTwoRegisters r14, rax, rdi;
is_deeply Assemble, <<END;
r15: 0000 0000 0000 0002
r14: 0000 0000 0000 0001
END
MinimumOfTwoRegisters($result, $first, $second)
Return in the specified register the value in the second register if it is less than the value in the first register
Parameter Description
1 $result Result register
2 $first First register
3 $second Second register
Example:
Mov rax, 1;
Mov rdi, 2;
PrintOutRegisterInHex MaximumOfTwoRegisters r15, rax, rdi;
PrintOutRegisterInHex MinimumOfTwoRegisters r14, rax, rdi; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply Assemble, <<END;
r15: 0000 0000 0000 0002
r14: 0000 0000 0000 0001
END
Increment($target, $amount)
Increment the specified register
Parameter Description
1 $target Target register
2 $amount Optional amount if not 1
Decrement($target, $amount)
Decrement the specified register
Parameter Description
1 $target Target register
2 $amount Optional amount if not 1
Plus($target, @source)
Add the last operands and place the result in the first operand
Parameter Description
1 $target Target register
2 @source Source registers
Example:
Copy r15, 2;
Copy r14, 3;
KeepFree r15;
Plus(r15, r15, r14); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex r15;
Copy r13, 4;
Minus(r12, r15, r13);
PrintOutRegisterInHex r12;
is_deeply Assemble, <<END;
r15: 0000 0000 0000 0005
r12: 0000 0000 0000 0001
END
Minus($target, $s1, $s2)
Subtract the third operand from the second operand and place the result in the first operand
Parameter Description
1 $target Target register
2 $s1 Register to subtract from
3 $s2 Register to subtract
Example:
Copy r15, 2;
Copy r14, 3;
KeepFree r15;
Plus(r15, r15, r14);
PrintOutRegisterInHex r15;
Copy r13, 4;
Minus(r12, r15, r13); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex r12;
is_deeply Assemble, <<END;
r15: 0000 0000 0000 0005
r12: 0000 0000 0000 0001
END
Zmm
Operations on zmm registers
InsertIntoXyz($reg, $unit, $pos)
Shift and insert the specified word, double, quad from rax or the contents of xmm0 into the specified xyz register at the specified position shifting data above it to the left towards higher order bytes.
Parameter Description
1 $reg Register to insert into
2 $unit Width of insert
3 $pos Position of insert in units from least significant byte starting at 0
Example:
my $s = Rb 0..63;
Vmovdqu8 xmm0,"[$s]"; # Number each byte
Vmovdqu8 ymm1,"[$s]";
Vmovdqu8 zmm2,"[$s]";
Vmovdqu8 zmm3,"[$s]";
SetRegisterToMinusOne rax; # Insert some ones
InsertIntoXyz xmm0, 2, 4; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
InsertIntoXyz ymm1, 4, 5; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
InsertIntoXyz zmm2, 8, 6; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex xmm0; # Print the insertions
PrintOutRegisterInHex ymm1;
PrintOutRegisterInHex zmm2;
ClearRegisters xmm0; # Insert some zeroes
InsertIntoXyz zmm3, 16, 2; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex zmm3;
my $r = Assemble;
ok $r =~ m(xmm0: 0D0C 0B0A 0908 FFFF 0706 0504 0302 0100);
ok $r =~ m(ymm1: 1B1A 1918 1716 1514 FFFF FFFF 1312 1110 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100);
ok $r =~ m(zmm2: 3736 3534 3332 3130 FFFF FFFF FFFF FFFF 2F2E 2D2C 2B2A 2928 2726 2524 2322 2120 1F1E 1D1C 1B1A 1918 1716 1514 1312 1110 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100);
ok $r =~ m(zmm3: 2F2E 2D2C 2B2A 2928 2726 2524 2322 2120 0000 0000 0000 0000 0000 0000 0000 0000 1F1E 1D1C 1B1A 1918 1716 1514 1312 1110 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100);
LoadTargetZmmFromSourceZmm($target, $targetOffset, $source, $sourceOffset, $length)
Load bytes into the numbered target zmm register at a register specified offset with source bytes from a numbered source zmm register at a specified register offset for a specified register length.
Parameter Description
1 $target Number of zmm register to load
2 $targetOffset Register containing start or 0 if from the start
3 $source Numbered source zmm register
4 $sourceOffset Register containing length
5 $length Optional offset from stack top
Example:
my $s = Rb(17, 1..17);
LoadShortStringFromMemoryToZmm 0, $s; # Load a sample string
Keep zmm0;
PrintOutRegisterInHex xmm0;
LoadTargetZmmFromSourceZmm 1, Copy(rdi, 3), 0, Copy(rdx, 8), Copy(rsi, 2); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex xmm1;
KeepFree rdi;
LoadTargetZmmFromSourceZmm 2, Copy(rdi, 4), 0, rdx, rsi; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex xmm2;
Copy(zmm3, zmm0);
PrintOutRegisterInHex xmm3;
ClearRegisters zmm4;
Lea rax, "[$s+4]";
LoadZmmFromMemory 4, rdx, rsi, rax;
Sub rax, 4;
PrintOutRegisterInHex xmm4;
is_deeply Assemble, <<END;
xmm0: 0F0E 0D0C 0B0A 0908 0706 0504 0302 0111
xmm1: 0000 0000 0000 0000 0000 0009 0800 0000
xmm2: 0000 0000 0000 0000 0000 0908 0000 0000
xmm3: 0F0E 0D0C 0B0A 0908 0706 0504 0302 0111
xmm4: 0000 0000 0000 0504 0000 0000 0000 0000
END
my $s = Rb(13, 1..13);
my $t = Rb(1..64);
my $source = rax; # Address to load from
my $start = rsi; # Start position in the zmm register
my $length = rdi; # Length of copy
Copy $source, $s;
LoadShortStringFromMemoryToZmm 0, $s; # Load a sample string
KeepFree $source;
PrintOutRegisterInHex xmm0;
LoadZmmFromMemory 0, Increment(GetLengthOfShortString($start, 0)), Copy($length, 1), Copy($source, $t);
PrintOutRegisterInHex xmm0;
LoadZmmFromMemory 0, $start, $length, $source;
PrintOutRegisterInHex xmm0;
KeepFree $length;
LoadZmmFromMemory 0, $start, Minus($length, Copy(r13, 56), $start), $source;
SetLengthOfShortString 0, sil; # Set current length of zmm0
PrintOutRegisterInHex xmm0, zmm0;
is_deeply Assemble, <<END;
xmm0: 0000 0D0C 0B0A 0908 0706 0504 0302 010D
xmm0: 0001 0D0C 0B0A 0908 0706 0504 0302 010D
xmm0: 0201 0D0C 0B0A 0908 0706 0504 0302 010D
xmm0: 0201 0D0C 0B0A 0908 0706 0504 0302 0138
zmm0: 0000 0000 0000 0000 2A29 2827 2625 2423 2221 201F 1E1D 1C1B 1A19 1817 1615 1413 1211 100F 0E0D 0C0B 0A09 0807 0605 0403 0201 0D0C 0B0A 0908 0706 0504 0302 0138
END
LoadZmmFromMemory($target, $targetOffset, $length, $source)
Load bytes into the numbered target zmm register at a register specified offset with source bytes from memory addressed by a specified register for a specified register length from memory addressed by a specified register.
Parameter Description
1 $target Number of zmm register to load
2 $targetOffset Register containing start or 0 if from the start
3 $length Register containing length
4 $source Register addressing memory to load from
Structured Programming
Structured programming constructs
If($jump, $then, $else)
If
Parameter Description
1 $jump Jump op code of variable
2 $then Then - required
3 $else Else - optional
Example:
Mov rax, 0;
Test rax,rax;
IfNz
{PrintOutRegisterInHex rax;
} sub
{PrintOutRegisterInHex rbx;
};
KeepFree rax;
Mov rax, 1;
Test rax,rax;
IfNz
{PrintOutRegisterInHex rcx;
} sub
{PrintOutRegisterInHex rdx;
};
ok Assemble =~ m(rbx.*rcx)s;
IfEq($then, $else)
If equal execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
IfNe($then, $else)
If not equal execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
IfNz($then, $else)
If not zero execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
IfLt($then, $else)
If less than execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
IfLe($then, $else)
If less than or equal execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
IfGt($then, $else)
If greater than execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
IfGe($then, $else)
If greater than or equal execute the then body else the else body
Parameter Description
1 $then Then - required
2 $else Else - optional
For($body, $register, $limit, $increment)
For - iterate the body as long as register is less than limit incrementing by increment each time
Parameter Description
1 $body Body
2 $register Register
3 $limit Limit on loop
4 $increment Increment on each iteration
Example:
For # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{PrintOutRegisterInHex rax
} rax, 16, 1;
my $r = Assemble;
ok $r =~ m(( 0000){3} 0000)i;
ok $r =~ m(( 0000){3} 000F)i;
ForIn($full, $last, $register, $limit, $increment)
For - iterate the body as long as register plus increment is less than than limit incrementing by increment each time
Parameter Description
1 $full Body for full block
2 $last Body for last block
3 $register Register
4 $limit Limit on loop
5 $increment Increment on each iteration
ForEver($body)
Iterate for ever
Parameter Description
1 $body Body to iterate
Macro($body, %options)
Create a sub with optional parameters name=> the name of the subroutine so it can be reused rather than regenerated, comment=> a comment describing the sub
Parameter Description
1 $body Body
2 %options Options.
Subroutine($body, %options)
Create a subroutine that can be called in assembler code
Parameter Description
1 $body Body
2 %options Options.
Nasm::X86::Sub::call($sub, @parameters)
Call a sub passing it some parameters
Parameter Description
1 $sub Subroutine descriptor
2 @parameters Parameter variables
cr($body, @registers)
Call a subroutine with a reordering of the registers.
Parameter Description
1 $body Code to execute with reordered registers
2 @registers Registers to reorder
cxr($body, @registers)
Call a subroutine with a reordering of the xmm registers.
Parameter Description
1 $body Code to execute with reordered registers
2 @registers Registers to reorder
Example:
my $t = GenTree(2,2); # Tree description
$t->node->(); # Root
Movdqa xmm1, xmm0; # Root is in xmm1
if (1) # New left node
{$t->node->(); # Node in xmm0
Movdqa xmm2, xmm0; # Left is in xmm2
cxr {$t->insertLeft->()} 1,2; # Insert left under root # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
cxr {$t->dump->("Left")} 2; # Left node after insertion # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
}
if (1) # New right node in xmm0
{$t->node->();
Movdqa xmm3, xmm0; # Right is in xmm3
cxr {$t->insertRight->()} 1,3; # Insert left under root # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
cxr {$t->dump->("Right")} 3; # Right node after insertion # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
}
cxr # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{$t->dump->("Root"); # Root node after insertions
$t->isRoot->();
IfNz {PrintOutStringNL "root"} sub {PrintOutStringNL "NOT root"};
} 1;
PushRR xmm0; # Dump underlying byte string
PopRR rdi, rax;
$t->byteString->dump;
Exit; # Return to operating system
is_deeply Assemble, <<END; # Test tree so produced
Left
ArenaTreeNode at: 0000 0000 0000 00B0
up: 0000 0000 0000 0010
left: 0000 0000 0000 0000
right: 0000 0000 0000 0000
Right
ArenaTreeNode at: 0000 0000 0000 0150
up: 0000 0000 0000 0010
left: 0000 0000 0000 0000
right: 0000 0000 0000 0000
Root
ArenaTreeNode at: 0000 0000 0000 0010
up: 0000 0000 0000 0000
left: 0000 0000 0000 00B0
right: 0000 0000 0000 0150
root
Byte String
Size: 0000 0000 0000 1000
Used: 0000 0000 0000 01E0
END
Comment(@comment)
Insert a comment into the assembly code
Parameter Description
1 @comment Text of comment
Example:
Comment "Print a string from memory"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $s = "Hello World";
Mov rax, Rs($s);
Mov rdi, length $s;
PrintOutMemory;
ok Assemble =~ m(Hello World);
DComment(@comment)
Insert a comment into the data segment
Parameter Description
1 @comment Text of comment
RComment(@comment)
Insert a comment into the read only data segment
Parameter Description
1 @comment Text of comment
PrintErrNL()
Print a new line to stderr
PrintErrString($string)
Print a constant string to stderr.
Parameter Description
1 $string String
PrintErrStringNL($string)
Print a new line to stderr
Parameter Description
1 $string String
Example:
PrintOutStringNL "Hello World";
PrintErrStringNL "Hello World"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply Assemble, <<END;
Hello World
Hello World
END
PrintOutNL()
Print a new line to stdout
Example:
my $q = Rs('abababab');
Mov(rax, "[$q]");
PrintOutString "rax: ";
PrintOutRaxInHex;
PrintOutNL; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Xor rax, rax;
PrintOutString "rax: ";
PrintOutRaxInHex;
PrintOutNL; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok Assemble =~ m(rax: 6261 6261 6261 6261.*rax: 0000 0000 0000 0000)s;
PrintOutString($string)
Print a constant string to sysout.
Parameter Description
1 $string String
PrintOutStringNL($string)
Print a constant string to sysout followed by new line
Parameter Description
1 $string String
Example:
PrintOutStringNL "Hello World"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintErrStringNL "Hello World";
is_deeply Assemble, <<END;
Hello World
Hello World
END
my $t = GenTree(2,2); # Tree description
$t->node->(); # Root
Movdqa xmm1, xmm0; # Root is in xmm1
if (1) # New left node
{$t->node->(); # Node in xmm0
Movdqa xmm2, xmm0; # Left is in xmm2
cxr {$t->insertLeft->()} 1,2; # Insert left under root
cxr {$t->dump->("Left")} 2; # Left node after insertion
}
if (1) # New right node in xmm0
{$t->node->();
Movdqa xmm3, xmm0; # Right is in xmm3
cxr {$t->insertRight->()} 1,3; # Insert left under root
cxr {$t->dump->("Right")} 3; # Right node after insertion
}
cxr
{$t->dump->("Root"); # Root node after insertions
$t->isRoot->();
IfNz {PrintOutStringNL "root"} sub {PrintOutStringNL "NOT root"}; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
} 1;
PushRR xmm0; # Dump underlying byte string
PopRR rdi, rax;
$t->byteString->dump;
Exit; # Return to operating system
is_deeply Assemble, <<END; # Test tree so produced
Left
ArenaTreeNode at: 0000 0000 0000 00B0
up: 0000 0000 0000 0010
left: 0000 0000 0000 0000
right: 0000 0000 0000 0000
Right
ArenaTreeNode at: 0000 0000 0000 0150
up: 0000 0000 0000 0010
left: 0000 0000 0000 0000
right: 0000 0000 0000 0000
Root
ArenaTreeNode at: 0000 0000 0000 0010
up: 0000 0000 0000 0000
left: 0000 0000 0000 00B0
right: 0000 0000 0000 0150
root
Byte String
Size: 0000 0000 0000 1000
Used: 0000 0000 0000 01E0
END
PrintOutRaxInHex()
Write the content of register rax to stderr in hexadecimal in big endian notation
Example:
my $q = Rs('abababab');
Mov(rax, "[$q]");
PrintOutString "rax: ";
PrintOutRaxInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutNL;
Xor rax, rax;
PrintOutString "rax: ";
PrintOutRaxInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutNL;
ok Assemble =~ m(rax: 6261 6261 6261 6261.*rax: 0000 0000 0000 0000)s;
PrintOutRaxInReverseInHex()
Write the content of register rax to stderr in hexadecimal in little endian notation
Example:
Mov rax, 0x07654321;
Shl rax, 32;
Or rax, 0x07654321;
PushR rax;
PrintOutRaxInHex;
PrintOutNL;
PrintOutRaxInReverseInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutNL;
KeepFree rax;
Mov rax, rsp;
Mov rdi, 8;
PrintOutMemoryInHex;
PrintOutNL;
PopR rax;
KeepFree rax, rdi;
Mov rax, 4096;
PushR rax;
Mov rax, rsp;
Mov rdi, 8;
PrintOutMemoryInHex;
PrintOutNL;
PopR rax;
is_deeply Assemble, <<END;
0765 4321 0765 4321
2143 6507 2143 6507
2143 6507 2143 6507
0010 0000 0000 0000
END
PrintOutRegisterInHex(@r)
Print any register as a hex string
Parameter Description
1 @r Name of the register to print
Example:
my $q = Rs(('a'..'p')x4);
Mov r8,"[$q]";
PrintOutRegisterInHex r8; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok Assemble =~ m(r8: 6867 6665 6463 6261)s;
PrintOutRegistersInHex()
Print the general purpose registers in hex
Example:
my $q = Rs('abababab');
Mov(rax, 1);
Mov(rbx, 2);
Mov(rcx, 3);
Mov(rdx, 4);
Mov(r8, 5);
Lea r9, "[rax+rbx]";
PrintOutRegistersInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $r = Assemble;
ok $r =~ m( r8: 0000 0000 0000 0005.* r9: 0000 0000 0000 0003.*rax: 0000 0000 0000 0001)s;
ok $r =~ m(rbx: 0000 0000 0000 0002.*rcx: 0000 0000 0000 0003.*rdx: 0000 0000 0000 0004)s;
PrintOutZF()
Print the zero flag without disturbing it
Example:
SetZF;
PrintOutZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ClearZF;
PrintOutZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
SetZF;
PrintOutZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
SetZF;
PrintOutZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ClearZF;
PrintOutZF; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok Assemble =~ m(ZF=1.*ZF=0.*ZF=1.*ZF=1.*ZF=0)s;
Variables
Variable definitions and operations
Scopes
Each variable is contained in a scope in an effort to detect references to out of scope variables
Scope($name)
Create and stack a new scope and continue with it as the current scope
Parameter Description
1 $name Scope name
Example:
if (1)
{my $start = Scope(start); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $s1 = Scope(s1); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $s2 = Scope(s2); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $s2->depth, 2;
is_deeply $s2->name, q(s2);
ScopeEnd;
my $t1 = Scope(t1); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $t2 = Scope(t2); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $t1->depth, 2;
is_deeply $t1->name, q(t1);
is_deeply $t2->depth, 3;
is_deeply $t2->name, q(t2);
ok $s1->currentlyVisible;
ok !$s2->currentlyVisible;
ok $s1->contains($t2);
ok !$s2->contains($t2);
ScopeEnd;
is_deeply $s1->depth, 1;
is_deeply $s1->name, q(s1);
ScopeEnd;
}
ScopeEnd()
End the current scope and continue with the containing parent scope
Example:
if (1)
{my $start = Scope(start);
my $s1 = Scope(s1);
my $s2 = Scope(s2);
is_deeply $s2->depth, 2;
is_deeply $s2->name, q(s2);
ScopeEnd; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $t1 = Scope(t1);
my $t2 = Scope(t2);
is_deeply $t1->depth, 2;
is_deeply $t1->name, q(t1);
is_deeply $t2->depth, 3;
is_deeply $t2->name, q(t2);
ok $s1->currentlyVisible;
ok !$s2->currentlyVisible;
ok $s1->contains($t2);
ok !$s2->contains($t2);
ScopeEnd; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply $s1->depth, 1;
is_deeply $s1->name, q(s1);
ScopeEnd; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
}
Scope::contains($parent, $child)
Check that the named parent scope contains the specified child scope. If no child scope is supplied we use the current scope to check that the parent scope is currently visible
Parameter Description
1 $parent Parent scope
2 $child Child scope
Example:
if (1)
{my $start = Scope(start);
my $s1 = Scope(s1);
my $s2 = Scope(s2);
is_deeply $s2->depth, 2;
is_deeply $s2->name, q(s2);
ScopeEnd;
my $t1 = Scope(t1);
my $t2 = Scope(t2);
is_deeply $t1->depth, 2;
is_deeply $t1->name, q(t1);
is_deeply $t2->depth, 3;
is_deeply $t2->name, q(t2);
ok $s1->currentlyVisible;
ok !$s2->currentlyVisible;
ok $s1->contains($t2);
ok !$s2->contains($t2);
ScopeEnd;
is_deeply $s1->depth, 1;
is_deeply $s1->name, q(s1);
ScopeEnd;
}
Scope::currentlyVisible($scope)
Check that the named parent scope is currently visible
Parameter Description
1 $scope Scope to check for visibility
Example:
if (1)
{my $start = Scope(start);
my $s1 = Scope(s1);
my $s2 = Scope(s2);
is_deeply $s2->depth, 2;
is_deeply $s2->name, q(s2);
ScopeEnd;
my $t1 = Scope(t1);
my $t2 = Scope(t2);
is_deeply $t1->depth, 2;
is_deeply $t1->name, q(t1);
is_deeply $t2->depth, 3;
is_deeply $t2->name, q(t2);
ok $s1->currentlyVisible;
ok !$s2->currentlyVisible;
ok $s1->contains($t2);
ok !$s2->contains($t2);
ScopeEnd;
is_deeply $s1->depth, 1;
is_deeply $s1->name, q(s1);
ScopeEnd;
}
Definitions
Variable definitions
Variable($size, $name, $expr)
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
Vb($name, $expr)
Define a byte variable
Parameter Description
1 $name Name of variable
2 $expr Initializing expression
Vw($name, $expr)
Define a word variable
Parameter Description
1 $name Name of variable
2 $expr Initializing expression
Vd($name, $expr)
Define a double word variable
Parameter Description
1 $name Name of variable
2 $expr Initializing expression
Vq($name, $expr)
Define a quad variable
Parameter Description
1 $name Name of variable
2 $expr Initializing expression
Example:
my $a = Vq(a, 3); $a->print; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $c = $a + 2; $c->print;
my $d = $c - $a; $d->print;
my $e = $d == 2; $e->print;
my $f = $d != 2; $f->print;
my $g = $a * 2; $g->print;
my $h = $g / 2; $h->print;
my $i = $a % 2; $i->print;
If ($a == 3, sub{PrintOutStringNL "a == 3"});
is_deeply Assemble, <<END;
0300 0000 0000 0000
0500 0000 0000 0000
0200 0000 0000 0000
0100 0000 0000 0000
0000 0000 0000 0000
0600 0000 0000 0000
0300 0000 0000 0000
0100 0000 0000 0000
a == 3
END
VxyzInit($var, @expr)
Initialize an xyz register from general purpose registers
Parameter Description
1 $var Variable
2 @expr Initializing general purpose registers or undef
Vx($name, @expr)
Define an xmm variable
Parameter Description
1 $name Name of variable
2 @expr Initializing expression
Vy($name, @expr)
Define an ymm variable
Parameter Description
1 $name Name of variable
2 @expr Initializing expression
Vz($name, @expr)
Define an zmm variable
Parameter Description
1 $name Name of variable
2 @expr Initializing expression
Vr($name, $ref)
Define a reference variable
Parameter Description
1 $name Name of variable
2 $ref Variable being referenced
Operations
Variable operations
Variable::address($left, $offset)
Get the address of a variable with an optional offset
Parameter Description
1 $left Left variable
2 $offset Optional offset
Variable::copy($left, $right)
Copy one variable into another
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::copyRef($left, $right)
Copy one variable into an referenced variable
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::copyAddress($left, $right)
Copy a reference to a variable
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::equals($op, $left, $right)
Equals operator
Parameter Description
1 $op Operator
2 $left Left variable
3 $right Right variable
Variable::assign($left, $op, $right)
Assign to the left hand side the value of the right hand side
Parameter Description
1 $left Left variable
2 $op Operator
3 $right Right variable
Variable::plusAssign($left, $right)
Implement plus and assign
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::minusAssign($left, $right)
Implement minus and assign
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::arithmetic($op, $name, $left, $right)
Return a variable containing the result of an arithmetic operation on the left hand and right hand side variables
Parameter Description
1 $op Operator
2 $name Operator name
3 $left Left variable
4 $right Right variable
Variable::add($left, $right)
Add the right hand variable to the left hand variable and return the result as a new variable
Parameter Description
1 $left Left variable
2 $right Right variable
Example:
my $a = Vq(a, 3); $a->print;
my $c = $a + 2; $c->print;
my $d = $c - $a; $d->print;
my $e = $d == 2; $e->print;
my $f = $d != 2; $f->print;
my $g = $a * 2; $g->print;
my $h = $g / 2; $h->print;
my $i = $a % 2; $i->print;
If ($a == 3, sub{PrintOutStringNL "a == 3"});
is_deeply Assemble, <<END;
0300 0000 0000 0000
0500 0000 0000 0000
0200 0000 0000 0000
0100 0000 0000 0000
0000 0000 0000 0000
0600 0000 0000 0000
0300 0000 0000 0000
0100 0000 0000 0000
a == 3
END
Variable::sub($left, $right)
Subtract the right hand variable from the left hand variable and return the result as a new variable
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::times($left, $right)
Multiply the left hand variable by the right hand variable and return the result as a new variable
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::division($op, $left, $right)
Return a variable containing the result or the remainder that occurs when the left hand side is divided by the right hand side
Parameter Description
1 $op Operator
2 $left Left variable
3 $right Right variable
Variable::divide($left, $right)
Divide the left hand variable by the right hand variable and return the result as a new variable
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::mod($left, $right)
Divide the left hand variable by the right hand variable and return the remainder as a new variable
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::boolean($sub, $op, $left, $right)
Combine the left hand variable with the right hand variable via a boolean operator
Parameter Description
1 $sub Operator
2 $op Operator name
3 $left Left variable
4 $right Right variable
Variable::eq($left, $right)
Check whether the left hand variable is equal to the right hand variable
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::ne($left, $right)
Check whether the left hand variable is not equal to the right hand variable
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::ge($left, $right)
Check whether the left hand variable is greater than or equal to the right hand variable
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::gt($left, $right)
Check whether the left hand variable is greater than the right hand variable
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::le($left, $right)
Check whether the left hand variable is less than or equal to the right hand variable
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::lt($left, $right)
Check whether the left hand variable is less than the right hand variable
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::print($left)
Write the value of a variable on stdout
Parameter Description
1 $left Left variable
Example:
my $a = Vq(a, 3); $a->print;
my $c = $a + 2; $c->print;
my $d = $c - $a; $d->print;
my $e = $d == 2; $e->print;
my $f = $d != 2; $f->print;
my $g = $a * 2; $g->print;
my $h = $g / 2; $h->print;
my $i = $a % 2; $i->print;
If ($a == 3, sub{PrintOutStringNL "a == 3"});
is_deeply Assemble, <<END;
0300 0000 0000 0000
0500 0000 0000 0000
0200 0000 0000 0000
0100 0000 0000 0000
0000 0000 0000 0000
0600 0000 0000 0000
0300 0000 0000 0000
0100 0000 0000 0000
a == 3
END
my $a = Vq(a, 3); $a->dump;
my $b = Vq(b, 2); $b->dump;
my $c = $a + $b; $c->dump;
my $d = $c - $a; $d->dump;
my $e = $d == $b; $e->dump;
my $f = $d != $b; $f->dump;
my $g = $a * $b; $g->dump;
my $h = $g / $b; $h->dump;
my $i = $a % $b; $i->dump;
is_deeply Assemble, <<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
END
Variable::dump($left, $title)
Dump the value of a variable on stdout
Parameter Description
1 $left Left variable
2 $title Optional title
Example:
my $a = Vq(a, 3); $a->dump;
my $b = Vq(b, 2); $b->dump;
my $c = $a + $b; $c->dump;
my $d = $c - $a; $d->dump;
my $e = $d == $b; $e->dump;
my $f = $d != $b; $f->dump;
my $g = $a * $b; $g->dump;
my $h = $g / $b; $h->dump;
my $i = $a % $b; $i->dump;
is_deeply Assemble, <<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
END
Variable::debug($left)
Dump the value of a variable on stdout with an indication of where the dump came from
Parameter Description
1 $left Left variable
Variable::isRef($variable)
Check whether the specified variable is a reference to another variable
Parameter Description
1 $variable Variable
Variable::setReg($variable, $register, @registers)
Set the named registers from the content of the variable
Parameter Description
1 $variable Variable
2 $register Register to load
3 @registers Optional further registers to load
Variable::getReg($variable, $register, @registers)
Load the variable from the named registers
Parameter Description
1 $variable Variable
2 $register Register to load
3 @registers Optional further registers to load from
Variable::incDec($left, $op)
Increment or decrement a variable
Parameter Description
1 $left Left variable operator
2 $op Address of operator to perform inc or dec
Variable::inc($left)
Increment a variable
Parameter Description
1 $left Variable
Variable::dec($left)
Decrement a variable
Parameter Description
1 $left Variable
Variable::str($left)
The name of the variable
Parameter Description
1 $left Variable
Variable::min($left, $right)
Minimum of two variables
Parameter Description
1 $left Left variable
2 $right Right variable
Example:
my $a = Vq("a", 1);
my $b = Vq("b", 2);
my $c = $a->min($b);
my $d = $a->max($b);
$a->dump;
$b->dump;
$c->dump;
$d->dump;
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
Variable::max($left, $right)
Maximum of two variables
Parameter Description
1 $left Left variable
2 $right Right variable
Example:
my $a = Vq("a", 1);
my $b = Vq("b", 2);
my $c = $a->min($b);
my $d = $a->max($b);
$a->dump;
$b->dump;
$c->dump;
$d->dump;
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
Variable::and($left, $right)
And two variables
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::or($left, $right)
Or two variables
Parameter Description
1 $left Left variable
2 $right Right variable
Variable::setMask($start, $length, $mask)
Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere
Parameter Description
1 $start Variable containing start of mask
2 $length Variable containing length of mask
3 $mask Mask register
Example:
my $start = Vq("Start", 7);
my $length = Vq("Length", 3);
$start->setMask($length, k7);
PrintOutRegisterInHex k7;
is_deeply Assemble, <<END;
k7: 0000 0000 0000 0380
END
Variable::setZmm($source, $zmm, $offset, $length)
Load bytes from the memory addressed by specified source variable into the numbered zmm register at the offset in the specified offset moving the number of bytes in the specified variable
Parameter Description
1 $source Variable containing the address of the source
2 $zmm Number of zmm to load
3 $offset Variable containing offset in zmm to move to
4 $length Variable containing length of move
Example:
my $s = Rb(0..128);
my $source = Vq(Source, $s);
if (1) # First block
{my $offset = Vq(Offset, 7);
my $length = Vq(Length, 3);
$source->setZmm(0, $offset, $length);
}
if (1) # Second block
{my $offset = Vq(Offset, 33);
my $length = Vq(Length, 12);
$source->setZmm(0, $offset, $length);
}
PrintOutRegisterInHex zmm0;
is_deeply Assemble, <<END;
zmm0: 0000 0000 0000 0000 0000 0000 0000 0000 0000 000B 0A09 0807 0605 0403 0201 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0201 0000 0000 0000 0000
END
my $a = Vz a, Rb((map {"0x${_}0"} 0..9, 'a'..'f')x4);
my $b = Vz b, Rb((map {"0x0${_}"} 0..9, 'a'..'f')x4);
$a ->loadZmm(0); # Show variable in zmm0
$b ->loadZmm(1); # Show variable in zmm1
($a + $b)->loadZmm(2); # Add bytes and show in zmm2
($a - $b)->loadZmm(3); # Subtract bytes and show in zmm3
PrintOutRegisterInHex "zmm$_" for 0..3;
is_deeply Assemble, <<END;
zmm0: F0E0 D0C0 B0A0 9080 7060 5040 3020 1000 F0E0 D0C0 B0A0 9080 7060 5040 3020 1000 F0E0 D0C0 B0A0 9080 7060 5040 3020 1000 F0E0 D0C0 B0A0 9080 7060 5040 3020 1000
zmm1: 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100 0F0E 0D0C 0B0A 0908 0706 0504 0302 0100
zmm2: FFEE DDCC BBAA 9988 7766 5544 3322 1100 FFEE DDCC BBAA 9988 7766 5544 3322 1100 FFEE DDCC BBAA 9988 7766 5544 3322 1100 FFEE DDCC BBAA 9988 7766 5544 3322 1100
zmm3: E1D2 C3B4 A596 8778 695A 4B3C 2D1E 0F00 E1D2 C3B4 A596 8778 695A 4B3C 2D1E 0F00 E1D2 C3B4 A596 8778 695A 4B3C 2D1E 0F00 E1D2 C3B4 A596 8778 695A 4B3C 2D1E 0F00
END
Variable::loadZmm($source, $zmm)
Load bytes from the memory addressed by the specified source variable into the numbered zmm register.
Parameter Description
1 $source Variable containing the address of the source
2 $zmm Number of zmm to get
Variable::saveZmm($target, $zmm)
Save bytes into the memory addressed by the target variable from the numbered zmm register.
Parameter Description
1 $target Variable containing the address of the source
2 $zmm Number of zmm to put
getBwdqFromZmmAsVariable($size, $zmm, $offset)
Get the numbered byte|word|double word|quad word from the numbered zmm register and return it in a variable
Parameter Description
1 $size Size of get
2 $zmm Numbered zmm
3 $offset Offset in bytes
getBFromZmmAsVariable($zmm, $offset)
Get the byte from the numbered zmm register and return it in a variable
Parameter Description
1 $zmm Numbered zmm
2 $offset Offset in bytes
getWFromZmmAsVariable($zmm, $offset)
Get the word from the numbered zmm register and return it in a variable
Parameter Description
1 $zmm Numbered zmm
2 $offset Offset in bytes
getDFromZmmAsVariable($zmm, $offset)
Get the double word from the numbered zmm register and return it in a variable
Parameter Description
1 $zmm Numbered zmm
2 $offset Offset in bytes
Example:
my $s = Rb(0..8);
my $c = Vq("Content", "[$s]");
$c->putBIntoZmm(0, 4);
$c->putWIntoZmm(0, 6);
$c->putDIntoZmm(0, 10);
$c->putQIntoZmm(0, 16);
PrintOutRegisterInHex zmm0;
getBFromZmmAsVariable(0, 12)->dump;
getWFromZmmAsVariable(0, 12)->dump;
getDFromZmmAsVariable(0, 12)->dump; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
getQFromZmmAsVariable(0, 12)->dump;
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
getQFromZmmAsVariable($zmm, $offset)
Get the quad word from the numbered zmm register and return it in a variable
Parameter Description
1 $zmm Numbered zmm
2 $offset Offset in bytes
Variable::putBwdqIntoZmm($content, $size, $zmm, $offset)
Place the value of the content variable at the byte|word|double word|quad word in the numbered zmm register
Parameter Description
1 $content Variable with content
2 $size Size of put
3 $zmm Numbered zmm
4 $offset Offset in bytes
Variable::putBIntoZmm($content, $zmm, $offset)
Place the value of the content variable at the byte in the numbered zmm register
Parameter Description
1 $content Variable with content
2 $zmm Numbered zmm
3 $offset Offset in bytes
Variable::putWIntoZmm($content, $zmm, $offset)
Place the value of the content variable at the word in the numbered zmm register
Parameter Description
1 $content Variable with content
2 $zmm Numbered zmm
3 $offset Offset in bytes
Variable::putDIntoZmm($content, $zmm, $offset)
Place the value of the content variable at the double word in the numbered zmm register
Parameter Description
1 $content Variable with content
2 $zmm Numbered zmm
3 $offset Offset in bytes
Example:
my $s = Rb(0..8);
my $c = Vq("Content", "[$s]");
$c->putBIntoZmm(0, 4);
$c->putWIntoZmm(0, 6);
$c->putDIntoZmm(0, 10);
$c->putQIntoZmm(0, 16);
PrintOutRegisterInHex zmm0;
getBFromZmmAsVariable(0, 12)->dump;
getWFromZmmAsVariable(0, 12)->dump;
getDFromZmmAsVariable(0, 12)->dump;
getQFromZmmAsVariable(0, 12)->dump;
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
Variable::putQIntoZmm($content, $zmm, $offset)
Place the value of the content variable at the quad word in the numbered zmm register
Parameter Description
1 $content Variable with content
2 $zmm Numbered zmm
3 $offset Offset in bytes
Variable::clearMemory($memory)
Clear the memory described in this variable
Parameter Description
1 $memory Variable describing memory as returned by Allocate Memory
Variable::copyMemoryFrom($target, $source)
Copy from one block of memory to another
Parameter Description
1 $target Variable describing the target
2 $source Variable describing the source
Variable::printOutMemoryInHex($memory)
Print allocated memory in hex
Parameter Description
1 $memory Variable describing the memory
Variable::freeMemory($memory)
Free the memory described in this variable
Parameter Description
1 $memory Variable describing memory as returned by Allocate Memory
Example:
my $N = Vq(size, 2048);
my $q = Rs('a'..'p');
AllocateMemory->call($N, my $address = Vq(address));
$address->dump;
Vmovdqu8 xmm0, "[$q]";
$address->setReg(rax);
Vmovdqu8 "[rax]", xmm0;
Mov rdi, 16;
PrintOutMemory;
PrintOutNL;
FreeMemory->call(address => $address, size=> $N);
ok Assemble =~ m(address: 0000.*abcdefghijklmnop)s;
Variable::for($limit, $body)
Iterate the body from 0 limit times.
Parameter Description
1 $limit Limit
2 $body Body
Example:
Vq(limit,10)->for(sub
{my ($i, $start, $next, $end) = @_;
$i->print;
});
is_deeply Assemble, <<END;
0000 0000 0000 0000
0100 0000 0000 0000
0200 0000 0000 0000
0300 0000 0000 0000
0400 0000 0000 0000
0500 0000 0000 0000
0600 0000 0000 0000
0700 0000 0000 0000
0800 0000 0000 0000
0900 0000 0000 0000
END
Processes
Create and manage processes
Fork()
Fork
Example:
Fork; # Fork # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Test rax,rax;
IfNz # Parent
{Mov rbx, rax;
WaitPid;
PrintOutRegisterInHex rax;
PrintOutRegisterInHex rbx;
KeepFree rax;
GetPid; # Pid of parent as seen in parent
Mov rcx,rax;
PrintOutRegisterInHex rcx;
}
sub # Child
{Mov r8,rax;
PrintOutRegisterInHex r8;
KeepFree rax;
GetPid; # Child pid as seen in child
Mov r9,rax;
PrintOutRegisterInHex r9;
KeepFree rax;
GetPPid; # Parent pid as seen in child
Mov r10,rax;
PrintOutRegisterInHex r10;
};
my $r = Assemble;
# r8: 0000 0000 0000 0000 #1 Return from fork as seen by child
# r9: 0000 0000 0003 0C63 #2 Pid of child
# r10: 0000 0000 0003 0C60 #3 Pid of parent from child
# rax: 0000 0000 0003 0C63 #4 Return from fork as seen by parent
# rbx: 0000 0000 0003 0C63 #5 Wait for child pid result
# rcx: 0000 0000 0003 0C60 #6 Pid of parent
if ($r =~ m(r8:( 0000){4}.*r9:(.*)\s{5,}r10:(.*)\s{5,}rax:(.*)\s{5,}rbx:(.*)\s{5,}rcx:(.*)\s{2,})s)
{ok $2 eq $4;
ok $2 eq $5;
ok $3 eq $6;
ok $2 gt $6;
}
GetPid()
Get process identifier
Example:
Fork; # Fork
Test rax,rax;
IfNz # Parent
{Mov rbx, rax;
WaitPid;
PrintOutRegisterInHex rax;
PrintOutRegisterInHex rbx;
KeepFree rax;
GetPid; # Pid of parent as seen in parent # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov rcx,rax;
PrintOutRegisterInHex rcx;
}
sub # Child
{Mov r8,rax;
PrintOutRegisterInHex r8;
KeepFree rax;
GetPid; # Child pid as seen in child # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov r9,rax;
PrintOutRegisterInHex r9;
KeepFree rax;
GetPPid; # Parent pid as seen in child
Mov r10,rax;
PrintOutRegisterInHex r10;
};
my $r = Assemble;
# r8: 0000 0000 0000 0000 #1 Return from fork as seen by child
# r9: 0000 0000 0003 0C63 #2 Pid of child
# r10: 0000 0000 0003 0C60 #3 Pid of parent from child
# rax: 0000 0000 0003 0C63 #4 Return from fork as seen by parent
# rbx: 0000 0000 0003 0C63 #5 Wait for child pid result
# rcx: 0000 0000 0003 0C60 #6 Pid of parent
if ($r =~ m(r8:( 0000){4}.*r9:(.*)\s{5,}r10:(.*)\s{5,}rax:(.*)\s{5,}rbx:(.*)\s{5,}rcx:(.*)\s{2,})s)
{ok $2 eq $4;
ok $2 eq $5;
ok $3 eq $6;
ok $2 gt $6;
}
GetPidInHex()
Get process identifier in hex as 8 zero terminated bytes in rax
Example:
GetPidInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
ok Assemble =~ m(rax: 00);
GetPPid()
Get parent process identifier
Example:
Fork; # Fork
Test rax,rax;
IfNz # Parent
{Mov rbx, rax;
WaitPid;
PrintOutRegisterInHex rax;
PrintOutRegisterInHex rbx;
KeepFree rax;
GetPid; # Pid of parent as seen in parent
Mov rcx,rax;
PrintOutRegisterInHex rcx;
}
sub # Child
{Mov r8,rax;
PrintOutRegisterInHex r8;
KeepFree rax;
GetPid; # Child pid as seen in child
Mov r9,rax;
PrintOutRegisterInHex r9;
KeepFree rax;
GetPPid; # Parent pid as seen in child # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov r10,rax;
PrintOutRegisterInHex r10;
};
my $r = Assemble;
# r8: 0000 0000 0000 0000 #1 Return from fork as seen by child
# r9: 0000 0000 0003 0C63 #2 Pid of child
# r10: 0000 0000 0003 0C60 #3 Pid of parent from child
# rax: 0000 0000 0003 0C63 #4 Return from fork as seen by parent
# rbx: 0000 0000 0003 0C63 #5 Wait for child pid result
# rcx: 0000 0000 0003 0C60 #6 Pid of parent
if ($r =~ m(r8:( 0000){4}.*r9:(.*)\s{5,}r10:(.*)\s{5,}rax:(.*)\s{5,}rbx:(.*)\s{5,}rcx:(.*)\s{2,})s)
{ok $2 eq $4;
ok $2 eq $5;
ok $3 eq $6;
ok $2 gt $6;
}
GetUid()
Get userid of current process
Example:
GetUid; # Userid # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
my $r = Assemble;
ok $r =~ m(rax:( 0000){3});
WaitPid()
Wait for the pid in rax to complete
Example:
Fork; # Fork
Test rax,rax;
IfNz # Parent
{Mov rbx, rax;
WaitPid; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
PrintOutRegisterInHex rbx;
KeepFree rax;
GetPid; # Pid of parent as seen in parent
Mov rcx,rax;
PrintOutRegisterInHex rcx;
}
sub # Child
{Mov r8,rax;
PrintOutRegisterInHex r8;
KeepFree rax;
GetPid; # Child pid as seen in child
Mov r9,rax;
PrintOutRegisterInHex r9;
KeepFree rax;
GetPPid; # Parent pid as seen in child
Mov r10,rax;
PrintOutRegisterInHex r10;
};
my $r = Assemble;
# r8: 0000 0000 0000 0000 #1 Return from fork as seen by child
# r9: 0000 0000 0003 0C63 #2 Pid of child
# r10: 0000 0000 0003 0C60 #3 Pid of parent from child
# rax: 0000 0000 0003 0C63 #4 Return from fork as seen by parent
# rbx: 0000 0000 0003 0C63 #5 Wait for child pid result
# rcx: 0000 0000 0003 0C60 #6 Pid of parent
if ($r =~ m(r8:( 0000){4}.*r9:(.*)\s{5,}r10:(.*)\s{5,}rax:(.*)\s{5,}rbx:(.*)\s{5,}rcx:(.*)\s{2,})s)
{ok $2 eq $4;
ok $2 eq $5;
ok $3 eq $6;
ok $2 gt $6;
}
ReadTimeStampCounter()
Read the time stamp counter and return the time in nanoseconds in rax
Example:
for(1..10)
{ReadTimeStampCounter; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
}
my @s = split /
/, Assemble;
my @S = sort @s;
is_deeply \@s, \@S;
Stack
Manage data on the stack
Push, Pop, Peek
Generic versions of push, pop, peek
PushRR(@r)
Push registers onto the stack without tracking
Parameter Description
1 @r Register
PushR(@r)
Push registers onto the stack
Parameter Description
1 @r Register
Example:
Mov rax, 0x11111111;
Mov rbx, 0x22222222;
PushR my @save = (rax, rbx); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov rax, 0x33333333;
PopR @save;
PrintOutRegisterInHex rax;
PrintOutRegisterInHex rbx;
is_deeply Assemble,<<END;
rax: 0000 0000 1111 1111
rbx: 0000 0000 2222 2222
END
PopRR(@r)
Pop registers from the stack without tracking
Parameter Description
1 @r Register
PopR(@r)
Pop registers from the stack
Parameter Description
1 @r Register
Example:
Mov rax, 0x11111111;
Mov rbx, 0x22222222;
PushR my @save = (rax, rbx);
Mov rax, 0x33333333;
PopR @save; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
PrintOutRegisterInHex rbx;
is_deeply Assemble,<<END;
rax: 0000 0000 1111 1111
rbx: 0000 0000 2222 2222
END
PeekR($r)
Peek at register on stack
Parameter Description
1 $r Register
Declarations
Declare variables and structures
Structures
Declare a structure
Structure()
Create a structure addressed by a register
Structure::field($structure, $length, $comment)
Add a field of the specified length with an optional comment
Parameter Description
1 $structure Structure data descriptor
2 $length Length of data
3 $comment Optional comment
StructureField::addr($field, $register)
Address a field in a structure by either the default register or the named register
Parameter Description
1 $field Field
2 $register Optional address register else rax
All8Structure($N)
Create a structure consisting of 8 byte fields
Parameter Description
1 $N Number of variables required
Stack Frame
Declare local variables in a frame on the stack
LocalData()
Map local data
LocalData::start($local)
Start a local data area on the stack
Parameter Description
1 $local Local data descriptor
LocalData::free($local)
Free a local data area on the stack
Parameter Description
1 $local Local data descriptor
LocalData::variable($local, $length, $comment)
Add a local variable
Parameter Description
1 $local Local data descriptor
2 $length Length of data
3 $comment Optional comment
LocalVariable::stack($variable)
Address a local variable on the stack
Parameter Description
1 $variable Variable
LocalData::allocate8($local, @comments)
Add some 8 byte local variables and return an array of variable definitions
Parameter Description
1 $local Local data descriptor
2 @comments Optional comment
AllocateAll8OnStack($N)
Create a local data descriptor consisting of the specified number of 8 byte local variables and return an array: (local data descriptor, variable definitions...)
Parameter Description
1 $N Number of variables required
Memory
Allocate and print memory
PrintOutMemoryInHex()
Dump memory from the address in rax for the length in rdi
Example:
Mov rax, 0x07654321;
Shl rax, 32;
Or rax, 0x07654321;
PushR rax;
PrintOutRaxInHex;
PrintOutNL;
PrintOutRaxInReverseInHex;
PrintOutNL;
KeepFree rax;
Mov rax, rsp;
Mov rdi, 8;
PrintOutMemoryInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutNL;
PopR rax;
KeepFree rax, rdi;
Mov rax, 4096;
PushR rax;
Mov rax, rsp;
Mov rdi, 8;
PrintOutMemoryInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutNL;
PopR rax;
is_deeply Assemble, <<END;
0765 4321 0765 4321
2143 6507 2143 6507
2143 6507 2143 6507
0010 0000 0000 0000
END
PrintOutMemoryInHexNL()
Dump memory from the address in rax for the length in rdi and then print a new line
PrintOutMemory()
Print the memory addressed by rax for a length of rdi::
Example:
Comment "Print a string from memory";
my $s = "Hello World";
Mov rax, Rs($s);
Mov rdi, length $s;
PrintOutMemory; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok Assemble =~ m(Hello World);
PrintOutMemoryNL()
Print the memory addressed by rax for a length of rdi followed by a new line
AllocateMemory()
Allocate the specified amount of memory via mmap and return its address
Example:
my $N = Vq(size, 2048);
my $q = Rs('a'..'p');
AllocateMemory->call($N, my $address = Vq(address)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$address->dump;
Vmovdqu8 xmm0, "[$q]";
$address->setReg(rax);
Vmovdqu8 "[rax]", xmm0;
Mov rdi, 16;
PrintOutMemory;
PrintOutNL;
FreeMemory->call(address => $address, size=> $N);
ok Assemble =~ m(address: 0000.*abcdefghijklmnop)s;
my $N = Vq(size, 4096); # Size of the initial allocation which should be one or more pages
AllocateMemory->call($N, my $A = Vq(address)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$A->dump;
ClearMemory->call($N, $A);
$A->setReg(rax);
$N->setReg(rdi);
PrintOutMemoryInHex;
FreeMemory->call($N, $A);
my $r = Assemble;
if ($r =~ m((0000.*0000))s)
{is_deeply length($1), 9748;
}
my $N = 256;
my $s = Rb 0..$N-1;
AllocateMemory->call(Vq(size, $N), my $a = Vq(address)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
CopyMemory ->call(Vq(source, $s), Vq(size, $N), target => $a);
AllocateMemory->call(Vq(size, $N), my $b = Vq(address)); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
CopyMemory ->call(source => $a, target => $b, Vq(size, $N));
$b->setReg(rax);
Mov rdi, $N;
PrintOutMemoryInHexNL;
is_deeply Assemble, <<END;
0001 0203 0405 06070809 0A0B 0C0D 0E0F1011 1213 1415 16171819 1A1B 1C1D 1E1F2021 2223 2425 26272829 2A2B 2C2D 2E2F3031 3233 3435 36373839 3A3B 3C3D 3E3F4041 4243 4445 46474849 4A4B 4C4D 4E4F5051 5253 5455 56575859 5A5B 5C5D 5E5F6061 6263 6465 66676869 6A6B 6C6D 6E6F7071 7273 7475 76777879 7A7B 7C7D 7E7F8081 8283 8485 86878889 8A8B 8C8D 8E8F9091 9293 9495 96979899 9A9B 9C9D 9E9FA0A1 A2A3 A4A5 A6A7A8A9 AAAB ACAD AEAFB0B1 B2B3 B4B5 B6B7B8B9 BABB BCBD BEBFC0C1 C2C3 C4C5 C6C7C8C9 CACB CCCD CECFD0D1 D2D3 D4D5 D6D7D8D9 DADB DCDD DEDFE0E1 E2E3 E4E5 E6E7E8E9 EAEB ECED EEEFF0F1 F2F3 F4F5 F6F7F8F9 FAFB FCFD FEFF
END
FreeMemory()
Free memory
Example:
my $N = Vq(size, 4096); # Size of the initial allocation which should be one or more pages
AllocateMemory->call($N, my $A = Vq(address));
$A->dump;
ClearMemory->call($N, $A);
$A->setReg(rax);
$N->setReg(rdi);
PrintOutMemoryInHex;
FreeMemory->call($N, $A); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $r = Assemble;
if ($r =~ m((0000.*0000))s)
{is_deeply length($1), 9748;
}
ClearMemory()
Clear memory - the address of the memory is in rax, the length in rdi
Example:
my $N = Vq(size, 4096); # Size of the initial allocation which should be one or more pages
AllocateMemory->call($N, my $A = Vq(address));
$A->dump;
ClearMemory->call($N, $A); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$A->setReg(rax);
$N->setReg(rdi);
PrintOutMemoryInHex;
FreeMemory->call($N, $A);
my $r = Assemble;
if ($r =~ m((0000.*0000))s)
{is_deeply length($1), 9748;
}
CopyMemory()
Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
Example:
my $s = Rb 0; Rb 1; Rw 2; Rd 3; Rq 4;
my $t = Db 0; Db 1; Dw 2; Dd 3; Dq 4;
Vmovdqu8 xmm0, "[$s]";
Vmovdqu8 xmm1, "[$t]";
PrintOutRegisterInHex xmm0;
PrintOutRegisterInHex xmm1;
Sub rsp, 16;
Mov rax, rsp; # Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
Mov rdi, 16;
Mov rsi, $s;
CopyMemory->call(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);
Files
Process a file
OpenRead()
Open a file, whose name is addressed by rax, for read and return the file descriptor in rax
Example:
Mov rax, Rs($0); # File to read
OpenRead; # Open file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
CloseFile; # Close file
PrintOutRegisterInHex rax;
KeepFree rax, rdi;
Mov rax, Rs(my $f = "zzzTemporaryFile.txt"); # File to write
OpenWrite; # Open file
CloseFile; # Close file
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rax: 0000 0000 0000 0000
END
ok -e $f; # Created file
unlink $f;
OpenWrite()
Create the file named by the terminated string addressed by rax for write
Example:
Mov rax, Rs($0); # File to read
OpenRead; # Open file
PrintOutRegisterInHex rax;
CloseFile; # Close file
PrintOutRegisterInHex rax;
KeepFree rax, rdi;
Mov rax, Rs(my $f = "zzzTemporaryFile.txt"); # File to write
OpenWrite; # Open file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
CloseFile; # Close file
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rax: 0000 0000 0000 0000
END
ok -e $f; # Created file
unlink $f;
CloseFile()
Close the file whose descriptor is in rax
Example:
Mov rax, Rs($0); # File to read
OpenRead; # Open file
PrintOutRegisterInHex rax;
CloseFile; # Close file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
KeepFree rax, rdi;
Mov rax, Rs(my $f = "zzzTemporaryFile.txt"); # File to write
OpenWrite; # Open file
CloseFile; # Close file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
is_deeply Assemble, <<END;
rax: 0000 0000 0000 0003
rax: 0000 0000 0000 0000
END
ok -e $f; # Created file
unlink $f;
StatSize()
Stat a file whose name is addressed by rax to get its size in rax
Example:
Mov rax, Rs($0); # File to stat
StatSize; # Stat the file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
my $r = Assemble =~ s( ) ()gsr;
if ($r =~ m(rax:([0-9a-f]{16}))is) # Compare file size obtained with that from fileSize()
{is_deeply $1, sprintf("%016X", fileSize($0));
}
ReadFile()
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
Example:
ReadFile->call(Vq(file, Rs($0)), (my $s = Vq(size)), my $a = Vq(address)); # Read file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$a->setReg(rax);
$s->setReg(rdi);
PrintOutMemory; # Print memory
my $r = Assemble(1 => (my $f = temporaryFile)); # Assemble and execute
my $i = index(removeNonAsciiChars(readFile $f), removeNonAsciiChars(readFile $0)); # Output contains this file
ok $i > -1;
Short Strings
Operations on Short Strings
LoadShortStringFromMemoryToZmm2($zmm)
Load the short string addressed by rax into the zmm register with the specified number
Parameter Description
1 $zmm Zmm register to load
LoadShortStringFromMemoryToZmm($zmm, $address)
Load the short string addressed by rax into the zmm register with the specified number
Parameter Description
1 $zmm Zmm register to load
2 $address Address of string in memory
Example:
my $s = Rb(3, 0x01, 0x02, 0x03);
my $t = Rb(7, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a);
LoadShortStringFromMemoryToZmm 0, $s; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
LoadShortStringFromMemoryToZmm 1, $t; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ConcatenateShortStrings(0, 1);
PrintOutRegisterInHex xmm0;
PrintOutRegisterInHex xmm1;
my $r = Assemble;
ok $r =~ m(xmm0: 0000 0000 000A 0908 0706 0504 0302 010A);
ok $r =~ m(xmm1: 0000 0000 0000 0000 0A09 0807 0605 0407);
GetLengthOfShortString($reg, $zmm)
Get the length of the short string held in the numbered zmm register into the specified register
Parameter Description
1 $reg Register to hold length
2 $zmm Number of zmm register containing string
SetLengthOfShortString($zmm, $reg)
Set the length of the short string held in the numbered zmm register into the specified register
Parameter Description
1 $zmm Number of zmm register containing string
2 $reg Register to hold length
ConcatenateShortStrings($left, $right)
Concatenate the numbered source zmm containing a short string with the short string in the numbered target zmm.
Parameter Description
1 $left Target zmm
2 $right Source zmm
Hash functions
Hash functions
Hash()
Hash a string addressed by rax with length held in rdi and return the hash code in r15
Example:
Mov rax, "[rbp+24]";
Cstrlen; # Length of string to hash
Mov rdi, r15;
Hash(); # Hash string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex r15;
my $e = Assemble keep=>'hash'; # Assemble to the specified file name
ok qx($e "") =~ m(r15: 0000 3F80 0000 3F80); # Test well known hashes
ok qx($e "a") =~ m(r15: 0000 3F80 C000 45B2);
if (0 and $develop) # 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);
}
Byte Strings
Operations on Byte Strings
Cstrlen()
Length of the C style string addressed by rax returning the length in r15
Example:
my $s = Rs("abcd");
Mov rax, $s;
Cstrlen; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex r15;
ok Assemble =~ m(r15: 0000 0000 0000 0004);
CreateByteString(%options)
Create an relocatable string of bytes in an arena and returns its address in rax. Optionally add a chain header so that 64 byte blocks of memory can be freed and reused within the byte string.
Parameter Description
1 %options Free=>1 adds a free chain.
Example:
my $a = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$a->q('aa');
$a->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aa
END
my $a = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $b = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$a->q('aa');
$b->q('bb');
$a->out;
PrintOutNL;
$b->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aa
bb
END
my $a = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $b = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$a->q('aa');
$a->q('AA');
$a->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aaAA
END
my $a = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $b = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$a->q('aa');
$b->q('bb');
$a->q('AA');
$b->q('BB');
$a->q('aa');
$b->q('bb');
$a->out;
$b->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aaAAaabbBBbb
END
my $a = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$a->q('ab');
my $b = CreateByteString; # Create target byte string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$a->bs(r15);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$a->bs, source=>$b->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$a->bs, source=>$b->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->out; PrintOutNL; # Print byte string
$b->out; PrintOutNL; # Print byte string
$a->length->call($a->bs, my $sa = Vq(size)); $sa->dump;
$a->length->call($b->bs, my $sb = Vq(size)); $sb->dump;
$a->clear ->call($a->bs);
$a->length->call($a->bs, my $sA = Vq(size)); $sA->dump;
$a->length->call($b->bs, my $sB = Vq(size)); $sB->dump;
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
ByteString::length($byteString)
Get the length of a byte string
Parameter Description
1 $byteString Byte string descriptor
ByteString::makeReadOnly($byteString)
Make a byte string read only
Parameter Description
1 $byteString Byte string descriptor
Example:
my $s = CreateByteString; # Create a byte string
$s->q("Hello"); # Write data to byte string
$s->makeReadOnly ->call($s->bs); # Make byte string read only - tested above
$s->makeWriteable->call($s->bs); # Make byte string writable again
$s->q(" World"); # Try to write to byte string
$s->out;
ok Assemble =~ m(Hello World);
ByteString::makeWriteable($byteString)
Make a byte string writable
Parameter Description
1 $byteString Byte string descriptor
Example:
my $s = CreateByteString; # Create a byte string
$s->q("Hello"); # Write data to byte string
$s->makeReadOnly ->call($s->bs); # Make byte string read only - tested above
$s->makeWriteable->call($s->bs); # Make byte string writable again
$s->q(" World"); # Try to write to byte string
$s->out;
ok Assemble =~ m(Hello World);
ByteString::allocate($byteString)
Allocate the amount of space indicated in rdi in the byte string addressed by rax and return the offset of the allocation in the arena in rdi
Parameter Description
1 $byteString Byte string descriptor
Example:
my $s = CreateByteString; # Create a byte string
$s->allocate->call($s->bs, Vq(size, 0x20), my $o1 = Vq(offset)); # Allocate space wanted
$s->allocate->call($s->bs, Vq(size, 0x30), my $o2 = Vq(offset));
$s->allocate->call($s->bs, Vq(size, 0x10), my $o3 = Vq(offset));
$o1->dump;
$o2->dump;
$o3->dump;
is_deeply Assemble, <<END;
offset: 0000 0000 0000 0018
offset: 0000 0000 0000 0038
offset: 0000 0000 0000 0068
END
ByteString::m($byteString)
Append the content with length rdi addressed by rsi to the byte string addressed by rax
Parameter Description
1 $byteString Byte string descriptor
ByteString::q($byteString, $string)
Append a constant string to the byte string
Parameter Description
1 $byteString Byte string descriptor
2 $string String
Example:
my $s = CreateByteString; # Create a string
$s->read->call($s->bs, Vq(file, Rs($0)));
$s->out;
my $r = Assemble(1 => my $f = temporaryFile);
is_deeply fileMd5Sum($f), fileMd5Sum($0); # Output contains this file
unlink $f;
ByteString::ql($byteString, $const)
Append a quoted string containing new line characters to the byte string addressed by rax
Parameter Description
1 $byteString Byte string
2 $const Constant
Example:
my $s = CreateByteString; # Create a string
$s->ql(<<END); # Write code to execute
#!/usr/bin/bash
whoami
ls -la
pwd
END
$s->write ->call($s->bs, my $f = Vq('file', Rs("zzz.sh"))); # Write code to a file
executeFileViaBash->call($f); # Execute the file
unlinkFile ->call($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.
ByteString::char($byteString, $char)
Append a character expressed as a decimal number to the byte string addressed by rax
Parameter Description
1 $byteString Byte string descriptor
2 $char Number of character to be appended
ByteString::nl($byteString)
Append a new line to the byte string addressed by rax
Parameter Description
1 $byteString Byte string descriptor
Example:
my $a = CreateByteString; # Create a string
$a->q('aa');
$a->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aa
END
my $a = CreateByteString; # Create a string
my $b = CreateByteString; # Create a string
$a->q('aa');
$b->q('bb');
$a->out;
PrintOutNL;
$b->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aa
bb
END
my $a = CreateByteString; # Create a string
my $b = CreateByteString; # Create a string
$a->q('aa');
$a->q('AA');
$a->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aaAA
END
my $a = CreateByteString; # Create a string
my $b = CreateByteString; # Create a string
$a->q('aa');
$b->q('bb');
$a->q('AA');
$b->q('BB');
$a->q('aa');
$b->q('bb');
$a->out;
$b->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aaAAaabbBBbb
END
my $a = CreateByteString; # Create a string
$a->q('ab');
my $b = CreateByteString; # Create target byte string
$a->bs(r15);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$a->bs, source=>$b->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$a->bs, source=>$b->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->out; PrintOutNL; # Print byte string
$b->out; PrintOutNL; # Print byte string
$a->length->call($a->bs, my $sa = Vq(size)); $sa->dump;
$a->length->call($b->bs, my $sb = Vq(size)); $sb->dump;
$a->clear ->call($a->bs);
$a->length->call($a->bs, my $sA = Vq(size)); $sA->dump;
$a->length->call($b->bs, my $sB = Vq(size)); $sB->dump;
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
my $s = CreateByteString;
$s->q("A");
$s->nl;
$s->q("B");
$s->out;
PrintOutNL;
is_deeply Assemble, <<END;
A
B
END
ByteString::z($byteString)
Append a trailing zero to the byte string addressed by rax
Parameter Description
1 $byteString Byte string descriptor
Example:
my $s = CreateByteString; # Create a string
$s->read->call($s->bs, Vq(file, Rs($0)));
$s->out;
my $r = Assemble(1 => my $f = temporaryFile);
is_deeply fileMd5Sum($f), fileMd5Sum($0); # Output contains this file
unlink $f;
ByteString::rdiInHex()
Add the content of register rdi in hexadecimal in big endian notation to a byte string
Example:
my $s = CreateByteString; # Create a string
Mov rdi, 0x88776655;
Shl rdi, 32;
Or rdi, 0x44332211;
$s->rdiInHex; # Append a constant to the byte string
$s->out;
ok Assemble =~ m(8877665544332211);
ByteString::append($byteString)
Append one byte string to another
Parameter Description
1 $byteString Byte string descriptor
ByteString::clear($byteString)
Clear the byte string addressed by rax
Parameter Description
1 $byteString Byte string descriptor
Example:
my $a = CreateByteString; # Create a string
$a->q('aa');
$a->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aa
END
my $a = CreateByteString; # Create a string
my $b = CreateByteString; # Create a string
$a->q('aa');
$b->q('bb');
$a->out;
PrintOutNL;
$b->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aa
bb
END
my $a = CreateByteString; # Create a string
my $b = CreateByteString; # Create a string
$a->q('aa');
$a->q('AA');
$a->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aaAA
END
my $a = CreateByteString; # Create a string
my $b = CreateByteString; # Create a string
$a->q('aa');
$b->q('bb');
$a->q('AA');
$b->q('BB');
$a->q('aa');
$b->q('bb');
$a->out;
$b->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aaAAaabbBBbb
END
my $a = CreateByteString; # Create a string
$a->q('ab');
my $b = CreateByteString; # Create target byte string
$a->bs(r15);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$a->bs, source=>$b->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$a->bs, source=>$b->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->out; PrintOutNL; # Print byte string
$b->out; PrintOutNL; # Print byte string
$a->length->call($a->bs, my $sa = Vq(size)); $sa->dump;
$a->length->call($b->bs, my $sb = Vq(size)); $sb->dump;
$a->clear ->call($a->bs);
$a->length->call($a->bs, my $sA = Vq(size)); $sA->dump;
$a->length->call($b->bs, my $sB = Vq(size)); $sB->dump;
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
ByteString::write($byteString)
Write the content in a byte string addressed by rax to a temporary file and replace the byte string content with the name of the temporary file
Parameter Description
1 $byteString Byte string descriptor
Example:
my $s = CreateByteString; # Create a string
$s->ql(<<END); # Write code to execute
#!/usr/bin/bash
whoami
ls -la
pwd
END
$s->write ->call($s->bs, my $f = Vq('file', Rs("zzz.sh"))); # Write code to a file
executeFileViaBash->call($f); # Execute the file
unlinkFile ->call($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.
ByteString::read($byteString)
Read the named file (terminated with a zero byte) and place it into the named byte string.
Parameter Description
1 $byteString Byte string descriptor
Example:
my $s = CreateByteString; # Create a string
$s->read->call($s->bs, Vq(file, Rs($0)));
$s->out;
my $r = Assemble(1 => my $f = temporaryFile);
is_deeply fileMd5Sum($f), fileMd5Sum($0); # Output contains this file
unlink $f;
ByteString::out($byteString)
Print the specified byte string addressed by rax on sysout
Parameter Description
1 $byteString Byte string descriptor
Example:
my $a = CreateByteString; # Create a string
$a->q('aa');
$a->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aa
END
my $a = CreateByteString; # Create a string
my $b = CreateByteString; # Create a string
$a->q('aa');
$b->q('bb');
$a->out;
PrintOutNL;
$b->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aa
bb
END
my $a = CreateByteString; # Create a string
my $b = CreateByteString; # Create a string
$a->q('aa');
$a->q('AA');
$a->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aaAA
END
my $a = CreateByteString; # Create a string
my $b = CreateByteString; # Create a string
$a->q('aa');
$b->q('bb');
$a->q('AA');
$b->q('BB');
$a->q('aa');
$b->q('bb');
$a->out;
$b->out;
PrintOutNL;
is_deeply Assemble, <<END; # Assemble and execute
aaAAaabbBBbb
END
my $a = CreateByteString; # Create a string
$a->q('ab');
my $b = CreateByteString; # Create target byte string
$a->bs(r15);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$a->bs, source=>$b->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$a->bs, source=>$b->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->append->call(target=>$b->bs, source=>$a->bs);
$a->out; PrintOutNL; # Print byte string
$b->out; PrintOutNL; # Print byte string
$a->length->call($a->bs, my $sa = Vq(size)); $sa->dump;
$a->length->call($b->bs, my $sb = Vq(size)); $sb->dump;
$a->clear ->call($a->bs);
$a->length->call($a->bs, my $sA = Vq(size)); $sA->dump;
$a->length->call($b->bs, my $sB = Vq(size)); $sB->dump;
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
my $s = CreateByteString; # Create a string
$s->ql(<<END); # Write code to execute
#!/usr/bin/bash
whoami
ls -la
pwd
END
$s->write ->call($s->bs, my $f = Vq('file', Rs("zzz.sh"))); # Write code to a file
executeFileViaBash->call($f); # Execute the file
unlinkFile ->call($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.
executeFileViaBash()
Execute the file named in the byte string addressed by rax with bash
unlinkFile()
Unlink the named file
ByteString::dump($byteString)
Dump details of a byte string
Parameter Description
1 $byteString Byte string descriptor
Example:
my $t = GenTree(2,2); # Tree description
$t->node->(); # Root
Movdqa xmm1, xmm0; # Root is in xmm1
if (1) # New left node
{$t->node->(); # Node in xmm0
Movdqa xmm2, xmm0; # Left is in xmm2
cxr {$t->insertLeft->()} 1,2; # Insert left under root
cxr {$t->dump->("Left")} 2; # Left node after insertion
}
if (1) # New right node in xmm0
{$t->node->();
Movdqa xmm3, xmm0; # Right is in xmm3
cxr {$t->insertRight->()} 1,3; # Insert left under root
cxr {$t->dump->("Right")} 3; # Right node after insertion
}
cxr
{$t->dump->("Root"); # Root node after insertions
$t->isRoot->();
IfNz {PrintOutStringNL "root"} sub {PrintOutStringNL "NOT root"};
} 1;
PushRR xmm0; # Dump underlying byte string
PopRR rdi, rax;
$t->byteString->dump;
Exit; # Return to operating system
is_deeply Assemble, <<END; # Test tree so produced
Left
ArenaTreeNode at: 0000 0000 0000 00B0
up: 0000 0000 0000 0010
left: 0000 0000 0000 0000
right: 0000 0000 0000 0000
Right
ArenaTreeNode at: 0000 0000 0000 0150
up: 0000 0000 0000 0010
left: 0000 0000 0000 0000
right: 0000 0000 0000 0000
Root
ArenaTreeNode at: 0000 0000 0000 0010
up: 0000 0000 0000 0000
left: 0000 0000 0000 00B0
right: 0000 0000 0000 0150
root
Byte String
Size: 0000 0000 0000 1000
Used: 0000 0000 0000 01E0
END
Block Strings
Strings made from zmm sized blocks of text
ByteString::CreateBlockString($byteString)
Create a string from a doubly link linked list of 64 byte blocks linked via 4 byte offsets in the byte string addressed by rax and return its descriptor
Parameter Description
1 $byteString Byte string description
BlockString::allocBlock($blockString, $bsa)
Allocate a block to hold a zmm register in the specified byte string and return the offset of the block in a variable
Parameter Description
1 $blockString Block string descriptor
2 $bsa Variable containing address of underlying byte string
BlockString::getBlockLengthInZmm($blockString, $zmm)
Get the block length of the numbered zmm and return it in a variable
Parameter Description
1 $blockString Block string descriptor
2 $zmm Number of zmm register
BlockString::setBlockLengthInZmm($blockString, $length, $zmm)
Set the block length of the numbered zmm to the specified length
Parameter Description
1 $blockString Block string descriptor
2 $length Length as a variable
3 $zmm Number of zmm register
BlockString::getBlock($blockString, $bsa, $block, $zmm)
Get the block with the specified offset in the specified block string and return it in the numbered zmm
Parameter Description
1 $blockString Block string descriptor
2 $bsa Byte string variable
3 $block Offset of the block as a variable
4 $zmm Number of zmm register to contain block
BlockString::putBlock($blockString, $bsa, $block, $zmm)
Write the numbered zmm to the block at the specified offset in the specified byte string
Parameter Description
1 $blockString Block string descriptor
2 $bsa Byte string variable
3 $block Block in byte string
4 $zmm Content variable
BlockString::getNextAndPrevBlockOffsetFromZmm($blockString, $zmm)
Get the offsets of the next and previous blocks as variables from the specified zmm
Parameter Description
1 $blockString Block string descriptor
2 $zmm Zmm containing block
BlockString::putNextandPrevBlockOffsetIntoZmm($blockString, $zmm, $next, $prev)
Save next and prev offsets into a zmm representing a block
Parameter Description
1 $blockString Block string descriptor
2 $zmm Zmm containing block
3 $next Next offset as a variable
4 $prev Prev offset as a variable
BlockString::dump($blockString)
Dump a block string to sysout
Parameter Description
1 $blockString Block string descriptor
BlockString::appendSub($blockString, $first, $source, $length, $bsa)
Append the specified content in memory to the specified block string
Parameter Description
1 $blockString Block string descriptor
2 $first Variable containing offset of first block
3 $source Variable addressing source
4 $length Variable containing length of source
5 $bsa Variable containing byte string address
BlockString::append($blockString, $source, $length)
Append the specified content in memory to the specified block string
Parameter Description
1 $blockString Block string descriptor
2 $source Variable addressing source
3 $length Variable containing length of source
Tree
Tree operations
GenTree($keyLength, $dataLength)
Generate a set of routines to manage a tree held in a byte string with key and data fields of specified widths. Allocate a byte string to contain the tree, return its address in xmm0=(0, tree).
Parameter Description
1 $keyLength Fixed key length in bytes
2 $dataLength Fixed data length in bytes
Example:
my $t = GenTree(2,2); # Tree description # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$t->node->(); # Root
Movdqa xmm1, xmm0; # Root is in xmm1
if (1) # New left node
{$t->node->(); # Node in xmm0
Movdqa xmm2, xmm0; # Left is in xmm2
cxr {$t->insertLeft->()} 1,2; # Insert left under root
cxr {$t->dump->("Left")} 2; # Left node after insertion
}
if (1) # New right node in xmm0
{$t->node->();
Movdqa xmm3, xmm0; # Right is in xmm3
cxr {$t->insertRight->()} 1,3; # Insert left under root
cxr {$t->dump->("Right")} 3; # Right node after insertion
}
cxr
{$t->dump->("Root"); # Root node after insertions
$t->isRoot->();
IfNz {PrintOutStringNL "root"} sub {PrintOutStringNL "NOT root"};
} 1;
PushRR xmm0; # Dump underlying byte string
PopRR rdi, rax;
$t->byteString->dump;
Exit; # Return to operating system
is_deeply Assemble, <<END; # Test tree so produced
Left
ArenaTreeNode at: 0000 0000 0000 00B0
up: 0000 0000 0000 0010
left: 0000 0000 0000 0000
right: 0000 0000 0000 0000
Right
ArenaTreeNode at: 0000 0000 0000 0150
up: 0000 0000 0000 0010
left: 0000 0000 0000 0000
right: 0000 0000 0000 0000
Root
ArenaTreeNode at: 0000 0000 0000 0010
up: 0000 0000 0000 0000
left: 0000 0000 0000 00B0
right: 0000 0000 0000 0150
root
Byte String
Size: 0000 0000 0000 1000
Used: 0000 0000 0000 01E0
END
Assemble
Assemble generated code
Start()
Initialize the assembler
Exit($c)
Exit with the specified return code or zero if no return code supplied. Assemble() automatically adds a call to Exit(0) if the last operation in the program is not a call to Exit.
Parameter Description
1 $c Return code
LocateIntelEmulator()
Assemble the generated code
Assemble(%options)
Assemble the generated code
Parameter Description
1 %options Options
Example:
PrintOutStringNL "Hello World";
PrintErrStringNL "Hello World";
is_deeply Assemble, <<END; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Hello World
Hello World
END
BlockString Definition
Block string definition
Output fields
address
Variable addressing first block in string
byteString
Bytes string definition
length
Variable containing maximum length in a block
links
Location of links in bytes in zmm
next
Location of next offset in block in bytes
offset
Size of an offset is size of eax
prev
Location of prev offset in block in bytes
size
Size of a block == size of a zmm
Attributes
The following is a list of all the attributes in this package. A method coded with the same name in your package will over ride the method of the same name in this package and thus provide your value for the attribute in place of the default value supplied for this attribute by this package.
Replaceable Attribute List
Pi32 Pi64
Pi32
Pi as a 32 bit float
Pi64
Pi as a 64 bit float
Private Methods
Label()
Create a unique label
Dbwdq($s, @d)
Layout data
Parameter Description
1 $s Element size
2 @d Data to be laid out
Rbwdq($s, @d)
Layout data
Parameter Description
1 $s Element size
2 @d Data to be laid out
hexTranslateTable()
Create/address a hex translate table and return its label
PrintOutRipInHex()
Print the instruction pointer in hex
PrintOutRflagsInHex()
Print the flags register in hex
Variable::confirmIsMemory($memory, $address, $length)
Check that variable describes allocated memory and optionally load registers with its length and size
Parameter Description
1 $memory Variable describing memory as returned by Allocate Memory
2 $address Register to contain address
3 $length Register to contain size
ByteString::updateSpace($byteString)
Make sure that the byte string addressed by rax has enough space to accommodate content of length rdi
Parameter Description
1 $byteString Byte string descriptor
removeNonAsciiChars($string)
Return a copy of the specified string with all the non ascii characters removed
Parameter Description
1 $string String
totalBytesAssembled()
Total size in bytes of all files assembled during testing
Index
1 All8Structure - Create a structure consisting of 8 byte fields
2 AllocateAll8OnStack - Create a local data descriptor consisting of the specified number of 8 byte local variables and return an array: (local data descriptor, variable definitions.
3 AllocateMemory - Allocate the specified amount of memory via mmap and return its address
4 Assemble - Assemble the generated code
5 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
6 BlockString::append - Append the specified content in memory to the specified block string
7 BlockString::appendSub - Append the specified content in memory to the specified block string
8 BlockString::dump - Dump a block string to sysout
9 BlockString::getBlock - Get the block with the specified offset in the specified block string and return it in the numbered zmm
10 BlockString::getBlockLengthInZmm - Get the block length of the numbered zmm and return it in a variable
11 BlockString::getNextAndPrevBlockOffsetFromZmm - Get the offsets of the next and previous blocks as variables from the specified zmm
12 BlockString::putBlock - Write the numbered zmm to the block at the specified offset in the specified byte string
13 BlockString::putNextandPrevBlockOffsetIntoZmm - Save next and prev offsets into a zmm representing a block
14 BlockString::setBlockLengthInZmm - Set the block length of the numbered zmm to the specified length
15 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
16 ByteString::append - Append one byte string to another
17 ByteString::char - Append a character expressed as a decimal number to the byte string addressed by rax
18 ByteString::clear - Clear the byte string addressed by rax
19 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
20 ByteString::dump - Dump details of a byte string
21 ByteString::length - Get the length of a byte string
22 ByteString::m - Append the content with length rdi addressed by rsi to the byte string addressed by rax
23 ByteString::makeReadOnly - Make a byte string read only
24 ByteString::makeWriteable - Make a byte string writable
25 ByteString::nl - Append a new line to the byte string addressed by rax
26 ByteString::out - Print the specified byte string addressed by rax on sysout
27 ByteString::q - Append a constant string to the byte string
28 ByteString::ql - Append a quoted string containing new line characters to the byte string addressed by rax
29 ByteString::rdiInHex - Add the content of register rdi in hexadecimal in big endian notation to a byte string
30 ByteString::read - Read the named file (terminated with a zero byte) and place it into the named byte string.
31 ByteString::updateSpace - Make sure that the byte string addressed by rax has enough space to accommodate content of length rdi
32 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
33 ByteString::z - Append a trailing zero to the byte string addressed by rax
34 ClearMemory - Clear memory - the address of the memory is in rax, the length in rdi
35 ClearRegisters - Clear registers by setting them to zero
36 ClearZF - Clear the zero flag
37 CloseFile - Close the file whose descriptor is in rax
38 Comment - Insert a comment into the assembly code
39 ConcatenateShortStrings - Concatenate the numbered source zmm containing a short string with the short string in the numbered target zmm.
40 Copy - Copy the source to the target register
41 CopyMemory - Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
42 cr - Call a subroutine with a reordering of the registers.
43 CreateByteString - Create an relocatable string of bytes in an arena and returns its address in rax.
44 Cstrlen - Length of the C style string addressed by rax returning the length in r15
45 cxr - Call a subroutine with a reordering of the xmm registers.
46 Db - Layout bytes in the data segment and return their label
47 Dbwdq - Layout data
48 DComment - Insert a comment into the data segment
49 Dd - Layout double words in the data segment and return their label
50 Decrement - Decrement the specified register
51 Dq - Layout quad words in the data segment and return their label
52 Ds - Layout bytes in memory and return their label
53 Dw - Layout words in the data segment and return their label
54 executeFileViaBash - Execute the file named in the byte string addressed by rax with bash
55 Exit - Exit with the specified return code or zero if no return code supplied.
56 Float32 - 32 bit float
57 Float64 - 64 bit float
58 For - For - iterate the body as long as register is less than limit incrementing by increment each time
59 ForEver - Iterate for ever
60 ForIn - For - iterate the body as long as register plus increment is less than than limit incrementing by increment each time
61 Fork - Fork
62 FreeMemory - Free memory
63 GenTree - Generate a set of routines to manage a tree held in a byte string with key and data fields of specified widths.
64 getBFromZmmAsVariable - Get the byte from the numbered zmm register and return it in a variable
65 getBwdqFromZmmAsVariable - Get the numbered byte|word|double word|quad word from the numbered zmm register and return it in a variable
66 getDFromZmmAsVariable - Get the double word from the numbered zmm register and return it in a variable
67 GetLengthOfShortString - Get the length of the short string held in the numbered zmm register into the specified register
68 GetPid - Get process identifier
69 GetPidInHex - Get process identifier in hex as 8 zero terminated bytes in rax
70 GetPPid - Get parent process identifier
71 getQFromZmmAsVariable - Get the quad word from the numbered zmm register and return it in a variable
72 GetUid - Get userid of current process
73 getWFromZmmAsVariable - Get the word from the numbered zmm register and return it in a variable
74 Hash - Hash a string addressed by rax with length held in rdi and return the hash code in r15
75 hexTranslateTable - Create/address a hex translate table and return its label
76 If - If
77 IfEq - If equal execute the then body else the else body
78 IfGe - If greater than or equal execute the then body else the else body
79 IfGt - If greater than execute the then body else the else body
80 IfLe - If less than or equal execute the then body else the else body
81 IfLt - If less than execute the then body else the else body
82 IfNe - If not equal execute the then body else the else body
83 IfNz - If not zero execute the then body else the else body
84 Increment - Increment the specified register
85 InsertIntoXyz - Shift and insert the specified word, double, quad from rax or the contents of xmm0 into the specified xyz register at the specified position shifting data above it to the left towards higher order bytes.
86 Keep - Mark free registers so that they are not updated until we Free them or complain if the register is already in use.
87 KeepFree - Free registers so that they can be reused
88 KeepPop - Reset the status of the specified registers to the status quo ante the last push
89 KeepPush - Push the current status of the specified registers and then mark them as free
90 KeepReturn - Pop the specified register and mark it as in use to effect a subroutine return with this register.
91 KeepSet - Confirm that the specified registers are in use
92 Label - Create a unique label
93 LoadShortStringFromMemoryToZmm - Load the short string addressed by rax into the zmm register with the specified number
94 LoadShortStringFromMemoryToZmm2 - Load the short string addressed by rax into the zmm register with the specified number
95 LoadTargetZmmFromSourceZmm - Load bytes into the numbered target zmm register at a register specified offset with source bytes from a numbered source zmm register at a specified register offset for a specified register length.
96 LoadZmmFromMemory - Load bytes into the numbered target zmm register at a register specified offset with source bytes from memory addressed by a specified register for a specified register length from memory addressed by a specified register.
97 LocalData - Map local data
98 LocalData::allocate8 - Add some 8 byte local variables and return an array of variable definitions
99 LocalData::free - Free a local data area on the stack
100 LocalData::start - Start a local data area on the stack
101 LocalData::variable - Add a local variable
102 LocalVariable::stack - Address a local variable on the stack
103 LocateIntelEmulator - Assemble the generated code
104 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
105 MaximumOfTwoRegisters - Return in the specified register the value in the second register if it is greater than the value in the first register
106 MinimumOfTwoRegisters - Return in the specified register the value in the second register if it is less than the value in the first register
107 Minus - Subtract the third operand from the second operand and place the result in the first operand
108 Nasm::X86::Sub::call - Call a sub passing it some parameters
109 OpenRead - Open a file, whose name is addressed by rax, for read and return the file descriptor in rax
110 OpenWrite - Create the file named by the terminated string addressed by rax for write
111 PeekR - Peek at register on stack
112 Plus - Add the last operands and place the result in the first operand
113 PopR - Pop registers from the stack
114 PopRR - Pop registers from the stack without tracking
115 PrintErrNL - Print a new line to stderr
116 PrintErrString - Print a constant string to stderr.
117 PrintErrStringNL - Print a new line to stderr
118 PrintOutMemory - Print the memory addressed by rax for a length of rdi::
119 PrintOutMemoryInHex - Dump memory from the address in rax for the length in rdi
120 PrintOutMemoryInHexNL - Dump memory from the address in rax for the length in rdi and then print a new line
121 PrintOutMemoryNL - Print the memory addressed by rax for a length of rdi followed by a new line
122 PrintOutNL - Print a new line to stdout
123 PrintOutRaxInHex - Write the content of register rax to stderr in hexadecimal in big endian notation
124 PrintOutRaxInReverseInHex - Write the content of register rax to stderr in hexadecimal in little endian notation
125 PrintOutRegisterInHex - Print any register as a hex string
126 PrintOutRegistersInHex - Print the general purpose registers in hex
127 PrintOutRflagsInHex - Print the flags register in hex
128 PrintOutRipInHex - Print the instruction pointer in hex
129 PrintOutString - Print a constant string to sysout.
130 PrintOutStringNL - Print a constant string to sysout followed by new line
131 PrintOutZF - Print the zero flag without disturbing it
132 PushR - Push registers onto the stack
133 PushRR - Push registers onto the stack without tracking
134 Rb - Layout bytes in the data segment and return their label
135 Rbwdq - Layout data
136 RComment - Insert a comment into the read only data segment
137 Rd - Layout double words in the data segment and return their label
138 ReadFile - Read a file whose name is addressed by rax into memory.
139 ReadTimeStampCounter - Read the time stamp counter and return the time in nanoseconds in rax
140 RegisterSize - Return the size of a register
141 removeNonAsciiChars - Return a copy of the specified string with all the non ascii characters removed
142 ReorderSyscallRegisters - Map the list of registers provided to the 64 bit system call sequence
143 ReorderXmmRegisters - Map the list of xmm registers provided to 0-31
144 RestoreFirstFour - Restore the first 4 parameter registers
145 RestoreFirstFourExceptRax - Restore the first 4 parameter registers except rax so it can return its value
146 RestoreFirstFourExceptRaxAndRdi - Restore the first 4 parameter registers except rax and rdi so we can return a pair of values
147 RestoreFirstSeven - Restore the first 7 parameter registers
148 RestoreFirstSevenExceptRax - Restore the first 7 parameter registers except rax which is being used to return the result
149 RestoreFirstSevenExceptRaxAndRdi - Restore the first 7 parameter registers except rax and rdi which are being used to return the results
150 Rq - Layout quad words in the data segment and return their label
151 Rs - Layout bytes in read only memory and return their label
152 Rw - Layout words in the data segment and return their label
153 SaveFirstFour - Save the first 4 parameter registers making any parameter registers read only
154 SaveFirstSeven - Save the first 7 parameter registers
155 Scope - Create and stack a new scope and continue with it as the current scope
156 Scope::contains - Check that the named parent scope contains the specified child scope.
157 Scope::currentlyVisible - Check that the named parent scope is currently visible
158 ScopeEnd - End the current scope and continue with the containing parent scope
159 SetLabel - Set a label in the code section
160 SetLengthOfShortString - Set the length of the short string held in the numbered zmm register into the specified register
161 SetMaskRegister - Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere
162 SetRegisterToMinusOne - Set the specified register to -1
163 SetZF - Set the zero flag
164 Start - Initialize the assembler
165 StatSize - Stat a file whose name is addressed by rax to get its size in rax
166 Structure - Create a structure addressed by a register
167 Structure::field - Add a field of the specified length with an optional comment
168 StructureField::addr - Address a field in a structure by either the default register or the named register
169 Subroutine - Create a subroutine that can be called in assembler code
170 totalBytesAssembled - Total size in bytes of all files assembled during testing
171 unlinkFile - Unlink the named file
172 UnReorderSyscallRegisters - Recover the initial values in registers that were reordered
173 UnReorderXmmRegisters - Recover the initial values in the xmm registers that were reordered
174 Variable - Create a new variable with the specified size and name initialized via an expression
175 Variable::add - Add the right hand variable to the left hand variable and return the result as a new variable
176 Variable::address - Get the address of a variable with an optional offset
177 Variable::and - And two variables
178 Variable::arithmetic - Return a variable containing the result of an arithmetic operation on the left hand and right hand side variables
179 Variable::assign - Assign to the left hand side the value of the right hand side
180 Variable::boolean - Combine the left hand variable with the right hand variable via a boolean operator
181 Variable::clearMemory - Clear the memory described in this variable
182 Variable::confirmIsMemory - Check that variable describes allocated memory and optionally load registers with its length and size
183 Variable::copy - Copy one variable into another
184 Variable::copyAddress - Copy a reference to a variable
185 Variable::copyMemoryFrom - Copy from one block of memory to another
186 Variable::copyRef - Copy one variable into an referenced variable
187 Variable::debug - Dump the value of a variable on stdout with an indication of where the dump came from
188 Variable::dec - Decrement a variable
189 Variable::divide - Divide the left hand variable by the right hand variable and return the result as a new variable
190 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
191 Variable::dump - Dump the value of a variable on stdout
192 Variable::eq - Check whether the left hand variable is equal to the right hand variable
193 Variable::equals - Equals operator
194 Variable::for - Iterate the body from 0 limit times.
195 Variable::freeMemory - Free the memory described in this variable
196 Variable::ge - Check whether the left hand variable is greater than or equal to the right hand variable
197 Variable::getReg - Load the variable from the named registers
198 Variable::gt - Check whether the left hand variable is greater than the right hand variable
199 Variable::inc - Increment a variable
200 Variable::incDec - Increment or decrement a variable
201 Variable::isRef - Check whether the specified variable is a reference to another variable
202 Variable::le - Check whether the left hand variable is less than or equal to the right hand variable
203 Variable::loadZmm - Load bytes from the memory addressed by the specified source variable into the numbered zmm register.
204 Variable::lt - Check whether the left hand variable is less than the right hand variable
205 Variable::max - Maximum of two variables
206 Variable::min - Minimum of two variables
207 Variable::minusAssign - Implement minus and assign
208 Variable::mod - Divide the left hand variable by the right hand variable and return the remainder as a new variable
209 Variable::ne - Check whether the left hand variable is not equal to the right hand variable
210 Variable::or - Or two variables
211 Variable::plusAssign - Implement plus and assign
212 Variable::print - Write the value of a variable on stdout
213 Variable::printOutMemoryInHex - Print allocated memory in hex
214 Variable::putBIntoZmm - Place the value of the content variable at the byte in the numbered zmm register
215 Variable::putBwdqIntoZmm - Place the value of the content variable at the byte|word|double word|quad word in the numbered zmm register
216 Variable::putDIntoZmm - Place the value of the content variable at the double word in the numbered zmm register
217 Variable::putQIntoZmm - Place the value of the content variable at the quad word in the numbered zmm register
218 Variable::putWIntoZmm - Place the value of the content variable at the word in the numbered zmm register
219 Variable::saveZmm - Save bytes into the memory addressed by the target variable from the numbered zmm register.
220 Variable::setMask - Set the mask register to ones starting at the specified position for the specified length and zeroes elsewhere
221 Variable::setReg - Set the named registers from the content of the variable
222 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
223 Variable::str - The name of the variable
224 Variable::sub - Subtract the right hand variable from the left hand variable and return the result as a new variable
225 Variable::times - Multiply the left hand variable by the right hand variable and return the result as a new variable
226 Vb - Define a byte variable
227 Vd - Define a double word variable
228 Vq - Define a quad variable
229 Vr - Define a reference variable
230 Vw - Define a word variable
231 Vx - Define an xmm variable
232 VxyzInit - Initialize an xyz register from general purpose registers
233 Vy - Define an ymm variable
234 Vz - Define an zmm variable
235 WaitPid - Wait for the pid in rax to complete
Installation
This module is written in 100% Pure Perl and, thus, it is easy to read, comprehend, use, modify and install via cpan:
sudo cpan install Nasm::X86
Author
Copyright
Copyright (c) 2016-2021 Philip R Brenan.
This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.