Keil5 内联汇编

Keil5 内联汇编

问题

最近工程使用协处理器,需要用到内联汇编。
keil5使用GCC风格内联汇编时,会在返回R1寄存器值之前,对R1做压栈处理,导致得不到正确的返回值。因此必须按照Keil指定格式对返回值做定义。

百度了一下的,都是各种离谱答案,所以做个笔记.
其实官网就有,用法如下,测试已通过。

例子

编译器提供了内联汇编器,使您能够在 C 或 C++ 源代码中编写汇编代码,例如访问 C 或 C++ 不可用的目标处理器功能。
__asm 关键字可以使用 GNU 内联汇编语法将内联汇编代码合并到一个函数中。 例如:

#include <stdio.h>

int add(int i, int j)
{
  int res = 0;
  __asm ("ADD %[result], %[input_i], %[input_j]"
    : [result] "=r" (res)
    : [input_i] "r" (i), [input_j] "r" (j)
  );
  return res;
}

int main(void)
{
  int a = 1;
  int b = 2;
  int c = 0;

  c = add(a,b);

  printf("Result of %d + %d = %d\n", a, b, c);
}

这个例子是真的很经典,a是输入,c是输出,多个输入按上面例子用冒号打头新起一行完事。

内联汇编器不支持以 armasm 汇编器语法编写的旧式汇编代码。 有关将 armasm 语法汇编代码迁移到 GNU 语法的更多信息,请参阅迁移和兼容性指南

说明

__asm 内联汇编语句的一般形式是:

__asm [volatile] (code); /* Basic inline assembly syntax */
/* Extended inline assembly syntax */ 
__asm [volatile] (code_template 
       : output_operand_list 
      [: input_operand_list 
      [: clobbered_register_list]] 
  );

对具有处理器副作用的汇编指令使用 volatile 限定符,编译器可能不知道这些副作用。 volatile 限定符禁用某些编译器优化,否则可能会导致编译器删除代码块。 volatile 限定符是可选的,但您应该考虑在汇编代码块周围使用它,以确保编译器在使用 -O1 或更高版本进行编译时不会删除它们。

code 是汇编指令,例如“ADD R0, R1, R2”code_template 是汇编指令的模板,例如“ADD %[result], %[input_i], %[input_j]”

如果您指定的是 code_template 而不是代码,那么您必须在指定可选的 input_operand_listclobbered_register_list 之前指定 output_operand_list

output_operand_list 是输出操作数列表,以逗号分隔。每个操作数由方括号中的符号名称、约束字符串和括号中的 C 表达式组成。在这个例子中,有一个输出操作数:[result] "=r" (res)。该列表可以为空。例如:

__asm ("ADD R0, %[input_i], %[input_j]"
    :  /* This is an empty output operand list */
    : [input_i] "r" (i), [input_j] "r" (j)
  );

input_operand_list 是输入操作数的可选列表,以逗号分隔。 输入操作数使用与输出操作数相同的语法。 在这个例子中,有两个输入操作数:[input_i] "r" (i), [input_j] "r" (j)。 该列表可以为空。

clobbered_register_list 是一个逗号分隔的字符串列表。 每个字符串都是汇编代码可能修改的寄存器的名称,但最终值并不重要。 为了防止编译器在内联汇编字符串中为模板字符串使用寄存器,请将寄存器添加到 clobber 列表中。

例如,如果寄存器保存一个临时值,请将其包含在 clobber 列表中。 编译器避免使用此列表中的寄存器作为输入或输出操作数,或在执行汇编代码时使用它来存储另一个值。

该列表可以为空。 除了寄存器之外,该列表还可以包含特殊参数:

  • “cc”
    该指令影响条件代码标志。
  • “memory”
    该指令访问未知的内存地址。

clobbered_register_list 中的寄存器必须使用小写字母而不是大写字母。 带有 clobbered_register_list 的示例指令是:

__asm ("ADD R0, %[input_i], %[input_j]"
    :  /* This is an empty output operand list */
    : [input_i] "r" (i), [input_j] "r" (j)
    : "r5","r6","cc","memory" /*Use "r5" instead of "R5" */
  );

定义符号和标签

您可以使用内联汇编来定义符号。 例如:

__asm (".global __use_no_semihosting\n\t");

要定义标签,请在标签名称后使用 :。 例如:

__asm ("my_label:\n\t");

多条指令

您可以在同一个__asm 语句中编写多个指令。 此示例显示了用一个 __asm 语句为 Arm®v8‑M 主线架构编写的中断处理程序。

void HardFault_Handler(void)
{
  asm (
    "TST LR, #0x40\n\t"
    "BEQ from_nonsecure\n\t"
  "from_secure:\n\t"
    "TST LR, #0x04\n\t"
    "ITE EQ\n\t"
    "MRSEQ R0, MSP\n\t"
    "MRSNE R0, PSP\n\t"
    "B hard_fault_handler_c\n\t"
  "from_nonsecure:\n\t"
    "MRS R0, CONTROL_NS\n\t"
    "TST R0, #2\n\t"
    "ITE EQ\n\t"
    "MRSEQ R0, MSP_NS\n\t"
    "MRSNE R0, PSP_NS\n\t"
    "B hard_fault_handler_c\n\t"
  );
}

将上面的处理程序代码复制到 file.c 中,然后您可以使用以下命令编译它:

armclang --target=arm-arm-none-eabi -march=armv8-m.main -S file.c -o file.s

嵌入式汇编

您可以使用 __attribute__((naked)) 编写嵌入式程序集。 有关更多信息,请参阅 Arm 编译器参考指南中的 __attribute__((naked))

本文实际来自于Keil官方教程

下一篇准备写 《尽可能简单的将VSCODE变成IDE》

Keil5是一款常用的嵌入式开发工具,用于编写和调试嵌入式系统的程序。下面是Keil5中常见的26个错误及其解释: 1. Error C000: Syntax error in expression 这个错误表示表达式中存在语法错误。 2. Error C001: Undefined symbol 这个错误表示使用了未定义的符号。 3. Error C002: Illegal use of register 这个错误表示在不允许的地方使用了寄存器。 4. Error C003: Constant expression required 这个错误表示需要一个常量表达式。 5. Error C004: Type mismatch 这个错误表示类型不匹配。 6. Error C005: Illegal use of floating-point 这个错误表示在不允许使用浮点数的地方使用了浮点数。 7. Error C006: Illegal use of bit-field 这个错误表示在不允许使用位域的地方使用了位域。 8. Error C007: Illegal use of pointer 这个错误表示在不允许使用指针的地方使用了指针。 9. Error C008: Illegal use of array 这个错误表示在不允许使用数组的地方使用了数组。 10. Error C009: Illegal use of structure 这个错误表示在不允许使用结构体的地方使用了结构体。 11. Error C010: Illegal use of union 这个错误表示在不允许使用联合体的地方使用了联合体。 12. Error C011: Illegal use of enum 这个错误表示在不允许使用枚举的地方使用了枚举。 13. Error C012: Illegal use of typedef 这个错误表示在不允许使用类型定义的地方使用了类型定义。 14. Error C013: Illegal use of function 这个错误表示在不允许使用函数的地方使用了函数。 15. Error C014: Illegal use of macro 这个错误表示在不允许使用宏的地方使用了宏。 16. Error C015: Illegal use of inline 这个错误表示在不允许使用内联函数的地方使用了内联函数。 17. Error C016: Illegal use of asm 这个错误表示在不允许使用汇编代码的地方使用了汇编代码。 18. Error C017: Illegal use of interrupt 这个错误表示在不允许使用中断的地方使用了中断。 19. Error C018: Illegal use of pragma 这个错误表示在不允许使用编译指示的地方使用了编译指示。 20. Error C019: Illegal use of attribute 这个错误表示在不允许使用属性的地方使用了属性。 21. Error C020: Illegal use of volatile 这个错误表示在不允许使用volatile关键字的地方使用了volatile关键字。 22. Error C021: Illegal use of restrict 这个错误表示在不允许使用restrict关键字的地方使用了restrict关键字。 23. Error C022: Illegal use of inline assembly 这个错误表示在不允许使用内联汇编的地方使用了内联汇编。 24. Error C023: Illegal use of preprocessor directive 这个错误表示在不允许使用预处理指令的地方使用了预处理指令。 25. Error C024: Illegal use of linker directive 这个错误表示在不允许使用链接器指令的地方使用了链接器指令。 26. Error C025: Illegal use of debugger directive 这个错误表示在不允许使用调试器指令的地方使用了调试器指令。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

idk500

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值