Ассемблер: попытайтесь понять небольшую функцию

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

Конечно, я прошу помогать, потому что исходный код не более доступен. Кто-либо может помочь мне знать то, что этот код делает с маленьким алгоритмом на каком-либо высоком языке? Это было бы хорошо. Я пробовал в течение многих часов без результатов.

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}
12
задан CB Bailey 27 February 2010 в 00:41
поделиться

5 ответов

За исключением двух последних строк, это может быть что-то вроде следующего.
Пожалуйста, не бейте меня, если я ошибаюсь на 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;
}
6
ответ дан 2 December 2019 в 21:02
поделиться

Да. Присвоение Placemark имени и описания сделает его кликаемым объектом в Google Earth и откроется с информационным окном, в котором будут показаны оба объекта. Вы можете создать ролловер/mouseover поведение, используя карты стилей, вот пример, который делает оба:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>Highlighted Icon</name>
<description>Place your mouse over the icon to see it display the new
      icon</description>
<StyleMap id="exampleStyleMap">
  <Pair>
    <key>normal</key>
    <!-- you could also use a <styleUrl> here instead of inlining -->
    <Style>
      <PolyStyle>
        <color>7dff0000</color>
      </PolyStyle>
    </Style>
  </Pair>
  <Pair>
    <key>highlight</key>
    <!-- you could also use a <styleUrl> here instead of inlining -->
    <Style>
      <PolyStyle>
        <color>7dffffff</color>
      </PolyStyle>
    </Style>
  </Pair>
</StyleMap>

<!-- and now, a Placemark that uses the StyleMap -->
<Placemark>
  <name>Roll over this polygon</name>
  <description>this will show up when clicked</description>
  <visibility>1</visibility>
  <styleUrl>#exampleStyleMap</styleUrl>
  <Polygon>
    <tessellate>1</tessellate>
    <altitudeMode>absolute</altitudeMode>
    <outerBoundaryIs>
      <LinearRing>
        <coordinates>
          -112.3372510731295,36.14888505105317,1784
          -112.3356128688403,36.14781540589019,1784
          -112.3368169371048,36.14658677734382,1784
          -112.3384408457543,36.14762778914076,1784
          -112.3372510731295,36.14888505105317,1784
        </coordinates>
      </LinearRing>
    </outerBoundaryIs>
  </Polygon>
</Placemark>
</Document>
</kml>
-121--4779920-

я думаю, что вы хотите определить функцию сравнения, где вы можете определить ранг между любыми 2 предметами в списке.

    int CompareObject1(Object1 left, Object1 right)
    {
        // TODO: cases where your items are null

        // compare Property1 values
        if (left.Property1)
        {
            if (right.Property1)
            {
                // items at same rank
                return 0;
            }
            else
            {
                // left item is higher rank than right
                return -1;
            }
        }
        else if (right.Property1)
        {
            // right item is higher rank than left
            return 1;
        }

        // Property1 doesn't indicate position, move along
        // TODO: repeat for Property2

        // Property2 doesn't indicate position, move along
        // TODO: repeat for Property3

        // if we get here, no determination can 
        // be made/don't bother to move anything
        return 0;
    }

возвращаемое значение указывает, должен ли левый или правый объект быть ранжирован выше с -1 или 1 (или 0 для предпочтения). просто убедитесь, что вы покрываете все ваши условия.

тогда вы можете использовать это как

List<Object1> foo = new List<Object1>() { <items...> };
foo.Sort(CompareObject1);

, если вы список заканчивается назад, я, вероятно, перевернул знаки в функции сравнения. ваши правила сортировки противоречивы, поэтому я позволю вам сортировать Property2 и Property3.

-121--3594855-

Мой ASM немного ржавый, поэтому никаких гнилых помидоров, пожалуйста. Предположим, что это начинается с sub _ FFFF7B38 :

Команда PUSH {LR} заповедников регистр линии связи, который представляет собой специальный регистр, содержащий обратный адрес во время вызова подпрограммы.

ДОБАВЛЯЕТ наборов флагам (например, CMN ). Также ADD R2, R0, # 0 добавляет R0 к 0 и хранению в R2. (Исправление от Чарльза в комментариях)

LDRB R3, [R2] загружает содержимое R2 в основную память вместо регистра, на который ссылается R3 . LDRB загружает только один байт. Три неиспользуемых байта в слове обнуляются при загрузке. В основном, получение R2 из регистров и в безопасном хранении (может быть).

CMP R3, # 0 выполняет вычитание между двумя операндами и устанавливает флаги регистра, но не сохраняет результат. Эти флаги ведут к...

BEQ loc_FFFF7B521, что означает «Если предыдущее сравнение было равно, перейти к loc_FFFF7B521» или если (R3 = 0) {перейти к loc_FFFF7B521;}

So, если R3 не равно нулю, то команда SUBS R1, # 1 вычитает один из R1 и устанавливает флаг.

BCC loc_FFFF7B52 вызовет переход к loc _ FFFF7B52 , если флаг переноса набора.

(snip)

Наконец, POP {LR} восстанавливает предыдущий обратный адрес, который содержался в регистре ссылки до выполнения этого кода.

Edit - Пока я был в машине, Керд писал о том, о чем я думал, когда пытался написать свой ответ и у меня не было времени.

1
ответ дан 2 December 2019 в 21:02
поделиться

Как насчет этого: Набор инструкций для ARM

Некоторые подсказки / упрощенный asm

  • Push - помещает что-то в «стек» / память
  • Add - Обычно «добавляет», как в +
  • Pop извлекает что-то из "стека" / Memory
  • CMP - это сокращение от Compare, которое сравнивает что-то с чем-то другим.

X: или: Неважно: означает, что следующее является «подпрограммой». Вы когда-нибудь использовали "goto" в Java? На самом деле похоже на это.

Если у вас есть следующее (игнорируйте, если это правильный arm-asm, это просто псевдоним):

PUSH 1
x:     
    POP %eax

Сначала он помещает 1 в стек, а затем помещает его обратно в eax (что является сокращением от расширенного топора, который является регистр, в который можно поместить 32-битный объем данных)

Что же тогда делает x: ? Что ж, предположим, что до этого также есть 100 строк asm, тогда вы можете использовать инструкцию "jump" для перехода к x: .

Это небольшое введение в asm. Упрощенный.

Попытайтесь понять приведенный выше код и изучить набор инструкций.

1
ответ дан 2 December 2019 в 21:02
поделиться

Филип предоставил несколько указателей, вам также необходимо ознакомиться с соглашением о вызовах ARM. (То есть, какие регистры содержат аргументы функции при входе, а какие - ее возвращаемое значение.)

После быстрого чтения я думаю, что этот код является strnlen или чем-то тесно связанным с ним.

2
ответ дан 2 December 2019 в 21:02
поделиться

Вот инструкции, прокомментированные строка за строкой

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;
}

Edit: Теперь, когда моя путаница с битом переноса и 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 , если нет.

4
ответ дан 2 December 2019 в 21:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: