2010-05-02 3 views
2

В настоящее время это проект домашней работы, в котором я и мой товарищ по команде застряли. Нам не уделялось много внимания в Ассамблее, и это должно быть нашим первым уроком по дому. Задача состоит в создании программы, которая преобразует 0xAABBCCDD в 0xDDCCBBAA.ARM Assembly - Converting Endianness

Я не ищу ответа, так как это победит цель, но мы сильно расстроены сложностью этой глупой вещи. Мы считаем, что у нас есть хорошее начало для создания жизнеспособного решения, но мы просто не можем придумать остальную часть программы.

Во-первых, мы маскировать каждый Tupel (AA), (бб), (сс), (дд) в другом регистре:

LDR R0, LittleEndian // 0xAABBCCDD 
AND R1, R0, #0xFF000000 // 0xAA 
AND R2, R0, #0x00FF0000 // 0xBB 
AND R3, R0, #0x0000FF00 // 0xCC 
AND R4, R0, #0x000000FF // 0xDD 

Тогда мы попытаться вновь согласовать их в регистр R0 , но, черт возьми, если бы мы могли придумать хорошее решение ...

Наши лучшие усилия пришли:

ORR R0, R1, LSL #24 
ORR R0, R2, LSL #8 
ORR R0, R3, LSR #8 
ORR R0, R4, LSR #24 

который произвел 0xBBBBCCDD по какой-то причине; мы действительно не знаем.

Любые советы были бы весьма благодарны. Опять же, мы просим о помощи, но не для решения.

Приветствия!

+2

Существует также специальная функция для этого. BSWAP. –

ответ

3

Я думаю, что вам нужно сделать (ARM немного ржавый):

MOV R0, R1, LSR #24 
ORR R0, R2, LSR #8 
ORR R0, R3, LSL #8 
ORR R0, R4, LSL #24 

То есть, MOV в первой инструкции, как вы что-нибудь из старого R0 не хотят, чтобы повлиять на новый стоимость.

Я не вижу никакого способа сделать это более «подсказкой», как если бы вы все равно выполнили всю работу.

+0

Считаете ли вы, что можете разработать немного больше о работе этого кода? Зачем было сначала МОВ, чтобы все это сбилось с пути? – IAE

+1

Ну, если у вас все еще есть исходное значение R0 в R0, а вы просто 'или' новые байты в R0, то вместо того, чтобы просто переставлять байт R0, будет иметь исходное значение R0, создавая неверную результат. –

+0

Спасибо за объяснение! Помогли много ^^ – IAE

3

Ваш код выглядит хорошо.

Ваша ошибка в том, что вы изменили значение LSL и LSR.

Возьмите R0, например:

AND R1, R0, #0xFF000000 // 0xAA 

В результате этой операции не вызывает 0xAA. Он генерирует 0xAA000000.

Вторая инструкция, которая обрабатывает R1:

ORR R0, R1, LSL #24 

сместит данные из регистра. Просто не осталось места 8 верхних битов.

Если Ото вы переносите данные вправо, как это:

ORR R0, R1, LSR #24 

Данные заканчивается в низшем байт. Где вы хотите, чтобы это было. Это должно дать вам достаточную помощь для выполнения вашей домашней работы. :-)

+0

Спасибо за вашу поддержку! У меня был еще один вопрос, если вы не возражаете. # 24 представляет 2^n, в этом случае 2^24, правильно? Но если мы имеем только 0x00000000 = 8 бит, то мы действительно делаем overkill, и писать # 24 не нужно, или? – IAE

+1

@SoulBeaver: Нет, у вас есть 8 "nibbles" (шестнадцатеричные цифры), каждый из которых имеет 4 бита. '0xAABBCCDD' имеет ширину 32 бит. –

1

Кроме того, похоже, что вы не смогли очистить регистр R0 (установить его ко всем нулевым битам), прежде чем использовать ORR для перемещения бит.

5

На ARMv6 и выше вы можете просто использовать инструкцию rev, но я предполагаю, что вам не разрешено делать это по любой причине.

Как почему вы получили результат, который вы сделали, я прошел через свой код и прокомментирован фактические значения регистров эксплуатируются на:

LDR R0, LittleEndian // r0 = 0xAABBCCDD 
AND R1, R0, #0xFF000000 // r1 = 0xAA000000 
AND R2, R0, #0x00FF0000 // r2 = 0x00BB0000 
AND R3, R0, #0x0000FF00 // r3 = 0x0000CC00 
AND R4, R0, #0x000000FF // r4 = 0x000000DD 

ORR R0, R1, LSL #24  // r0 = 0xAABBCCDD | 0x00000000 = 0xAABBCCDD 
ORR R0, R2, LSL #8  // r0 = 0xAABBCCDD | 0xBB000000 = 0xBBBBCCDD 
ORR R0, R3, LSR #8  // r0 = 0xBBBBCCDD | 0x000000CC = 0xBBBBCCDD 
ORR R0, R4, LSR #24  // r0 = 0xBBBBCCDD | 0x00000000 = 0xBBBBCCDD 

То, что здесь происходит то, что у вас есть направления сдвига назад; вместо левого сдвига 0xAA000000 от 24, вы хотите до правый переключить на 24, давая 0x000000AA. Кроме того, вы никогда не обнуляли содержимое r0, которое вам также нужно будет сделать для того, чтобы этот подход работал. Если вы устраните эти проблемы, ваш код будет работать по назначению (хотя есть более компактные способы выполнения одной и той же задачи).

2

В то время как вопрос довольно старый, я хотел добавить свое предложение для кода, потому что ему просто нужно 6 инструкций вместо 8. Ему также нужно всего 3 регистра вместо 5. Это должно быть лучшим решением для чего угодно перед armv6 (который имеет инструкцию rev).

// We're starting with r0 = 4321 
mov r2, r0, lsr #24    // r2 = 0004 
and r1, r0, #16711680   // r1 = 0300 
orr r2, r2, r0, lsl #24   // r2 = 1004 
orr r2, r2, r1, lsr #8   // r2 = 1034 
and r0, r0, #65280    // r0 = 0020 
orr r0, r2, r0, lsl #8   // r0 = 1234 
Смежные вопросы