Несоответствие типа операнда GAS Assembler для cmovz

Пытаюсь написать простую программу сборки. По какой-то причине условные ходы, кажется, выдают мне эту ошибку. Если я заменю их обычной инструкцией mov, она сработает. Что не так со следующим кодом?

    .section .data

supported:
    .asciz "AVX is supported"
notsupported:
    .asciz "AVX is not supported"


    .section .text
    .global main
main:
    movq $1, %rax
    cpuid
    andq $0x10000000, %rcx
    cmovnz $supported, %rdi
    cmovz $notsupported, %rdi
    callq puts

    movq $0, %rax
    ret
cpuid.S:15: Error: operand type mismatch for `cmovnz'
cpuid.S:16: Error: operand type mismatch for `cmovz'

person chasep255    schedule 23.07.2015    source источник


Ответы (1)


Если вы посмотрите описание CMOVcc в руководстве Intel, вы увидите, что исходный операнд должен быть r/m64 (то есть 64-битным регистром или ячейкой памяти). $supported и $notsupported являются немедленными и поэтому не квалифицируются как r/m64.

Вы можете сделать что-то вроде этого:

movabs $notsupported,%rdi
movabs $supported,%rbx
testq $0x10000000, %rcx   # checks the desired bit without clobbering %rcx
cmovnz %rbx,%rdi
person Michael    schedule 23.07.2015
comment
Не могли бы вы сделать мне одолжение и объяснить, чем отличается movabs от movq? - person chasep255; 23.07.2015
comment
При использовании movq $supported,%rbx вы получите машинный код, в котором непосредственное кодирование 32-битного кода, что может привести к ошибкам перемещения во время связывания. Отсюда причина использования movabs, что приводит к немедленному кодированию в 64 бита. - person Michael; 23.07.2015
comment
То есть при сборке адреса ваших ярлыков еще не известны. Таким образом, ассемблер просто выводит смещения относительно начала раздела, в котором они расположены. Эти смещения могут быть достаточно малы, чтобы поместиться в 32 бита, но когда компоновщик вмешивается и назначает адреса разделам и соответственно перемещает код, для этих адресов вполне может потребоваться 64 бита. - person Michael; 23.07.2015
comment
Не лучше ли использовать leaq something(%rip), %rdi? - person harold; 23.07.2015
comment
@harold: Это действительно приводит к уменьшению машинного кода на 2 байта для каждого загруженного адреса. - person Michael; 23.07.2015
comment
Если условие для cmov обычно ложно, оно сохранит инструкцию поместить константу в память, а не как немедленную. Тогда cmov my_const(%rip), %rdi. Если это случается часто, это дополнительная строка кэша (и даже страница памяти), которая может отсутствовать в D-кэше L1 и DTLB. - person Peter Cordes; 23.07.2015