SimplifyC++ Article
Designing an x86-64 Assembler Arithmetic and Logic
Designing an x86-64 Assembler: Arithmetic and Logic
1. Arithmetic and Logic Instructions Overview
Arithmetic and logic instructions form the core computational capabilities of the x86-64 processor. These instructions perform essential operations such as addition, subtraction, multiplication, division, bitwise manipulation, and comparisons that underpin all algorithmic processing in assembly code.
The x86-64 architecture provides a rich set of arithmetic and logic instructions optimized for a wide range of operand sizes, including byte (8-bit), word (16-bit), doubleword (32-bit), and quadword (64-bit), as well as vectorized SIMD data types. These instructions also include variants supporting immediate operands, register-to-register, memory-to-register, and register-to-memory operations.
Understanding these instructions, their behavior, flags impact, and encoding requirements is critical in designing a fully compliant assembler.
2. Arithmetic Instructions
Addition (ADD)
Purpose: Adds source operand to destination operand, storing the result in the destination.
Operands: Register, memory, immediate.
Flag effects: Updates Carry Flag (CF), Overflow Flag (OF), Zero Flag (ZF), Sign Flag (SF), Auxiliary Carry Flag (AF), and Parity Flag (PF).
Example:
ADD RAX, RBXadds the contents ofRBXtoRAX.
Subtraction (SUB)
Purpose: Subtracts source operand from destination operand, storing the result in the destination.
Operands: Register, memory, immediate.
Flag effects: Same as ADD.
Example:
SUB RCX, 10subtracts immediate 10 fromRCX.
Multiplication
Unsigned multiply (MUL): Multiplies the accumulator register (
AL,AX,EAX,RAX) by the source operand.Signed multiply (IMUL): Similar to
MULbut treats operands as signed integers.IMUL Variants: Supports one-operand, two-operand, and three-operand forms for flexibility:
One-operand form uses
RAXas implicit source/destination.Two- and three-operand forms support destination explicit registers or memory operands with immediate values.
Flag effects: Flags are undefined or partially set depending on operand sizes.
Example:
IMUL RBX, RCXmultipliesRBXbyRCXstoring result inRBX.
Division
Unsigned division (DIV): Divides the accumulator (
AX,DX:AX,RDX:RAX) by the operand.Signed division (IDIV): Signed variant of
DIV.Operands: Only register or memory operand as divisor.
Results: Quotient stored in accumulator (
AL,AX,EAX,RAX), remainder inAH,DX, orRDXaccordingly.Exception: Division by zero or overflow triggers processor exception.
Example:
IDIV RCXdividesRDX:RAXbyRCX.
Increment (INC) and Decrement (DEC)
Increment or decrement the operand by 1.
Does not affect the carry flag, which is crucial for certain multi-word arithmetic operations.
Commonly used for loops or counters.
Example:
INC RAXadds 1 toRAX.
Negate (NEG)
Two’s complement negation of operand (computes
0 - operand).Sets flags according to result.
Example:
NEG RAXnegatesRAX.
3. Logic Instructions
Logic instructions perform bitwise operations on operands, essential for bit masking, setting, clearing bits, and conditional operations.
AND
Bitwise AND of source and destination.
Flags updated similarly to arithmetic instructions.
Commonly used for masking bits.
Example:
AND RAX, 0xFFmasks lower byte ofRAX.
OR
Bitwise OR of operands.
Used to set bits.
Example:
OR RDX, RBX.
XOR
Bitwise exclusive OR.
Useful for toggling bits and for certain algorithms such as parity checks.
XORing a register with itself sets it to zero efficiently.
Example:
XOR RAX, RAXclearsRAX.
NOT
Bitwise NOT (ones’ complement).
Inverts all bits of operand.
Example:
NOT RBX.
4. Compare and Test Instructions
These instructions perform logical comparisons and set flags without changing the operands themselves.
CMP
Subtracts source from destination for flag evaluation only.
No result is stored; only flags updated.
Frequently used before conditional jumps.
Example:
CMP RAX, RBX.
TEST
Bitwise AND between operands, updating flags.
No operands are changed.
Often used to test if bits are set or clear.
Example:
TEST RAX, 1tests if the least significant bit is set.
5. Shift and Rotate Instructions
Used for bitwise shifting and rotating bits within a register or memory operand.
SHL/SAL (Shift Left / Shift Arithmetic Left): Shifts bits left, filling least significant bits with zero.
SHR (Shift Right Logical): Shifts bits right, filling with zero.
SAR (Shift Arithmetic Right): Shifts bits right, filling with sign bit (preserving signedness).
ROL, ROR (Rotate Left/Right): Circular bit shifts.
RCL, RCR (Rotate through Carry Left/Right): Rotate bits through carry flag.
These instructions affect CF and OF flags accordingly.
Example:
SHL RAX, 1doublesRAXvalue by shifting left one bit.
6. Extended Precision Arithmetic
x86-64 supports instructions for extended precision arithmetic critical for multi-word integer calculations.
Instructions like
ADC(Add with Carry) andSBB(Subtract with Borrow) incorporate the carry flag, allowing chaining additions and subtractions across multiple registers.These instructions maintain correctness in large integer arithmetic beyond 64 bits.
Example:
ADC RBX, RCX.
7. SIMD Arithmetic and Logic Instructions
The x86-64 ISA includes vectorized arithmetic and logic instructions operating on XMM, YMM, and ZMM registers for floating-point and integer packed data.
Integer SIMD: Instructions like
VPADDQ(packed add quadword),VPMULLD(packed multiply doubleword).Floating-point SIMD: Instructions like
VADDPD(add packed double-precision floating-point),VSUBPS(subtract packed single-precision).Bitwise SIMD:
VPAND,VPOR,VPXORperform logical operations on vectors.These instructions rely on VEX and EVEX prefixes for extended register sets and widths.
8. Flags Behavior and Usage
Arithmetic and logic instructions modify CPU flags, which affect control flow and conditional instructions.
Flags affected include:
CF (Carry Flag): Set on unsigned overflow (addition, subtraction).
OF (Overflow Flag): Set on signed overflow.
ZF (Zero Flag): Set if result is zero.
SF (Sign Flag): Reflects sign of result.
AF (Auxiliary Carry Flag): Used internally for BCD operations.
PF (Parity Flag): Set if result has even parity.
Careful management of flag states is essential for correct conditional branching and multi-instruction arithmetic sequences.
9. Instruction Encoding Considerations
Arithmetic and logic instructions employ opcodes that vary based on operand size, direction, and type.
The assembler must correctly generate REX prefixes for 64-bit operands and extended registers.
Immediate operand encoding has size constraints: 8-bit immediates can be sign-extended or zero-extended automatically depending on the instruction.
Shift/rotate instructions require careful encoding of the count operand, which can be immediate or implicitly specified in the
CLregister.SIMD variants use VEX/EVEX prefix encoding, with additional opcode bytes for different operations and vector sizes.
10. Summary
The arithmetic and logic instruction set of the x86-64 ISA is a rich and versatile collection enabling integer and floating-point computations, bitwise manipulation, and complex control flow decisions. A complete assembler must provide comprehensive support for these instructions, handling variations in operand sizes, flag behaviors, immediate values, and SIMD extensions.
Mastering these instructions enables the creation of efficient, high-performance assembly programs and underpins all higher-level language constructs that translate into machine code.
What did you think?
Sign in to react or comment.
Comments
0No comments yet.