内联汇编
2026/8/24大约 2 分钟
C语言内联汇编:asm 怎么用
内联汇编就是:
在 C 代码中直接嵌入汇编指令。
常用于:
关中断
访问特殊寄存器
内存屏障
性能关键指令一、最简单的形式
GCC:
void foo(void)
{
asm volatile("cpsid i");
}这里:
C函数
↓
asm
↓
执行 ARM 汇编指令cpsid i 就是关闭 IRQ 中断。
二、为什么有时看到另一种写法?
我之前在 Keil 里看到过:
__asm void PendSV_Handler(void)
{
MRS R0, PSP
...
}这也是内联/嵌入汇编,只是Keil 的语法。
而 GCC 常见:
asm volatile(
"mov %1, %0"
: "=r"(result)
: "r"(input)
);所以:
Keil/ARMCC
→ __asm
GCC
→ asm / __asm__概念相同,语法不同。
三、GCC 为什么有 输出 : 输入 : clobber?
例如:
asm volatile(
"add %1, %0"
: "=r"(result)
: "r"(input)
: "cc"
);分别表示:
输出
↓
result
输入
↓
input
clobber
↓
汇编修改了 CPU 状态/资源这是在告诉编译器:
这段汇编用了什么、产生了什么、破坏了什么。
否则编译器可能错误优化。
四、为什么有 volatile?
asm volatile("cpsid i");表示:
这段汇编具有实际意义,不能被编译器随意删除或合并。
例如关闭中断这种操作,即使它没有 C 返回值,也绝对不能被优化掉。
五、为什么嵌入式需要它?
例如 ARM Cortex-M:
asm volatile("cpsid i"); // 关中断
asm volatile("cpsie i"); // 开中断
asm volatile("dmb");
asm volatile("dsb");
asm volatile("isb");这些功能普通 C 语句无法直接表达,就需要访问 ARM 特殊指令。
六、Keil 和 GCC 不要混
Keil:
__asm void PendSV_Handler(void)
{
MRS R0, PSP
...
}GCC:
void PendSV_Handler(void)
{
__asm volatile(
"MRS R0, PSP"
:
:
: "r0"
);
}不要混着写。
使用哪种语法,取决于你的编译器。
七、最终记忆
内联汇编
↓
C代码里嵌入汇编
Keil
↓
__asm
GCC
↓
asm / __asm__
GCC扩展格式
↓
asm("指令" : 输出 : 输入 : clobber)内联汇编的核心不是“写一个汇编函数”,而是让 C 代码直接执行编译器无法用普通 C 表达的底层指令。

