Sign Extension and Negation (movsx, neg)
Sign Extension and Negation (movsx, neg)
This page explains how to handle signed numbers of different sizes and how to change their sign in x86-64 assembly.
Copying signed numbers
When using mov to copy signed numbers, the sign bit is not automatically extended to the larger register size. This can lead to incorrect values when moving smaller signed values into larger registers.
Example:
mov ax, -42 mov bx, ax ; bx = -42 (ok, same size) mov ecx, bx ; ecx = 65494 (wrong!) ; the negative value was reinterpreted as an unsigned 16-bit number
movsx — move with sign extension
movsx copies a smaller signed value into a larger register while preserving its sign.
Syntax:
movsx destination, source
Example:
mov ax, -42 movsx edx, ax ; edx = -42 (correct) movsx rbx, edx ; rbx = -42 (sign extended again)
The CPU copies the sign bit from the source to fill the unused higher bits in the destination register.
movzx — move with zero extension
For unsigned values, movzx fills the upper bits with zeros.
Example:
mov al, 0xFF movzx eax, al ; eax = 0x000000FF = 255
movzx is the correct instruction when working with unsigned data.
Negation (neg instruction)
neg changes the sign of a signed value (computes two’s complement). It subtracts the operand from zero: 0 − operand.
Syntax:
neg operand
Example:
mov rax, 42 neg rax ; rax = −42 add rax, 42 ; rax = 0
neg affects these flags:
- CF – set if operand ≠ 0
- SF – set if result is negative
- OF – set if signed overflow occurs
- ZF – set if result is 0
Example combining movsx and neg
mov ax, -10 movsx eax, ax ; correctly sign-extend to 32-bit neg eax ; change sign → +10
Summary
- mov copies raw bits without sign extension.
- movsx extends signed values correctly to larger registers.
- movzx is for unsigned zero-extension.
- neg inverts the sign using two’s complement arithmetic.
These instructions are essential for correctly handling mixed data sizes and signed arithmetic in low-level programming.