Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

X86 Assembly/Arithmetic

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

All arithmetic instructions are executed in (one of) the ALU arithmetic logic units. The ALU can only perform integer arithmetics, for floating point instructions see chapter “Floating Point”. Basic operations Arithmetic instructions take two operands: a destination and a source. The destination must be a register or a memory location. The source may be either a memory location, a register, or a constant value. Note that at most one operand may be a memory location. Addition and Subtraction add addend destination This adds addend to destination and stores the result in destination. sub subtrahend destination Like add, only it subtracts subtrahend from destination instead. In C: destination -= subtrahend; Multiplication Unsigned Multiplication mul multiplicand This multiplies multiplicand by the value of corresponding byte-length in the accumulator. width of multiplicand 1 byte 2 bytes 4 bytes 8 bytes corresponding multiplier AL AX EAX RAX product higher part stored in AH DX EDX RDX product lower part stored in AL AX EAX RAX+ result registers used by mul In the second case, the target is not EAX for backward compatibility with code written for older processors. Affected flags are: OF overflow flag ≔ higher part of product ≠ 0 CF carry flag ≔ higher part of product ≠ 0 All other flags are undefined. Signed Multiplication imul multiplicand This instruction is almost like mul, but it treats the sign bit (the MSB most-significant bit), differently. The imul instruction also accepts two other formats: imul multiplicand destination This multiplies destination by multiplicand and puts the result, the product, in destination. imul multiplier product multiplicand This multiplies multiplier by multiplicand and places it into product. Division div divisor This divides the value in the dividend register(s) by divisor, see table below. idiv As div, only signed. width of divisor 1 byte 2 bytes 4 bytes 8 bytes dividend AX DX ○ AX EDX ○ EAX RDX ○ RAX remainder stored in AH DX EDX RDX quotient stored in AL AX EAX RAX+ result registers for div The circle (○) means concatenation. With divisor size 4, this means that EDX are the bits 32-63 and EAX are bits 0-31 of the input number (with lower bit numbers being less significant, in this example). As you typically have 32 or 64-bit input values for signed division, you often need to use CDQ or CQO to sign-extend EAX into EDX or RAXinto RDX just before the division. If quotient does not fit into quotient register, arithmetic overflow interrupt occurs. All flags are in undefined state after the operation. Sign Inversion neg Arithmetically negates the argument (i.e. two's complement negation). Carry Arithmetic Instructions adc Add with carry. Adds src + CF to dest, storing result in dest. Usually follows a normal add instruction to deal with values twice as large as the size of the register. In the following example, source contains a 64-bit number which will be added to destination. mov eax, [source] ; read low 32 bits mov edx, [source+4] ; read high 32 bits add [destination], eax ; add low 32 bits adc [destination+4], edx ; add high 32 bits, plus carry sbb Subtract with borrow. Subtracts src + CF from dest, storing result in dest. Usually follows a normal sub instruction to deal with values twice as large as the size of the register. Increment and Decrement Increment inc augend This instruction increments the register value augend by 1. It performs much faster than add arg, 1, but it does not affect the CF carry flag. Decrement dec minuend Operation Decrements the value in minuend by 1, but this is much faster than the semantically equivalent sub minuend, 1. Operands Minuend may be either a register or memory operand. Application Some programming language represent Boolean values with either all bits zero, or all bits set to one. When you are programming Boolean functions you need to take account of this. The dec instruction can help you with this. Very often you set the final (Boolean) result based on flags. By choosing an instruction that is opposite of the intended and then decrementing the resulting value you will obtain a value satisfying the programming language’s requirements. Here is a trivial example testing for zero. xor rax, rax ; rax ≔ false (ensure result is not wrong due to any residue) test rdi, rdi ; rdi ≟ 0 (ZF ≔ rax = 0) setnz al ; al ≔ ¬ZF dec rax ; rax ≔ rax − 1If you intend to set false the “erroneously” set 1 will be “fixed” by dec. If you intend to set true, which is represented by −1, you will decrement the value zero, the “underflow” of which causing all bits to flip. Note, some architectures execute dec slowly, because of the fact that the flags register is overwritten only partially. It therefore is usually more efficient to use negsetz al       ; al ≔ ZF neg rax       ; rax ≔ 0 − raxwhich will affect the CF carry flag too, though. Since inc and dec do not affect the CF carry flag, you can use these instructions to update a loop’s counting variable without overwriting some information stored in it. If you need an instruction that does not affect any flags while implicitly also performing a dec, you could use the rather slow loop. Pointer arithmetic The lea instruction can be used for arithmetic, especially on pointers. See chapter “data transfer”, § “load effective address”.