Преобразование порядка байтов в ARM - PullRequest
15 голосов
/ 26 ноября 2010

Как мне преобразовать большой или обратный порядок байтов в ARM?

Ответы [ 3 ]

21 голосов
/ 26 ноября 2010

Вы говорите о режимах с прямым порядком байтов ARM или читаете что-то, написанное каким-либо другим процессором с прямым порядком байтов и т. Д.?

Обычно при преобразовании в / из старшего / младшего порядка вы меняете байты.Таким образом, 0xABCD - это 0xCDAB, если смотреть как 16-битное число, 0x12345678 - это 0x78563412, если смотреть как 32-битное число.

Ядра ARM armv5 и старше (ARM7, ARM9 и т. Д.) Имеют режим байтов, известный как BE-32,значение большого порядкового слова инварианта.armv6 и новее (mpcore, cortex-somethings) имеют BE-8 или байтовый инвариант с прямым порядком байтов.

Таким образом, если вы используете armv4, например, в режиме с прямым порядком байтов и в режиме с прямым (маленьким) порядком байтов, слово read (ldr) со значением 0x12345678 будет равно 0x12345678 для слова с прямым порядком байтов по одному и тому же адресу.Слово инвариант, означающее чтение слова, дает тот же ответ.Считывание байтов нулевого адреса в режиме с прямым порядком байтов того же адреса будет 0x78, а чтение байтов с прямым порядком байтов (ldrb) будет 0x12.

Таким образом, вы должны пойти дальше, просто сказав, является ли он большим или малым порядком байтов, но какие инструкции используются.

Для armv6 или новее, если ldr по какому-либо адресу приводит к 0x12345678, то в режиме с прямым порядком байтов ldr с того же адреса приведет к 0x78563412.Обратите внимание, что в режиме с прямым или обратным порядком выборки инструкций для этого адреса на armv6 или новее получит 0x12345678.При использовании ldrb в прямом и обратном порядке в том же адресе один и тот же адрес приводит к 0x78, ldrb с большим порядковым номером или более поздней версии также приводит к 0x78.это связано с тем, что armv6 и более новые версии являются байтово-инвариантными, то есть байтовые доступы к одному и тому же адресу приводят к тому, что в этих архитектурах происходит переключение на одно и то же значение, доступ к полуслову, слову и двойному слову в режиме с прямым порядком байтов.Поскольку выборки инструкций не меняются местами, и поскольку бит endian находится в psr во время работы скомпилированной программы с прямым порядком байтов, вы можете переключиться на big endian, выполнить ряд инструкций, а затем вернуться в основной режим, и это не повлияет на выборки инструкций и не прерывает их.Встречаются.

setend be
ldr r0,[r1]
add r0,r0,#7
str r0,[r1]
setend le

На некоторых веб-страницах упоминается этот байт с четырьмя инструкциями на случай, если вы хотите запустить native little endian (очень хорошая идея) и выполнить обмен с использованием ассемблера (не всегда хорошая идея,зависит от того, что вы делаете).

  eor r3,r1,r1, ror #16
  bic r3,r3,#0x00FF0000
  mov r0,r1,ror #8
  eor r0,r0,r3, lsr #8

с r1, являющимся входом, на котором он появляется, и r0, являющимся выходом

Для armv6 или новее вышеупомянутое можно выполнить с помощью

  rev r0,r1
5 голосов
/ 25 июля 2016

Проверьте, есть ли команда обращения байтов, например (__REV (), __REV16 (), __REVSH ()).Это встроенные инструкции по сборке, в которых используется аппаратное обеспечение, в отличие от более медленной, но портативной работы с ответами выше.( ссылка1 , ссылка2 )

2 голосов
/ 26 ноября 2010

Подумайте, как бы вы преобразовали порядок байтов в языке высокого уровня, таком как C, а затем, когда вы поймете, что вы можете легко перевести его в сборку ARM, например,

uint16_t x = 0x0102;
uint16_t y = (x << 8) | (x >> 8); // y = 0x0201

Так что для 16-битного случая у вас есть две смены (одна левая и одна правая) и ИЛИ. Вы должны быть в состоянии сделать это в 3 инструкциях.

...