先来一个小插曲
#define TO_STRING(x) #x
int main() {
const char *str = TO_STRING(Hello, World!);
printf("%s\n", str); // 输出 "Hello, World!"
return 0;
}
printf 接受一个指针, #x 相当于一个地址
在头文件里面, 下面定义一个函数(宏的方式)
#define read_csr(csr) \
({ \
register unsigned long __v; \
__asm__ __volatile__ ("csrr %0, " #csr \
: "=r" (__v) : \
: "memory"); \
__v; \
})
调用这个函数
void sbi_main(void)
{
unsigned long val; //汇编的函数返回值
val = read_csr(mstatus); //给函数传递参数,不是string
write_csr(mstatus, val);
}
内敛的汇编的基本格式
asm ( assembler template
: output operands /* 可选 ,输出参数*/
: input operands /* 可选 ,输入参数*/
: clobbered registers /* 可选 ,可能修改的寄存器,破坏性描述符,就是对环境的影响*/
);
举个例子01:
#include <stdio.h>
int main() {
int a = 10, b = 20;
int result;
__asm__ (
"add %0, %1, %2\n\t"
: "=r" (result)
: "r" (a), "r" (b)
);
printf("Result: %d\n", result);
return 0;
}
解释:
=r 表示将结果存储在一个通用寄存器中
"r" (a), "r" (b):这是输入操作数部分。r 表示将变量 a 和 b 的值加载到通用寄存器中
类似c语言的字段类型,汇编也有一些参数说明(约束字符)
比如上面的r就是一种, 输入放到通用寄存器中
通用约束字符
r:表示操作数应放在一个通用寄存器中。
m:表示操作数应放在内存中。
i:表示操作数是一个立即数(常量)。
g:表示操作数可以是一个通用寄存器、内存或立即数。
0, 1, 2, ...:表示操作数与第几个操作数相同。
破坏描述符
"cc":表示汇编代码会修改条件码寄存器(condition code register)。
"memory":表示汇编代码会修改内存。
"r0", "r1", ...:表示汇编代码会修改特定的寄存器(特定于目标架构)。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。