Arithmetic
Integer arithmetic, flags, multiplication, division, and practical numeric patterns.
Integer arithmetic is mostly ordinary two-operand work, with two important exceptions: multiply and divide can use the paired rdx:rax result, and signed division needs the dividend extended correctly first.
The everyday instructions
add and sub update their destination. inc and dec change it by one, while neg flips the sign using two's complement. All of them update status flags that later branches can inspect.
mov x, 100
mov y, 50
mov rax, x
; -----------------------------------------------------------------------------
; add dest, source
; -----------------------------------------------------------------------------
add rax, y
; -----------------------------------------------------------------------------
; sub dest, source
; -----------------------------------------------------------------------------
sub rax, x
; -----------------------------------------------------------------------------
; inc dest
; -----------------------------------------------------------------------------
inc rax
; -----------------------------------------------------------------------------
; dec dest
; -----------------------------------------------------------------------------
dec rax
; -----------------------------------------------------------------------------
; neg dest
; -----------------------------------------------------------------------------
neg rax
Keep in mind: The source operand is unchanged; the destination receives the result.
Multiply has useful forms
The one-operand mul/imul forms use rax implicitly and can produce a double-width result in rdx:rax. The two- and three-operand imul forms are often easier when you only need the low half.
mov rax, 100
mov rcx, 100
imul rcx
imul rax, rcx
imul rdx, rax, 8
Keep in mind: Use the explicit destination forms when you do not need the high half in rdx.
Division needs a prepared dividend
div and idiv divide the combined rdx:rax value. Clear rdx for a positive unsigned-sized dividend; use cqo before signed 64-bit division when rax may be negative.
xor rdx, rdx
mov rax, 100
mov rcx, 2
idiv rcx
Keep in mind: After division, rax holds the quotient and rdx holds the remainder.
Bits are data too
and masks bits, or sets them, and xor toggles them. XORing a register with itself is the standard compact way to produce zero.
xor rcx, rcx
xor rdx, rdx
mov rcx, 0101b
mov rdx, 0011b
xor rcx, rdx
and rcx, rdx
or rcx, rdx
Keep in mind: Think of masks as small yes/no filters applied independently to every bit.
Keep these rules
- Arithmetic writes the destination and updates flags.
- Multiply and divide have implicit rax/rdx conventions.
- Prepare the high half of a dividend before div or idiv.