Reputation: 23
I am trying to make an atbash cypher in assembly x86, where 'a'
s become 'z'
s, 'b'
s become 'y'
s, and so on. I'm using the equation such that (122-char) + 97 (in ascii values) is the atbash character.
mov al, 'c'
mov rax, 122
mov rcx, al
sub rax, rcx
add rax, 97
When executing these lines however, it says there is an invalid combination of opcode and operands.
How do i perform this equation with char
s and int
s correctly?
Thank you in advance.
Upvotes: 2
Views: 914
Reputation: 21562
This line: mov rcx, al
is not valid, since there is no encoding of mov
that has an r64
destination and an r/m8
source.
This line is redundant anyway:
mov al, 'c'
mov rax, 122
The al
partial register is an alias for the least significant byte of the register rax
. You are overwriting the 'c'
with 122
immediately after the next line. If you intend to copy just the 'c'
to rcx
, you could use the movzx
instruction, which zero-extends into the full destination from the r/m
source:
mov al, 'c'
movzx ecx, al ; upper 32 bits are zeroed too
Fortunately, unlike its 32-bit predecessor, x86_64 has a few more GPRs that you can use (r8
to r15
). Use some of those for the arithmetic with 122
and 97
to implement your cipher.
Upvotes: 1
Reputation: 365637
If you want to zero- or sign-extend a byte into a 64-bit register, use movzx ecx, al
or movsx rcx, al
respectively.
Note that you were getting "invalid combination of opcode and operands" when assembling, before there's any machine code to execute. That's because you picked a mnemonic (mov
) that has no valid encoding for those operands.
(122-char) + 97
= 122+97 - char
which is trivial to implement. 122+97 = 219 which is still only 1 byte, so you could use 8-bit operand-size if you wanted to.
;; input in EAX or AL
;; result in ECX or CL
mov ecx, 'z'+'a' ; let the assembler do the math with ASCII constants
sub ecx, eax
Or in one register with worse latency:
sub al, 'z'+'a' ; c - 219
neg al ; 219 - c
Upvotes: 3