Почему можно использовать регистр xzr вместо литерала 0 на ARMv8?
Я читал sve whitepaper из ARM и наткнулся на что-то, что показалось мне странным (в Примере без SVE):
mov x8, xzr
Я не знал, что это за регистр xzr, поэтому я посмотрел его и нашел некоторое содержание из ARM, утверждающее, что во многих контекстах он был синонимом нуля.
Таким образом, похоже, что x8 инициализируется до нуля, что имеет смысл, потому что он выполняется непосредственно перед циклом, где x8 используется в качестве цикла счетчик.
Чего я не понимаю, так это почему не был использован литерал 0 вместо xzr? Например:
mov x8, 0
Подводя итог, я задаюсь вопросом: почему здесь можно использовать регистр xzr вместо литерала 0?5 ответов:
Я думаю, что сравнение
mov x8, xzrvsmov x8, #0является чем-то вроде отвлекающего маневра.Как показывает ответ @old_timer, нет никакого усиления кодирования, и вполне вероятно (хотя, по общему признанию, я не проверял) небольшое или полное увеличение производительности конвейера.
То, что
Я думаю, что это важная характеристика, на которую оригинальный 'некоторый контент из ARM', упомянутый в OP, пренебрегает указать.xzrдает нам, однако - в дополнение к фиктивному регистру согласно ответу @InfinitelyManic - это доступ к нулевому операнду без необходимости загружать и занимать реальный регистр. Это имеет двойное преимущество одного меньше инструкций, и еще один регистр, доступный для хранения "реальных" данных.Вот что я имею в виду под
mov x8, xzrпротивmov x8, #0быть отвлекающим маневром. Если мы обнуляемx8с намерением затем изменить его, то использованиеxzrили#0довольно произвольно (хотя я бы предпочел#0как более очевидное). Но если мы обнуляемx8чисто для того, чтобы снабдить нулевым операндом последующую инструкцию, тогда нам было бы лучше использовать - где это разрешено -xzrвместоx8в качестве операнда в этой инструкции, а не обнулятьx8вообще.
mov x8,xzr mov x8,#0 mov x8,0Производит
0000000000000000 <.text>: 0: aa1f03e8 mov x8, xzr 4: d2800008 mov x8, #0x0 // #0 8: d2800008 mov x8, #0x0 // #0Никакого реального удивления там не было, кроме того, что это позволило немедленно без знака фунта. Это не проблема размера инструкции (опять же неудивительно, что с x86,например,xor rax, rax дешевле, чем mov rax, 0), возможно, есть увеличение производительности конвейера (несмотря на распространенное мнение, что инструкции берут больше, чем один запуск часов, чтобы закончить).
Скорее всего, это личное предпочтение вещь у нас есть этот прохладный mips как всегда нулевой регистр вещь позволяет использовать его только для веселье.
Эти две инструкции должны быть идентичны - как с точки зрения эффекта, так и ожидаемой эффективности.
На самом деле они оба псевдонимы инструкций более общего назначения.
mov x8, 0кодируется какorr x8, xzr, 0Псевдонимы полезны, потому что они делают ASM более читаемым. Вторая кодировка демонстрирует, почему наличие нулевого регистра
mov x8, xzrкодируется какorr x8, xzr, xzrxzrможет быть полезным. Поскольку мы знаем, что xzr всегда равен нулю, мы можем повторно использоватьorrинструкция дляmov. Без негоmovпотребовало бы другой кодировки, и поэтому было бы потрачено впустую пространство кодировки.
Этот ответ не является "на четвереньках" Для OP.
XZR может использоваться для отбрасывания результатов; например, "ldr xzr, [sp], 16". См. GDB ниже
0x7fffffef40: 0x00000000 0x00000000 0x00400498 0x00000000 0x7fffffef50: 0x00000000 0x00000000 0x00000000 0x00000000 ldr x0,=0xdead (gdb) ldr x1,=0xc0de (gdb) stp x0, x1, [sp, #-16]! (gdb) x/8x $sp 0x7fffffef30: 0x0000dead 0x00000000 0x0000c0de 0x00000000 0x7fffffef40: 0x00000000 0x00000000 0x00400498 0x00000000 ldr xzr, [sp], #16 (gdb) x/8x $sp 0x7fffffef40: 0x00000000 0x00000000 0x00400498 0x00000000 0x7fffffef50: 0x00000000 0x00000000 0x00000000 0x00000000Также помните, что в ARMv8 стек должен быть выровнен по четырем словам или SP mod 16 = 0. Таким образом, вы можете использовать XZR один из регистров пары "pushed" или "pop".
stp x1, xzr, [sp, #-16]! ldp x10, xzr, [sp], #16
TL; DR
Для загрузки 64-битного литерала в регистр требуется несколько команд, но только одна команда устанавливается в 0 с помощью zxr. Поэтому код короче и быстрее.
Чтобы переместить литерал в регистр, вы должны использовать инструкцию MOVL, смотрите это из ссылки arm:
Таким образом, загрузка литерала в регистр-это многоступенчатый процесс. Если вы просто хотите очистить реестр, то у них есть ярлык. zxr-это псевдо-регистр, который всегда считывает ноль, что является общим значением, которое вам понадобится, и перемещение регистра в регистр может быть сделано в одной инструкции.Псевдо-инструкция MOVL
Загрузите регистр либо с помощью:
A 32-bit or 64-bit immediate value. Any address.MOVL генерирует либо две, либо четыре инструкции... мова, MOVK пара.
В сборке микрочипов они имеют схожую концепцию. Чтобы установить регистр в литерал, вы должны сделать что-то вроде:
MOVLW 10 (Move 10 to the working register) MOVWF 0x1234 (Move the working register to address 0x1234)Но для установки в ноль у них есть инструкция:
CLRF 0x1234 (Set 0x1234 to zero)