397 lines
16 KiB
XML
397 lines
16 KiB
XML
|
<?xml version="1.0"?>
|
||
|
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
||
|
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
|
||
|
|
||
|
<refentry id="yasm_arch">
|
||
|
|
||
|
<refentryinfo>
|
||
|
<title>Yasm Supported Architectures</title>
|
||
|
<date>October 2006</date>
|
||
|
<productname>Yasm</productname>
|
||
|
<author>
|
||
|
<firstname>Peter</firstname>
|
||
|
<surname>Johnson</surname>
|
||
|
<affiliation>
|
||
|
<address><email>peter@tortall.net</email></address>
|
||
|
</affiliation>
|
||
|
</author>
|
||
|
|
||
|
<copyright>
|
||
|
<year>2004</year>
|
||
|
<year>2005</year>
|
||
|
<year>2006</year>
|
||
|
<year>2007</year>
|
||
|
<holder>Peter Johnson</holder>
|
||
|
</copyright>
|
||
|
</refentryinfo>
|
||
|
|
||
|
<refmeta>
|
||
|
<refentrytitle>yasm_arch</refentrytitle>
|
||
|
<manvolnum>7</manvolnum>
|
||
|
</refmeta>
|
||
|
|
||
|
<refnamediv>
|
||
|
<refname>yasm_arch</refname>
|
||
|
<refpurpose>Yasm Supported Target Architectures</refpurpose>
|
||
|
</refnamediv>
|
||
|
|
||
|
<refsynopsisdiv>
|
||
|
<cmdsynopsis>
|
||
|
<command>yasm</command>
|
||
|
<arg choice="plain">
|
||
|
<option>-a <replaceable>arch</replaceable></option>
|
||
|
</arg>
|
||
|
<arg choice="opt">
|
||
|
<option>-m <replaceable>machine</replaceable></option>
|
||
|
</arg>
|
||
|
<arg choice="plain">
|
||
|
<option><replaceable>...</replaceable></option>
|
||
|
</arg>
|
||
|
</cmdsynopsis>
|
||
|
</refsynopsisdiv>
|
||
|
|
||
|
<refsect1>
|
||
|
<title>Description</title>
|
||
|
|
||
|
<para>The standard Yasm distribution includes a number of modules
|
||
|
for different target architectures. Each target architecture can
|
||
|
support one or more machine architectures.</para>
|
||
|
|
||
|
<para>The architecture and machine are selected on the
|
||
|
|
||
|
<citerefentry>
|
||
|
<refentrytitle>yasm</refentrytitle>
|
||
|
<manvolnum>1</manvolnum>
|
||
|
</citerefentry>
|
||
|
|
||
|
command line by use of the <option>-a
|
||
|
<replaceable>arch</replaceable></option> and <option>-m
|
||
|
<replaceable>machine</replaceable></option> command line options,
|
||
|
respectively.</para>
|
||
|
|
||
|
<para>The machine architecture may also automatically be selected by
|
||
|
certain object formats. For example, the <quote>elf32</quote>
|
||
|
object format selects the <quote>x86</quote> machine architecture
|
||
|
by default, while the <quote>elf64</quote> object format selects
|
||
|
the <quote>amd64</quote> machine architecture by default.</para>
|
||
|
</refsect1>
|
||
|
|
||
|
<refsect1>
|
||
|
<title>x86 Architecture</title>
|
||
|
|
||
|
<para>The <quote>x86</quote> architecture supports the IA-32
|
||
|
instruction set and derivatives and the AMD64 instruction set. It
|
||
|
consists of two machines: <quote>x86</quote> (for the IA-32 and
|
||
|
derivatives) and <quote>amd64</quote> (for the AMD64 and
|
||
|
derivatives). The default machine for the <quote>x86</quote>
|
||
|
architecture is the <quote>x86</quote> machine.</para>
|
||
|
|
||
|
<refsect2>
|
||
|
<title>BITS Setting</title>
|
||
|
|
||
|
<para>The x86 architecture BITS setting specifies to Yasm the
|
||
|
processor mode in which the generated code is intended to execute.
|
||
|
x86 processors can run in three different major execution modes:
|
||
|
16-bit, 32-bit, and on AMD64-supporting processors, 64-bit. As
|
||
|
the x86 instruction set contains portions whose function is
|
||
|
execution-mode dependent (such as operand-size and address-size
|
||
|
override prefixes), Yasm cannot assemble x86 instructions
|
||
|
correctly unless it is told by the user in what processor mode the
|
||
|
code will execute.</para>
|
||
|
|
||
|
<para>The BITS setting can be changed in a variety of ways. When
|
||
|
using the NASM-compatible parser, the BITS setting can be changed
|
||
|
directly via the use of the <userinput>BITS xx</userinput>
|
||
|
assembler directive. The default BITS setting is determined by
|
||
|
the object format in use.</para>
|
||
|
</refsect2>
|
||
|
|
||
|
<refsect2>
|
||
|
<title>BITS 64 Extensions</title>
|
||
|
|
||
|
<para>The AMD64 architecture is a new 64-bit architecture developed
|
||
|
by AMD, based on the 32-bit x86 architecture. It extends the
|
||
|
original x86 architecture by doubling the number of general
|
||
|
purpose and SIMD registers, extending the arithmetic operations
|
||
|
and address space to 64 bits, as well as other features.</para>
|
||
|
|
||
|
<para>Recently, Intel has introduced an essentially identical
|
||
|
version of AMD64 called EM64T.</para>
|
||
|
|
||
|
<para>When an AMD64-supporting processor is executing in 64-bit
|
||
|
mode, a number of additional extensions are available, including
|
||
|
extra general purpose registers, extra SSE2 registers, and
|
||
|
RIP-relative addressing.</para>
|
||
|
|
||
|
<para>Yasm extends the base NASM syntax to support AMD64 as
|
||
|
follows. To enable assembly of instructions for the 64-bit mode
|
||
|
of AMD64 processors, use the directive <userinput>BITS
|
||
|
64</userinput>. As with NASM's BITS directive, this does not
|
||
|
change the format of the output object file to 64 bits; it only
|
||
|
changes the assembler mode to assume that the instructions being
|
||
|
assembled will be run in 64-bit mode. To specify an AMD64 object
|
||
|
file, use <option>-m amd64</option> on the Yasm command line, or
|
||
|
explicitly target a 64-bit object format such as <option>-f
|
||
|
win64</option> or <option>-f elf64</option>.</para>
|
||
|
|
||
|
<refsect3>
|
||
|
<title>Register Changes</title>
|
||
|
|
||
|
<para>The additional 64-bit general purpose registers are named
|
||
|
r8-r15. There are also 8-bit (rXb), 16-bit (rXw), and 32-bit
|
||
|
(rXd) subregisters that map to the least significant 8, 16, or 32
|
||
|
bits of the 64-bit register. The original 8 general purpose
|
||
|
registers have also been extended to 64-bits: eax, edx, ecx, ebx,
|
||
|
esi, edi, esp, and ebp have new 64-bit versions called rax, rdx,
|
||
|
rcx, rbx, rsi, rdi, rsp, and rbp respectively. The old 32-bit
|
||
|
registers map to the least significant bits of the new 64-bit
|
||
|
registers.</para>
|
||
|
|
||
|
<para>New 8-bit registers are also available that map to the 8
|
||
|
least significant bits of rsi, rdi, rsp, and rbp. These are
|
||
|
called sil, dil, spl, and bpl respectively. Unfortunately, due
|
||
|
to the way instructions are encoded, these new 8-bit registers
|
||
|
are encoded the same as the old 8-bit registers ah, dh, ch, and
|
||
|
bh. The processor tells which is being used by the presence of
|
||
|
the new REX prefix that is used to specify the other extended
|
||
|
registers. This means it is illegal to mix the use of ah, dh,
|
||
|
ch, and bh with an instruction that requires the REX prefix for
|
||
|
other reasons. For instance:</para>
|
||
|
|
||
|
<screen>add ah, [r10]</screen>
|
||
|
|
||
|
<para>(NASM syntax) is not a legal instruction because the use of
|
||
|
r10 requires a REX prefix, making it impossible to use ah.</para>
|
||
|
|
||
|
<para>In 64-bit mode, an additional 8 SSE2 registers are also
|
||
|
available. These are named xmm8-xmm15.</para>
|
||
|
</refsect3>
|
||
|
|
||
|
<refsect3>
|
||
|
<title>64 Bit Instructions</title>
|
||
|
|
||
|
<para>By default, most operations in 64-bit mode remain 32-bit;
|
||
|
operations that are 64-bit usually require a REX prefix (one bit
|
||
|
in the REX prefix determines whether an operation is 64-bit or
|
||
|
32-bit). Thus, essentially all 32-bit instructions have a 64-bit
|
||
|
version, and the 64-bit versions of instructions can use extended
|
||
|
registers <quote>for free</quote> (as the REX prefix is already
|
||
|
present). Examples in NASM syntax:</para>
|
||
|
|
||
|
<screen>mov eax, 1 ; 32-bit instruction</screen>
|
||
|
<screen>mov rcx, 1 ; 64-bit instruction</screen>
|
||
|
|
||
|
<para>Instructions that modify the stack (push, pop, call, ret,
|
||
|
enter, and leave) are implicitly 64-bit. Their 32-bit
|
||
|
counterparts are not available, but their 16-bit counterparts
|
||
|
are. Examples in NASM syntax:</para>
|
||
|
|
||
|
<screen>push eax ; illegal instruction</screen>
|
||
|
<screen>push rbx ; 1-byte instruction</screen>
|
||
|
<screen>push r11 ; 2-byte instruction with REX prefix</screen>
|
||
|
</refsect3>
|
||
|
|
||
|
<refsect3>
|
||
|
<title>Implicit Zero Extension</title>
|
||
|
|
||
|
<para>Results of 32-bit operations are implicitly zero-extended to
|
||
|
the upper 32 bits of the corresponding 64-bit register. 16 and 8
|
||
|
bit operations, on the other hand, do not affect upper bits of
|
||
|
the register (just as in 32-bit and 16-bit modes). This can be
|
||
|
used to generate smaller code in some instances. Examples in
|
||
|
NASM syntax:</para>
|
||
|
|
||
|
<screen>mov ecx, 1 ; 1 byte shorter than mov rcx, 1</screen>
|
||
|
<screen>and edx, 3 ; equivalent to and rdx, 3</screen>
|
||
|
</refsect3>
|
||
|
|
||
|
<refsect3>
|
||
|
<title>Immediates</title>
|
||
|
|
||
|
<para>For most instructions in 64-bit mode, immediate values
|
||
|
remain 32 bits; their value is sign-extended into the upper 32
|
||
|
bits of the target register prior to being used. The exception
|
||
|
is the mov instruction, which can take a 64-bit immediate when
|
||
|
the destination is a 64-bit register. Examples in NASM
|
||
|
syntax:</para>
|
||
|
|
||
|
<screen>add rax, 1 ; optimized down to signed 8-bit</screen>
|
||
|
<screen>add rax, dword 1 ; force size to 32-bit</screen>
|
||
|
<screen>add rax, 0xffffffff ; sign-extended 32-bit</screen>
|
||
|
<screen>add rax, -1 ; same as above</screen>
|
||
|
<screen>add rax, 0xffffffffffffffff ; truncated to 32-bit (warning)</screen>
|
||
|
<screen>mov eax, 1 ; 5 byte</screen>
|
||
|
<screen>mov rax, 1 ; 5 byte (optimized to signed 32-bit)</screen>
|
||
|
<screen>mov rax, qword 1 ; 10 byte (forced 64-bit)</screen>
|
||
|
<screen>mov rbx, 0x1234567890abcdef ; 10 byte</screen>
|
||
|
<screen>mov rcx, 0xffffffff ; 10 byte (does not fit in signed 32-bit)</screen>
|
||
|
<screen>mov ecx, -1 ; 5 byte, equivalent to above</screen>
|
||
|
<screen>mov rcx, sym ; 5 byte, 32-bit size default for symbols</screen>
|
||
|
<screen>mov rcx, qword sym ; 10 byte, override default size</screen>
|
||
|
|
||
|
<para>The handling of mov reg64, unsized immediate is different
|
||
|
between YASM and NASM 2.x; YASM follows the above behavior, while
|
||
|
NASM 2.x does the following:</para>
|
||
|
|
||
|
<screen>add rax, 0xffffffff ; sign-extended 32-bit immediate</screen>
|
||
|
<screen>add rax, -1 ; same as above</screen>
|
||
|
<screen>add rax, 0xffffffffffffffff ; truncated 32-bit (warning)</screen>
|
||
|
<screen>add rax, sym ; sign-extended 32-bit immediate</screen>
|
||
|
<screen>mov eax, 1 ; 5 byte (32-bit immediate)</screen>
|
||
|
<screen>mov rax, 1 ; 10 byte (64-bit immediate)</screen>
|
||
|
<screen>mov rbx, 0x1234567890abcdef ; 10 byte instruction</screen>
|
||
|
<screen>mov rcx, 0xffffffff ; 10 byte instruction</screen>
|
||
|
<screen>mov ecx, -1 ; 5 byte, equivalent to above</screen>
|
||
|
<screen>mov ecx, sym ; 5 byte (32-bit immediate)</screen>
|
||
|
<screen>mov rcx, sym ; 10 byte instruction</screen>
|
||
|
<screen>mov rcx, qword sym ; 10 byte (64-bit immediate)</screen>
|
||
|
</refsect3>
|
||
|
|
||
|
<refsect3>
|
||
|
<title>Displacements</title>
|
||
|
|
||
|
<para>Just like immediates, displacements, for the most part,
|
||
|
remain 32 bits and are sign extended prior to use. Again, the
|
||
|
exception is one restricted form of the mov instruction: between
|
||
|
the al/ax/eax/rax register and a 64-bit absolute address (no
|
||
|
registers allowed in the effective address). In NASM syntax, use
|
||
|
of the 64-bit absolute form requires
|
||
|
<userinput>[qword]</userinput>. Examples in NASM syntax:</para>
|
||
|
|
||
|
<screen>mov eax, [1] ; 32 bit, with sign extension</screen>
|
||
|
<screen>mov al, [rax-1] ; 32 bit, with sign extension</screen>
|
||
|
<screen>mov al, [qword 0x1122334455667788] ; 64-bit absolute</screen>
|
||
|
<screen>mov al, [0x1122334455667788] ; truncated to 32-bit (warning)</screen>
|
||
|
</refsect3>
|
||
|
|
||
|
<refsect3>
|
||
|
<title>RIP Relative Addressing</title>
|
||
|
|
||
|
<para>In 64-bit mode, a new form of effective addressing is
|
||
|
available to make it easier to write position-independent code.
|
||
|
Any memory reference may be made RIP relative (RIP is the
|
||
|
instruction pointer register, which contains the address of the
|
||
|
location immediately following the current instruction).</para>
|
||
|
|
||
|
<para>In NASM syntax, there are two ways to specify RIP-relative
|
||
|
addressing:</para>
|
||
|
|
||
|
<screen>mov dword [rip+10], 1</screen>
|
||
|
|
||
|
<para>stores the value 1 ten bytes after the end of the
|
||
|
instruction. <userinput>10</userinput> can also be a symbolic
|
||
|
constant, and will be treated the same way. On the other
|
||
|
hand,</para>
|
||
|
|
||
|
<screen>mov dword [symb wrt rip], 1</screen>
|
||
|
|
||
|
<para>stores the value 1 into the address of symbol
|
||
|
<userinput>symb</userinput>. This is distinctly different than
|
||
|
the behavior of:</para>
|
||
|
|
||
|
<screen>mov dword [symb+rip], 1</screen>
|
||
|
|
||
|
<para>which takes the address of the end of the instruction, adds
|
||
|
the address of <userinput>symb</userinput> to it, then stores the
|
||
|
value 1 there. If <userinput>symb</userinput> is a variable,
|
||
|
this will <emphasis>not</emphasis> store the value 1 into the
|
||
|
<userinput>symb</userinput> variable!</para>
|
||
|
|
||
|
<para>Yasm also supports the following syntax for RIP-relative
|
||
|
addressing:</para>
|
||
|
|
||
|
<screen>mov [rel sym], rax ; RIP-relative</screen>
|
||
|
<screen>mov [abs sym], rax ; not RIP-relative</screen>
|
||
|
|
||
|
<para>The behavior of:</para>
|
||
|
|
||
|
<screen>mov [sym], rax</screen>
|
||
|
|
||
|
<para>Depends on a mode set by the DEFAULT directive, as follows.
|
||
|
The default mode is always "abs", and in "rel" mode, use of
|
||
|
registers, an fs or gs segment override, or an explicit "abs"
|
||
|
override will result in a non-RIP-relative effective
|
||
|
address.</para>
|
||
|
|
||
|
<screen>default rel</screen>
|
||
|
<screen>mov [sym], rbx ; RIP-relative</screen>
|
||
|
<screen>mov [abs sym], rbx ; not RIP-relative (explicit override)</screen>
|
||
|
<screen>mov [rbx+1], rbx ; not RIP-relative (register use)</screen>
|
||
|
<screen>mov [fs:sym], rbx ; not RIP-relative (fs or gs use)</screen>
|
||
|
<screen>mov [ds:sym], rbx ; RIP-relative (segment, but not fs or gs)</screen>
|
||
|
<screen>mov [rel sym], rbx ; RIP-relative (redundant override)</screen>
|
||
|
|
||
|
<screen>default abs</screen>
|
||
|
<screen>mov [sym], rbx ; not RIP-relative</screen>
|
||
|
<screen>mov [abs sym], rbx ; not RIP-relative</screen>
|
||
|
<screen>mov [rbx+1], rbx ; not RIP-relative</screen>
|
||
|
<screen>mov [fs:sym], rbx ; not RIP-relative</screen>
|
||
|
<screen>mov [ds:sym], rbx ; not RIP-relative</screen>
|
||
|
<screen>mov [rel sym], rbx ; RIP-relative (explicit override)</screen>
|
||
|
</refsect3>
|
||
|
|
||
|
<refsect3>
|
||
|
<title>Memory references</title>
|
||
|
|
||
|
<para>Usually the size of a memory reference can be deduced by
|
||
|
which registers you're moving--for example, "mov [rax],ecx" is a
|
||
|
32-bit move, because ecx is 32 bits. YASM currently gives the
|
||
|
non-obvious "invalid combination of opcode and operands" error if
|
||
|
it can't figure out how much memory you're moving. The fix in
|
||
|
this case is to add a memory size specifier: qword, dword, word,
|
||
|
or byte.</para>
|
||
|
|
||
|
<para>Here's a 64-bit memory move, which sets 8 bytes starting at
|
||
|
rax:</para>
|
||
|
|
||
|
<screen>mov qword [rax], 1</screen>
|
||
|
|
||
|
<para>Here's a 32-bit memory move, which sets 4 bytes:</para>
|
||
|
|
||
|
<screen>mov dword [rax], 1</screen>
|
||
|
|
||
|
<para>Here's a 16-bit memory move, which sets 2 bytes:</para>
|
||
|
|
||
|
<screen>mov word [rax], 1</screen>
|
||
|
|
||
|
<para>Here's an 8-bit memory move, which sets 1 byte:</para>
|
||
|
|
||
|
<screen>mov byte [rax], 1</screen>
|
||
|
</refsect3>
|
||
|
</refsect2>
|
||
|
</refsect1>
|
||
|
|
||
|
<refsect1>
|
||
|
<title>lc3b Architecture</title>
|
||
|
|
||
|
<para>The <quote>lc3b</quote> architecture supports the LC-3b ISA as
|
||
|
used in the ECE 312 (now ECE 411) course at the University of
|
||
|
Illinois, Urbana-Champaign, as well as other university courses.
|
||
|
See <ulink url="http://courses.ece.uiuc.edu/ece411/"/> for more
|
||
|
details and example code. The <quote>lc3b</quote> architecture
|
||
|
consists of only one machine: <quote>lc3b</quote>.</para>
|
||
|
</refsect1>
|
||
|
|
||
|
<refsect1>
|
||
|
<title>See Also</title>
|
||
|
|
||
|
<para><citerefentry>
|
||
|
<refentrytitle>yasm</refentrytitle>
|
||
|
<manvolnum>1</manvolnum>
|
||
|
</citerefentry></para>
|
||
|
</refsect1>
|
||
|
|
||
|
<refsect1>
|
||
|
<title>Bugs</title>
|
||
|
|
||
|
<para>When using the <quote>x86</quote> architecture, it is overly
|
||
|
easy to generate AMD64 code (using the <userinput>BITS
|
||
|
64</userinput> directive) and generate a 32-bit object file (by
|
||
|
failing to specify <option>-m amd64</option> on the command line or
|
||
|
selecting a 64-bit object format). Similarly, specifying
|
||
|
<option>-m amd64</option> does not default the BITS setting to
|
||
|
64. An easy way to avoid this is by directly specifying
|
||
|
a 64-bit object format such as <option>-f elf64</option>.</para>
|
||
|
</refsect1>
|
||
|
</refentry>
|