Зачем использовать LDR поверх MOV (или наоборот) в сборке ARM?

Я просматриваю этот учебник: http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/ok01.html

Первая строка сборки:

ldr r0,=0x20200000 

вторая:

 mov r1,#1 

Я думал, что ldr для загрузки значений из памяти в регистры. Но, похоже, значение = означает, что значение 0x20200000 не является адресом памяти. Обе строки, похоже, загружают абсолютные значения.

    Это трюк / ярлык. скажем, например

     ldr r0,=main 

    что произойдет, если ассемблер будет выделять слово данных рядом с инструкцией, но за пределами пути команды

     ldr r0,main_addr ... b somewhere main_addr: .data main 

    Теперь разворачиваем этот трюк на константы / немедленно, например, те, которые не могут вписаться в немедленную инструкцию перемещения:

     top: add r1,r2,r3 ldr r0,=0x12345678 eor r1,r2,r3 eor r1,r2,r3 b top 

    собрать, разобрать

     00000000 : 0: e0821003 add r1, r2, r3 4: e59f0008 ldr r0, [pc, #8] ; 14  8: e0221003 eor r1, r2, r3 c: e0221003 eor r1, r2, r3 10: eafffffa b 0  14: 12345678 eorsne r5, r4, #125829120 ; 0x7800000 

    и вы видите, что ассемблер добавил слово данных для вас и изменил ldr на родственника компьютера для вас.

    теперь, если вы используете немедленное действие, которое вписывается в инструкцию 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 : 0: e0821003 add r1, r2, r3 4: e59f0010 ldr r0, [pc, #16] ; 1c  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  1c: 12345678 eorsne r5, r4, #125829120 ; 0x7800000 

    Так что это в основном ярлык для ввода текста, понимайте, что вы даете ассемблеру возможность найти место, чтобы придерживаться постоянной, что обычно делает хорошую работу, иногда жалуется, не уверен, что я видел, что он не делает это безопасно. Иногда вам нужен код .ltorg или .pool, чтобы побудить ассемблера найти место.

    Более короткий ответ, только от человека, который ближе к вашему уровню, надеется, что это поможет: в 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.

    Как и другие ответы, я думаю, что я мог бы упростить ответ.

    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, сопровождающую значение.

    • В противном случае значение сохраняется в виде данных, загруженных в ОЗУ, в местоположении. И он загружается в требуемый регистр путем доступа из памяти с использованием смещения от счетчика программ.

    Надеюсь, это помогло.

    Давайте будем гением компьютера.