用于STM32F407 micro的gcc ARM
以下功能在FreeRtosTCP中用作健全性检查
UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc )
{
uint32_t offset = ( uint32_t ) ( ((const char *)pxDesc) - ((const char *)xNetworkBuffers) );
if( ( offset >= (uint32_t)(sizeof( xNetworkBuffers )) ) || ( ( offset % sizeof( xNetworkBuffers[0] ) ) != 0 ) )
return pdFALSE;
return (UBaseType_t) (pxDesc - xNetworkBuffers) + 1;
}
有问题的行是---> offset> =(uint32_t)(sizeof(xNetworkBuffers))
gcc在cmp之后而不是bhs产生一条bhi指令。
如果尝试像上面的代码中所示那样强制转换两者,但是似乎没有任何东西可以使用bhs指令。
任何帮助表示赞赏。
谢谢。
乔
答案 0 :(得分:2)
知道xNetworkBuffers数组编译器的确切大小可以简单地对其进行优化。很好奇,我尝试了一下。以下是经过少量修改的代码以及asm输出和说明:
#include <stdint.h>
typedef struct abc {
char data[10];
}NetworkBufferDescriptor_t;
NetworkBufferDescriptor_t xNetworkBuffers[5];
int bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc )
{
uint32_t offset = ( uint32_t ) ( ((const char *)pxDesc) - ((const char *)xNetworkBuffers) );
if( ( offset >= (uint32_t)(sizeof( xNetworkBuffers )) ) || ( ( offset % sizeof( xNetworkBuffers[0] ) ) != 0 ) )
return 0;
return (int) (pxDesc - xNetworkBuffers) + 1;
}
并且asm输出为:
bIsValidNetworkDescriptor:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 16
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
add fp, sp, #0
sub sp, sp, #20
str r0, [fp, #-16]
ldr r3, [fp, #-16]
ldr r2, .L5
sub r3, r3, r2 str r3, [fp, #-8] ldr r3, [fp, #-8] cmp r3, #49 bhi .L2
ldr r1, [fp, #-8]
ldr r3, .L5+4
umull r2, r3, r1, r3
lsr r2, r3, #3
mov r3, r2
lsl r3, r3, #2
add r3, r3, r2
lsl r3, r3, #1
sub r2, r1, r3
cmp r2, #0
beq .L3
.L2:
mov r3, #0
b .L4
.L3:
ldr r3, [fp, #-16]
ldr r2, .L5
sub r3, r3, r2
asr r2, r3, #1
mov r3, r2
lsl r3, r3, #1
add r3, r3, r2
lsl r1, r3, #4
add r3, r3, r1
lsl r1, r3, #8
add r3, r3, r1
lsl r1, r3, #16
add r3, r3, r1
lsl r3, r3, #2
add r3, r3, r2
add r3, r3, #1
.L4:
mov r0, r3
add sp, fp, #0
@ sp needed
ldr fp, [sp], #4
bx lr
.L6:
.align 2
.L5:
在引用了asm代码的块中,您可以看到它与49而不是50(这是xNetworkBuffers的实际大小)进行比较,因此我得出的结论是
offset >= (uint32_t)(sizeof( xNetworkBuffers ))
也等于
offset > (uint32_t)(sizeof( xNetworkBuffers ) - 1) )
,在这种情况下,编译器可以使用BHI产生相同的结果
答案 1 :(得分:1)
从技术上来讲,我认为GCC生成的代码是正确的。 offset
不能大于INT_MAX
,因为这是此体系结构上ptrdiff_t
中可表示的最大值。
您可以像这样计算差异:
uintptr_t offset = (uintptr_t)pxDesc - (uintptr_t)xNetworkBuffers;
这仍然是实现定义的,但可以避免溢出问题。