Chrinovic Mukanya

Implicit State Changes in x86

In x86-64, an instruction has a side effect when it modifies the processor state beyond its explicit destination operand. This usually involves updating the RFLAGS register, the Stack Pointer (RSP), or the Instruction Pointer (RIP). Here are some examples and their side effects.

Arithmetic and Logic Instructions

Almost all arithmetic instructions have the side effect of updating the RFLAGS register. These flags (ZF, SF, CF, OF, PF, AF) describe the result of the operation.

ADD/SUB/IMUL - These modify flags to indicate if the result was zero, negative, or caused an overflow. AND/OR/XOR - These always clear the Carry (CF) and Overflow (OF) flags as a side effects.

CMP(Compare) - This is instruction is primarily used for it's side effects nature. It's only purpose is to subtract the source from the destination and update flags, it doesn't store the result of the subtraction anywhere. the RFLAGS register is read and the flags are analyzed for what could have the Compare resulted in.

Given an instruction CMP RAX, RBX, which internally performs the computation RAX - RBX.

Zero flag(ZF): Set to 1 if RAX and RBX are equal, because RAX - RBX = 0; Sign Flag(SF): Set to 1 if result is negative, meaning RAX < RBX in signed logic. Carry Flag(CF): Set to 1 if an unsigned borrow was needed, meaning RAX < RBX in unsigned logic. Overflow Flag(ZF): Set to 1 if the subtraction resulted in a signed number too large or too small for the register.

Stack Manipulation Instructions

These instructions are shorthand for a data move plus an arithmetic operation on the RSP (Stack Pointer) register.

PUSH src: Explicit: Moves value to the top of the stack. Side Effect: Decrements RSP by 8 (in 64-bit mode).

POP dest Explicit: Load the value at [RSP] into the destination. Side Effect: Increments RSP by 8.

Control Flow Instructions

These instructions primarily exist to modify the RIP (Instruction Pointer), which is not directly accessible via standard MOV instructions.

CALL label: Side Effect 1: Pushes the return address (address of the next instruction) onto the stack. Side Effect 2: Subtracts 8 from RSP. Side Effect 3: Sets RIP to the target address.

RET: Side Effect 1: Pops the value from the top of the stack into RIP. Side Effect 2: Adds 8 to RSP.

JMP/Jcc(Jump): Changes the RIP based on the conditions in the RFLAGS register.

String Instructions

Instructions like MOVSB, STOSB, and LODSB are designed for high-speed memory operations and have significant side effects on index registers.

MOVSB (Move String Byte): Explicit: Copy a byte from [RSI] to [RDI]. Side Effect: Automatically Increments or decrements both RSI and RDI based on the state of the Direction Flag(DF).

Specialized Hardware Instructions

IDIV (Integer Divide): Explicit: Divides the value in RAX by the operand. Side Effect: It automatically stores the quotient in RAX and the remainder in RDX. You cannot use IDIV without affecting both registers.

CPUID Explicit: Queries processor information. Side Effect: Overwrites RAX, RBX, RCX and RDX simultaneously with hardware metadata.

Well, not many might care about these things or to little extent, however emulator and compiler folks deeply need to worry and consider them at all times.