This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
我参与了安全关键型软件的开发、达到了 RTCA/DO - 178C A 级
编译器:
TI-CGT-ARM_18.14.LTS
选项:
-mv7R4
--code_state=32
-Ooff
--opt_for_speed=0
-c99
考虑以下 C 源代码:
#define true 1.
#define false 0
typedef unsigned char BOOL;
静态 BOOL Test_A (const BOOL 参数 A);
int main (void){
(空) Test_A (真);
返回(0);
}
静态 BOOL 测试_A (常量 BOOL 参数 A)
{
bool 结果=!ParamA;
返回(结果);
}
使用逻辑否定运算符的源代码行的反汇编如下:
21 BOOL 结果=!ParamA;
00002894: E5DD1000 ldrb R1、[R13]
00002898: E3A0C000 MOV R12、#0
0000289c: E3510000 CMP R1、#0
000028a0: E3A00000 mov r0、#0
000028a4: 0A000000 beq $C$L1
000028a8: E3A00001 mov r0、#1
$C$L1:
000028ac: E3500000 CMP r0、#0
000028b0: 1A000000 bne $C$L2
000028b4: E3A0C001 MOV R12、#1
$C$L2:
000028b8: E5CDC001 strb R12、[R13、#1]
即使优化已关闭(-Ooff)、上述实现似乎不必要地复杂、尤其是寄存器 r0的使用。
问题:
为什么实现使用"附加"寄存器(r0)和两个标签而不是下面示例中详述的单个标签实现、是否有合理的理由?
00002894: E5DD0000 ldrb r0、[R13]
00002898: E3A0C001 MOV R12、#1
0000289c: E3500000 CMP r0、#0
000028a0: 0A000000 beq $C$L1
000028a4: E3A0C000 MOV R12、#0
$C$L1:
000028a8: E5CDC001 strb R12、[R13、#1]
禁用优化后、无需考虑高效代码生成。 除了匹配实际源代码之外、编译器还将生成函数序言和结语块、以控制栈的分配/取消分配。 编译器将为栈分配局部变量。 这可能导致分支数量超过必要数量。 编译器不会优化控制流或寄存器的使用。
Alan、您好、感谢您的回答。
我非常熟悉如何生成函数 prolog 和 epilog 块来控制分配/取消分配、以及编译器将本地变量分配到栈。
我在下面的示例函数中包含了完全反汇编。
test_a():
0000288c: E24DD008 SUB R13、R13、#8
00002890: E5CD0000 strb r0、[R13]
21 BOOL 结果=!ParamA;
00002894: E5DD1000 ldrb R1、[R13]
00002898: E3A0C000 MOV R12、#0
0000289c: E3510000 CMP R1、#0
000028a0: E3A00000 mov r0、#0
000028a4: 0A000000 beq $C$L1
000028a8: E3A00001 mov r0、#1
$C$L1:
000028ac: E3500000 CMP r0、#0
000028b0: 1A000000 bne $C$L2
000028b4: E3A0C001 MOV R12、#1
$C$L2:
000028b8: E5CDC001 strb R12、[R13、#1]
23 回返(结果);
000028bc: E5DD0001 ldrb r0、[R13、#1]
24 }
000028c0: E28DD008 添加 R13、R13、#8
000028c4: E12FFF1E BX LR
前两条指令构成序言块:
在我可以确定的范围内、在执行第二条指令后、寄存器 r0可用于其他用途。
最后三条指令构成结语块:
结语块之前的单个指令将逻辑否定的结果存储到栈上的局部变量‘Result’。
鉴于上述情况、我无法看到函数序言和结语块或栈中局部变量的分配与逻辑否定的实现有何关系。
我曾希望你们能够解释我无法确定的执行逻辑否定所需的具体内容,因为 ‘我不会期待最佳解决方案,但即使优化关闭(-Ooff),高效代码生成没有考虑因素’寄存器分配也是出于合理的原因?
我很惊讶、如果使用 if 语句实现逻辑否定、那么编译器生成的指令比使用逻辑否定运算符时少、请参阅下面的 Test_B。
静态 BOOL 测试_B (常量 BOOL 参数 A)
{
bool 结果= true;
if (ParamA!= false)
{
结果= false;
}
返回(结果);
}
TEST_B():
0000285c: E24DD008 SUB R13、R13、#8
00002860: E5CD0000 strb r0、[R13]
32 BOOL 结果= true;
00002864: E3A0C001 MOV R12、#1
00002868: E5CDC001 strb R12、[R13、#1]
34 IF (ParamA!= false)
0000286c: E5DDC000 ldrb R12、[R13]
00002870: E35C0000 CMP R12、#0
00002874: 0A000001 beq $C$L3
36 结果= false;
00002878: E3A0C000 MOV R12、#0
0000287c: E5CDC001 strb R12、[R13、#1]
39 次返回(结果);
$C$L3:
00002880: E5DD0001 ldrb r0、[R13、#1]
40 }
00002884: E28DD008 添加 R13、R13、#8
00002888: E12FFF1E BX LR
我怀疑我必须简单地将编译器用于逻辑否定的实现记录为次优、并指出不需要使用两个寄存器和两个标签。
您正在体验编译器的实际工作方式。 编译器的早期阶段会生成正确但效率低下的代码。 有时效率很低。 编译器的后续阶段(其中有许多阶段)会逐渐将代码更改为更高效的代码。
[引用 userid="467206" URL"~/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/1194722/logical-negation-operator---register-usage--ooff/4510955 #4510955"]我怀疑我必须简单地将编译器用于逻辑否定的实现作为次优记录、并声明不需要使用两个寄存器和两个标签。这可能是最好的前进方式。
谢谢、此致、
乔治