
我们先给汇编代码添加注释：

x in %rdi, y in %rsi, z in %rdx
eval:
    subq $104, %rsp     // 给栈分配了104个字节的空间
    movq %rdx, 24(%rsp) // 把z的值保存在偏移量为24的位置
    leaq 24(%rsp), %rax // %rax保存了z的指针
    movq %rdi, (%rsp)   // 把x的值保存在偏移量为0的位置
    movq %rsi, 8(%rsp)  // 把y的值保存在偏移量为8的位置
    movq %rax, 16(%rsp) // 把z的指针值保存在偏移量为16的位置
    leaq 64(%rsp), %rdi // 把偏移量为64的指针赋值给%rdi，当做参数传递给后边的函数
    call process

    movq 72(%rsp), %rax // 取出偏移量为72的值赋值给%rax
    addq 64(%rsp), %rax // +
    addq 80(%rsp), %rax // +
    addq $104, %rsp      // 恢复栈顶指针
    ret


process:
    movq %rdi, %rax         // 把参数保存到%rax
    movq 24(%rsp), %rdx     // %rdx = &z 这里有点意思，当调用call后会把函数下边代码的地址压入栈中
    movq (%rdx), %rdx       // %rdx = z
    movq 16(%rsp), %rcx     // %rcx = y
    movq %rcx, (%rdi)       // 把y保存到偏移量为64 + 8 = 72的位置
    movq 8(%rsp), %rcx      // %rcx = x
    movq %rcx, 8(%rdi)      // 把x保存到偏移量为64 + 8 + 8 = 80的位置
    movq %rdx, 16(%rdi)     // 把z保存到偏移量为64 + 8 + 16 = 88的位置
    ret


通过上边的注释，下边的问题就很清楚了

A:
-----------     <-- 108

    z
-----------     <-- 24
    &z
-----------     <-- 16
    y
-----------     <-- 8
    x
-----------     <-- %rsp

B:
传递了一个相对于%rsp偏移量为64的指针

C:
直接使用偏移量来访问的s的元素

D:
直接设置偏移量

E:
-----------     <-- 108


-----------     <-- 88
    z
-----------     <-- 80
    x
-----------     <-- 72
    y
-----------     <-- 64 --- %rax

-----------     <-- 32
    z
-----------     <-- 24
    &z
-----------     <-- 16
    y
-----------     <-- 8
    x
-----------     <-- %rsp

F:
通过这个例子，我们能够发现，如果把结构作为参数，那么实际传递的会是一个空的位置指针，函数把数据
存储在这个位置上，同时返回值也是这个指针。