我正在使用 GNU arm-none-eabi 工具链为我的 Cortex M3 微控制器开发嵌入式 C 应用程序。
我计划采用供应商在我的 C 应用程序中实现的汇编子例程。我计划创建一个新的 C 函数,然后在其中使用扩展内联汇编协议编写内联汇编块。在这篇文章中,我计划将此汇编子例程视为黑匣子,并计划向此论坛询问如何构建输入和破坏列表;该例程没有输出。
汇编子例程期望在调用之前预先设置 r0、r1 和 r2。此外,子例程使用寄存器 r4、r5、r6、r7、r8、r9 作为临时寄存器来执行其功能。它写入设备上的一系列内存,由 r0 和 r1 指定,分别是起始地址和停止地址。
所以,我正在检查我的假设是否正确。我的问题如下。
void my_asm_ported_func(int reg_r0, int reg_r1, int reg_r2 {
__asm__ __volatile__ (
"ldr r0, %0 \n\t",
"ldr r1, %1 \n\t",
"ldr r2, %2 \n\t",
"<vendor code...> ",
: /* no outputs */
: "r" (reg_r0), "r" (reg_r1), "r" (reg_r2) /* inputs */
: "r0", "r1", "r2", "r4", "r5", "r6",
"r7", "r8", "r9", "memory" /* clobbers …Run Code Online (Sandbox Code Playgroud) 使用arm-none-eabi-readelf -h ideself.elf可以找到:
Entry point address: 0x800107d
Run Code Online (Sandbox Code Playgroud)
使用arm-none-eabi-objdump -D ideself.elf可以找到:
0800107c <Reset_Handler>:
800107c: f8df d034 ldr.w sp, [pc, #52] ; 80010b4 <LoopForever+0x2>
8001080:......................................................
Run Code Online (Sandbox Code Playgroud)
为什么启动reset_handler不等于0x800107d而不是0x800107c
0x800107c 中的字节不执行?执行 3/4 四字节指令 ?
由于Apple对安全性的考虑, LDR无法正常工作,但我如何加载,例如:
.data
.align 4
.mynumber: .quad 0x123456789ABCDEF0
Run Code Online (Sandbox Code Playgroud)
我了解 ADRP,但不确定我是否了解它的工作原理。
我已经这样做了(ADRP、@PAGE、@PAGEOFF 是从其他来源获取的):
.global _start
.text
_start:
ADRP X2, arr1@PAGE
ADD X2, X2, arr1@PAGEOFF
mov X0, #0 // Use 0 return code
mov X16, #1 // System call number 1 terminates this program
svc #0x80 // Call kernel to terminate the program
.data
.align 4
arr1: .FILL 10, 4, 0
mynumber: .quad 0x123456789ABCDEF0
myoctaword: .octa 0x12345678876543211234567887654321
Run Code Online (Sandbox Code Playgroud) 在ARM Neon ISA中,这两条指令有区别吗?
vst1.32 {d12, d13, d14, d15}, [r4]
Run Code Online (Sandbox Code Playgroud)
和
vst1.8 {d12, d13, d14, d15}, [r4]
Run Code Online (Sandbox Code Playgroud)
基于文档中的伪代码:
case type of
when '0111'
regs = 1; if align<1> == '1' then UNDEFINED;
when '1010'
regs = 2; if align == '11' then UNDEFINED;
when '0110'
regs = 3; if align<1> == '1' then UNDEFINED;
when '0010'
regs = 4;
otherwise
SEE "Related encodings";
alignment = if align == '00' then 1 else 4 << UInt(align);
ebytes = 1 << …Run Code Online (Sandbox Code Playgroud) 我们有一个简单的架构:
PIC通过基于中断的I2C通信协议与ARM通信以传输数据.在中断内部,我们发出一个从I2C层(总线)读取数据的任务.
在数据有限的情况下,我们通常不会有太多问题来读取数据并将其发送到上层.如果这个数据非常庞大,中断将被连接很长时间.
第一个问题是:
我对吗?
如果我是对的,如何避免相同?......或者我们可以采用不同的方案吗?
代码如下所示,我想知道在结尾部分
0000e0b4 001d22d0 ldrsbeq r2, [sp], -r0
Run Code Online (Sandbox Code Playgroud)
这是否为这行代码进行计算,因为它加载了结束部分中定义的地址
0000e03c e59f4070 ldr r4, [pc, #112] ; 0xe0b4
Run Code Online (Sandbox Code Playgroud)
为什么代码以这种方式组织?
-[Cube message1]:
0000e02c e92d40f0 push {r4, r5, r6, r7, lr}
0000e030 e28d700c add r7, sp, #12 ; 0xc
0000e034 e24dd008 sub sp, sp, #8 ; 0x8
0000e038 e59f1070 ldr r1, [pc, #112] ; 0xe0b0
0000e03c e59f4070 ldr r4, [pc, #112] ; 0xe0b4
0000e040 e1a06000 mov r6, r0
0000e044 e591e000 ldr lr, [r1]
0000e048 e5941000 ldr r1, [r4]
0000e04c e59e5000 ldr r5, [lr]
0000e050 …Run Code Online (Sandbox Code Playgroud) 以下指令之间是否有任何区别(除了旗帜感情)?
ADD R6, SP, #0xDC
Run Code Online (Sandbox Code Playgroud)
和
LDR R6, [SP, #0xDC]
Run Code Online (Sandbox Code Playgroud) 我在Cortex-R4中运行的C代码中进行优化.首先,当我在条件检查中指出"__builtin_expect"时,我没有看到汇编代码输出有任何变化.似乎编译器生成了不必要的跳转.
我的C代码:
bit ++; (Likely)
if(__builtin_expect(bit >= 32),0)
{
bit -=32; // unlikely code
xxxxxx; // unlikely code
xxxxxx; // unlikely code
xxxxxx; // unlikely code
}
bit = bit*2 // something (Likely)
return bit;
Run Code Online (Sandbox Code Playgroud)
----生成的ASM代码--------(位=> r0)
ADD r2,r2,#1
CMP r0,#0x20
BCC NoDecrement
SUB r0,r0,#0x20
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
NoDecrement LSL r0,r0,#1
BX lr
Run Code Online (Sandbox Code Playgroud)
----我期望的ASM代码--------
ADD r2,r2,#1
CMP r0,#0x20
BHE Decrement
JumbBack LSL r0,r0,#1
BX lr
Decrement SUB r0,r0,#0x20
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
B JumbBack
Run Code Online (Sandbox Code Playgroud)
假设这段C代码在循环中运行,那么每次都必须跳转(因为if条件只传递一次).是否有任何其他编译器设置实际上,按预期生成代码.. ??
我正在制作一个带有三个按钮的小设备(就像放射线一样的按钮),每个按钮都有自己的动作.这些按钮及其动作将由我将放在此设备上的非常小的实时操作系统控制.
PS没有预制板(例如arduino).我会自己建造这块板子.
任何反馈将不胜感激!
我有一个充满NEON的注册表float32.我想将它们四舍五入到最接近的整数,而不必转回主CPU.转换float32为uint32简单截断的NEON指令,例如39.7变为39,而不是40.我不太关心如何0.5处理 - 从零或圆到圆,甚至两个都为我工作.
我能看到实现舍入的最佳途径是
int32(因此截断)float32int32,转换回float32,并留出以防万一我们正在四舍五入0.5(不需要abs值,因为我知道在我的情况下他们都是正面的)这似乎是丑陋,缓慢和复杂的.
有更清洁,更快,更简单,更健全的方式吗?