## 源程序
#include <stdio.h>
int array_sum(int *array,int n)
{
int t = 0,i = 0;
for(i = 0; i < n; ++i){
t += array[i];
}
return t;
}
int main(int argc,char * argv[])
{
int a[5] = {1,2,3,4,5};
int sum = array_sum(a,5);
return sum;
}
编译
gcc -S -o sum.s ass_array.c
汇编代码
.file "ass_array.c" ;生命是哪个源文件
.text
.globl array_sum
.type array_sum, @function
array_sum:
.LFB0:
.cfi_startproc
pushq %rbp ;保存调用函数(main)基址到栈中
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp ;设置rbp为当前调用函数的基址指针,即保存当前栈顶
.cfi_def_cfa_register 6
movq %rdi, -24(%rbp) ;将数组a的地址保存到 rbp-24地址上。
movl %esi, -28(%rbp) ;将数组的长度保存到 rbp - 28 地址上,也就是n。
movl $0, -4(%rbp) ;初始化变量t
movl $0, -8(%rbp) ;初始化变量i
jmp .L2
.L3:
movl -8(%rbp), %eax ;将i值保存到 eax寄存器中
cltq ;有符号数扩展指令,扩展为 rax
leaq 0(,%rax,4), %rdx ;rax * 4 + 0 = rdx 相当于==> i * 4 计算偏移量
movq -24(%rbp), %rax ;将a的地址放入 rax
addq %rdx, %rax ;获取a数组的第几个元素的地址
movl (%rax), %eax ;将a[i]的值赋值给 eax
addl %eax, -4(%rbp) ; 计算 t += a[i]
addl $1, -8(%rbp) ; ++i
.L2:
movl -8(%rbp), %eax ;将i保存到eax中
cmpl -28(%rbp), %eax ;将数组长度n和i进行比较,如果 i < N 跳转到 .L3,否则继续执行
jl .L3
movl -4(%rbp), %eax ;将计算结果t存放到返回寄存器eax中。
popq %rbp ;恢复调用函数基址指针
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size array_sum, .-array_sum
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp ;保存rbp寄存器
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp ;将rsp寄存器当前值,赋值给rbp,保存当前的rbp值
.cfi_def_cfa_register 6
subq $48, %rsp ;在栈中分配 48 个字节的空间
movl %edi, -36(%rbp) ;将edi保存在 rbp-36 这个栈地址上,占用四个字节
movq %rsi, -48(%rbp) ;将 rsi 寄存器值保存在 rbp-48 这个栈地址上
movl $1, -32(%rbp) ; 数组a的首地址,赋值a[0]。
movl $2, -28(%rbp) ;a[1]
movl $3, -24(%rbp)
movl $4, -20(%rbp)
movl $5, -16(%rbp)
leaq -32(%rbp), %rax ;将数组a的地址保存到 rax寄存器中,也就是&a。
movl $5, %esi ;保存array_sum函数的第二个参数,入参顺序为从右到左。
movq %rax, %rdi ;将array_sum函数的第一个参数保存到rdi寄存器中,也就是&a,因为rax会保存函数的返回值,所以必须将rax腾出来。
call array_sum ;调用次函数
movl %eax, -4(%rbp) ;将返回值放入rbp-4栈地址上。
movl -4(%rbp), %eax ;返回值复制给sum。
leave ;恢复rsp的值,并且pop出rbp
;movq %rbp,%rsp;pop %rbp;
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
.section .note.GNU-stack,"",@progbits
c源码
#include <stdio.h>
struct point
{
int x;
int y;
};
void point_init(struct point * p,int x,int y)
{
p->x = x;
p->y = y;
}
int main()
{
struct point p;
int x = 10;
int y = 20;
point_init(&p,x,y);
printf("p->x : [%d], p->y :[%d]\n",p.x,p.y);
return 0;
}
汇编源码
.file "struct.c"
.text
.globl point_init
.type point_init, @function
point_init:
.LFB0:
.cfi_startproc
pushq %rbp ;保存调用函数基地址
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp ;获取当前函数基地址
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp) ;取出&p
movl %esi, -12(%rbp) ;取出 x
movl %edx, -16(%rbp) ;取出y
movq -8(%rbp), %rax ;将p的地址取出,并且赋值给rax
movl -12(%rbp), %edx ;取出x 的值
movl %edx, (%rax) ;将x的值赋值给 p->x = x
movq -8(%rbp), %rax ;将p的地址取出
movl -16(%rbp), %edx ;将y的值赋值给edx
movl %edx, 4(%rax) ;p->y = y
nop ;占位指令
popq %rbp ;恢复main函数基址
.cfi_def_cfa 7, 8
ret ;弹出保存的rip
.cfi_endproc
.LFE0:
.size point_init, .-point_init
.section .rodata
.LC0:
.string "p->x : [%d], p->y :[%d]\n"
.text
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp ;保存调用函数基址指针
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp ;获取当前函数基址指针
.cfi_def_cfa_register 6
subq $16, %rsp ;分配栈空间
movl $10, -4(%rbp) ;给x赋值
movl $20, -8(%rbp) ;给y赋值
movl -8(%rbp), %edx ;取出第三个参数y
movl -4(%rbp), %ecx ;取出第二个参数 x
leaq -16(%rbp), %rax ;去p的地址,将地址付给rax
movl %ecx, %esi ;将第二个参数赋值给 esi
movq %rax, %rdi ;将&p赋值给rdi
call point_init ;调用函数,并将call吓一跳地址入栈,rsp-8。
movl -12(%rbp), %edx ;将p.y入栈
movl -16(%rbp), %eax ;将p.x赋值给eax
movl %eax, %esi ;将eax赋值给esi,入栈
leaq .LC0(%rip), %rdi ;将第一个参数入栈。
movl $0, %eax ;将eax清空
call printf@PLT
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (Debian 9.2.1-19) 9.2.1 20191109"
.section .note.GNU-stack,"",@progbits