linux assembly

## 源程序

#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 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值