结合实例分析arm指令集中的adds指令与arm内嵌汇编
qq截图进来的图全部丢失了。。。。。。。。郁闷。。。。。。
以下是ffmpege0.11.1源码中的一个函数,稍微做了点修改
注意:编译器我arm-linux-gcc4.4.1,其他的编译器请读者自行验证
static av_always_inline av_const int32_t av_clipl_int32_arm(int64_t a)
{
int x, y;
#ifndef MELIS
__asm__ ("adds %1, %R2, %Q2, lsr #31 \n\t"
"itet ne \n\t" //反汇编之后发现该条指令不起作用,可以删除
"mvnne %1, #1<<31 \n\t"
"moveq %0, %Q2 \n\t"
"eorne %0, %1, %R2, asr #31 \n\t"
: "=r"(x), "=&r"(y) : "r"(a):"cc");
#else
__asm__
{
adds y, (((int*) &a)[1]), (((unsigned*) &a)[0]), lsr #31
mvnne y, #1<<31
moveq x, (((unsigned*) &a)[0])
eorne x, y, (((int*) &a)[1]), asr #31
}
#endif
return x;
}
分析:
__asm__是内嵌汇编的标志,这个不多说。
%0表示x,%1表示y,%2表示a,%R2表示a的高32位,%Q2表示a的低32位。
%R2表示a的高32位,%Q2表示a的低32位是怎么来的呢?
查看编写测试程序查看反汇编代码,测试程序如下:
#include <stdio.h>
int main()
{
long long int a=0x2200LL; //用long long int a=0x110022002200LL测试会发现输出结果是0x7fffffff,请读者自行测试
printf("0x%x\n", av_clipl_int32_arm(a));
return 0;
}
在linux下用arm-linux-gcc反汇编,反汇编的关键代码如下:
000083ec <av_clipl_int32_arm>:
83ec: e92d0810 push {r4, fp}
83f0: e28db004 add fp, sp, #4
83f4: e24dd010 sub sp, sp, #16
83f8: e50b0014 str r0, [fp, #-20]
83fc: e50b1010 str r1, [fp, #-16]
8400: e24b4014 sub r4, fp, #20
8404: e8940018 ldm r4, {r3, r4}
8408: e0942fa3 adds r2, r4, r3, lsr #31
840c: 13e02102 mvnne r2, #-2147483648; 0x80000000
8410: 01a03003 moveq r3, r3
8414: 10223fc4 eorne r3, r2, r4, asr #31
8418: e50b300c str r3, [fp, #-12]
841c: e50b2008 str r2, [fp, #-8]
8420: e51b300c ldr r3, [fp, #-12]
8424: e1a00003 mov r0, r3
8428: e24bd004 sub sp, fp, #4
842c: e8bd0810 pop {r4, fp}
8430: e12fff1e bx lr
00008434 <main>:
8434: e92d4810 push {r4, fp, lr}
8438: e28db008 add fp, sp, #8
843c: e24dd00c sub sp, sp, #12
8440: e3a03c22 mov r3, #8704; 0x2200
8444: e3a04000 mov r4, #0
8448: e50b3014 str r3, [fp, #-20]
844c: e50b4010 str r4, [fp, #-16]
8450: e59f402c ldr r4, [pc, #44]; 8484 <main+0x50>
8454: e24b1014 sub r1, fp, #20
8458: e8910003 ldm r1, {r0, r1}
845c: ebffffe2 bl 83ec <av_clipl_int32_arm>
8460: e1a03000 mov r3, r0
8464: e1a00004 mov r0, r4
8468: e1a01003 mov r1, r3
846c: ebffffae bl 832c <_init+0x48>
8470: e3a03000 mov r3, #0
8474: e1a00003 mov r0, r3
8478: e24bd008 sub sp, fp, #8
847c: e8bd4810 pop {r4, fp, lr}
8480: e12fff1e bx lr
8484: 0000850c .word 0x0000850c
根据代码画出函数的栈帧结构图:设sp的初始地址为0x2400000c
push {r4, fp, lr}-----r4,fp,lr依次入栈:那么栈指针sp指向0x24000000,sp、fp指针值应该是系统分配
add fp, sp, #8------fp
sub sp, sp, #12-----sp下移12byte,留出3个空位
mov r3, #8704; 0x2200 ----r3=0x2200
mov r4, #0 ----r4=0x0
str r3, [fp, #-20] -------将r3的值0x2200存到fp-20字节(fp下移五格)内存处
str r4, [fp, #-16] ----r4=0x0的值存到fp下移4格的内存处
注意:从这里就可以看出来arm-linux-gcc 4.4.1编译器处理器对64位数据结构的处理,用两个连续的32位的寄存器进行存放,低地址的寄存器存低32位数据,高地址的寄存器存高32位数据。
ldr r4, [pc, #44]; 8484 <main+0x50> ----将0x8484内存单元的值赋给r4,r4=0x850c
sub r1, fp, #20 ------------------------r1变成了指针,指向fp-20内存单元
ldm r1, {r0, r1} ------------------------将r1指向的内存单元0x24000000-12开始的连续8个字节内存单元数据依次赋值给r0,r1
此时在看看源码就更清楚了,64字节的a变量,分别用r0,r1来存放。
bl 83ec <av_clipl_int32_arm> ---跳转到子函数
画出子函数的栈帧:
push {r4, fp} ---保存main函数的fp指针=0x24000008
add fp, sp, #4 ------fp上移四个字节
sub sp, sp, #16------sp给函数形参空出栈空间
str r0, [fp, #-20]-----将r0的值0x2200存到内存空间0x24000000-12-24处
str r1, [fp, #-16]-----将r1的值0x0存到内存空间
sub r4, fp, #20 -----r4指向r0所在的内存地址
ldm r4, {r3, r4} -----也就是将r0,r1的值分别赋值给r3,r4那么r3=0x2200,r4=0x0
adds r2, r4, r3, lsr #31 ------此时r3,r4分别等于r0,r1,也即是0x2200逻辑右移31位(为0),0+0=0,由于加了s标志,那么cpu的状态寄存器将改变,计算结果r2为0将设置z标志位,于是eq条件成立。接下来的mvnne和eorne指令将不会运行,只有moveq运行。
840c: 13e02102 mvnne r2, #-2147483648; 0x80000000
8410: 01a03003 moveq r3, r3
8414: 10223fc4 eorne r3, r2, r4, asr #31
8418: e50b300c str r3, [fp, #-12] ------保存r3
841c: e50b2008 str r2, [fp, #-8] -------保存r2
8420: e51b300c ldr r3, [fp, #-12] -------取出r3,r3就是x
8424: e1a00003 mov r0, r3
8428: e24bd004 sub sp, fp, #4 ----移动sp,为恢复r4、子函数fp做准备
842c: e8bd0810 pop {r4, fp} -----恢复r4、子函数fp
8430: e12fff1e bx lr -----跳转到main函数
后面就不分析了,要注意的地方就是r3就是x。也就是子函数的返回值。
如果a=0x110022002200LL呢?
"adds %1, %R2, %Q2, lsr #31 \n\t" // y= 0x1100 +(0x22002200 >> 31)=0x1100,此处cpu状态寄存器z标志没有发生改变,将运行mvnne和eorne指令
"mvnne %1, #1<<31 \n\t" // y = ~0x80000000 = 0x7fffffff
"moveq %0, %Q2 \n\t" //不执行
"eorne %0, %1, %R2, asr #31 \n\t" //x = y^(0x1100 >>31) = 0x7fffffff^0x0 = 0x7fffffff
: "=r"(x), "=&r"(y) : "r"(a):"cc");
如果a=0x110022002200LL子函数将返回0x7fffffff,也即是说如果a大于32位将返回0x7fffffff,小于32位则返回原值。
结合实例分析arm指令集中的adds指令与arm内嵌汇编相关推荐
- swi 指令能用在C语言吗,内嵌汇编指令的应用举例
下面是在C语言程序中嵌入式汇编程序的例子.通过这几个例子,可帮助用户更好地理解内嵌汇编的特点及用法. (1) 字符串复制 本例主要介绍如何使用指令BL调用子程序. 注意,在内嵌的SWI和BL指令中, ...
- 嵌入式:ARM内嵌汇编及C和ARM汇编相互调用
内嵌汇编 在C程序中嵌入汇编程序可以实现一些高级语言没有的功能,并可以提高执行效率.armcc和armcpp内嵌汇编器支持完整的ARM指令集:tcc和tcpp用于Thumb指集.但是内嵌汇编器并不支持 ...
- 在IAR中使用汇编指令\内嵌汇编
先看内嵌汇编示例,两种写法(IAR8.3实测可正常编译运行.功能是跳转执行程序,设置栈顶指针) //示例一: if (((*(__IO uint32_t *)ApplicationAddress) & ...
- DPDK 跟踪库tracepoint源码实例分析
DPDK笔记 DPDK 跟踪库tracepoint源码实例分析 RToax 2021年4月 注意: 跟踪库 基于DPDK 20.05 DPDK跟踪库:trace library 1. trace流程源 ...
- ARM_NEON_CNN编程 SIMD单指令多数据流 intrinsics指令 内联汇编 CNN卷积网络优化 深度学习优化
ARM_NEON_CNN编程 SIMD单指令多数据流 intrinsics指令 内联汇编 CNN卷积网络优化 深度学习优化 博文末尾支持二维码赞赏哦 _ 本文github 神经网络arm neon加速 ...
- linux arm gcc 内联汇编参考手册
关于本文档 GNU C 编译器为 ARM 精简指令系统处理器提供了在 C 代码中内嵌汇编的功能.这种非常酷的特性提供了一些 C 代码没有的功能,比如手工优化软件关键代码.使用相关的处理器指令. 本文假 ...
- ARM 内联汇编-1
转自:(72条消息) 10. ARM 内联汇编学习笔记_天昼AI实验室的博客-CSDN博客_armv8 内联汇编 基本思想:随手记录一下ARM的内联汇编的基础语法,以便更深入的学习NCNN源码~ AR ...
- 【reverse】通俗易懂的gcc内联汇编入门+示例:实现花指令
文章目录 引言 依赖 Hello world Demo1:读取函数若干个字节的数据 效果 Demo2:基础的花指令 效果 如何去除花指令 参考资料 引言 基于Visual Studio的内联汇编教程已 ...
- 西门子for循环例子_西门子S7-200 SMART PLC功能指令学习及实例分析
原标题:西门子S7-200 SMART PLC功能指令学习及实例分析 一.定时器 1.S7-200 SMART CPU提供了接通延时定时器.(TON).保持型接通延时定时器(TONR).断开延时定时器 ...
最新文章
- 3月14号,oracle的说道多多
- 企业必须由真正在乎它的人掌控
- 14.8.4 Moving or Copying InnoDB Tables to Another Machine 移动或者拷贝 InnoDB 表到另外机器...
- 架构风格与基于网络的软件架构设计
- pptx字体类的相关方法
- Linux实时查看日志,访问前10IP 和相关命令
- android中的progressbar,Android中ProgressBar用法简单实例
- UTF-8转换成GBK
- 有些CAD通过Arcgis程序读取后,发现面积不对
- python怎么下载panda包_pandas python下载
- 摄影构图学pdf_简单易懂,摄影小白也能Get的摄影技巧!
- c 连接oracle otl,C++类库:OTL通用的数据库连接类库
- 贪心算法题目 推销员
- linux 光功率 模块_光模块基本参数-消光比/光功率/灵敏度
- 信息安全工程第四章网络安全体系与网络安全模型要点小结
- leetcode807. 保持城市天际线(java)
- android 获得ram大小,Android中获取(RAM)总运存大小和可用运存大小
- python 操作微信 群发_python 调用微信 发消息
- 强人工智能基本问题:自上而下还是自下而上? 1
- src // 的意思/src相对协议/src为//开头的图片怎么加载