Рукоятка ассемблера вправо смещается после мультилпы долго? - PullRequest
2 голосов
/ 24 июня 2010

Вопрос начинающего ARM на ассемблере.Я пишу свою первую программу на ассемблере и пытаюсь закодировать этот фрагмент Си.

int x = somevalue1 << 12; // s19.12 

int y = somevalue2 << 12; // s19.12

int a = somevalue3 << 12; // s19.12 

int b = somevalue4 << 12; // s19.12

int c = somevalue4 << 12; // s19.12

long long acc = (long long) a * b;

acc += (long long) x * y;

int res = (acc >> 24);

acc += (long long) c * a;

Я кодировал первую часть и вычислял сумму в регистрах r10, r11.

@ r6 =a, r4 = b, r0 = x,r2 =y, r3=c

smull r10, r11, r6, r4  @acc = a * b

smlal r10, r11, r0, r2  @acc += x * y

Теперь мне нужно извлечь значение res из r10r11 регистрируется путем смещения вправо «long long» на 24 бита.Как мне это сделать?

-спасибо

1 Ответ

3 голосов
/ 24 июня 2010

r10 содержит младшие 32 бита, а r11 содержит старшие 32 бита.

r10           r11
0  1  2  3    4  5  6  7

Результат, который вы хотите, выглядит следующим образом:

r12
3  4  5  6

То есть конечный результат будет содержать младшие 24 бита r11 и старшие 8 бит r10. Если вы используете беззнаковую арифметику, извлечь биты так просто. Поскольку вы используете подписанную арифметику, вам нужно сохранить знак. Также обратите внимание, что по необходимости вы также отбрасываете старшие 8 бит, конвертируя long long в целое число.

Сначала давайте переместим младшие 24 бита r11 в их окончательное положение. Арифметическое смещение влево гарантирует сохранение знака.

mov r12, r11 asl #8

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

orr r12, r10 lsr #24

Вышеуказанное эквивалентно этому C:

r12 = ((signed)r11 << 8);
r12 |= ((unsigned)r10 >> 24);

Конечно, вы можете просто позволить компилятору сгенерировать такой код для вас. Чтобы компилятор корректно переместил long long в C, вам нужно использовать:

int res = (acc >> 24LL);
...