0

I have a question on the AND instruction in 64-bit mode. I have this manual telling me that the AND 32-bit immediate is to be sign-extended to 64-bit. But I can't do this

and rax,0x80000000

Which is ridiculous I think because 0x800000 is a perfect DWORD operand. The highest I can go with it is

and rax,0x7fffffff

So what's happening here? I can't use MSb=1 to sign-extend an operand? If so, then how's sign-extension is supposed to work against an operand without being able to use it as in 0x80000000?

Thanks for you replies.

phuclv
  • 37,963
  • 15
  • 156
  • 475
royalfinest
  • 155
  • 1
  • 8
  • 2
    You can't encode `0x80000000` as that would be sign extended to `0xffffffff80000000`. You can however use `and eax, 0x80000000` to achieve the required effect given that 32 bit operations zero the top bits. – Jester Nov 19 '18 at 21:36
  • I don't get it. It's a 64-bit operation anyway. Why can't 0xffffffff80000000 work? – royalfinest Nov 19 '18 at 21:37
  • That **does** work but that's obviously not `0x80000000`. – Jester Nov 19 '18 at 21:38
  • So in a way of saying it, I can only use +positive immediate operand? – royalfinest Nov 19 '18 at 21:39
  • Since it's sign extended you can use negative too but you need to specify them as negative. Depends somewhat on your assembler. – Jester Nov 19 '18 at 21:46
  • Thanks jester. I am not actually questioning your replies. I am more concern about the misleading information from the manual. By not allowing sign-extension to work properly against an operand, then the manual shouldn't simply say "sign-extend the 32-bit operand to 64-bit" because from what I know, that's not how sign-extension work. If "sign-extension" in AND entry implies different meaning that what is written in MOVSXD/MOXSX "sign-extension" entry definition, then ... I don't know what to say. LOL. – royalfinest Nov 19 '18 at 21:52
  • 1
    It's exactly the same thing. Of course `movsx` does not take an immediate so you can't really compare. The point is `0x80000000` as an operand is sign extended to `0xffffffff80000000` which makes it no longer equal to `0x000000080000000` that you have written hence most assemblers don't allow it. If you write it as `-2147483648` that will be encoded as `0x80000000`. – Jester Nov 19 '18 at 22:02
  • Jester, have you looked into the AND 0x7ffffffff encoding? If you look at it then you'll know that there's nothing wrong with AND 0x80000000 either. There's no wrap-around no nothing that should limit it to just positive operand. It's a perfect 6-bytes 64-bit encoding with REX and stuff. I don't know, I could be missing something obvious here. Too much chemicals. – royalfinest Nov 19 '18 at 22:16
  • 5
    There is nothing wrong with `0x80000000` in the machine code but that means `0xffffffff80000000` due to sign extension. To avoid the possible confusion of writing `x` but getting `y` the assemblers don't allow that. As I said, you **can** get that output if you write `-2147483648`. – Jester Nov 19 '18 at 22:19
  • 4
    @royalfinest - `and rax,-0x80000000` should also work. – rcgldr Nov 19 '18 at 22:36
  • Not quite a duplicate of [addq with 64bit immediates?](https://stackoverflow.com/q/23762332) since this question realizes that the immediate is only a dword, but not realizing it needs to be a value such that `i == (int32_t)i`, i.e. one that can fit in a *sign-extended* 32-bit immediate. Assemblers work with values, not encodings, that's why we use them. (Some assemblers do truncate and warn, like NASM would I think stuff that `0x80000000` into the sign-extended dword immediate, encoding `and rax, 0xffffffff80000000`.) – Peter Cordes Jun 15 '22 at 01:14

1 Answers1

0

“by preventing people from doing something stupid, you might prevent them from doing something clever”: an attitude born of respect and humility; you don’t know all the answers, so don’t impose random stupidity like Jester pointed out in the comments.

fwiw, gcc / gnu as understands:

and $0x80000000, %rax

clang, religiously infused, insisted upon:

and $0xffffffff80000000, %rax

now, quick, are there enough f’s there? Does this help readability? If you don’t understand sign extension, how much assembly are you going to understand anyways?

mevets
  • 10,070
  • 1
  • 21
  • 33
  • GAS (GNU assembler (GNU Binutils) 2.36.1) correctly rejects `and $0x80000000, %rax` with `Error: operand type mismatch for 'and'`. So does GAS 2.25.1. What version are you using? – Peter Cordes Jun 15 '22 at 01:12