AT&T syntax (usually identifiable by %
) generally follows this format:
operation src, dest
which has the effect of doing:
dest = dest operation src
So for instance:
add %rdx, %rax
means add the contents of register rdx to register rax and store the result in register rax (ie: rax += rdx
).
Personally, I tend to find Intel syntax (what you will find in the instruction set architecture specifications) a bit easier to read:
operation dest, src
So for instance, the same example as above would be written as add rax, rdx
.
Therefore, let me first rewrite your code into Intel assembly:
mov rax, QWORD PTR [rsp + 88]
add rax, QWORD PTR [rsp + 80]
add rax, QWORD PTR [rsp + 96]
add rax, QWORD PTR [rsp + 104]
add rsp, 120
The first line is simply a quadword (64-bit) load from rsp + 88
. The next few lines add various values to the value that we just loaded. The final line increases the stack pointer by 120 bytes. In C-like pseudocode, that looks like this:
// Given:
// byte *stack;
// uint64_t rax;
rax = *(u64 *) &stack[88];
rax += *(u64 *) &stack[90];
rax += *(u64 *) &stack[96];
rax += *(u64 *) &stack[104];
stack += 120;
So at the end of the block, the stack pointer should have been increased by 120 bytes (thus decreasing the stack by 120 bytes, because the stack grows downward on x86_64). If we reorder what we have so far and combine common operations, we get this:
u64 *nums = (u64 *) &stack[80];
// sizeof (u64) = 8
// 80, 88, 96, 104
rax = nums[0] + nums[1] + nums[2] + nums[3];
stack + 120;
TL;DR: the code presented doesn't move anything. It takes the sum of four 64-bit integers from the stack and places it into register rax, after which it decreases the stack pointer (increases rsp) by 120 bytes.