我尝试将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
我试着把缓冲区中的值移到寄存器中,但似乎也不起作用。我还试着改变异或运算中缓冲区和整数的顺序,仍然没有结果。
1条答案
按热度按时间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
中的b
后缀所完成的。另请参阅https://sourceware.org/binutils/docs/as/i386_002dVariations.html。