Путаница с `ldmdb` в сборке ARM - PullRequest
1 голос
/ 14 марта 2019

Документы ARM для инструкции ldmdb, по-видимому, противоречат сами себе.

  1. В описании addr_mode документы указывают, что адрес БДсоответствует «Уменьшить адрес перед каждым доступом».

  2. Далее в разделе «Операция» документы указывают, что «адреса памяти, используемые для доступа, имеют интервалы в 4 байта в диапазоне от Rn до Rn-4*(n-1).

Я запутался в том, что эти два оператора не находятся в прямом конфликте: если адрес (хранящийся в Rn) уменьшается перед каждым доступомне будет ли первый (самый высокий) доступный адрес Rn - 4?

Основываясь на поведении, которое я наблюдал при выполнении некоторого кода, кажется, что адрес фактически уменьшается после каждыйдоступ (согласуется со вторым поведением).

Я неправильно интерпретирую это? Каково действительное поведение ldm / stm в режиме адресации БД?

1 Ответ

2 голосов
/ 14 марта 2019

Мне кажется довольно ясным:

LDMDB/LDMEA)

address = R[n] - 4*BitCount(registers);
for i = 0 to 14
  if registers<i> == '1' then
    R[i] = MemA[address,4]; address = address + 4;

if registers<15> == '1' then
  LoadWritePC(MemA[address,4]);

if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);

LDM (LDMIA / LDMFD)

address = R[n];
for i = 0 to 14
  if registers<i> == '1' then
    R[i] = MemA[address,4]; address = address + 4;

if registers<15> == '1' then
  LoadWritePC(MemA[address,4]);

if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);

, поэтому, если r5 = 0x1000

ldmdb r5,{r2,r1}

конечный результатэто:

r2 = mem[0x0FFC]
r1 = mem[0x0FF8]

из псевдокода

address = 0x1000 - (2*4) = 0x0FF8, then for each register flag in the list
mem[address] = r1, address += 4
mem[address] = r2, address += 4

Я думаю, что DB означает, что ничего не будет записано в начальный адрес (0x1000 в этом примере).

если r5 = 0x1000

ldmia r5,{r1,r2}

, конечный результат будет

r1 = mem[0x1000]
r2 = mem[0x1004]

из псевдокода

address = 0x1000
for each register flag enabled
r1 = mem[address] address += 4
r2 = mem[address] address += 4

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

Или вы можете просто попробовать инструкцию на процессоре или симуляторе и проверить память.

Если это не имеет смысла, найдите одно из альтернативных / совместимых справочных руководств по архитектуре ARM и прочитайте это описание.ARM время от времени переписывает их описания ...

Вполне возможно, что в документации есть ошибки.


редактировать.Да, этот текст выглядит совершенно неверным:

Для LDMDB, LDMEA, STMDB и STMFD адреса памяти, используемые для доступа, имеют 4-байтовые интервалы в диапазоне от Rn до Rn - 4 * (n-1)где n - количество регистров в регистре.Доступ осуществляется в порядке убывания номеров регистров, причем регистр с наибольшим номером использует самый высокий адрес памяти, а регистр с самым низким номером - самый низкий адрес памяти.Если указан суффикс обратной записи, значение Rn - 4 * (n-1) записывается обратно в Rn.

должно быть от rn - 4 до rn - (4 * n) и rn - (4 *)n)

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

...