ARM GCC内联汇编
ARM GCC内联汇编
通用的内嵌汇编模板
__asm volatile (
code
:output operand list
:input operand list
:clobber list
);
Example
C内联汇编:
// __attribute__((naked))
__attribute__((noinline))
uint8_t asm_test(uint8_t a, uint8_t b)
{
uint8_t c;
__asm volatile (
"adds %[res], %[src0], %[src1]\n\t"
:[res] "=r" (c)
:[src0] "r" (a), [src1] "r" (b)
:
);
return c;
}
反汇编代码:
0040a350 <asm_test>:
40a350: 1840 adds r0, r0, r1
40a352: b2c0 uxtb r0, r0
40a354: 4770 bx lr
- 使用
__attribute__((naked)可以使函数开头和结尾没有保存和恢复的指令(由编译器自动添加),使用__attribute__((noinline))可以使函数不被优化为嵌入某个函数的汇编指令,而是保持一个函数的形式。 - 使用operand list与C函数的变量和入参进行交互,格式为
[alias] "修饰符" (C variable),使用[]和()绑定变量的语法很像超链接,比如[browser](https://google.com)。 - operand list中的各项以逗号
,分隔 - 对于早期gcc,不支持使用alias标识变量,而是使用%0,%1...这种根据变量出现的顺序编号,这样的缺陷在于一旦中间加一个操作符,所有的编号都变了
- 使用volatile可以禁止编译器优化,用于将咱写的汇编指令都编译出来,比如
mov r0, r0就不会再被优化
Operand List中修饰符
- 定义数据类型

- 输入输出类型
| Modifier | 含义 |
|---|---|
| = | write-only,仅用于output operand list |
| + | read-write,定义操作数可读可写,仅用于output operand list |
| & | 指示编译器将变量绑定到特定的寄存器,避免与其它寄存器冲突,引发输出值被改变的问题,&只能放在+/=之后 |
没有=,+修饰的操作符都是read-only的,input operand list都是read-only,所以想对同一变量又读又写,那只能将它放在output operand list并用+修饰。
Example
- 立即数搭配宏进行使用,因为内联汇编里的东西没法被预处理
#define A 20
void demo(void)
{
__asm volatile (
"mov r0, %[imm]\n\t"
:
:[imm] "I" (A)
:
);
}
/* -------------------对应汇编----------------------- */
0040a364 <demo>:
40a364: f04f 000a mov.w r0, #10
40a368: 4770 bx lr
&的作用
/* ---------------------正确写法带&----------------------- */
uint32_t tab[2];
uint8_t asm_test(uint8_t a, uint8_t b)
{
uint32_t rdv, wdv=1;
__asm volatile (
"ldr %[rd], [%[tab]]\n\t"
"str %[wr], [%[tab], #4]\n\t"
:[rd] "=&r" (rdv)
:[tab] "r" (tab),[wr] "r" (wdv)
:
);
return 1;
}
/* ---------------------对应汇编----------------------- */
0040a350 <asm_test>:
40a350: 2001 movs r0, #1
40a352: 4b02 ldr r3, [pc, #8] @ (40a35c <asm_test+0xc>)
40a354: 681a ldr r2, [r3, #0]
40a356: 6058 str r0, [r3, #4]
40a358: 4770 bx lr
40a35a: bf00 nop
40a35c: 200023fc .word 0x200023fc
/* ---------------------错误写法无&----------------------- */
uint32_t tab[2];
uint8_t asm_test(uint8_t a, uint8_t b)
{
uint32_t rdv, wdv=1;
__asm volatile (
"ldr %[rd], [%[tab]]\n\t"
"str %[wr], [%[tab], #4]\n\t"
:[rd] "=r" (rdv)
:[tab] "r" (tab),[wr] "r" (wdv)
:
);
return 1;
}
/* ---------------------对应汇编----------------------- */
0040a350 <asm_test>:
40a350: 2001 movs r0, #1
40a352: 4b02 ldr r3, [pc, #8] @ (40a35c <asm_test+0xc>)
40a354: 681b ldr r3, [r3, #0]
40a356: 6058 str r0, [r3, #4]
40a358: 4770 bx lr
40a35a: bf00 nop
40a35c: 200023fc .word 0x200023fc
在错误的写法中,由于不带&,造成rd和tab共用了寄存器r3;加上&后,rd用的r2,没有受到干扰,这些行为和编译器类型及版本有关系,为了避免出错,直接将output operand list都加上&修饰。
Clobber List
破坏列表,告诉编译器我在这段汇编代码中改变了什么,比如改变了寄存器,内存等等,这样编译器会在执行这段汇编代码之前保存一下将被改变的数据。
| 类型 | 含义 |
|---|---|
| r0, r1... | 表示寄存器将被改变,在执行汇编之前将push对应的寄存器,并在执行完汇编之后pop出来 |
| memory | 告诉编译器内存将会被改变,在执行汇编之前,将那些还未写入内存的值赶紧写入 |
| cc | 告诉编译器condition code状态寄存器将改变 |
Example
对于memory和cc没构建出好的例子,只有关于寄存器的了。
/*--------------------------C--------------------------*/
uint8_t asm_test(uint8_t a, uint8_t b)
{
__asm volatile (
"mov r0, r0\n\t"
:
:
:"r4"
);
return 0;
}
/*--------------------------汇编--------------------------*/
0040a350 <asm_test>:
40a350: b510 push {r4, lr}
40a352: 4600 mov r0, r0
40a354: 2000 movs r0, #0
40a356: bd10 pop {r4, pc}
果然编译器对咱指定的"r4"做了保存恢复的操作。
ARM GCC内联汇编的更多相关文章
- 推荐一篇讲arm架构gcc内联汇编的文章
这是来自ethernut网站的一篇文章,原文链接: http://www.ethernut.de/en/documents/arm-inline-asm.html 另外,据说nut/os是个不错的开源 ...
- ARM体系下的GCC内联汇编
转:http://andyhuzhill.github.io/arm/gcc/asm/2012/09/25/gcc-inline-assemly/ 在操作系统级的编程中,有时候,C语言并不能完全的使用 ...
- ARM嵌入式开发中的GCC内联汇编__asm__
在针对ARM体系结构的编程中,一般很难直接使用C语言产生操作协处理器的相关代码,因此使用汇编语言来实现就成为了唯一的选择.但如果完全通过汇编代码实现,又会过于复杂.难以调试.因此,C语言内嵌汇编的方式 ...
- 最牛X的GCC 内联汇编
导读 正如大家知道的,在C语言中插入汇编语言,其是Linux中使用的基本汇编程序语法.本文将讲解 GCC 提供的内联汇编特性的用途和用法.对于阅读这篇文章,这里只有两个前提要求,很明显,就是 x86 ...
- GCC内联汇编入门
原文为GCC-Inline-Assembly-HOWTO,在google上可以找到原文,欢迎指出翻译错误. 中文版说明 由于译者水平有限,故译文出错之处,还请见谅.C语言的关键字不译,一些单词或词组( ...
- [翻译] GCC 内联汇编 HOWTO
目录 GCC 内联汇编 HOWTO 原文链接与说明 1. 简介 1.1 版权许可 1.2 反馈校正 1.3 致谢 2. 概览 3. GCC 汇编语法 4. 基本内联 5. 扩展汇编 5.1 汇编程序模 ...
- 汇编语言---GCC内联汇编
转:http://www.cnblogs.com/taek/archive/2012/02/05/2338838.html GCC支持在C/C++代码中嵌入汇编代码,这些代码被称作是"GCC ...
- GCC 内联汇编(GCC内嵌ARM汇编规则)
转:http://smileleeboo.howbbs.com/posts/list/3127/81062.html 更多文档参见:http://pan.baidu.com/s/1eQ7nd8Q 有时 ...
- ARM GCC 内嵌汇编手册
转自:http://blogold.chinaunix.net/u2/69404/showart_1922655.html ARM GCC 内嵌(inline)汇编手册 关于这篇文档这篇文章是本人为方 ...
- gcc 内联汇编简介
啊 啊 在内联汇编中,标识寄存器的一个%变成了两个% 啊 如图是内联汇编的模板 assembler template 是汇编代码 output operands TODO input operands ...
随机推荐
- jmeter使用:解决压测时获取token问题
在执行压测过程中,首先要执行登录接口来获取token.如果并发数比较大只需要一个用户的登录token,可以使用setup线程组.如果是模拟多个用户登录获取token,需要使用仅一次控制器. 一.添加s ...
- Yuque Rich Text(语雀富文本编辑器)
Yuque Rich Text(语雀富文本编辑器) 由于本人觉得语雀编辑器非常好用,很符合我的使用习惯,然后发现语雀的Chrome浏览器插件实现了编辑器的功能,所以将其富文本的功能拆分位一个单独的Vu ...
- 微信支付功能的设计实现与关键实践(UniApp+Java)全代码
感觉本篇对你有帮助可以关注一下我的微信公众号(深入浅出谈java),会不定期更新知识和面试资料.技巧!!! 温馨提醒:阅读时可打开导航栏 概述 在移动互联网时代,支付功能已成为应用开发的核心能力之一. ...
- crypto14解题思路
crypto14解题思路 ##二进制 001100110011001100100000001101000011010100100000001101010011000000100000001100100 ...
- scrcpy - Android手机投屏操作神器
推荐一个Genymotion推出的投屏工具,跨平台,自定义码率,最重要的是开源,简直良心. Github:https://github.com/Genymobile/scrcpy 下载地址: http ...
- 【记录】IDA和Ollydbg查看指令地址及地址对应的指令
文章目录 在IDA中查看指令地址 在Ollydbg中查看指令地址 在Ollydbg中查看地址对应的指令 在IDA中查看指令地址 在Ollydbg中查看指令地址 ollydbg在对应指令处,右键-查看- ...
- Notepad++之"常用技术"
一.^ 前面 数据准备 二.$ 后面 准备 结果
- GPT 1-3 简单介绍
GPT-1 简介 2018年6月,OpenAI公司发表了论文"Improving Language Understanding by Generative Pretraining" ...
- Android Studio 虚拟机一直黑屏原因及解决办法
虚拟机一直黑屏原因: android模拟器在创建时,一般默认设置为热启动,所以每次关闭模拟器时,会提示保存当前运行界面状态,若选择取消,则下一次启动会以最近一次保存的状态启动显示.如果某次关闭时保存的 ...
- 安卓手机上部署nodejs服务器
一.准备软件 Termux 下载地址: 链接:https://pan.baidu.com/s/1J3OQITWc34uT-Mc8B-moPA?pwd=ug9j 提取码:ug9j KSW ...