Skip to content

Commit

Permalink
doc: break the documentation into chapters
Browse files Browse the repository at this point in the history
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 <hpa@zytor.com>
  • Loading branch information
H. Peter Anvin committed Aug 13, 2024
1 parent 7c47273 commit 5be149b
Show file tree
Hide file tree
Showing 25 changed files with 9,632 additions and 9,540 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ TAGS
/doc/Makefile
/doc/html
/doc/info
/doc/inslist.src
/doc/insns.src
/doc/version.src
/doc/warnings.src
/doc/perlbreq.src
Expand Down
839 changes: 839 additions & 0 deletions doc/16bit.src

Large diffs are not rendered by default.

504 changes: 504 additions & 0 deletions doc/32bit.src

Large diffs are not rendered by default.

183 changes: 183 additions & 0 deletions doc/64bit.src
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}.

34 changes: 22 additions & 12 deletions doc/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,15 @@ XZFILES = @XZFILES@
# Auxiliary files referenced by the HTML files
HTMLAUX = nasmdoc.css local.css nasmlogw.png

SRCS = nasmdoc.src inslist.src changes.src \
warnings.src version.src perlbreq.src
# Generated input files
GENSRC = insns.src version.src perlbreq.src

# Top-level input file
SRCS = nasmdoc.src

# All input files (except auto-dependencies)
ALLSRCS = $(SRCS) $(GENSRC)

OUT = html nasmdoc.txt nasmdoc.pdf $(XZFILES)
XZOUT = nasmdoc.pdf.xz

Expand All @@ -60,25 +67,25 @@ all: $(OUT)

xzfiles: $(XZOUT)

inslist.src: inslist.pl ../x86/insns.dat
$(RUNPERL) $^
insns.src: inslist.pl ../x86/insns.dat
$(RUNPERL) $^ $@

html: $(HTMLAUX)
$(MKDIR_P) html
for f in $(HTMLAUX); do $(CP_UF) "$(srcdir)/$$f" html/; done
$(MAKE) html/nasmdoc0.html

RDSRC = $(RUNPERL) $(srcdir)/rdsrc.pl -I$(srcdir)/
RDSRC = $(RUNPERL) $(srcdir)/rdsrc.pl -I$(srcdir) -M$(@F).dep

html/nasmdoc0.html: $(SRCS) rdsrc.pl
html/nasmdoc0.html: $(ALLSRCS) rdsrc.pl
$(RM_F) html/*.html
$(RDSRC) -ohtml html nasmdoc.src
$(RDSRC) -ohtml html $<

nasmdoc.dip: $(SRCS) rdsrc.pl
$(RDSRC) dip nasmdoc.src
nasmdoc.dip: $(ALLSRCS) rdsrc.pl
$(RDSRC) dip $<

nasmdoc.txt: $(SRCS) rdsrc.pl
$(RDSRC) txt nasmdoc.src
nasmdoc.txt: $(ALLSRCS) rdsrc.pl
$(RDSRC) txt $<

version.src: $(top_srcdir)/version.pl $(top_srcdir)/version
$(RUNPERL) $(top_srcdir)/version.pl docsrc \
Expand Down Expand Up @@ -113,7 +120,7 @@ nasmdoc.pdf.xz: nasmdoc-raw.pdf
clean:
-$(RM_F) *.rtf *.hpj *.texi *.gid *.ipf *.dip
-$(RM_F) *.aux *.cp *.fn *.ky *.pg *.log *.toc *.tp *.vr
-$(RM_F) inslist.src version.src perlbreq.src fontpath Fontmap
-$(RM_F) $(GENSRC)fontpath Fontmap
-$(RM_F) nasmdoc*.ps nasmdoc-raw.pdf

spotless: clean
Expand All @@ -133,3 +140,6 @@ install: all
.SECONDARY:

.DELETE_ON_ERROR:

# Generated dependencies
-include *.dep
4 changes: 4 additions & 0 deletions doc/changelog.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
\A{changelog} \i{NASM Version History}

\& changes.src

108 changes: 108 additions & 0 deletions doc/contact.src
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.

Loading

0 comments on commit 5be149b

Please sign in to comment.