Sign Extension and Negation (movsx, neg)

From MediaWiki
Jump to navigation Jump to search

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.