Инструкция по разборке рычага с плавающей запятой - PullRequest
2 голосов
/ 12 августа 2011

Я пытаюсь воссоздать следующий фрагмент разборки рук в c ++:

00003188    ed910a06    flds    s0, [r1, #24]
0000318c    edd10a07    flds    s1, [r1, #28]
00003190    ec800a02    fstmias r0, {s0-s1}
00003194        4770    bx  lr
00003196        bf00    nop

Во-первых, является ли s0 единым регистром прецессии? И что делают flsl и fstmias. Я пробовал следующий код, но он не дает тот же результат:

float s0 = r1[6];
float s1 = r1[7];

Что не так с тем, что я пробовал?

1 Ответ

4 голосов
/ 13 августа 2011

Поскольку это очень тривиальная функция, давайте рассмотрим ее построчно. Я предполагаю, что вы опубликовали функцию complete .

00003188    ed910a06    flds    s0, [r1, #24]

FLDS находится в этой форме: "FLD {cond} Fd, [Rn {, #offset}]", с точностью до s (= одинарная точность). Как указано в документации, загружается плавающее значение одинарной точности, расположенное в r1 + 24 в s0.

0000318c    edd10a07    flds    s1, [r1, #28]

И еще одна загрузка, на этот раз с r1 + 28 (это соответствует тому, что вы пишете с r1[7]).

00003190    ec800a02    fstmias r0, {s0-s1}

FSTMIAS перечисляет "FSTM {cond} Rn, {!} VFPregisters". Здесь у вас есть addressmode = IA, что означает «Увеличение адреса после каждой передачи», а точность = одиночная. Эта инструкция сохраняет указанные регистры по адресу, указанному в r0 Увеличение адреса после каждого хранилища. Другими словами, он хранит s0 в [r0] и s1 в [r0+4].

00003194        4770    bx  lr

BX - это ветвь (и, возможно, переключение обратно в режим ARM) для регистрации значения - предпочтительный способ возврата из функций (см. Раздел 5.1 здесь ). В этом случае регистр является регистром связи, который содержит обратный адрес.

00003196        bf00    nop

Нет работы. Ничего не делает, обычно вставляется для выравнивания функций в памяти.

соглашение о вызовах для ARM-THUMB (раздел 4.1) гласит, что первые четыре аргумента передаются в r0-r3 (== a1-a4), и мы можем видеть из разборки, что r0 и r1 используются, поэтому функция принимает 2 параметра. Неясно, возвращает ли функция значение (такое же, как первый вход) или не возвращает значение. Чтобы выяснить это, вам придется заглянуть на сайты звонков.

На языке C у нас есть функция, которая принимает два значения указателя в качестве входных данных, загружает два float s из смещений 24 и 28 из второго параметра и сохраняет их в смещениях 0 и 4 в первом. Без дальнейшего знания программы невозможно определить, должны ли параметры быть массивами, структурами или чем-то еще.

Предполагая, что они являются массивами, перевод на C тривиален:

void mystery_function(float* dst, const float* src) {
    dst[0] = src[6];
    dst[1] = src[7];
}
...