Язык ассемблера: попытайтесь понять небольшую функцию
для моей работы, мне нужно отменить то, что делает эта часть кода (ARM9). Im java developper, и я действительно не понимаю эту часть кода, связанную с одной функцией.
Конечно, я прошу помощи, потому что исходный код недоступен. Кто-нибудь может помочь мне узнать, что делает этот код с алгоритмом smal на любом высоком языке? Это было бы хорошо. Я пробовал много часов без каких-либо результатов.
sub_FFFF7B38
PUSH {LR}
ADDS R2, R0, #0
LDRB R3, [R2]
CMP R3, #0
BEQ loc_FFFF7B52
SUBS R1, #1
BCC loc_FFFF7B52
loc_FFFF7B46:
ADDS R0, #1
LDRB R3, [R0]
CMP R3, #0
BEQ loc_FFFF7B52
SUBS R1, #1
BCS loc_FFFF7B46
loc_FFFF7B52:
SUBS R0, R0, R2
POP {R1}
Ответы
Ответ 1
За исключением двух последних строк, это может быть что-то вроде следующего.
Пожалуйста, не ударяйте меня, если я не на 100% верен.
Если
R0
- p0
или p
и
R1
- n
и
R2
- временное значение (отредактировано, сначала я подумал: i
или адрес p0[i]
)
R3
- временное значение
.
sub_FFFF7B38
PUSH {LR} ; save return address
ADDS R2, R0, #0 ; move R0 to R2
LDRB R3, [R2] ; load *p0
CMP R3, #0 ; if *p0==0
BEQ loc_FFFF7B52 ; then jump to loc_FFFF7B52
SUBS R1, #1 ; decrement n
BCC loc_FFFF7B52 ; if there was a borrow (i.e. n was 0): jump to loc_FFFF7B52
loc_FFFF7B46:
ADDS R0, #1 ; increment p
LDRB R3, [R0] ; load *p
CMP R3, #0 ; if *p==0
BEQ loc_FFFF7B52 ; jump to loc_FFFF7B52
SUBS R1, #1 ; decrement n
BCS loc_FFFF7B46 ; if there was no borrow (i.e. n was not 0): jump to loc_FFFF7B46
loc_FFFF7B52:
SUBS R0, R0, R2 ; calculate p - p0
POP {R1} ; ??? I don't understand the purpose of this
; isn't there missing something?
или в C:
int f(char *p0, unsigned int n)
{
char *p;
if (*p0==0 || n--==0)
return 0;
for(p=p0; *++p && n>0; n--)
{
}
return p - p0;
}
Ответ 2
Вот инструкции, прокомментированные по строке
sub_FFFF7B38
PUSH {LR} ; save LR (link register) on the stack
ADDS R2, R0, #0 ; R2 = R0 + 0 and set flags (could just have been MOV?)
LDRB R3, [R2] ; Load R3 with a single byte from the address at R2
CMP R3, #0 ; Compare R3 against 0...
BEQ loc_FFFF7B52 ; ...branch to end if equal
SUBS R1, #1 ; R1 = R1 - 1 and set flags
BCC loc_FFFF7B52 ; branch to end if carry was clear which for subtraction is
; if the result is not positive
loc_FFFF7B46:
ADDS R0, #1 ; R0 = R0 + 1 and set flags
LDRB R3, [R0] ; Load R3 with byte from address at R0
CMP R3, #0 ; Compare R3 against 0...
BEQ loc_FFFF7B52 ; ...branch to end if equal
SUBS R1, #1 ; R1 = R1 - 1 and set flags
BCS loc_FFFF7B46 ; loop if carry set which for subtraction is
; if the result is positive
loc_FFFF7B52:
SUBS R0, R0, R2 ; R0 = R0 - R2
POP {R1} ; Load what the previously saved value of LR into R1
; Presumably the missing next line is MOV PC, R1 to
; return from the function.
Итак, в самом базовом C-коде:
void unknown(const char* r0, int r1)
{
const char* r2 = r0;
char r3 = *r2;
if (r3 == '\0')
goto end;
if (--r1 <= 0)
goto end;
loop:
r3 = *++r0;
if (r3 == '\0')
goto end;
if (--r1 > 0)
goto loop;
end:
return r0 - r2;
}
Добавление некоторых структур управления, чтобы избавиться от goto
s:
void unknown(const char* r0, int r1)
{
const char* r2 = r0;
char r3 = *r2;
if (r3 != '\0')
{
if (--r1 >= 0)
do
{
if (*++r0 == '\0')
break;
} while (--r1 >= 0);
}
return r0 - r2;
}
Изменить: Теперь, когда моя путаница в бит переноса и SUBS
была очищена, это имеет больше смысла.
Упрощая:
void unknown(const char* r0, int r1)
{
const char* r2 = r0;
while (*r0 != '\0' && --r1 >= 0)
r0++;
return r0 - r2;
}
В словах это находит индекс первого NUL
в первых символах r1
указателя строки на r0
или возвращает r1
, если не существует.
Ответ 3
Filip предоставил некоторые указатели, вам также нужно прочитать соглашение о вызове ARM. (То есть, какой регистр содержит аргументы функции при вводе и какое его возвращаемое значение.)
С быстрым чтением я думаю, что этот код является strnlen или чем-то близким к нему.
Ответ 4
Как насчет этого: Набор инструкций для ARM
Некоторые подсказки/упрощенные asm
- Push - помещает что-то в "Stack" /Memory
- Добавить - Обычная "добавить", как в +
- Pop возвращает что-то из "стека" / "Память"
- CMP - отсутствует в сравнении, что сравнивает что-то с чем-то другим.
X:
или: Whatever:
означает, что следующая "подпрограмма". Когда-либо использовались "goto" в Java? Как и на самом деле.
Если у вас есть следующее (игнорируйте, если это правильно arm-asm, это просто pseduo):
PUSH 1
x:
POP %eax
Сначала он поместил бы 1 в стек, а затем поместил бы его обратно в eax (что является коротким для расширенного топора, который является регистром, где вы можете поместить 32-битное количество данных)
Теперь, что делает X:
? Предположим, что до этого есть 100 строк asm, тогда вы можете использовать "переход" для перехода к X:
.
Это немного введение в ас. Упрощенная.
Попробуйте понять приведенный выше код и изучите набор инструкций.
Ответ 5
Моя ASM немного ржавая, поэтому никаких гнилых помидоров, пожалуйста. Предполагая, что это начинается с sub_FFFF7B38
:
Команда PUSH {LR}
сохраняет регистр ссылок, который является специальным регистром, который содержит адрес возврата во время вызова подпрограммы.
ADDS
устанавливает флаги (например, CMN
). Также ADDS R2, R0, #0
добавляет R0
в 0 и сохраняет в R2. (Исправление от Чарльза в комментариях)
LDRB R3, [R2]
загружает содержимое R2
в основную память вместо регистра, на который ссылается R3
. LDRB
загружает только один байт. Три неиспользуемых байта в слове обнуляются после загрузки. В принципе, получение R2
из регистров и в безопасном хранении (возможно).
CMP R3, #0
выполняет вычитание между двумя операндами и устанавливает флаги регистров, но не сохраняет результат. Эти флаги приводят к...
BEQ loc_FFFF7B521
, что означает "Если предыдущее сравнение было равным, перейдите к loc_FFFF7B521" или if(R3 == 0) {goto loc_FFFF7B521;}
Итак, если R3
не равно нулю, команда SUBS R1, #1
вычитает один из R1
и устанавливает флаг.
BCC loc_FFFF7B52
приведет к выполнению перехода на loc_FFFF7B52
, если установлен флаг переноса.
(snip)
Наконец, POP {LR}
восстанавливает предыдущий обратный адрес, который был сохранен в реестре ссылок до выполнения этого кода.
Изменить. Пока я был в машине, Творог объяснил, что я думал, когда пытался написать свой ответ и не успел.