ASM_(x86-64)::Operators
Now we understand how to assign values to and between registers, but that wouldn't be very useful to do much. That's where operators come in. If you've never heard of the term operators from programming, it is just a fancy way to refer to actions that we can perform.
Basic operator syntax
In x86-64 assembly, most operators tend to follow a general structure. It's helpful to learn this structure so you can learn to use operators you've never seen before, even without consulting the documentation too much.
In general, most operators are used in the following structure:
operator src, dst
src
and dst
are referred to as operands, meaning they are the objects being operated on.
So far, we've covered one type of operand, registers!
Another popular form of operands are memory addresses, but we will cover this in a future lesson.
If you're familiar with programming, the above instruction will then do something like so.
src = operator(src, dst);
As we can see, the operator is applied to both operands, and the resultant value is stored back into the src
operand.
Let's try this out with a real operator.
Arithmetic Operators
As children the first operator we usually learn is addition. Let's do the same here.
add src, dst
The add
instruction is the operator that handles addition (+
)!
As mentioned earlier, the above instruction will reassign src
with the value of add(src, dst)
(src + dst
).
Try to predict the resultant value of rax
, before running the code to verify your answer.
Initializing...
add
, there are various other instructions for the other arithmetic operations.
We've listed the common ones below.
sub
sub
is used for subtraction (-
).
It's functionality is very similar to that of add
.
Initializing...
imul/mul
imul
is used for signed multiplication (*
).
There are three forms that can be used for this instruction:
- one-operand form
- two-operand form
- three-operand form
two-operand form is similar to that of add
and sub
.
Instructions using this form will be written as:
imul src, dst
Which results in
src = src * dst
one-operand form implicitly assigns the src
operand as the rax
register.
Therefore, you only need to specify the dst
operator.
The effects of the instruction will be similar to the two-operand form.
We will leave explanation of three-operand form as a exercise of documentation reading to you.
Here, you can see all three forms of the instruction being used. Be sure to step through the code and predict the result of each instruction before it runs.
Initializing...
overflows
One key difference that the one-operand form has in imul
is tht it is the only one that can support an overflow of the dst
register.
As we know, the operands we have current support up to 64-bits of data.
However, multiplying 2 64-bit values could lead to a value larger than 64-bits.
Usually, the value is truncated to 64-bits, meaning that the calculation will be done correctly, but any bits beyond 64-bits will just be removed and ignored.
For the one-operand form of imul
, it will set rdx
to the bits of the calculation that exceed 64-bits.
This allows for greater range of calculation.
mul
mul
is very similar to one-operand imul
, except that the operands are treated as unsigned values.
idiv/div
idiv
and div
are used for division (*
).
Similar to imul
and mul
, they are the signed and unsigned versions respectively.
Binary Operators
not
The not
instruction takes one operand, and performs a binary NOT.
Also known as one's complement negation, or "flipping all the bits".
and
The and
instruction take two operands src
and dst
and performs a binary AND.
or
The or
instruction take two operands src
and dst
and performs a binary OR.
xor
The xor
instruction take two operands src
and dst
and performs a binary exclusive-OR.
Initializing...
Unare Quiz #1
To test your knowledge thus far, we've prepared our special unare challenges! Try to understand the assembly snippet below, and write the corresponding C code that could generate such a assembly snippet.
Few things to note:
The first and last few instructions can be ignored as they are instructions preparing the stack, generated by the compiler.
push rbp
mov rbp, rsp
...
pop rbp
ret
The first 6 arguments of a function are passed in the rdi, rsi, rdx, rcx, r8, r9
registers.
The return value of a function is copied into rax
before the function returns.
With this knowledge, give this problem a try!
Quiz
Write the equivalent C code for the following assembly (x86-64) snippet.
Assembly (x86-64)