Assembly Language - Arithmetic Instructions
\\\\n\\\\nArithmetic instructions are the foundation of mathematical operations executed by the CPU. This chapter provides a detailed introduction to addition, subtraction, multiplication, division, and related carry operations in the x86 architecture.
\\\\n\\\\n\\\\n\\\\n
ADD - Addition Instruction
\\\\n\\\\nADD adds the source operand and destination operand, storing the result in the destination operand.
Example
\\\\n\\\\n; File path: add_demo.asm\\\\n\\\\n; ADD Instruction example:Calculate 100 + 200 + 300\\\\n\\\\nsection.data\\\\n\\\\n a dd 100\\\\n\\\\n b dd 200\\\\n\\\\n c dd 300\\\\n\\\\n sum dd 0\\\\n\\\\nsection.text\\\\n\\\\nglobal _start\\\\n\\\\n_start:\\\\n\\\\n; Method 1: Register += Immediatei.e.number\\\\n\\\\nmov eax,; eax = 100\\\\n\\\\nadd eax,200; eax = 100 + 200 = 300\\\\n\\\\n; Method 2: Register += Register\\\\n\\\\nmov ebx,; ebx = 200\\\\n\\\\nadd eax,ebx; eax = 300 + 200 = 500\\\\n\\\\n; Method 3: Register += RAM\\\\n\\\\nadd eax,; eax = 500 + 300 = 800\\\\n\\\\n; Store result\\\\n\\\\nmov,eax; sum = 800\\\\n\\\\n; Impact of Addition on Flag Characters\\\\n\\\\nmov eax,0xFFFFFFFF; eax = Largest 32 characters unsigned number\\\\n\\\\nadd eax,1; eax = 0(overflow wraparound)\\\\n\\\\n; CF = 1(produces Carry)characters)\\\\n\\\\n; ZF = 1(Resultis 0)\\\\n\\\\n; OF = 0(No overflow from signed perspective)\\\\n\\\\nmov eax,1\\\\n\\\\nmov ebx,0\\\\n\\\\nint 0x80\\\\n\\\\n\\\\n\\\\n
SUB - Subtraction Instruction
\\\\n\\\\nSUB subtracts the source operand from the destination operand, storing the result in the destination operand.
Example
\\\\n\\\\n; File path: sub_demo.asm\\\\n\\\\n; SUB Instruction example\\\\n\\\\nsection.data\\\\n\\\\n x dd 1000\\\\n\\\\n y dd 300\\\\n\\\\nsection.text\\\\n\\\\nglobal _start\\\\n\\\\n_start:\\\\n\\\\n; Basic subtraction\\\\n\\\\nmov eax,; eax = 1000\\\\n\\\\nsub eax,; eax = 1000 - 300 = 700\\\\n\\\\n; Impact of Subtraction on Flag Characters\\\\n\\\\nmov eax,10\\\\n\\\\nsub eax,20; eax = -10(i.e. 0xFFFFFFF6)\\\\n\\\\n; CF = 1(Generates borrow characters: 10 < 20)\\\\n\\\\n; SF = 1(ResultisNegative)\\\\n\\\\n; ZF = 0(ResultNon-zero)\\\\n\\\\n; OF = 0(Unsigned overflow)\\\\n\\\\n; Subtract from itself: commonly used to zero out\\\\n\\\\nmov eax,12345\\\\n\\\\nsub eax,eax; eax = 0\\\\n\\\\n; ZF = 1, CF = 0\\\\n\\\\n; This is a classic method to zero out a SetRegister (Compare mov eax, 0 Efficiency High)\\\\n\\\\nmov eax,1\\\\n\\\\nmov ebx,0\\\\n\\\\nint 0x80\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n
sub eax, eaxis a classic trick to zero out a register. It only takes 2 bytes, whilemov eax, 0takes 5 bytes. It is commonly used in scenarios requiring extreme size optimization (such as shellcode).
\\\\n\\\\n
INC / DEC - Increment/Decrement Instructions
\\\\n\\\\nSimpler instructions for adding or subtracting 1 compared to ADD/SUB:
\\\\n\\\\nExample
\\\\n\\\\n; INC and DEC Example\\\\n\\\\nsection.data\\\\n\\\\n counter dd 0\\\\n\\\\nsection.text\\\\n\\\\nglobal _start\\\\n\\\\n_start:\\\\n\\\\nmov dword,0; counter = 0\\\\n\\\\ninc dword; counter = 1(RAMOperand)\\\\n\\\\ninc dword; counter = 2\\\\n\\\\nmov ecx,10\\\\n\\\\ndec ecx; ecx = 9\\\\n\\\\ndec ecx; ecx = 8\\\\n\\\\n; INC/DEC Does not affect the CF flag characters (this is an important difference from ADD/SUB)\\\\n\\\\n; But will affect ZF, SF, OF, PF\\\\n\\\\n; Use INC in loop\\\\n\\\\nmov ecx,5\\\\n\\\\nmov eax,0\\\\n\\\\n loop_inc:\\\\n\\\\ninc eax; eax Every time add 1\\\\n\\\\nloop loop_inc ; Repeat 5 times, eax final = 5\\\\n\\\\nmov ebx,eax; Return Value = 5\\\\n\\\\nmov eax,1\\\\n\\\\nint 0x80\\\\n\\\\n\\\\n\\\\n
MUL - Unsigned Multiplication
\\\\n\\\\nMUL performs unsigned multiplication. The rules for multiplication are somewhat special:
| Operand Size | \\\\nMultiplier | \\\\nMultiplicand (Implicit) | \\\\nResult Storage | \\\\n
|---|---|---|---|
| 1 byte | \\\\nAny 8-bit register or memory | \\\\nAL | \\\\nAX = AL × operand | \\\\n
| 2 bytes | \\\\nAny 16-bit register or memory | \\\\nAX | \\\\nDX:AX = AX × operand | \\\\n
| 4 bytes | \\\\nAny 32-bit register or memory | \\\\nEAX | \\\\nEDX:EAX = EAX × operand | \\\\n
Example
\\\\n\\\\n; File path: mul_demo.asm\\\\n\\\\n; MUL Unsigned multiplication example\\\\n\\\\nsection.data\\\\n\\\\n val1 dd 1000\\\\n\\\\n val2 dd 2000\\\\n\\\\n result_low dd 0\\\\n\\\\n result_high dd 0\\\\n\\\\nsection.text\\\\n\\\\nglobal _start\\\\n\\\\n_start:\\\\n\\\\n; 32 charactersMultiplication: EDX:EAX = EAX × Operands\\\\n\\\\nmov eax,; eax = 1000\\\\n\\\\nmul dword; edx:eax = 1000 × 2000 = 2,000,000\\\\n\\\\n; Result = 2,000,000 = 0x001E8480\\\\n\\\\n; EAX = 0x001E8480(Low 32 characters)\\\\n\\\\n; EDX = 0x00000000(High 32 characters,Due to / SinceisResultdoes not exceed 32 bits) characters)\\\\n\\\\n; Large number multiplication demonstration (Result exceeds 32 characters)\\\\n\\\\nmov eax,0xFFFFFFFF; eax = 4,294,967,295\\\\n\\\\nmov ebx,2; ebx = 2\\\\n\\\\nmul ebx; edx:eax = 0xFFFFFFFF × 2\\\\n\\\\n; EAX = 0xFFFFFFFE\\\\n\\\\n; EDX = 0x00000001(High 32 characters)\\\\n\\\\n; CF = 1(ResultExceeds 32 characters)\\\\n\\\\n; Store Result\\\\n\\\\nmov,eax\\\\n\\\\nmov,edx\\\\n\\\\nmov eax,1\\\\n\\\\nmov ebx,0\\\\n\\\\nint 0x80\\\\n\\\\n\\\\n\\\\n
IMUL - Signed Multiplication
\\\\n\\\\nIMUL is used for multiplication of signed numbers and has three forms:
Example
\\\\n\\\\n; File path: imul_demo.asm\\\\n\\\\n; IMUL Signed multiplication example\\\\n\\\\nsection.data\\\\n\\\\n a dd-100\\\\n\\\\n b dd 3\\\\n\\\\nsection.text\\\\n\\\\nglobal _start\\\\n\\\\n_start:\\\\n\\\\n; SingleOperandsFormat: same as MUL\\\\n\\\\nmov eax,; eax = -100\\\\n\\\\nimul dword; edx:eax = -100 × 3 = -300\\\\n\\\\n; EAX = -300(0xFFFFFED4)\\\\n\\\\n; EDX = 0xFFFFFFFF(Sign extension)\\\\n\\\\n; Two-Operand form: reg = reg × Operands\\\\n\\\\nmov ebx,; ebx = -100\\\\n\\\\nimul ebx,; ebx = -100 × 3 = -300\\\\n\\\\n; ResultMust fit within 32 characters\\\\n\\\\n; Three-Operand form: reg = Operand 1 × Immediatei.e.number\\\\n\\\\nimul ecx,,5; ecx = -100 × 5 = -500\\\\n\\\\nmov eax,1\\\\n\\\\nmov ebx,0\\\\n\\\\nint 0x80\\\\n\\\\n\\\\n\\\\n\\\\nThe main difference between
\\\\nMULandIMULis how they handle signs:MULinterprets operands as unsigned numbers, whileIMULinterprets them as signed numbers. For example, 0xFFFFFFFF is 4294967295 in MUL but -1 in IMUL.
\\\\n\\\\n
DIV - Unsigned Division
\\\\n\\\\nDIV performs unsigned division, with rules symmetric to MUL:
| Divisor Size | \\\\nDividend (Implicit) | \\\\nQuotient | \\\\nRemainder | \\\\n
|---|---|---|---|
| 1 byte | \\\\nAX | \\\\nAL | \\\\nAH | \\\\n
| 2 bytes | \\\\nDX:AX | \\\\nAX | \\\\nDX | \\\\n
| 4 bytes | \\\\nEDX:EAX | \\\\nEAX | \\\\nEDX | \\\\n
Example
\\\\n\\\\n; File path: div_demo.asm\\\\n\\\\n; DIV Unsigned division example\\\\n\\\\nsection.data\\\\n\\\\n dividend dd 1000\\\\n\\\\n divisor dd 7\\\\n\\\\n quotient dd 0\\\\n\\\\n remainder dd 0\\\\n\\\\nsection.text\\\\n\\\\nglobal _start\\\\n\\\\n_start:\\\\n\\\\n; 32 charactersDivision: edx:eax / Divisor\\\\n\\\\n; Dividend Divisorneeds to be extended to EDX first:EAX\\\\n\\\\nmov eax,; eax = 1000\\\\n\\\\nmov edx,0; edx = 0(High 32 charactersZero out)\\\\n\\\\ndiv dword; edx:eax / 7\\\\n\\\\n; EAX = 142(Quotient)\\\\n\\\\n; EDX = 6(Remainder: 1000 = 142×7 + 6)\\\\n\\\\nmov,eax; quotient = 142\\\\n\\\\nmov,edx; remainder = 6\\\\n\\\\n; Byte division example: 55 / 4\\\\n\\\\nmov ax,55; Dividend Divisor\\\\n\\\\nmov bl,4; Divisor\\\\n\\\\ndiv bl; al = 13(Quotient), ah = 3(Remainder)\\\\n\\\\nmov eax,1\\\\n\\\\nmov ebx,0\\\\n\\\\nint 0x80\\\\n\\\\n\\\\n\\\\n\\\\nBefore performing division, always clear EDX with
\\\\nmov edx, 0orxor edx, edx! If EDX contains old data, the dividend value will be incorrect. This is the most common division bug for beginners.
\\\\n\\\\n
IDIV - Signed Division
\\\\n\\\\nIDIV is used for signed division. Before division, use the CDQ instruction to sign-extend EAX into EDX:EAX:
Example
\\\\n\\\\n; IDIV Signed division example\\\\n\\\\n; Calculate -100 / 3\\\\n\\\\nmov eax,-100; eax = -100\\\\n\\\\ncdq; Sign extension: edx:eax = -100\\\\n\\\\n; cdq Set eax Sign of characters copied to all characters of edx\\\\n\\\\nmov ebx,3; Divisor\\\\n\\\\nidiv ebx; eax = -33(Quotient), edx = -1(Remainder)\\\\n\\\\n; Verification: -100 = -33 × 3 + (-1)\\\\n\\\\n\\\\n\\\\n
ADC / SBB - Add/Subtract with Carry/Borrow
\\\\n\\\\nUsed for large number operations (data exceeding 32 bits):
\\\\n\\\\nExample
\\\\n\\\\n; File path: adc_sbb_demo.asm\\\\n\\\\n; 64 charactersaddmethod:two 64 charactersnumberAdd\\\\n\\\\nsection.data\\\\n\\\\n; 64 charactersOperand a = 0x00000001 FFFFFFFF\\\\n\\\\n a_low dd 0xFFFFFFFF\\\\n\\\\n a_high dd 0x00000001\\\\n\\\\n; 64 charactersOperand b = 0x00000000 00000005\\\\n\\\\n b_low dd 0x00000005\\\\n\\\\n b_high dd 0x00000000\\\\n\\\\n; Result\\\\n\\\\n result_low dd 0\\\\n\\\\n result_high dd 0\\\\n\\\\nsection.text\\\\n\\\\nglobal _start\\\\n\\\\n_start:\\\\n\\\\n; Low 32 charactersAdd\\\\n\\\\nmov eax,\\\\n\\\\nadd eax,; eax = 0xFFFFFFFF + 5 = 0x00000004\\\\n\\\\n; CF = 1(Generates Carry characters!)\\\\n\\\\nmov,eax; result_low = 0x00000004\\\\n\\\\n; High 32 charactersaddCarrycharacters\\\\n\\\\nmov eax,\\\\n\\\\nadc eax,; adc = add + CF\\\\n\\\\n; eax = 1 + 0 + 1(Carry characters) = 2\\\\n\\\\nmov,eax; result_high = 2\\\\n\\\\n; Final 64-bit result: 0x00000002 00000004\\\\n\\\\n; Verification: 0x1FFFFFFF + 5 = 0x200000004\\\\n\\\\n; SBB Subtraction similarly (with borrow characters)\\\\n\\\\nmov eax,\\\\n\\\\nsub eax,; Low 32 charactersSubtract\\\\n\\\\nmov,eax\\\\n\\\\nmov eax,\\\\n\\\\nsbb eax,; sbb = sub - CF\\\\n\\\\nmov eax,1\\\\n\\\\nmov ebx,0\\\\n\\\\nint 0x80\\\\n\\\\n\\\\n\\\\n
Arithmetic Instructions Quick Reference
\\\\n\\\\n| Instruction | \\\\nFormat | \\\\nFunction | \\\\nAffected Flags | \\\\n
|---|---|---|---|
| ADD | \\\\nadd dest, src | \\\\ndest = dest + src | \\\\nCF, ZF, SF, OF, PF | \\\\n
| SUB | \\\\nsub dest, src | \\\\ndest = dest - src | \\\\nCF, ZF, SF, OF, PF | \\\\n
| INC | \\\\ninc dest | \\\\ndest = dest + 1 | \\\\nZF, SF, OF, PF (does not affect CF) | \\\\n
| DEC | \\\\ndec dest | \\\\ndest = dest - 1 | \\\\nZF, SF, OF, PF (does not affect CF) | \\\\n
| MUL | \\\\nmul src | \\\\nUnsigned multiplication | \\\\nCF, OF | \\\\n
| IMUL | \\\\nimul src | \\\\nSigned multiplication | \\\\nCF, OF | \\\\n
| DIV | \\\\ndiv src | \\\\nUnsigned division | \\\\nUndefined | \\\\n
| IDIV | \\\\nidiv src | \\\\nSigned division | \\\\nUndefined | \\\\n
| ADC | \\\\nadc dest, src | \\\\ndest = dest + src + CF | \\\\nCF, ZF, SF, OF, PF | \\\\n
| SBB | \\\\nsbb dest, src | \\\\ndest = dest - src - CF | \\\\nCF, ZF, SF, OF, PF | \\\\n
| NEG | \\\\nneg dest | \\\\ndest = -dest (negate) | \\\\nCF, ZF, SF, OF, PF | \\\\n
YouTip