Looking for help!
Name
Nasm::X86 - Generate Nasm assembler code
Synopsis
Write and execute x64 instructions from perl, using perl as a macro assembler as shown in the following examples.
Avx512 instructions
Use avx512 instructions to reorder data using 512 bit zmm registers:
Start;
my $q = Rs my $s = join '', ('a'..'p')x4;
Mov rax, Ds('0'x128);
Vmovdqu32 zmm0, "[$q]";
Vprolq zmm1, zmm0, 32;
Vmovdqu32 "[rax]", zmm1;
Mov rdi, length $s;
PrintOutMemory;
Exit;
ok $s =~ m(abcdefghijklmnopabcdefghijklmnopabcdefghijklmnopabcdefghijklmnop)s;
ok Assemble =~ m(efghabcdmnopijklefghabcdmnopijklefghabcdmnopijklefghabcdmnopijkl)s;
Dynamic string held in an arena
Create a dynamic byte string, add some content to it and then print it.
Start; # Start the program
my $q = Rs my $t = 'ab';
my $s = CreateByteString; # Create a string
Mov rsi, $q; # Address of memory to copy
Mov rdi, length $t; # Length of memory to copy
$s->m; # Copy memory into byte string
Mov rdi, rax; # Save source byte string
CreateByteString; # Create target byte string
$s->copy; # Copy source to target
Xchg rdi, rax; # Swap source and target byte strings
$s->copy; # Copy source to target
Xchg rdi, rax; # Swap source and target byte strings
$s->copy;
Xchg rdi, rax;
$s->copy;
Xchg rdi, rax;
$s->copy;
$s->out; # Print byte string
Exit; # Return to operating system
Assemble =~ m(($t x 8)); # Assemble and execute
Process management
Start a child process and wait for it, printing out the process identifiers of each process involved:
Start; # Start the program
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;
};
Exit; # Return to operating system
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:
Start; # Start the program
Mov rax, Rs($0); # File to read
ReadFile; # Read file
PrintOutMemory; # Print memory
Exit; # Return to operating system
my $r = Assemble; # Assemble and execute
ok index($r, readFile($0)) > -1; # Output contains this file
Installation
You will need the Intel Software Development Emulator and the Networkwide Assembler installed on your test system. For full details of how to do this see: https://github.com/philiprbrenan/NasmX86/blob/main/.github/workflows/main.yml
Description
Generate Nasm assembler code
Version "202104014".
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
Ds(@d)
Layout bytes in memory and return their label
Parameter Description
1 @d Data to be laid out
Example:
Start;
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;
Exit;
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:
Start;
Comment "Print a string from memory";
my $s = "Hello World";
Mov rax, Rs($s); # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov rdi, length $s;
PrintOutMemory;
Exit;
ok Assemble =~ m(Hello World);
Db(@bytes)
Layout bytes in the data segment and return their label
Parameter Description
1 @bytes Bytes to layout
Dw(@words)
Layout words in the data segment and return their label
Parameter Description
1 @words Words to layout
Dd(@dwords)
Layout double words in the data segment and return their label
Parameter Description
1 @dwords Double words to layout
Dq(@qwords)
Layout quad words in the data segment and return their label
Parameter Description
1 @qwords Quad words to layout
Rb(@bytes)
Layout bytes in the data segment and return their label
Parameter Description
1 @bytes Bytes to layout
Rw(@words)
Layout words in the data segment and return their label
Parameter Description
1 @words Words to layout
Rd(@dwords)
Layout double words in the data segment and return their label
Parameter Description
1 @dwords Double words to layout
Rq(@qwords)
Layout quad words in the data segment and return their label
Parameter Description
1 @qwords Quad words to layout
Registers
Operations on registers
SaveFirstFour()
Save the first 4 parameter registers
RestoreFirstFour()
Restore the first 4 parameter registers
RestoreFirstFourExceptRax()
Restore the first 4 parameter registers except rax so it can return its value
SaveFirstSeven()
Save the first 7 parameter registers
RestoreFirstSeven()
Restore the first 7 parameter registers
RestoreFirstSevenExceptRax()
Restore the first 7 parameter registers except rax which is being used to return the result
RestoreFirstSevenExceptRaxAndRdi()
Restore the first 7 parameter registers except rax and rdi which are being used to return the results
RegisterSize($r)
Return the size of a register
Parameter Description
1 $r Register
ClearRegisters(@registers)
Clear registers by setting them to zero
Parameter Description
1 @registers Registers
Structured Programming
Structured programming constructs
If($then, $else)
If
Parameter Description
1 $then Then - required
2 $else Else - optional
Example:
Start;
Mov rax, 0;
Test rax,rax;
If # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{PrintOutRegisterInHex rax;
} sub
{PrintOutRegisterInHex rbx;
};
Mov rax, 1;
Test rax,rax;
If # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{PrintOutRegisterInHex rcx;
} sub
{PrintOutRegisterInHex rdx;
};
Exit;
ok Assemble =~ m(rbx.*rcx)s;
For($body, $register, $limit, $increment)
For
Parameter Description
1 $body Body
2 $register Register
3 $limit Limit on loop
4 $increment Increment
Example:
Start; # Start the program
For # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{PrintOutRegisterInHex rax
} rax, 16, 1;
Exit; # Return to operating system
my $r = Assemble;
ok $r =~ m(( 0000){3} 0000)i;
ok $r =~ m(( 0000){3} 000F)i;
S($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.
Example:
Start;
Mov rax, 0x44332211;
PrintOutRegisterInHex rax;
my $s = S # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
{PrintOutRegisterInHex rax;
Inc rax;
PrintOutRegisterInHex rax;
};
Call $s;
PrintOutRegisterInHex rax;
Exit;
my $r = Assemble;
ok $r =~ m(0000 0000 4433 2211.*2211.*2212.*0000 0000 4433 2212)s;
Comment(@comment)
Insert a comment into the assembly code
Parameter Description
1 @comment Text of comment
Example:
Start;
Comment "Print a string from memory"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
my $s = "Hello World";
Mov rax, Rs($s);
Mov rdi, length $s;
PrintOutMemory;
Exit;
ok Assemble =~ m(Hello World);
PrintOutNl()
Write a new line
Example:
Start;
my $q = Rs('abababab');
Mov(rax, "[$q]");
PrintOutString "rax: ";
PrintOutRaxInHex;
PrintOutNl; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Xor rax, rax;
PrintOutString "rax: ";
PrintOutRaxInHex;
PrintOutNl; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Exit;
ok Assemble =~ m(rax: 6261 6261 6261 6261.*rax: 0000 0000 0000 0000)s;
PrintOutString($string)
Write a constant string to sysout.
Parameter Description
1 $string String
Example:
Start;
PrintOutString "Hello World"; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Exit;
ok Assemble =~ m(Hello World);
PrintOutRaxInHex()
Write the content of register rax to stderr in hexadecimal in big endian notation
Example:
Start;
my $q = Rs('abababab');
Mov(rax, "[$q]");
PrintOutString "rax: ";
PrintOutRaxInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutNl;
Xor rax, rax;
PrintOutString "rax: ";
PrintOutRaxInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutNl;
Exit;
ok Assemble =~ m(rax: 6261 6261 6261 6261.*rax: 0000 0000 0000 0000)s;
ReverseBytesInRax()
Reverse the bytes in rax
PrintOutRaxInReverseInHex()
Write the content of register rax to stderr in hexadecimal in little endian notation
Example:
Start;
Mov rax, 0x88776655;
Shl rax, 32;
Or rax, 0x44332211;
PrintOutRaxInHex;
PrintOutRaxInReverseInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Exit;
ok Assemble =~ m(8877 6655 4433 2211 1122 3344 5566 7788)s;
PrintOutRegisterInHex($r)
Print any register as a hex string
Parameter Description
1 $r Name of the register to print
Example:
Start;
my $q = Rs(('a'..'p')x4);
Mov r8,"[$q]";
PrintOutRegisterInHex r8; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Exit;
ok Assemble =~ m(r8: 6867 6665 6463 6261)s;
PrintOutRipInHex()
Print the instruction pointer in hex
PrintOutRflagsInHex()
Print the flags register in hex
PrintOutRegistersInHex()
Print the general purpose registers in hex
Example:
Start;
my $q = Rs('abababab');
Mov(rax, 1);
Mov(rbx, 2);
Mov(rcx, 3);
Mov(rdx, 4);
Mov(r8, 5);
Lea r9, "[rax+rbx]";
PrintOutRegistersInHex; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Exit;
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;
Processes
Create and manage processes
Fork()
Fork
Example:
Start; # Start the program
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;
};
Exit; # Return to operating system
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;
}
Start; # Start the program
GetUid; # Userid
PrintOutRegisterInHex rax;
Exit; # Return to operating system
my $r = Assemble;
ok $r =~ m(rax:( 0000){3});
GetPid()
Get process identifier
Example:
Start; # Start the program
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;
};
Exit; # Return to operating system
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;
}
Start; # Start the program
GetUid; # Userid
PrintOutRegisterInHex rax;
Exit; # Return to operating system
my $r = Assemble;
ok $r =~ m(rax:( 0000){3});
GetPPid()
Get parent process identifier
Example:
Start; # Start the program
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;
};
Exit; # Return to operating system
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;
}
Start; # Start the program
GetUid; # Userid
PrintOutRegisterInHex rax;
Exit; # Return to operating system
my $r = Assemble;
ok $r =~ m(rax:( 0000){3});
GetUid()
Get userid of current process
WaitPid()
Wait for the pid in rax to complete
Example:
Start; # Start the program
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;
};
Exit; # Return to operating system
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;
}
Start; # Start the program
GetUid; # Userid
PrintOutRegisterInHex rax;
Exit; # Return to operating system
my $r = Assemble;
ok $r =~ m(rax:( 0000){3});
ReadTimeStampCounter()
Read the time stamp counter and return the time in nanoseconds in rax
Example:
Start;
for(1..10)
{ReadTimeStampCounter; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
}
Exit;
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
PushR(@r)
Push registers onto the stack
Parameter Description
1 @r Register
PopR(@r)
Pop registers from the stack
Parameter Description
1 @r Register
PeekR($r)
Peek at register on stack
Parameter Description
1 $r Register
Declarations
Declare variables and structures
Structures
Declare a structure
Structure($register)
Create a structure addressed by a register
Parameter Description
1 $register Register locating the structure
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)
Address a field in a structure
Parameter Description
1 $field Field
All8Structure($base, $N)
Create a structure consisting of 8 byte fields
Parameter Description
1 $base Base register
2 $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
PrintOutMemory()
Print the memory addressed by rax for a length of rdi
Example:
Start;
Comment "Print a string from memory";
my $s = "Hello World";
Mov rax, Rs($s);
Mov rdi, length $s;
PrintOutMemory; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Exit;
ok Assemble =~ m(Hello World);
AllocateMemory()
Allocate the amount of memory specified in rax via mmap and return the address of the allocated memory in rax
Example:
Start;
my $N = 2048;
my $q = Rs('a'..'p');
Mov rax, $N;
AllocateMemory; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
Vmovdqu8 xmm0, "[$q]";
Vmovdqu8 "[rax]", xmm0;
Mov rdi,16;
PrintOutMemory;
PrintOutNl;
Mov rdi, $N;
FreeMemory;
PrintOutRegisterInHex rax;
Exit;
ok Assemble =~ m(abcdefghijklmnop)s;
Start;
my $N = 4096;
my $S = RegisterSize rax;
Mov rax, $N;
AllocateMemory; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
Mov rdi, $N;
ClearMemory;
PrintOutRegisterInHex rax;
PrintOutMemoryInHex;
Exit;
my $r = Assemble;
if ($r =~ m((0000.*0000))s)
{is_deeply length($1), 10289;
}
FreeMemory()
Free memory via mmap. The address of the memory is in rax, the length to free is in rdi
Example:
Start;
my $N = 2048;
my $q = Rs('a'..'p');
Mov rax, $N;
AllocateMemory;
PrintOutRegisterInHex rax;
Vmovdqu8 xmm0, "[$q]";
Vmovdqu8 "[rax]", xmm0;
Mov rdi,16;
PrintOutMemory;
PrintOutNl;
Mov rdi, $N;
FreeMemory; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
Exit;
ok Assemble =~ m(abcdefghijklmnop)s;
Start;
my $N = 4096;
my $S = RegisterSize rax;
Mov rax, $N;
AllocateMemory;
PrintOutRegisterInHex rax;
Mov rdi, $N;
ClearMemory;
PrintOutRegisterInHex rax;
PrintOutMemoryInHex;
Exit;
my $r = Assemble;
if ($r =~ m((0000.*0000))s)
{is_deeply length($1), 10289;
}
ClearMemory()
Clear memory - the address of the memory is in rax, the length in rdi
CopyMemory()
Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
Files
Process a file
OpenRead()
Open a file, whose name is addressed by rax, for read and return the file descriptor in rax
Example:
Start; # Start the program
Mov rax, Rs($0); # File to stat
OpenRead; # Open file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
Close(rax); # Close file
PrintOutRegisterInHex rax;
Exit; # Return to operating system
my $r = Assemble;
ok $r =~ m(( 0000){3} 0003)i; # Expected file number
ok $r =~ m(( 0000){4})i; # Expected file number
Close($fdes)
Close a file descriptor
Parameter Description
1 $fdes File descriptor
Example:
Start; # Start the program
Mov rax, Rs($0); # File to stat
OpenRead; # Open file
PrintOutRegisterInHex rax;
Close(rax); # Close file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
Exit; # Return to operating system
my $r = Assemble;
ok $r =~ m(( 0000){3} 0003)i; # Expected file number
ok $r =~ m(( 0000){4})i; # Expected file number
StatSize()
Stat a file whose name is addressed by rax to get its size in rax
Example:
Start; # Start the program
Mov rax, Rs($0); # File to stat
StatSize; # Stat the file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutRegisterInHex rax;
Exit; # Return to operating system
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:
Start; # Start the program
Mov rax, Rs($0); # File to read
ReadFile; # Read file # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutMemory; # Print memory
Exit; # Return to operating system
my $r = Assemble; # Assemble and execute
ok index($r =~ s([^0x0-0x7f]) ()gsr, readFile($0) =~ s([^0x0-0x7f]) ()gsr)>-1;# Output contains this file
Strings
Operations on Strings
CreateByteString()
Create an relocatable string of bytes in an arena and returns its address in rax
Example:
Start; # Start the program
my $q = Rs my $t = 'ab';
my $s = CreateByteString; # Create a string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
Mov rsi, $q; # Address of memory to copy
Mov rdi, length $t; # Length of memory to copy
$s->m; # Copy memory into byte string
Mov rdi, rax; # Save source byte string
CreateByteString; # Create target byte string # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
$s->copy; # Copy source to target
Xchg rdi, rax; # Swap source and target byte strings
$s->copy; # Copy source to target
Xchg rdi, rax; # Swap source and target byte strings
$s->copy;
Xchg rdi, rax;
$s->copy;
Xchg rdi, rax;
$s->copy;
$s->out; # Print byte string
Exit; # Return to operating system
Assemble =~ m(($t x 8)); # Assemble and execute
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::copy($byteString)
Append the byte string addressed by rdi to the byte string addressed by rax
Parameter Description
1 $byteString Byte string descriptor
ByteString::out($byteString)
Print the specified byte string addressed by rax on sysout
Parameter Description
1 $byteString Byte string descriptor
Assemble
Assemble generated code
Start()
Initialize the assembler
Example:
Start; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
PrintOutString "Hello World";
Exit;
ok Assemble =~ m(Hello World);
Exit($c)
Exit with the specified return code or zero if no return code supplied
Parameter Description
1 $c Return code
Example:
Start;
PrintOutString "Hello World";
Exit; # 𝗘𝘅𝗮𝗺𝗽𝗹𝗲
ok Assemble =~ m(Hello World);
Assemble(%options)
Assemble the generated code
Parameter Description
1 %options Options
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
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 amount of memory specified in rax via mmap and return the address of the allocated memory in rax
4 Assemble - Assemble the generated code
5 ByteString::copy - Append the byte string addressed by rdi to the byte string addressed by rax
6 ByteString::m - Append the content with length rdi addressed by rsi to the byte string addressed by rax
7 ByteString::out - Print the specified byte string addressed by rax on sysout
8 ClearMemory - Clear memory - the address of the memory is in rax, the length in rdi
9 ClearRegisters - Clear registers by setting them to zero
10 Close - Close a file descriptor
11 Comment - Insert a comment into the assembly code
12 CopyMemory - Copy memory, the target is addressed by rax, the length is in rdi, the source is addressed by rsi
13 CreateByteString - Create an relocatable string of bytes in an arena and returns its address in rax
14 Db - Layout bytes in the data segment and return their label
15 Dbwdq - Layout data
16 Dd - Layout double words in the data segment and return their label
17 Dq - Layout quad words in the data segment and return their label
18 Ds - Layout bytes in memory and return their label
19 Dw - Layout words in the data segment and return their label
20 Exit - Exit with the specified return code or zero if no return code supplied
21 For - For
22 Fork - Fork
23 FreeMemory - Free memory via mmap.
24 GetPid - Get process identifier
25 GetPPid - Get parent process identifier
26 GetUid - Get userid of current process
27 If - If
28 Label - Create a unique label
29 LocalData - Map local data
30 LocalData::allocate8 - Add some 8 byte local variables and return an array of variable definitions
31 LocalData::free - Free a local data area on the stack
32 LocalData::start - Start a local data area on the stack
33 LocalData::variable - Add a local variable
34 LocalVariable::stack - Address a local variable on the stack
35 OpenRead - Open a file, whose name is addressed by rax, for read and return the file descriptor in rax
36 PeekR - Peek at register on stack
37 PopR - Pop registers from the stack
38 PrintOutMemory - Print the memory addressed by rax for a length of rdi
39 PrintOutMemoryInHex - Dump memory from the address in rax for the length in rdi
40 PrintOutNl - Write a new line
41 PrintOutRaxInHex - Write the content of register rax to stderr in hexadecimal in big endian notation
42 PrintOutRaxInReverseInHex - Write the content of register rax to stderr in hexadecimal in little endian notation
43 PrintOutRegisterInHex - Print any register as a hex string
44 PrintOutRegistersInHex - Print the general purpose registers in hex
45 PrintOutRflagsInHex - Print the flags register in hex
46 PrintOutRipInHex - Print the instruction pointer in hex
47 PrintOutString - Write a constant string to sysout.
48 PushR - Push registers onto the stack
49 Rb - Layout bytes in the data segment and return their label
50 Rbwdq - Layout data
51 Rd - Layout double words in the data segment and return their label
52 ReadFile - Read a file whose name is addressed by rax into memory.
53 ReadTimeStampCounter - Read the time stamp counter and return the time in nanoseconds in rax
54 RegisterSize - Return the size of a register
55 RestoreFirstFour - Restore the first 4 parameter registers
56 RestoreFirstFourExceptRax - Restore the first 4 parameter registers except rax so it can return its value
57 RestoreFirstSeven - Restore the first 7 parameter registers
58 RestoreFirstSevenExceptRax - Restore the first 7 parameter registers except rax which is being used to return the result
59 RestoreFirstSevenExceptRaxAndRdi - Restore the first 7 parameter registers except rax and rdi which are being used to return the results
60 ReverseBytesInRax - Reverse the bytes in rax
61 Rq - Layout quad words in the data segment and return their label
62 Rs - Layout bytes in read only memory and return their label
63 Rw - Layout words in the data segment and return their label
64 S - 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
65 SaveFirstFour - Save the first 4 parameter registers
66 SaveFirstSeven - Save the first 7 parameter registers
67 SetLabel - Set a label in the code section
68 Start - Initialize the assembler
69 StatSize - Stat a file whose name is addressed by rax to get its size in rax
70 Structure - Create a structure addressed by a register
71 Structure::field - Add a field of the specified length with an optional comment
72 StructureField::addr - Address a field in a structure
73 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.