Assembly SUB Instruction
In x86-64 assembly language, the SUB
instruction is used to subtract the value of one operand from another, and store the result in the destination operand.
The SUB
instruction requires two operands, a source and destination:
SUB <destination>, <source>
Here, destination
is the operand where the result will be stored, while source
is the operand that will be subtracted from the destination.
The source operand may be a register , memory location, or an immediate value. But the destination
operand must be either a or .
In the following example, we subtract the value of the rbx
from the rax
register and store the result in rax
:
SUB rax, rbx
As mentioned, we can also use an immediate value as a source operand. In the following example, we subtract 5 from the value of the rax register:
SUB rax, 5
Let’s look at a more complete example, where we can actually track the values held in registers:
MOV rax, 2 ; set rax to '1'
MOV rbx, 1 ; set rbx to '2'
SUB rax, rbx ; rax will now equal '1'
In this example, we used the MOV instruction to set the rax register to ‘2’ and rbx to ‘1’. Following the SUB instruction, the value of rax will equal 2 – 1 = 1.
Integer Underflow and the SUB Instruction
One thing to keep in mind is that if the resulting value of a subtraction operation is negative, it will result in an integer underflow – an issue in which the value is smaller than that which can be held by the data type. As a result, the value of the difference will appear as a large positive number (rather than a small negative number).
This isn’t technically an error. It’s simply that in x86-64 assembly, negative numbers are represented by setting the high bit (31). the representation of the difference may not be in a preferred format. This is also called two’s complement.
To obtain a positive representation of the negative number, we first need to flip all of the bits and then add one.
To flip all of the bits, we can xor the original number with all one’s (e.g. 0xFFFFFFFF) and then add one.