С самого начала для набора команд большого пальца кодировка
0001110xxxnnnddd
является
adds rd,rn,#xxx
это более эффективная кодировка IF модификация of the flags вам подходит.
Псевдо-инструкция mov rd, rn означает, что флаги могут изменяться (как для рук, так и для asm в документе, очевидно). Так что исходная кодировка в порядке.
Теперь дизассемблер должен выбрать if immed == 0, а затем вывести mov rd, rn vs добавляет rd, rn, # 0, оба являются правильными дизассемблерами.
Теперь mov с одним регистром старшим и одним младшим говорит:
Unlike the low register MOV instruction described in MOV (2) on page A7-73, this instruction does not change the flags.
И теперь он попадает на язык ассемблера, который полностью определяется ассемблером, а не целью (НЕ ARM), и ужасный унифицированный синтаксис и так далее. Так что теперь это становится предметом c специально для инструмента. Ассемблер Gnu для большого пальца не любит, например, добавления (неунифицированный синтаксис, который, как мне кажется, значительно проще использовать для большого пальца), вы выполняете добавление и получаете добавление.
.thumb
add r0,r1,#0
mov r0,r1
adds r0,r1,#0
movs r0,r1
arm-none-eabi-as so.s -o so.o
so.s: Assembler messages:
so.s:5: Error: instruction not supported in Thumb16 mode -- `adds r0,r1,#0'
.thumb
add r0,r1,#0
mov r0,r1
movs r0,r1
00000000 <.text>:
0: 1c08 adds r0, r1, #0
2: 1c08 adds r0, r1, #0
4: 1c08 adds r0, r1, #0
Однако с movs все в порядке.
0x1c08 = 0x0001110000001000, и это инструкция добавления большого пальца, возвращающаяся к armv4t, когда все это началось.
.syntax unified
.thumb
add r0,r1,#0
mov r0,r1
adds r0,r1,#0
movs r0,r1
0: f101 0000 add.w r0, r1, #0
4: 4608 mov r0, r1
6: 1c08 adds r0, r1, #0
8: 0008 movs r0, r1
Итак, теперь в этом случае это другой язык ассемблера (тот же инструмент отличается язык ассемблера)
Итак, этот язык ассемблера уважает add vs add и mov vs movs.
Чтобы выполнить добавление без flah, вам нужна кодировка thumb2. Mov без флагов - это старший регистр mov 0x4608 0100011000001000 0x46xx
добавляет, как всегда, и movs теперь закодирован как сдвиг влево, но вместо дизассемблирования lsl r0, r1, # 0 они вместо этого разбирают как mov r0, r1, больше, чтобы вы могли разжевать, вместо того, чтобы просто дизассемблировать mov в качестве добавления. Почему они не использовали аддов? И вот еще одна проблема с этим: если вы посмотрите на инструкцию нижних регистров mov, по крайней мере, в старой руке, она описывает, что происходит с флагами, которые она показывает кодировкой добавления. Но если вы посмотрите на описание lsl, флаги разные, lsl не является заменой mov с флагами, по крайней мере, как описано в самой долгоживущей ARM ARM (с большим пальцем).
Хорошо, и это имеет смысл, они были полезны в старшей руке. если немедленное значение равно нулю, то нет никакого выполнения, поэтому он описывается как установленный в ноль вместе с подписанным флагом переполнения.
Lsl показывает перенос как неизменный, а не нулевой в одном документе по сравнению с другим. Так что, возможно, со временем произошли какие-то изменения в реализации инструкций или один из ARM ARMS оказался неправильным (что случается часто).
Короткий ответ, mov rd, rn всегда была псевдо-инструкцией, документированной как добавление, дизассемблер может распечатать ее в любом случае, это зависит от дизассемблера.
Язык ассемблера определяется инструмент не является целью, поэтому инструмент определяет, какое решение флага использовать в своем синтаксисе, и может выбирать между добавлением, старшими регистрами mov, кодировкой thumb2 или какой-либо другой кодировкой.
Мы не узнаем, Вопрос почему: зачем выбирать одну кодировку вместо другой, где возможны равные кодировки, часто часто выбирается более короткая (расширение thumb против thumb2) (xor в x86 против mov немедленно с нулем в качестве непосредственного). Но lsl vs add vs sub vs ...
Существуют и другие псевдоинструкции, которые вы найдете либо в документации по arm (документирует язык ассемблера его инструмента в то время), а также псевдоинструкции, которые Ассемблер добавляет в свой ассемблер, например, nop.
.thumb
nop
mov r8,r8
mov r4,r4
00000000 <.text>:
0: 46c0 nop ; (mov r8, r8)
2: 46c0 nop ; (mov r8, r8)
4: 1c24 adds r4, r4, #0
И теперь вопрос в том, почему они просто не распечатали это:
0: 1c08 mov r0,r1 ; (adds r0, r1, #0)
Мне также нравится, как дизассемблер подразумевает точку с запятой в качестве границы комментария, где ассемблер, как ни странно, не поддерживает это (как и любой другой ассемблер на pl anet (ну, большинство)).
Допустим, дизассемблер не знает, какой ассемблер был создан этот машинный код, поэтому для случаев, когда есть псевдо-инструкция, показывающая оба, было бы неплохо.