1

I've been stuck on a rather simple instruction, but everything in assembly only seems simple until I try to really understand it haha. I've paid attention to this post which clarifies some stuff but I'm still confused: Understanding intel SUB instruction

Here is a super simple situation:
Two strings are sent to function for comparison. I stripped down to keep the essentials.

function:
    mov al, [rdi]   ; == 0
    sub al, [rsi]   ; == 32
    ret             ; returns 224 and not -32 like I would like

I am guessing I need to check the overflow flag right after the sub instruction if it's on, then my result is negative. Or maybe the sign flag, more logically (both seem right in this case ?)

From that, I would need to subtract 256 to rax to make it -32 before returning... But it seems a little weird to me, there is got to be a cleaner way?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Bstorm
  • 247
  • 1
  • 10
  • 3
    Have a look at [Two's complement](https://en.wikipedia.org/wiki/Two%27s_complement). 224 and -32 are the same bit pattern. – zx485 Jun 13 '20 at 20:57

1 Answers1

3

The 8-bit values 224 and -32 are the same on x86 and x86-64, since it uses two's complement to represent negative numbers. Subtracting 256 wouldn't help you. It's up to the caller of the function to choose to interpret the result as signed (-128 to 127, in which case it's -32), or unsigned (0 to 255, in which case it's 224). I assume you're asking this because your code that calls this function is interpreting it wrongly. This could happen if you accidentally used movzx on the result instead of movsx to extend it, or worse, if you used ax, eax, or rax without extending it first (in which case you could end up with complete garbage like 0x11223344556677e0).

  • Thanks @Joseph Sible-Reinstate Monica indeed I get that it's the same binary representation, I just needed to "sign" it I guess, and yes you mentioned the right instruction for my situation, movzx solve it. Thank you so much I've been looking for this instruction all day ;) – Bstorm Jun 13 '20 at 21:13
  • @Bstorm You mean `movsx`? – Joseph Sible-Reinstate Monica Jun 13 '20 at 21:15
  • oops yes sorry typo. – Bstorm Jun 13 '20 at 21:17
  • Just, when you say extend it, you mean basically setting the whole register to zero by using mov rax, 0 ? Or am I missing something ? – Bstorm Jun 13 '20 at 21:19
  • @Bstorm There's two ways to extend a value: zero-extending and sign-extending. That's what `movzx` and `movsx` do. Doing `mov rax, 0` is not extending anything. – Joseph Sible-Reinstate Monica Jun 13 '20 at 21:20
  • Just to make sure I get how movsx works, after trying a few things: it's only thanks to the SF that it decides if it pads with 1 or 0 in order to give the sign ? – Bstorm Jun 13 '20 at 21:34
  • 1
    @Bstorm No, it has nothing to do with the sign flag. It decides based on the most significant bit of the input. It just looks like it's related to the sign flag because after `sub al, [rsi]`, the sign flag and the most significant bit of `al` happen to be the same. If you did something else to clear the sign flag in between the `sub` and the `movsx`, it would still pad a negative result with 1s. – Joseph Sible-Reinstate Monica Jun 13 '20 at 21:41
  • Great, I got a little deeper thanks to this post : https://stackoverflow.com/questions/56565510/x86-what-does-movsxd-rdx-edx-instruction-mean I start to wrap my head around the concept :) Thanks for the help. – Bstorm Jun 13 '20 at 21:58