Зачем использовать LDR поверх MOV (или наоборот) в сборке ARM?
Я просматриваю этот учебник: http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/ok01.html
Первая строка сборки:
ldr r0,=0x20200000
второе:
mov r1,#1
Я думал, что ldr
предназначено для загрузки значений из памяти в регистры. Но кажется, что =
означает, что 0x20200000 - это значение, а не адрес памяти. Кажется, что обе строки загружают абсолютные значения.
Ответы
Ответ 1
Это трюк/ярлык. например,
ldr r0,=main
что произойдет, если ассемблер будет выделять слово данных рядом с инструкцией, но за пределами пути команды
ldr r0,main_addr
...
b somewhere
main_addr: .data main
Теперь добавьте этот трюк в константы/немедленно, esp те, которые не могут вписаться в немедленную инструкцию перемещения:
top:
add r1,r2,r3
ldr r0,=0x12345678
eor r1,r2,r3
eor r1,r2,r3
b top
собрать, а затем разобрать
00000000 <top>:
0: e0821003 add r1, r2, r3
4: e59f0008 ldr r0, [pc, #8] ; 14 <top+0x14>
8: e0221003 eor r1, r2, r3
c: e0221003 eor r1, r2, r3
10: eafffffa b 0 <top>
14: 12345678 eorsne r5, r4, #125829120 ; 0x7800000
и вы видите, что ассемблер добавил слово данных для вас и изменил ldr на родственник pc для вас.
теперь, если вы используете немедленное действие, которое вписывается в инструкцию mov, тогда, в зависимости от ассемблера, возможно, с помощью gnu, как я использую, он превратил его в mov для меня
top:
add r1,r2,r3
ldr r0,=0x12345678
ldr r5,=1
mov r6,#1
eor r1,r2,r3
eor r1,r2,r3
b top
00000000 <top>:
0: e0821003 add r1, r2, r3
4: e59f0010 ldr r0, [pc, #16] ; 1c <top+0x1c>
8: e3a05001 mov r5, #1
c: e3a06001 mov r6, #1
10: e0221003 eor r1, r2, r3
14: e0221003 eor r1, r2, r3
18: eafffff8 b 0 <top>
1c: 12345678 eorsne r5, r4, #125829120 ; 0x7800000
Итак, это в основном ярлык для ввода текста, понимайте, что вы даете ассемблеру возможность найти место, чтобы придерживаться постоянной, что обычно делает хорошую работу, иногда жалуется, не уверен, что я видел, что он не в состоянии сделать это безопасно. Иногда вам нужен код .ltorg или .pool в коде, чтобы помочь ассемблеру найти место.
Ответ 2
Более короткий ответ, только от человека, который ближе к вашему уровню, надеется, что это поможет: в ARM инструкции имеют 32 бита. Некоторые биты используются для идентификации операции, некоторые для операндов, а в случае команды MOV некоторые доступны для немедленного значения (например, # 1).
Как вы видите здесь (стр. 33), для немедленного значения доступно только 12 бит. Вместо того, чтобы использовать каждый бит в качестве числа (от 0 до 2 ^ 12-1 ~ 4095), команда вычисляет ближайшее число, поворачивая правое (ROR) первые 8 бит на два раза, количество, указанное в последних 4 битах, То есть immediate = first 8 bits ROR 2*(last four bits)
.
Таким образом, мы можем достичь гораздо большего числа, чем просто 4096 (см. стр. 34 для краткого изложения возможных непосредственных действий).
На всякий случай, что наш номер не может быть преобразован в инструкцию, подобную предыдущей (257 не может быть выражен как 8 бит, повернутых два раза каждые 4 бита), тогда мы должны использовать LDR r0, = 257
В этом случае компилятор сохраняет номер 257 в памяти, рядом с программным кодом, поэтому его можно адресовать по отношению к ПК и загружать его из памяти, так же подробно объясняется в dwelch.
Примечание. Если вы следуете этому руководству, то при попытке "сделать" с mov r0, # 257 вы получите сообщение об ошибке, и вам придется вручную попробовать ldr r0, = 257.
Ответ 3
Как и другие ответы, я думаю, что могу упростить ответ.
ldr= Регистр LoaD
mov= MOVe
Оба эффективно делают одно и то же, но по-разному.
Разница во многом похожа на разницу между
#define CONST 5
и
int CONST = 5;
на языке C.
mov выполняется очень быстро, так как имеет сопутствующее значение, непосредственно сохраненное как часть инструкции (в 12-битном формате, описанном в ответе выше). Он имеет некоторые ограничения из-за того, как он сохраняет значение. Зачем? Поскольку
- 12 бит недостаточно для хранения огромных чисел, таких как 32-разрядные адреса памяти.
- Первые 8 бит ROR 2 * (последние 4 бита) не могут представлять только любое число, даже в 12-битном диапазоне.
ldr, с другой стороны, универсален (главным образом, из-за оптимизации компилятора). Он работает так (как показано в разобранной процедуре)
-
Если значение может быть представлено в 12-битном и первом 8 бит ROR 2 * (последние 4 бита) формате, тогда компилятор изменит его на mov, сопровождающее значение.
-
В противном случае значение сохраняется как данные, загруженные в ОЗУ, в месте. И он загружается в требуемый регистр путем доступа из памяти с использованием смещения от счетчика программ.
Я надеюсь, что это помогло.