### <a href="/contents/instruction-sets/x86.md"><-</a> [.instruction-sets](instruction-sets.md)[__x86-64__] <a href="ARM.md">-></a>

---
#### *<p align='center'> Canonical Form </p>*
---
* All addresses and pointers are 64-bit, but virtual addresses must be in canonical form. Canonical form means that bit 47 and bits 48-63 must match since modern processors only support 48-bit for address space rather than the full 64-bit. If the address is not in canonical form, an exception will be raised

---
#### *<p align='center'> Registers </p>*
---
* Aside from the old x86 registers being extended from 32-bit to 64-bit, extra General Purpose Registers have also been added (e.g. r8 to r15)
* 16 general-purpose registers each 64-bits (RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15)
  * DWORD (32-bit) version can be accessed with a D suffix, WORD (16-bit) with a W suffix, BYTE (8-bit) with a B suffix for registers R8 to R15
  * For registers with alternate names like x86 (e.g. RAX, RCX), size access for register is same as x86. For example, 32-bit version of RAX is EAX and the 16-bit version is DX
  * RBP is treated like another GPR. As a result, local variables are referenced through RSP
* 16 XMM registers, each 128-bit long. XMM registers are for SIMD instruction set, which is an extension to the x86-64 architecture. SIMD is for performing the same instruction on multiple data at once and/or for floating point operations
  * Floating point operations were once done using stack-based instruction set that accesses the FPU Register Stack. But now, it can be done using the SIMD instruction set

---
#### *<p align='center'> Calling Conventions </p>*
---
* Parameters are passed to registers instead of the stack. Although additional ones will still be stored on stack
* __Windows__: first 4 parameters are placed in RCX, RDX, R8, and R9
* __Linux__: first 6 parameters are placed in RDI, RSI, RDX, RCX, R8, and R9

---
#### *<p align='center'> Exception Handling </p>*
---
* __Windows__: on x86, Structured Exception Handling (SEH) is stored on the stack, which makes it vulnerable to buffer overflow attacks. SEH on x64 is implemented differently. SEH is table-based and no longer stored on the stack. It is instead stored in the PE Header
* __Linux__: for both x86 and x64, exception handling can be achieved through signals

---
#### *<p align='center'> Other Notable Differences From x86 </p>*
---
* Easier in 64-bit code to differentiate between pointers and data values. The most common size for storing integers is 32 bits and pointers are always 64 bits
* Supports instruction pointer-relative addressing on data. Unlike x86, referencing data will not use absolute address but rather an offset from RIP
* Can't directly push an immediate value on the stack with the PUSH instruction in x86-64
  * Needs to move the value into a register first and then push: ``` MOV RAX, 0x1122334455667788; PUSH RAX ```
* Have direct access to RIP (instruction pointer) unlike x86
  * This is valid: ```MOV RAX, RIP ```

#
<strong><p align='center'><a href="/contents/instruction-sets/x86.md">x86</a> <- <a href="/README.md#-reverse-engineering-reference-manual-beta-">RERM</a>[<a href="instruction-sets.md">.instruction-sets</a>] -> <a href="ARM.md">ARM</a></p></strong>
