gcc之-fomit-frame-point

2023-05-16

Kernel里的dump_stack(), oops打印出来的backstrace调用链表是怎样实现的呢?

大家都知道当发生函数调用的时候,函数的参数传递,返回值传递都要遵循一定的规则,在ARM体系架构下,这个规则叫做Procedure Call Standard for the ARM Architecture。在这个规则里规定了函数调用的时候,返回地址在LR里面,第一到第四个参数在r0~r3里面,第五到第八个参数在Stack里面,返回值在r0里面。这是基本规则,C编译器产生汇编指令是必须遵循这些规则,这也是ABI(Application Binary Interface)的一部分。另外,为了实现连续的函数调用,如fun_a()->func_b()->func_c(),每个函数的入口处必须先把LR压到stack里,否则func_b()调了func_c()之后,LR变成了func_c()的返回地址,而func_b()返回地址就丢失了。

有了以上这些原则,可以追溯函数的调用历史。即只要找到堆栈里的LR就知道是那个从那个函数调用过来的。要知道stack里LR的位置就必须要知道当前函数stack开始的地方,否则stack里那个位置存放了LR。通用的定位每个函数stack开始的地方的方法是在编译的时候让编译器在目标代码中嵌入stack frame(栈帧)。此外,gcc还能够在elf文件中生成unwind table,unwind table也能实现追踪call stack。下面主要讲述stack frame。


什么是Stack frame:

stack frame(栈帧)是用来追踪代码的调用过程和调用时的参数,通过读取stack frame信息可以知道到执行到当前位置的函数调用链表(call stack)。

Stack frame的本质是每次函数调用都在stack里记录一个frame,每一次函数调用叫做一个frame。ARM里的fp寄存器就是用来指证当前所在函数的frame的,fp总是指向当前函数堆栈的frame。
 

Stack frame的产生方法:


stack frame是由编译器产生的,也就是gcc在生成可执行代码时,在每个函数入口的地方“放置”一个stack frame。在调用gcc编译时可以指定参数来要求gcc产生或不产生stack frame,这个参数是:
 

-fomit-frame-point:让gcc不产生stack frame
-fno-omit-frame-pointer:让gcc产生stack frame

如果不指定这两个参数,是否产生stack frame取决于gcc default是omit-frame-point,还是 no-omit-frame-pointer。

Stack frame是什么样的

通过一个简单的C程序来看一下在binary里,stack frame究竟是怎样的

test.c:

 static int func_b(int a, int b, int c, int d, int e, int f)
{
       return a + b + c + d + e + f;
}

static int func_c(int a, int b)
{
       return a - b;
}

static int func_a(int x, int y)
{
       int a = 3;
       int b = 4;
       int c = 5;
       int d = 6;
       int e = 7;
       int f = 8;
       int ret;

       ret = func_b(a, b, c, d, e, f);

       ret = func_c(a, ret);

       return ret;
}

int main(int argc, char * argv[])
{
       int a = 1;
       int b = 2;
       int ret;

       ret = func_a(a, b);

       return ret;
}



编译有stack frame的binary:
   arm-none-linux-gnueabi-gcc -fno-omit-frame-pointer test.c -o test.no-omit-frame-pointer
编译无stack frame的binary:
   arm-none-linux-gnueabi-gcc -fomit-frame-pointer test.c -o test.omit-frame-pointer

分别objdump以上编译所得的两个binary:
   arm-none-linux-gnueabi-objdump -S test.no-omit-frame-pointer > test.no-omit-frame-pointer.objdump
   arm-none-linux-gnueabi-objdump -S test.omit-frame-pointer > test.omit-frame-pointer.objdump
   
打开两个dump出来的assembly (只关注我们的main(), func_a(), func_b()三个函数,忽略libc的部分):

test.no-omit-frame-pointer.objdump:

000084e4 <<func_b>>:
   84e4:   e52db004    push   {fp}      ; (str fp, [sp, #-4]!)
   84e8:   e28db000    add   fp, sp, #0
   84ec:   e24dd014    sub   sp, sp, #20
   84f0:   e50b0008    str   r0, [fp, #-8]
   84f4:   e50b100c    str   r1, [fp, #-12]
   84f8:   e50b2010    str   r2, [fp, #-16]
   84fc:   e50b3014    str   r3, [fp, #-20]    ; 0xffffffec
   8500:   e51b2008    ldr   r2, [fp, #-8]
   8504:   e51b300c    ldr   r3, [fp, #-12]
   8508:   e0822003    add   r2, r2, r3
   850c:   e51b3010    ldr   r3, [fp, #-16]
   8510:   e0822003    add   r2, r2, r3
   8514:   e51b3014    ldr   r3, [fp, #-20]    ; 0xffffffec
   8518:   e0822003    add   r2, r2, r3
   851c:   e59b3004    ldr   r3, [fp, #4]
   8520:   e0822003    add   r2, r2, r3
   8524:   e59b3008    ldr   r3, [fp, #8]
   8528:   e0823003    add   r3, r2, r3
   852c:   e1a00003    mov   r0, r3
   8530:   e28bd000    add   sp, fp, #0
   8534:   e8bd0800    ldmfd   sp!, {fp}
   8538:   e12fff1e    bx   lr

0000853c <<func_c>>:
   853c:   e52db004    push   {fp}      ; (str fp, [sp, #-4]!)
   8540:   e28db000    add   fp, sp, #0
   8544:   e24dd00c    sub   sp, sp, #12
   8548:   e50b0008    str   r0, [fp, #-8]
   854c:   e50b100c    str   r1, [fp, #-12]
   8550:   e51b2008    ldr   r2, [fp, #-8]
   8554:   e51b300c    ldr   r3, [fp, #-12]
   8558:   e0633002    rsb   r3, r3, r2
   855c:   e1a00003    mov   r0, r3
   8560:   e28bd000    add   sp, fp, #0
   8564:   e8bd0800    ldmfd   sp!, {fp}
   8568:   e12fff1e    bx   lr

0000856c <<func_a>>:
   856c:   e92d4800    push   {fp, lr}
   8570:   e28db004    add   fp, sp, #4
   8574:   e24dd030    sub   sp, sp, #48   ; 0x30
   8578:   e50b0028    str   r0, [fp, #-40]    ; 0xffffffd8
   857c:   e50b102c    str   r1, [fp, #-44]    ; 0xffffffd4
   8580:   e3a03003    mov   r3, #3
   8584:   e50b3008    str   r3, [fp, #-8]
   8588:   e3a03004    mov   r3, #4
   858c:   e50b300c    str   r3, [fp, #-12]
   8590:   e3a03005    mov   r3, #5
   8594:   e50b3010    str   r3, [fp, #-16]
   8598:   e3a03006    mov   r3, #6
   859c:   e50b3014    str   r3, [fp, #-20]    ; 0xffffffec
   85a0:   e3a03007    mov   r3, #7
   85a4:   e50b3018    str   r3, [fp, #-24]    ; 0xffffffe8
   85a8:   e3a03008    mov   r3, #8
   85ac:   e50b301c    str   r3, [fp, #-28]    ; 0xffffffe4
   85b0:   e51b3018    ldr   r3, [fp, #-24]    ; 0xffffffe8
   85b4:   e58d3000    str   r3, [sp]
   85b8:   e51b301c    ldr   r3, [fp, #-28]    ; 0xffffffe4
   85bc:   e58d3004    str   r3, [sp, #4]
   85c0:   e51b0008    ldr   r0, [fp, #-8]
   85c4:   e51b100c    ldr   r1, [fp, #-12]
   85c8:   e51b2010    ldr   r2, [fp, #-16]
   85cc:   e51b3014    ldr   r3, [fp, #-20]    ; 0xffffffec
   85d0:   ebffffc3    bl   84e4 <<func_b>>
   85d4:   e50b0020    str   r0, [fp, #-32]    ; 0xffffffe0
   85d8:   e51b0008    ldr   r0, [fp, #-8]
   85dc:   e51b1020    ldr   r1, [fp, #-32]    ; 0xffffffe0
   85e0:   ebffffd5    bl   853c <<func_c>>
   85e4:   e50b0020    str   r0, [fp, #-32]    ; 0xffffffe0
   85e8:   e51b3020    ldr   r3, [fp, #-32]    ; 0xffffffe0
   85ec:   e1a00003    mov   r0, r3
   85f0:   e24bd004    sub   sp, fp, #4
   85f4:   e8bd8800    pop   {fp, pc}

000085f8 <<main>>:
   85f8:   e92d4800    push   {fp, lr}
   85fc:   e28db004    add   fp, sp, #4
   8600:   e24dd018    sub   sp, sp, #24
   8604:   e50b0018    str   r0, [fp, #-24]    ; 0xffffffe8
   8608:   e50b101c    str   r1, [fp, #-28]    ; 0xffffffe4
   860c:   e3a03001    mov   r3, #1
   8610:   e50b3008    str   r3, [fp, #-8]
   8614:   e3a03002    mov   r3, #2
   8618:   e50b300c    str   r3, [fp, #-12]
   861c:   e51b0008    ldr   r0, [fp, #-8]
   8620:   e51b100c    ldr   r1, [fp, #-12]
   8624:   ebffffd0    bl   856c <<func_a>>
   8628:   e50b0010    str   r0, [fp, #-16]
   862c:   e51b3010    ldr   r3, [fp, #-16]
   8630:   e1a00003    mov   r0, r3
   8634:   e24bd004    sub   sp, fp, #4
   8638:   e8bd8800    pop   {fp, pc}

test.omit-frame-pointer.objdump:

 

000084e4 <<func_b>>:
   84e4:   e24dd010    sub   sp, sp, #16
   84e8:   e58d000c    str   r0, [sp, #12]
   84ec:   e58d1008    str   r1, [sp, #8]
   84f0:   e58d2004    str   r2, [sp, #4]
   84f4:   e58d3000    str   r3, [sp]
   84f8:   e59d200c    ldr   r2, [sp, #12]
   84fc:   e59d3008    ldr   r3, [sp, #8]
   8500:   e0822003    add   r2, r2, r3
   8504:   e59d3004    ldr   r3, [sp, #4]
   8508:   e0822003    add   r2, r2, r3
   850c:   e59d3000    ldr   r3, [sp]
   8510:   e0822003    add   r2, r2, r3
   8514:   e59d3010    ldr   r3, [sp, #16]
   8518:   e0822003    add   r2, r2, r3
   851c:   e59d3014    ldr   r3, [sp, #20]
   8520:   e0823003    add   r3, r2, r3
   8524:   e1a00003    mov   r0, r3
   8528:   e28dd010    add   sp, sp, #16
   852c:   e12fff1e    bx   lr

00008530 <<func_c>>:
   8530:   e24dd008    sub   sp, sp, #8
   8534:   e58d0004    str   r0, [sp, #4]
   8538:   e58d1000    str   r1, [sp]
   853c:   e59d2004    ldr   r2, [sp, #4]
   8540:   e59d3000    ldr   r3, [sp]
   8544:   e0633002    rsb   r3, r3, r2
   8548:   e1a00003    mov   r0, r3
   854c:   e28dd008    add   sp, sp, #8
   8550:   e12fff1e    bx   lr

00008554 <<func_a>>:
   8554:   e52de004    push   {lr}      ; (str lr, [sp, #-4]!)
   8558:   e24dd034    sub   sp, sp, #52   ; 0x34
   855c:   e58d000c    str   r0, [sp, #12]
   8560:   e58d1008    str   r1, [sp, #8]
   8564:   e3a03003    mov   r3, #3
   8568:   e58d302c    str   r3, [sp, #44]   ; 0x2c
   856c:   e3a03004    mov   r3, #4
   8570:   e58d3028    str   r3, [sp, #40]   ; 0x28
   8574:   e3a03005    mov   r3, #5
   8578:   e58d3024    str   r3, [sp, #36]   ; 0x24
   857c:   e3a03006    mov   r3, #6
   8580:   e58d3020    str   r3, [sp, #32]
   8584:   e3a03007    mov   r3, #7
   8588:   e58d301c    str   r3, [sp, #28]
   858c:   e3a03008    mov   r3, #8
   8590:   e58d3018    str   r3, [sp, #24]
   8594:   e59d301c    ldr   r3, [sp, #28]
   8598:   e58d3000    str   r3, [sp]
   859c:   e59d3018    ldr   r3, [sp, #24]
   85a0:   e58d3004    str   r3, [sp, #4]
   85a4:   e59d002c    ldr   r0, [sp, #44]   ; 0x2c
   85a8:   e59d1028    ldr   r1, [sp, #40]   ; 0x28
   85ac:   e59d2024    ldr   r2, [sp, #36]   ; 0x24
   85b0:   e59d3020    ldr   r3, [sp, #32]
   85b4:   ebffffca    bl   84e4 <<func_b>>
   85b8:   e58d0014    str   r0, [sp, #20]
   85bc:   e59d002c    ldr   r0, [sp, #44]   ; 0x2c
   85c0:   e59d1014    ldr   r1, [sp, #20]
   85c4:   ebffffd9    bl   8530 <<func_c>>
   85c8:   e58d0014    str   r0, [sp, #20]
   85cc:   e59d3014    ldr   r3, [sp, #20]
   85d0:   e1a00003    mov   r0, r3
   85d4:   e28dd034    add   sp, sp, #52   ; 0x34
   85d8:   e8bd8000    ldmfd   sp!, {pc}

000085dc <<main>>:
   85dc:   e52de004    push   {lr}      ; (str lr, [sp, #-4]!)
   85e0:   e24dd01c    sub   sp, sp, #28
   85e4:   e58d0004    str   r0, [sp, #4]
   85e8:   e58d1000    str   r1, [sp]
   85ec:   e3a03001    mov   r3, #1
   85f0:   e58d3014    str   r3, [sp, #20]
   85f4:   e3a03002    mov   r3, #2
   85f8:   e58d3010    str   r3, [sp, #16]
   85fc:   e59d0014    ldr   r0, [sp, #20]
   8600:   e59d1010    ldr   r1, [sp, #16]
   8604:   ebffffd2    bl   8554 <<func_a>>
   8608:   e58d000c    str   r0, [sp, #12]
   860c:   e59d300c    ldr   r3, [sp, #12]
   8610:   e1a00003    mov   r0, r3
   8614:   e28dd01c    add   sp, sp, #28
   8618:   e8bd8000    ldmfd   sp!, {pc}


    可以看到有stack frame的binary (test.no-omit-frame-pointer.objdump) 中每个main(), func_a(), func_b()入口的地 方都有push fp, lr和add fp, sp, #4;而无stack frame的binary (test.omit-frame-pointer.objdump) 中函数入口的地方并没有这两句指令。push fp的作用是把调用函数(caller)的fp保存到被调用函数(callee)的stack开始处,随后add fp, sp, #4将fp指向被调用函数(callee) 的stack开始的地方。fp总是指向当前函数的stack开始的地方,通过当前函数stack里保存的caller的fp可以追溯到caller的堆栈。通过fp的逐级连接就可以找到调用链上每个函数的stack,从而每个函数的LR(返回地址)都可以从stack里获得,只要在symbol table里搜索一下LR的值,就可以知道caller是哪个函数了。有了stack frame不但可以通过stack里的LR得到caller的地址,还可以知道函数调用时的参数,回想一下前面说的‘第一到第四个参数在r0~r3里面,第五到第八个参数在Stack里面’。具体分析一下上面的汇编代码,结合 Procedure Call Standard for the ARM Architecture规定的调用原则,绘制出stack frame的结构如下:



 从上面的例子可以看到一个函数(如func_a())的stack frame里,开始的地方放的是fp, lr(如果是最后一级的被调用函数,如func_b,func_c则lr无需保存到stack),然后是函数的内部变量,之后是该函数的参数1~参数4,最后是其调用的函数(本例中是func_b())的参数5~参数8。在本例中如果在func_b()中要追溯call stack,从lr可以知道哪个函数调用了它,fp寄存器保存了func_b的stack frame的起始地址,该地址上存放了上一级stack frame的起始地址(caller的stack frame),该地址向stack缩小方向存放了caller调用func_b()的时候传递的参数5~8(如果有参数5~8的话),该地址向stack伸长方向到存放调用下一个函数的参数5~8之前的位置存放了caller调用func_b()的时候传递的参数1~4。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gcc之-fomit-frame-point 的相关文章

  • GCC 和 -Wconversion

    让我们编译以下程序 int main uint16 t data 0 data uint16 t std round 3 14f return 0 with g Wconversion prog cpp 我们会得到warning conve
  • 为什么 -march=native 很少使用?

    对于大多数 C C 编译器 有一个可传递给编译器的标志 march native 它告诉编译器调整为主机 CPU 的微架构和 ISA 扩展生成的代码 即使它的名称不同 基于 LLVM 的编译器通常也有一个等效的选项 例如rustc or s
  • 后缀和前缀运算符作为函数参数 - 为什么会发生这种情况? [复制]

    这个问题在这里已经有答案了 在执行以下简单的 C 程序时 我发现了一个非常有趣的事实 include
  • 这种对有效类型规则的使用是否严格遵守?

    C99和C11中的有效类型规则规定 没有声明类型的存储可以用任何类型写入 并且存储非字符类型的值将相应地设置存储的有效类型 抛开 INT MAX 可能小于 123456789 的事实不谈 以下代码对有效类型规则的使用是否严格符合 inclu
  • GCC:数组类型具有不完整的元素类型

    我已经宣布了struct 我尝试传递这些结构的数组 以及double双精度数组和一个整数 到一个函数中 我得到一个 数组类型具有不完整的元素类型 当我编译它时来自 gcc 的消息 我在通过考试的过程中犯了什么错误struct到函数 type
  • 什么定义了类型的大小?

    ISO C 标准规定 sizeof char lt sizeof short lt sizeof int lt sizeof long 我在 BIT Linux mint 19 1 上使用 GCC 8 大小为long int is 8 我正
  • 为什么 GCC 交叉编译不构建“crti.o”?

    在尝试为arm构建gcc 4 x x交叉编译器时 我陷入了缺失的困境crti o文件在 BUILD DIR gcc子目录 An strace在顶层Makefile表明编译后的xgcc正在调用交联器ld with crti o 作为一个论点
  • iOS:将观察者添加到 UIView 的frame.origin.y?

    我正在尝试监视 UIView 框架原点的变化值并对其做出反应 我的代码 cell bottomView addObserver self forKeyPath frame origin options NSKeyValueObserving
  • 如何忽略“有符号和无符号整数表达式之间的比较”?

    谁能告诉我必须使用哪个标志才能使 gcc 忽略 有符号和无符号整数表达式之间的比较 警告消息 gcc Wno sign compare 但你确实应该修复它警告你的比较
  • 在GCC中添加父目录的包含路径

    我想将父目录中的文件包含在我正在处理的项目中 所有的头文件都在父目录中 有没有办法在命令行上使用 I 来搜索父目录中的包含而不使用绝对路径 我知道我可以使用 makefile 解决这些问题 并且我可能最终会这样做 但我想知道是否有一个可以使
  • 在 Borland C++ Builder 6 中使用帧缓冲区对象 (FBO)

    我对帧缓冲区对象 FBO 的命令 glGenFramebuffersEXT 有 访问冲突 void TGLForm DrawScene wglMakeCurrent ghDC ghRC glEnable GL TEXTURE 2D GLui
  • 无法链接 Boost 正则表达式

    我目前正在尝试编译一个KIT 的收缩层次实现 http algo2 iti kit edu english routeplanning php这需要 Boost Regex 提供的 Makefile 已经确保 并且我还手动仔细检查了这一点
  • Gtk-ERROR **:检测到 GTK+ 2.x 符号

    我正在使用 gcc 编译我的 c 应用程序 并使用以下标志 gcc evis c pkg config cflags libs gtk 2 0 libs clutter gtk 1 0 libs gthread 2 0 Wall o evi
  • 为什么 GCC 不对无法访问的代码发出警告?

    为什么 GCC 4 6 3 没有给我任何警告无法访问的代码在下面的例子中 include
  • C 中“complex”的默认类型

    根据我读过的文档 C99 和更高版本的支持float complex double complex and long double complex作为复杂类型 但是 此代码在使用时编译时不会发出警告gcc Wall Wextra inclu
  • 成员初始值设定项列表中的求值顺序是什么?

    我有一个带有一些参数的构造函数 我假设它们是按照列出的顺序初始化的 但在一种情况下 它们似乎是按相反的顺序初始化的 导致中止 当我反转参数时 程序停止中止 下面是我正在使用的语法的示例 a 之前需要初始化b 在这种情况下 你能保证这个初始化
  • 在 Android 上提取/修改视频帧

    我有一个视频文件 我想获取视频的每一帧并对帧进行一些修改 例如在其中绘制另一个位图 放置一些文本等 Android 中是否有任何 API 框架可用于从视频中获取帧 我在 iOS 中使用他们的 AVFramework 做了类似的事情 如果可以
  • C 编译器无法在 Mac OS Mountain Lion 上创建可执行文件

    我几乎浏览了每一页 但所有提示都不能解决问题 我正在运行 Mountain Lion 我有 Xcode 所有最新的开发工具 最新的 GCC 等等 我正在尝试设置 rbenv 和 ruby build 一切似乎都正常 但是当我去安装 ruby
  • 声明一个负长度的数组

    当创建负长度数组时 C 中会发生什么 例如 int n 35 int testArray n for int i 0 i lt 10 i testArray i i 1 这段代码将编译 并且启用 Wall 时不会出现警告 并且似乎您可以分配
  • 出现“重定位符号索引无效”错误时会发生什么?

    这是重现问题的测试 echo void whatever gt prog c gcc prog c 这会在 GCC 4 8 4 上产生以下错误 usr bin ld usr lib debug usr lib x86 64 linux gn

随机推荐

  • C++头文件重复包含问题

    为了避免同一个文件被include多次 有两种方式 1 span class token macro property span class token directive keyword ifdef span SOMEFILE H spa
  • TCP(select函数模型)

    客户端代码 include lt stdio h gt include lt sys types h gt include lt sys socket h gt include lt arpa inet h gt include lt st
  • i2c那些坑

    origin http bbs ntpcb com simple t126695 html I2C 的那些坑 一般情况下 xff0c i2c 设备焊接没什么问题 xff0c 按照设备手册一步步来 xff0c 基本上就顺风顺水能够用起来 如果
  • stm32f103系列引脚定义-功能图

    器件功能和配置 STM32F103xx增强型 STM32F103xx增强型模块框架图 STM32F103xx增强型VFQFPN36管脚图 STM32F103xx增强型LQFP100管脚图 STM32F103xx增强型LQFP64管脚图 ST
  • 用数百行代码实现60亿设备互联:微软重金收购的ThreadX硬在何处

    origin https www sohu com a 315222502 485057 2019年4月 xff0c 微软收购了ThreadX的母公司Express Logic 公司 而ThreadX有几亿个设备在运行 1 物联网操作系统简
  • Cache和DMA一致性

    cache读必须要buffer是cacheline对齐的 DMA应该多多少少知道点吧 DMA Direct Memory Access 是指在外接可以不用CPU干预 xff0c 直接把数据传输到内存的技术 这个过程中可以把CPU解放出来 x
  • stm32几种低功耗模式的实现和差别

    origin https blog csdn net jian3214 article details 99818603 01 前言 按功耗由高到低排列 xff0c STM32具有运行 睡眠 停止和待机四种工作模式 上电复位后 STM32
  • threadx也开源了

    前一段时间ucos开源了 xff0c 今天微软收购的threadx也开源了 xff0c 行业剧变呀 xff01 xff01 xff01 2020 5 26
  • armv8-M 32bit处理器

    https www eet china com mp a14579 html https developer arm com ip products processors cortex m 最早的Cortex M0属于Armv6 M架构 x
  • 作为ARM Cortex-M家族的继承者 Cortex-M23与M33有哪五大特色?

    http news eeworld com cn xfdz article 2017011259937 html 集微网消息 xff0c ARM处理器在嵌入式设备领域的应用非常广泛 基于ARM Cortex处理器的片上系统 xff08 So
  • emmc5.1, ufs2.0, ufs3.0

    总的来说 xff0c UFS3 0的综合性能 xff0c 特别是持续读写速度有着秒杀UFS2 1前辈的表现 xff0c 只是在随机读写和SQLite性能上 xff0c 却依旧和双通道的UFS2 1持平 xff0c 有些小遗憾 最后 xff0
  • 串行Norflash是如何实现XIP的?

    先说问题 xff1a 要想程序在串行的Norflash中运行 xff0c 到底需要做哪些工作 xff1f Norflash和Nandflash想必大家都知道 恕本人才学疏浅 xff0c 最近突然发现Norflash可以并行连接实现XIP x
  • ARM汇编语言 - 简介 [一]

    origin https zhuanlan zhihu com p 82490125 ARM汇编语言 简介 一 兰新宇 talk is cheap 说明 xff1a 本系列文章将主要以ARMv7和ARMv8架构为例 xff0c 介绍ARM汇
  • ARM汇编语言 - 简介 [二]

    上文介绍了ARM的数据传送指令 xff0c 本文将主要介绍ARM中的移位 序转和位操作等数据处理指令 移位指令 移位包括逻辑移位和算术移位 xff0c 所谓 逻辑 就是将寄存器中存放的内容仅仅视为一串bits xff0c 移位的时候只需要将
  • 智能小车开发的重点之一电机该如何选型

    一 智能小车的分类 二 电机的分类 无刷电机要好于有刷电机 xff0c 优点 xff1a 1 没有损耗 xff0c 有刷电机有寿命 2 静音 xff0c 有刷电机噪音比较大 无刷电机分为带霍尔传感器和不带霍尔传感器两种 xff0c 因为无刷
  • ARM汇编语言 - 简介 [三]

    上文介绍了ARM的数据处理指令 xff0c 本文将主要介绍ARM中的跳转指令 跳转指令 无条件跳转 ARM中的基础跳转指令就一个字母 34 B 34 xff0c 代表Branch xff0c 相比起x86中和它功能基本相同的 34 jmp
  • CAN总线35周年特别篇 -- CAN总线的前世今生

    origin https mp weixin qq com s MloRz 4sio8QGdNItNRBjQ CAN总线35周年之际 xff0c 花了一晚上时间整理翻译了下 xff0c 通过这个帖子大家会对当前市场上各种CAN名词有的全面系
  • 微控制器CPU性能测试基准CoreMark

    origin https www cnblogs com henjay724 p 8729364 html 痞子衡嵌入式 xff1a 微控制器CPU性能测试基准 EEMBC CoreMark 大家好 xff0c 我是痞子衡 xff0c 是正
  • 意外发现,Cortex-M7的性能和诸多关键参数碾压A7和R7

    origin https www amobbs com thread 5676525 1 1 html 之前一直以为ARM A R M M排在最后也最便宜 xff0c 肯定性能最低 xff0c 但最近意外发现并非如此 xff0c M7居然完
  • gcc之-fomit-frame-point

    Kernel里的dump stack oops打印出来的backstrace调用链表是怎样实现的呢 xff1f 大家都知道当发生函数调用的时候 xff0c 函数的参数传递 xff0c 返回值传递都要遵循一定的规则 xff0c 在ARM体系架