Как использовать инструкцию MOV в ARM с непосредственным номером в качестве второго операнда - PullRequest
16 голосов
/ 12 апреля 2010

Я только начинаю изучать язык ассемблера ARM, и не совсем понятно, как использовать MOV для передачи непосредственного числа в регистр.

Как из справочного руководства ARM, так и из моего учебника сказано, что диапазон непосредственного числа, следующего за инструкцией MOV, составляет 0-255. Но когда я тестирую на своем ПК в ADS 1.2 IDE, инструкция

MOV     R2, #0xFFFFFFFF

хорошо работает. Разве число 0xFFFFFFFF не выходит за пределы диапазона согласно спецификации?

Надеюсь, кто-нибудь может мне помочь.

Привет.

Ответы [ 7 ]

13 голосов
/ 12 апреля 2010

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

Эта небольшая статья имеет одно из самых ясных объяснений некоторых изхитрости, которые ARM-ассемблер может использовать, чтобы поместить большое число непосредственно в небольшое доступное пространство инструкции ARM:

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

Эти виды манипуляций не могут быть выполнены со всеми непосредственными значениями, но ассемблеры ARM предположительно довольно умныэто (и компиляторы C, безусловно, есть).Если никакие трюки сдвига / дополнения не могут быть выполнены, значение обычно загружается из относительного местоположения ПК или, возможно, путем «наращивания» значения из нескольких инструкций.

12 голосов
/ 12 апреля 2010

Одна инструкция ARM может кодировать только непосредственную константу, которая может быть представлена ​​в виде 8-разрядного непосредственного значения, смещенного на любую даже степень двух.

Однако есть также инструкция MVN, которая похожа на MOV, но инвертирует все биты. Таким образом, хотя MOV R2, #0xFFFFFFFF не может быть закодировано как инструкция MOV, оно может быть закодировано как MVN R2, #0. Ассемблер вполне может выполнить это преобразование для вас.

2 голосов
/ 05 ноября 2014

Инструкция MOV может принимать либо значение imm16, либо значение Operator2 (из-за длины инструкции, противоположной выравниванию памяти), которая должна соответствовать любому из следующих правил (скопировано из руководства по набору инструкций CortexM, X и Y - любое шестнадцатеричное значение):

  • Любая константа, которая может быть получена путем смещения 8-битного значения влево на любое количество бит в пределах 32-битного слова.
  • Любая константа в форме 0x00XY00XY.
  • Любая константа вида 0xXY00XY00.
  • Любая константа формы 0xXYXYXYXY.

Именно поэтому 0xFFFFFFFF принимается (соответствует 4-му правилу).

Если вы хотите собрать собственную 32-битную константу, вы можете использовать инструкцию MOVT , которая записывает в верхнюю половину регистра.

2 голосов
/ 07 ноября 2011

Довольно сложно определить, находятся ли заданные константы в допустимом диапазоне.

Как уже упоминал Мэтью, ассемблер протягивает вам руку, заменяя данные инструкции аналогичными, отрицательными, такими как mov / mvn, cmp / cmn, tst / tne и т. Д.

1 голос
/ 12 апреля 2010

Возможно, вы видите артефакты из знака расширения исходного значения. Если инструменты, которые вы используете для просмотра разборки, обрабатывают 0..255 как байт со знаком, то при загрузке его в больший тип int (или регистр) он заполнит все старшие биты знаковым битом оригинала. значение. Или, другими словами, если 0xFF является байтом со знаком, его десятичное значение равно -1. Поместите это в 32-битный регистр, и шестнадцатеричный код будет выглядеть как 0xFFFFFFFF, а его десятичное значение будет равно -1.

Попробуйте использовать значение без установленного старшего бита, например 0x7F. Поскольку бит знака не установлен, я предполагаю, что он будет заполнять верхние биты нулями при загрузке в больший регистр или поле типа int.

Также возможно, что компилятор / ассемблер усекает любое заданное вами значение. Я бы посчитал это ошибкой исходного кода, но ассемблеры - забавные звери. Если вы дадите ему 0x7FF, скомпилируется ли он в 0x7FF (не урезанный и больше 0..255) или в 0xFFFFFFFF (урезанный до 0..255, байт со знаком)?

0 голосов
/ 31 мая 2019

Если вы хотите переместить 0xffffffff в регистр, вы всегда можете сделать:

MOV R0, #-1

, потому что 0xffffffff является представлением с двойным дополнением -1

0 голосов
/ 12 апреля 2010

Одна возможность состоит в том, что ассемблер ARM отбрасывает значащие биты числа и использует только самый низкий FF.

Инструкция MOV является основным во многих наборах команд ЦП, и обычно ассемблер определяет размер целевого регистра и непосредственное значение, которое предоставляется.

Например, следующие инструкции MOV из набора x86:

MOV BL, 80h, ; 8bit
MOV BX, ACACh ;16bit
MOV EBX, 12123434h ; 32bit
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...