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内嵌汇编相关推荐

  1. swi 指令能用在C语言吗,内嵌汇编指令的应用举例

    下面是在C语言程序中嵌入式汇编程序的例子.通过这几个例子,可帮助用户更好地理解内嵌汇编的特点及用法. (1)  字符串复制 本例主要介绍如何使用指令BL调用子程序. 注意,在内嵌的SWI和BL指令中, ...

  2. 嵌入式:ARM内嵌汇编及C和ARM汇编相互调用

    内嵌汇编 在C程序中嵌入汇编程序可以实现一些高级语言没有的功能,并可以提高执行效率.armcc和armcpp内嵌汇编器支持完整的ARM指令集:tcc和tcpp用于Thumb指集.但是内嵌汇编器并不支持 ...

  3. 在IAR中使用汇编指令\内嵌汇编

    先看内嵌汇编示例,两种写法(IAR8.3实测可正常编译运行.功能是跳转执行程序,设置栈顶指针) //示例一: if (((*(__IO uint32_t *)ApplicationAddress) & ...

  4. DPDK 跟踪库tracepoint源码实例分析

    DPDK笔记 DPDK 跟踪库tracepoint源码实例分析 RToax 2021年4月 注意: 跟踪库 基于DPDK 20.05 DPDK跟踪库:trace library 1. trace流程源 ...

  5. ARM_NEON_CNN编程 SIMD单指令多数据流 intrinsics指令 内联汇编 CNN卷积网络优化 深度学习优化

    ARM_NEON_CNN编程 SIMD单指令多数据流 intrinsics指令 内联汇编 CNN卷积网络优化 深度学习优化 博文末尾支持二维码赞赏哦 _ 本文github 神经网络arm neon加速 ...

  6. linux arm gcc 内联汇编参考手册

    关于本文档 GNU C 编译器为 ARM 精简指令系统处理器提供了在 C 代码中内嵌汇编的功能.这种非常酷的特性提供了一些 C 代码没有的功能,比如手工优化软件关键代码.使用相关的处理器指令. 本文假 ...

  7. ARM 内联汇编-1

    转自:(72条消息) 10. ARM 内联汇编学习笔记_天昼AI实验室的博客-CSDN博客_armv8 内联汇编 基本思想:随手记录一下ARM的内联汇编的基础语法,以便更深入的学习NCNN源码~ AR ...

  8. 【reverse】通俗易懂的gcc内联汇编入门+示例:实现花指令

    文章目录 引言 依赖 Hello world Demo1:读取函数若干个字节的数据 效果 Demo2:基础的花指令 效果 如何去除花指令 参考资料 引言 基于Visual Studio的内联汇编教程已 ...

  9. 西门子for循环例子_西门子S7-200 SMART PLC功能指令学习及实例分析

    原标题:西门子S7-200 SMART PLC功能指令学习及实例分析 一.定时器 1.S7-200 SMART CPU提供了接通延时定时器.(TON).保持型接通延时定时器(TONR).断开延时定时器 ...

最新文章

  1. 3月14号,oracle的说道多多
  2. 企业必须由真正在乎它的人掌控
  3. 14.8.4 Moving or Copying InnoDB Tables to Another Machine 移动或者拷贝 InnoDB 表到另外机器...
  4. 架构风格与基于网络的软件架构设计
  5. pptx字体类的相关方法
  6. Linux实时查看日志,访问前10IP 和相关命令
  7. android中的progressbar,Android中ProgressBar用法简单实例
  8. UTF-8转换成GBK
  9. 有些CAD通过Arcgis程序读取后,发现面积不对
  10. python怎么下载panda包_pandas python下载
  11. 摄影构图学pdf_简单易懂,摄影小白也能Get的摄影技巧!
  12. c 连接oracle otl,C++类库:OTL通用的数据库连接类库
  13. 贪心算法题目 推销员
  14. linux 光功率 模块_光模块基本参数-消光比/光功率/灵敏度
  15. 信息安全工程第四章网络安全体系与网络安全模型要点小结
  16. leetcode807. 保持城市天际线(java)
  17. android 获得ram大小,Android中获取(RAM)总运存大小和可用运存大小
  18. python 操作微信 群发_python 调用微信 发消息
  19. 强人工智能基本问题:自上而下还是自下而上? 1
  20. src // 的意思/src相对协议/src为//开头的图片怎么加载

热门文章

  1. 杭州人才补助领取遇到的问题
  2. [译] 设计师的决策树
  3. 面试百度新浪头条b站阿里的研发实习生面试记录
  4. 基于C#的软件加密、授权与注册
  5. IP地址之无分类编址CIDR
  6. Android Glide加载gif
  7. 【背景建模】VIBE
  8. reStructuredText 初学者语法汇总
  9. 【概念梳理】NMS 非极大值抑制
  10. 2020 年百度之星·程序设计大赛 · 官方题解汇总