-
Notifications
You must be signed in to change notification settings - Fork 300
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
doc: break the documentation into chapters
Make the source code for the documentation a little easier to deal with by breaking it into individual chapter files. Add support to rdsrc.pl for auto-generating dependencies. Signed-off-by: H. Peter Anvin <[email protected]>
- Loading branch information
H. Peter Anvin
committed
Aug 13, 2024
1 parent
7c47273
commit 5be149b
Showing
25 changed files
with
9,632 additions
and
9,540 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
\C{64bit} Writing 64-bit Code (Unix, Win64) | ||
|
||
This chapter attempts to cover some of the common issues involved when | ||
writing 64-bit code, to run under \i{Win64} or Unix. It covers how to | ||
write assembly code to interface with 64-bit C routines, and how to | ||
write position-independent code for shared libraries. | ||
|
||
All 64-bit code uses a flat memory model, since segmentation is not | ||
available in 64-bit mode. The one exception is the \c{FS} and \c{GS} | ||
registers, which still add their bases. | ||
|
||
Position independence in 64-bit mode is significantly simpler, since | ||
the processor supports \c{RIP}-relative addressing directly; see the | ||
\c{REL} keyword (\k{effaddr}). On most 64-bit platforms, it is | ||
probably desirable to make that the default, using the directive | ||
\c{DEFAULT REL} (\k{default}). | ||
|
||
64-bit programming is relatively similar to 32-bit programming, but | ||
of course pointers are 64 bits long; additionally, all existing | ||
platforms pass arguments in registers rather than on the stack. | ||
Furthermore, 64-bit platforms use SSE2 by default for floating point. | ||
Please see the ABI documentation for your platform. | ||
|
||
64-bit platforms differ in the sizes of the C/C++ fundamental | ||
datatypes, not just from 32-bit platforms but from each other. If a | ||
specific size data type is desired, it is probably best to use the | ||
types defined in the standard C header \c{<inttypes.h>}. | ||
|
||
All known 64-bit platforms except some embedded platforms require that | ||
the stack is 16-byte aligned at the entry to a function. In order to | ||
enforce that, the stack pointer (\c{RSP}) needs to be aligned on an | ||
\c{odd} multiple of 8 bytes before the \c{CALL} instruction. | ||
|
||
In 64-bit mode, the default instruction size is still 32 bits. When | ||
loading a value into a 32-bit register (but not an 8- or 16-bit | ||
register), the upper 32 bits of the corresponding 64-bit register are | ||
set to zero. | ||
|
||
\H{reg64} Register Names in 64-bit Mode | ||
|
||
NASM uses the following names for general-purpose registers in 64-bit | ||
mode, for 8-, 16-, 32- and 64-bit references, respectively: | ||
|
||
\c AL/AH, CL/CH, DL/DH, BL/BH, SPL, BPL, SIL, DIL, R8B-R15B | ||
\c AX, CX, DX, BX, SP, BP, SI, DI, R8W-R15W | ||
\c EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, R8D-R15D | ||
\c RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8-R15 | ||
|
||
This is consistent with the AMD documentation and most other | ||
assemblers. The Intel documentation, however, uses the names | ||
\c{R8L-R15L} for 8-bit references to the higher registers. It is | ||
possible to use those names by definiting them as macros; similarly, | ||
if one wants to use numeric names for the low 8 registers, define them | ||
as macros. The standard macro package \c{altreg} (see \k{pkg_altreg}) | ||
can be used for this purpose. | ||
|
||
\H{id64} Immediates and Displacements in 64-bit Mode | ||
|
||
In 64-bit mode, immediates and displacements are generally only 32 | ||
bits wide. NASM will therefore truncate most displacements and | ||
immediates to 32 bits. | ||
|
||
The only instruction which takes a full \i{64-bit immediate} is: | ||
|
||
\c MOV reg64,imm64 | ||
|
||
NASM will produce this instruction whenever the programmer uses | ||
\c{MOV} with an immediate into a 64-bit register. If this is not | ||
desirable, simply specify the equivalent 32-bit register, which will | ||
be automatically zero-extended by the processor, or specify the | ||
immediate as \c{DWORD}: | ||
|
||
\c mov rax,foo ; 64-bit immediate | ||
\c mov rax,qword foo ; (identical) | ||
\c mov eax,foo ; 32-bit immediate, zero-extended | ||
\c mov rax,dword foo ; 32-bit immediate, sign-extended | ||
|
||
The length of these instructions are 10, 5 and 7 bytes, respectively. | ||
|
||
If optimization is enabled and NASM can determine at assembly time | ||
that a shorter instruction will suffice, the shorter instruction will | ||
be emitted unless of course \c{STRICT QWORD} or \c{STRICT DWORD} is | ||
specified (see \k{strict}): | ||
|
||
\c mov rax,1 ; Assembles as "mov eax,1" (5 bytes) | ||
\c mov rax,strict qword 1 ; Full 10-byte instruction | ||
\c mov rax,strict dword 1 ; 7-byte instruction | ||
\c mov rax,symbol ; 10 bytes, not known at assembly time | ||
\c lea rax,[rel symbol] ; 7 bytes, usually preferred by the ABI | ||
|
||
Note that \c{lea rax,[rel symbol]} is position-independent, whereas | ||
\c{mov rax,symbol} is not. Most ABIs prefer or even require | ||
position-independent code in 64-bit mode. However, the \c{MOV} | ||
instruction is able to reference a symbol anywhere in the 64-bit | ||
address space, whereas \c{LEA} is only able to access a symbol within | ||
within 2 GB of the instruction itself (see below.) | ||
|
||
The only instructions which take a full \I{64-bit displacement}64-bit | ||
\e{displacement} is loading or storing, using \c{MOV}, \c{AL}, \c{AX}, | ||
\c{EAX} or \c{RAX} (but no other registers) to an absolute 64-bit address. | ||
Since this is a relatively rarely used instruction (64-bit code generally uses | ||
relative addressing), the programmer has to explicitly declare the | ||
displacement size as \c{ABS QWORD}: | ||
|
||
\c default abs | ||
\c | ||
\c mov eax,[foo] ; 32-bit absolute disp, sign-extended | ||
\c mov eax,[a32 foo] ; 32-bit absolute disp, zero-extended | ||
\c mov eax,[qword foo] ; 64-bit absolute disp | ||
\c | ||
\c default rel | ||
\c | ||
\c mov eax,[foo] ; 32-bit relative disp | ||
\c mov eax,[a32 foo] ; d:o, address truncated to 32 bits(!) | ||
\c mov eax,[qword foo] ; error | ||
\c mov eax,[abs qword foo] ; 64-bit absolute disp | ||
|
||
A sign-extended absolute displacement can access from -2 GB to +2 GB; | ||
a zero-extended absolute displacement can access from 0 to 4 GB. | ||
|
||
\H{unix64} Interfacing to 64-bit C Programs (Unix) | ||
|
||
On Unix, the 64-bit ABI as well as the x32 ABI (32-bit ABI with the | ||
CPU in 64-bit mode) is defined by the documents at: | ||
|
||
\W{https://www.nasm.us/abi/unix64}\c{https://www.nasm.us/abi/unix64} | ||
|
||
Although written for AT&T-syntax assembly, the concepts apply equally | ||
well for NASM-style assembly. What follows is a simplified summary. | ||
|
||
The first six integer arguments (from the left) are passed in \c{RDI}, | ||
\c{RSI}, \c{RDX}, \c{RCX}, \c{R8}, and \c{R9}, in that order. | ||
Additional integer arguments are passed on the stack. These | ||
registers, plus \c{RAX}, \c{R10} and \c{R11} are destroyed by function | ||
calls, and thus are available for use by the function without saving. | ||
|
||
Integer return values are passed in \c{RAX} and \c{RDX}, in that order. | ||
|
||
Floating point is done using SSE registers, except for \c{long | ||
double}, which is 80 bits (\c{TWORD}) on most platforms (Android is | ||
one exception; there \c{long double} is 64 bits and treated the same | ||
as \c{double}.) Floating-point arguments are passed in \c{XMM0} to | ||
\c{XMM7}; return is \c{XMM0} and \c{XMM1}. \c{long double} are passed | ||
on the stack, and returned in \c{ST0} and \c{ST1}. | ||
|
||
All SSE and x87 registers are destroyed by function calls. | ||
|
||
On 64-bit Unix, \c{long} is 64 bits. | ||
|
||
Integer and SSE register arguments are counted separately, so for the case of | ||
|
||
\c void foo(long a, double b, int c) | ||
|
||
\c{a} is passed in \c{RDI}, \c{b} in \c{XMM0}, and \c{c} in \c{ESI}. | ||
|
||
\H{win64} Interfacing to 64-bit C Programs (Win64) | ||
|
||
The Win64 ABI is described by the document at: | ||
|
||
\W{https://www.nasm.us/abi/win64}\c{https://www.nasm.us/abi/win64} | ||
|
||
What follows is a simplified summary. | ||
|
||
The first four integer arguments are passed in \c{RCX}, \c{RDX}, | ||
\c{R8} and \c{R9}, in that order. Additional integer arguments are | ||
passed on the stack. These registers, plus \c{RAX}, \c{R10} and | ||
\c{R11} are destroyed by function calls, and thus are available for | ||
use by the function without saving. | ||
|
||
Integer return values are passed in \c{RAX} only. | ||
|
||
Floating point is done using SSE registers, except for \c{long | ||
double}. Floating-point arguments are passed in \c{XMM0} to \c{XMM3}; | ||
return is \c{XMM0} only. | ||
|
||
On Win64, \c{long} is 32 bits; \c{long long} or \c{_int64} is 64 bits. | ||
|
||
Integer and SSE register arguments are counted together, so for the case of | ||
|
||
\c void foo(long long a, double b, int c) | ||
|
||
\c{a} is passed in \c{RCX}, \c{b} in \c{XMM1}, and \c{c} in \c{R8D}. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
\A{changelog} \i{NASM Version History} | ||
|
||
\& changes.src | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
\A{contact} Contact Information | ||
|
||
\H{website} Website | ||
|
||
NASM has a \i{website} at | ||
\w{https://www.nasm.us/}. | ||
|
||
\i{New releases}, \i{release candidates}, and \I{snapshots, daily | ||
development}\i{daily development snapshots} of NASM are available from | ||
the official web site in source form as well as binaries for a number | ||
of common platforms. | ||
|
||
\S{forums} User Forums | ||
|
||
Users of NASM may find the Forums on the website useful. These are, | ||
however, not frequented much by the developers of NASM, so they are | ||
not suitable for reporting bugs. | ||
|
||
\S{develcom} Development Community | ||
|
||
The development of NASM is coordinated primarily though the | ||
\i\c{nasm-devel} mailing list. If you wish to participate in | ||
development of NASM, please join this mailing list. Subscription | ||
links and archives of past posts are available on the website. | ||
|
||
\H{bugs} \i{Reporting Bugs}\I{bugs} | ||
|
||
To report bugs in NASM, please use the \i{bug tracker} at | ||
\w{https://www.nasm.us/} (click on "Bug | ||
Tracker"), or if that fails then through one of the contacts in | ||
\k{website}. | ||
|
||
Please read \k{qstart} first, and don't report the bug if it's | ||
listed in there as a deliberate feature. (If you think the feature | ||
is badly thought out, feel free to send us reasons why you think it | ||
should be changed, but don't just send us mail saying `This is a | ||
bug' if the documentation says we did it on purpose.) Then read | ||
\k{problems}, and don't bother reporting the bug if it's listed | ||
there. | ||
|
||
If you do report a bug, \e{please} make sure your bug report includes | ||
the following information: | ||
|
||
\b What operating system you're running NASM under. Linux, | ||
FreeBSD, NetBSD, MacOS X, Win16, Win32, Win64, MS-DOS, OS/2, VMS, | ||
whatever. | ||
|
||
\b If you compiled your own executable from a source archive, compiled | ||
your own executable from \c{git}, used the standard distribution | ||
binaries from the website, or got an executable from somewhere else | ||
(e.g. a Linux distribution.) If you were using a locally built | ||
executable, try to reproduce the problem using one of the standard | ||
binaries, as this will make it easier for us to reproduce your problem | ||
prior to fixing it. | ||
|
||
\b Which version of NASM you're using, and exactly how you invoked | ||
it. Give us the precise command line, and the contents of the | ||
\c{NASMENV} environment variable if any. | ||
|
||
\b Which versions of any supplementary programs you're using, and | ||
how you invoked them. If the problem only becomes visible at link | ||
time, tell us what linker you're using, what version of it you've | ||
got, and the exact linker command line. If the problem involves | ||
linking against object files generated by a compiler, tell us what | ||
compiler, what version, and what command line or options you used. | ||
(If you're compiling in an IDE, please try to reproduce the problem | ||
with the command-line version of the compiler.) | ||
|
||
\b If at all possible, send us a NASM source file which exhibits the | ||
problem. If this causes copyright problems (e.g. you can only | ||
reproduce the bug in restricted-distribution code) then bear in mind | ||
the following two points: firstly, we guarantee that any source code | ||
sent to us for the purposes of debugging NASM will be used \e{only} | ||
for the purposes of debugging NASM, and that we will delete all our | ||
copies of it as soon as we have found and fixed the bug or bugs in | ||
question; and secondly, we would prefer \e{not} to be mailed large | ||
chunks of code anyway. The smaller the file, the better. A | ||
three-line sample file that does nothing useful \e{except} | ||
demonstrate the problem is much easier to work with than a | ||
fully fledged ten-thousand-line program. (Of course, some errors | ||
\e{do} only crop up in large files, so this may not be possible.) | ||
|
||
\b A description of what the problem actually \e{is}. `It doesn't | ||
work' is \e{not} a helpful description! Please describe exactly what | ||
is happening that shouldn't be, or what isn't happening that should. | ||
Examples might be: `NASM generates an error message saying Line 3 | ||
for an error that's actually on Line 5'; `NASM generates an error | ||
message that I believe it shouldn't be generating at all'; `NASM | ||
fails to generate an error message that I believe it \e{should} be | ||
generating'; `the object file produced from this source code crashes | ||
my linker'; `the ninth byte of the output file is 66 and I think it | ||
should be 77 instead'. | ||
|
||
\b If you believe the output file from NASM to be faulty, send it to | ||
us. That allows us to determine whether our own copy of NASM | ||
generates the same file, or whether the problem is related to | ||
portability issues between our development platforms and yours. We | ||
can handle binary files mailed to us as MIME attachments, uuencoded, | ||
and even BinHex. Alternatively, we may be able to provide an FTP | ||
site you can upload the suspect files to; but mailing them is easier | ||
for us. | ||
|
||
\b Any other information or data files that might be helpful. If, | ||
for example, the problem involves NASM failing to generate an object | ||
file while TASM can generate an equivalent file without trouble, | ||
then send us \e{both} object files, so we can see what TASM is doing | ||
differently from us. | ||
|
Oops, something went wrong.