ARMv7汇编代码分析
来源:互联网 发布:易建联nba体测数据 编辑:程序博客网 时间:2024/05/17 22:16
为了分析ARMv7架构寄存器的使用,利用C程序生成ARMv7汇编,并分析之。
1、C源程序代码如下(为了简化,函数功能很简单):
# cat callfunc.c
#include <stdio.h>#include <stdlib.h>#include <math.h>int main(){int input=10;int tmp,result;tmp = func1(input);result = func2(tmp);printf("result = %d \n", result);return 0;}int func1(int a){a++;return a;}int func2(int b){b=b*b;return b;}
2、交叉编译生成ARM汇编代码:
# arm-none-linux-gnueabi-gcc -march=armv7-a callfunc.c -S -o callfunc.asm
生成ARMv7的汇编代码如下:
.arch armv7-a.fpu softvfp.eabi_attribute 20, 1.eabi_attribute 21, 1.eabi_attribute 23, 3.eabi_attribute 24, 1.eabi_attribute 25, 1.eabi_attribute 26, 2.eabi_attribute 30, 6.eabi_attribute 34, 1.eabi_attribute 18, 4.file"callfunc.c".section.rodata.align2;2^2,即4字节对齐;以"."开头的是伪指令,具有编译器相关,平台无关性;.LC0:.ascii"result = %d \012\000".text.align2.globalmain;全局函数声明,相当于C语言中的extern.typemain, %functionmain:.fnstart;函数开始标志@ args = 0, pretend = 0, frame = 16;@标志注释,由编译器添加@ frame_needed = 1, uses_anonymous_args = 0stmfdsp!, {fp, lr};fp=r11=0,lr=0x40291664;分别存储fp,lr到sp,sp-4;sp0=sp-4;fp(R11)桢指针 ;;关于fp:通常在C程序编译过程中,所有函数的局部变量被分配在一个连续的存储区中,;一般这个存储区是在堆栈中,这个连续的存储区称为这个函数的存储“帧”,它是通过一个指针访问的。;寄存器 fp (桢指针)应当是零或者是指向栈回溯结构的列表中的最后一个结构,
;提供了一种追溯程序的方式,来反向跟踪调用的函数。
;即:其作用是用来回溯,从代码中也可以看出来,fp只是起标签作用,理论上不使用fp也不会影响程序执行.save {fp, lr};关于.save:其作用与以下.setfp、.pad等的伪指令作用类似,对相应汇编指令产生注释。;具体注释内容见网页(http://sourceware.org/binutils/docs/as/ARM-Directives.html).setfp fp, sp, #4addfp, sp, #4;sp=0xbe88f3e0,fp=0xbe88f3e4.pad #16subsp, sp, #16;sp=0xbe88f3d0movr3, #10;r3=10strr3, [fp, #-8];r3->fp-8即sp-4ldrr0, [fp, #-8];r3->r0blfunc1;jump to func1strr0, [fp, #-12];r0->fp-12ldrr0, [fp, #-12]blfunc2strr0, [fp, #-16]movwr3, #:lower16:.LC0movtr3, #:upper16:.LC0 ;movw和movt的作用为:r3 = (movt #:upper16:.LC0 << 16) | (movw #:lower16:.LC0)).;以上两句的作用就是输出.LC0段的.ascii那一行的内容,即打印那个result = %d \012\000movr0, r3ldrr1, [fp, #-16]blprintf;打印r0、r1中内容movr3, #0movr0, r3subsp, fp, #4ldmfdsp!, {fp, pc}.fnend.sizemain, .-main.align2.globalfunc1.typefunc1, %functionfunc1:.fnstart@ args = 0, pretend = 0, frame = 8@ frame_needed = 1, uses_anonymous_args = 0@ link register save eliminated.strfp, [sp, #-4]! ;r11(fp)入栈;sp=0xbe88f3d0-4=0xbe88f3cc,r11=0xbe88f3e4;fp(即r11)存储到sp-4(0x)的地址中.save {fp}.setfp fp, sp, #0addfp, sp, #0;fp=0xbe88f3cc.pad #12subsp, sp, #12;sp=0xbe88f3c0strr0, [fp, #-8];r0存储到fp-8指向的地址处ldrr3, [fp, #-8]addr3, r3, #1strr3, [fp, #-8]ldrr3, [fp, #-8]movr0, r3addsp, fp, #0ldmfdsp!, {fp};r11(fp)出栈bxlr.fnend.sizefunc1, .-func1.align2.globalfunc2.typefunc2, %functionfunc2:.fnstart@ args = 0, pretend = 0, frame = 8@ frame_needed = 1, uses_anonymous_args = 0@ link register save eliminated.strfp, [sp, #-4]!.save {fp}.setfp fp, sp, #0addfp, sp, #0.pad #12subsp, sp, #12strr0, [fp, #-8]ldrr3, [fp, #-8];r0->r3ldrr2, [fp, #-8];r0->r2mulr3, r2, r3 ;r2*r3->r3strr3, [fp, #-8]ldrr3, [fp, #-8]movr0, r3;r3->r0addsp, fp, #0ldmfdsp!, {fp};sp->fp ;pop fpbxlr.fnend.sizefunc2, .-func2.ident"GCC: (Sourcery CodeBench Lite 2011.09-70) 4.6.1".section.note.GNU-stack,"",%progbits
注意:
1、编译器默认用来传输参数的寄存器是r0~r3,参数超过四个就要用到栈。
2、bl printf:该命令是打印命令,默认打印r0开始的寄存器内容,测试过参数超过4个时候,打印时r0存储打印格式,r1-r3存储要打印的数,剩下的参数需要其他寄存器存储,但是printf如何实现打印多出来的几个寄存器的,目前暂不清楚。欢迎补充。
- ARMv7汇编代码分析
- 汇编代码分析
- 反汇编代码分析
- STM8汇编代码分析
- sdram汇编代码分析
- 反汇编代码分析
- 1.汇编代码分析
- 一段汇编代码的分析
- U-boot汇编代码分析
- 函数调用汇编代码分析
- C++反汇编代码分析
- 汇编代码的简单分析
- system_call的汇编代码分析
- 单片机汇编代码分析示例
- Linux内核分析【1】--分析汇编代码
- Linux内核源码分析--内核启动之(2)Image内核启动(汇编部分)(Linux-3.0 ARMv7)
- Linux内核源码分析--内核启动之(2)Image内核启动(汇编部分)(Linux-3.0 ARMv7)
- Linux内核源码分析--内核启动之(2)Image内核启动(汇编部分)(Linux-3.0 ARMv7)
- flash角色换装
- php字符串比较函数
- 地图设计__临时
- HDU 1558 Segment set, 计算几何+并查集
- 都是OpenGL惹的祸
- ARMv7汇编代码分析
- The equation----扩展欧几里得
- 成功的网站编辑需要注意的几点
- 特效表现设计分析
- mysqldump备份blob类型字段的表
- 用 vim 写 fortran 程序
- 为什么按照别人的方法做自己的站被K了?
- 网站推广优化菜鸟该如何一步步的进行呢?
- hibernate 报错信息“ 当 IDENTITY_INSERT 设置为 OFF 时,不能为表中的标识列插入显式值”