При написании части десериализатора для структуры данных в C мне нужен был способ чтения 16-битных и 32-битных целых чисел. Учитывая, что существует вероятность того, что этот код может быть скомпилирован и использован в архитектуре, которая не может иметь порядок с прямым порядком байтов, я решил написать вспомогательные функции, которые явно декодируются из порядка байтов с прямым порядком байтов:
#include <stdint.h>
void read_16(uint8_t *data, uint16_t *value) {
*value = data[0] | (data[1] << 8);
}
void read_32(uint8_t *data, uint32_t *value) {
*value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
}
Мне было любопытно, как это может быть скомпилировано в архитектуре с прямым порядком байтов. arm-none-eabi-gcc
с -mcpu=cortex-a9
и -Os
дает следующий вывод:
00000000 <read_16>:
0: e5d02001 ldrb r2, [r0, #1]
4: e5d03000 ldrb r3, [r0]
8: e1833402 orr r3, r3, r2, lsl #8
c: e1c130b0 strh r3, [r1]
10: e12fff1e bx lr
00000014 <read_32>:
14: e5903000 ldr r3, [r0]
18: e5813000 str r3, [r1]
1c: e12fff1e bx lr
Вопрос: Есть ли причина, по которой оптимизатор упростил бы загрузку-сохранение-хранилище для 32-битный, но не для 16-битный, учитывая, что такая операция допустима, будет короче и быстрее, а оптимизация для размера включена?
В частности, я ожидаю следующую сборку для read_16
:
ldrh r3, [r0]
strh r3, [r1]
bx lr