assembly XOR汇编x86-64 AT&T.在缓冲区中的字节和整数之间执行XOR

jslywgbw  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(141)

我尝试将B写入文件,读取它,将它与整数10进行异或运算,然后将结果写入文件,但是我得到了一个操作数不匹配。我如何才能将存储在缓冲区中的值与整数进行异或运算,然后将结果写回文件?谢谢!

.section .bss

buffer: .skip 1

      .align 8
file: .quad 0

.data

B: .byte 0x42

.text
filename: .asciz "file.bmp"
mode: .asciz "w+"
myText: .asciz "C"
toInt: .asciz "%u"



.global main

main:
    pushq   %rbp            
    movq    %rsp, %rbp      

    movq $filename , %rdi      
    movq $mode , %rsi         
    call fopen        

    mov %rax, file 

    mov $B, %rdi 
    mov $1, %rsi 
    mov $1, %rdx 
    mov file, %rcx 
    call fwrite

    mov file, %rdi 
    mov $0, %rsi 
    mov $0, %rdx 
    call fseek 

    mov $buffer, %rdi 
    mov $1, %rsi 
    mov $1, %rdx 
    mov file, %rcx 
    call fread

    movq $10, %r10
    xor %r10, $buffer

    mov $buffer, %rdi 
    mov $0, %rsi 
    mov $0, %rdx 
    mov file, %rcx 
    call fwrite

    movq    %rbp, %rsp     
    popq    %rbp            
    movq    $0, %rdi        
    call    exit

我试着把缓冲区中的值移到寄存器中,但似乎也不起作用。我还试着改变异或运算中缓冲区和整数的顺序,仍然没有结果。

jchrr9hc

jchrr9hc1#

两个问题。
首先,AT&T汇编中的$前缀表示一个 immediate 值,一个要编码到指令中的常量,用它作为指令的目的地没有意义;你不能修改一个常量。如果你想在一个给定的地址上读写内存的内容,你可以省略$。所以这意味着类似于xor %r10, buffer
但由于 * 操作数大小 * 的原因,这仍然是不正确的。对于大多数指令,x86-64可以对8、16、32或64位值进行操作。当操作数之一是寄存器时,其大小决定操作数大小。%r10是64位寄存器,因此xor %r10, buffer是64位操作。它将加载64位四字(8字节),将所有64位与%r10的对应位进行异或,写回所有的8个字节。这不是很好,因为buffer实际上只有1个字节;您甚至无法确定接下来的7个字节是否可以安全访问。
因此,您需要与%r10的低8位对应的8位寄存器(称为%r10b),而不是%r10。(对于传统寄存器%rax, %rbx等,低8位称为%al, %bl等。有关详细信息,请参阅Assembly registers in 64-bit architecture和您的架构参考手册。)因此,xor %r10b, buffer可以正常工作。
然而,xor指令仍然可以把立即数作为它的 source 操作数。您可以跳过加载%r10

xorb $10, buffer

由于此指令上没有寄存器操作数,因此我们必须手动指定操作数大小,这是xorb中的b后缀所完成的。另请参阅https://sourceware.org/binutils/docs/as/i386_002dVariations.html

相关问题