【问题标题】:GAS Assembler operand type mismatch for `cmovz''cmovz' 的 GAS 汇编器操作数类型不匹配
【发布时间】:2015-07-23 11:15:29
【问题描述】:

我正在尝试编写一个简单的汇编程序。出于某种原因,有条件的移动似乎给了我这个错误。如果我用普通的 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'

【问题讨论】:

    标签: assembly x86 gnu-assembler att


    【解决方案1】:

    如果您查看 Intel 手册中对 CMOVcc 的描述,您会发现源操作数必须是 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
    

    【讨论】:

    • 你能帮我一个忙,解释一下 movabs 的作用与说 movq 的不同吗?
    • 使用movq $supported,%rbx 时,您会得到机器码,其中立即数以 32 位编码,这可能会导致链接期间的重定位错误。因此使用 movabs 的原因是立即数被编码为 64 位。
    • 也就是说,在组装的时候,你的标签的地址还不知道。所以汇编器只输出相对于它们所在部分的开头的偏移量。这些偏移量可能小到足以容纳 32 位,但是当链接器介入并为这些部分分配地址并相应地重新定位代码时,这些地址很可能需要 64 位。
    • 使用leaq something(%rip), %rdi不是更好吗?
    • @harold:这确实会为每个加载的地址减少 2 个字节的机器代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-17
    • 2016-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多