0

The following code prints the value : -83396
The calculation I am doing here is Z2 = (var3 – var2 - 1000) + (var1 – 500)
So Z2 = (FFFF0000h - 4000h- 1000) + (24 - 500)
I am not sure how it turned out to be -83396? I am simply storing the values
in the registers for var2, var3 for calculation

.386
.model flat,stdcall
.stack 4096
ExitProcess proto,dwExitCode:dword

INCLUDE Irvine32.inc

.data
var1    byte    24
var2    word    4000h
var3    dword   0FFFF0000h
Z1    dword    ?
Z2    dword    ?
Z3    dword    ?
Z4    dword    ?

.code
main proc
xor eax,eax
xor ebx,ebx

mov eax, var3
movzx ebx, var2
sub eax, ebx
xor ebx,ebx
sub eax, 1000

xor ebx, ebx
movzx ebx, var1
sub ebx, 500
add eax, ebx
mov Z2, eax
call writeint




clc
invoke ExitProcess,0
main endp
end main
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
ravan
  • 37
  • 3
  • 1
    That's the right answer according to my calculator (using `(0xFFFF0000 - 0x4000- 1000) + (24 - 500) - 2**32` to wrap it into the signed-int range); what did you expect it to be? `FFFF0000h` is the 2's complement bit-pattern for `-65536`; perhaps you didn't know that? IDK what other reason you'd have to be surprised about the answer, so closing as a duplicate of a Q&A about that. – Peter Cordes Jun 11 '21 at 12:02
  • Also, you're not storing `var2` or `var3`, you're loading them *into* registers, as inputs. – Peter Cordes Jun 11 '21 at 12:05

1 Answers1

2

It's because your resultant value is being treated as a two's complement number.

The value ffff000016 as a two's complement number is -65,536. Subtract 400016 (16,384), then another 1,000. Then add 24 and subtract 500. This gives you -83,396, exactly what you're seeing.

But, even if they're all unsigned along the way, treating the result as a signed(1) gives you the same issue (these are all hexadecimal numbers except the ones in parentheses):

  ffff0000
-     4000  (16,384)
==========
  fffec000
-      3e8  (1,000)
==========
  fffebc18
+       18  (24)
==========
  fffebc30
-      1f4  (500)
==========
  fffeba3c

That final value, in 32-bit 2's complement, would be (all hex):

  - (100000000 - fffeba3c)
= - 145c4

And 145c416 is 83,396.


(1) One of the great features of two's complement is that the way bits are manipulated for adding or subtracting is exactly the same as for unsigned values of the same size.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • But `WriteInt` treats the result as signed int32_t, not an unsigned number; use Irvine32 `WriteDec` or `WriteHex` for that. (http://csc.csudh.edu/mmccullough/asm/help/index.html?page=source%2Firvinelib%2Fwritehex.htm) – Peter Cordes Jun 11 '21 at 12:22
  • 2
    Note that the only "treating as 2's complement" is happening during the printing. Everything else is zero-extending to 32-bit, or is already 32-bit. `add` and `sub` aren't "treating as 2's complement" in any way that makes a difference: you could equally describe the question's result as from just doing the unsigned math (including with one large input close to UINT_MAX), with wrapping to `uint32_t` register width, then taking that result as an `int32_t` by passing it to WriteInt. No "interpreting" or "treating" is happening until the printing step, other than FLAGS setting. – Peter Cordes Jun 11 '21 at 15:03
  • So it's the `writeint` that's giving the meaning of 2's complement to it and so what I understand is then none of the instructions assume anything to do with 2's complement etc. they simply add or subtract. Also what I thought is that subtraction is done like addition inside ALU. But it seems that is wrong the `sub` instruction internally does actual subtraction it seems and has the logic of borrowing n all. So when doing a `sub` the number won't get converted to a 2's complement form it will simply do a binary subtraction. Is that correct? – ravan Jun 11 '21 at 18:59
  • @ravan: You can't truly tell how the ALU works internally. The FLAGS (OF and CF) are set according to actual subtraction, with CF being a borrow output from the most significant bit. But an internal implementation that worked by adding `-x` (calculated as `~x + 1` if you want) would produce the same 32-bit binary result in the output register; remember that the output is always truncated to fit in the operand-size. **It doesn't matter how the bits got there (adding negative numbers vs. subtracting), just how you interpret them.** (Since you're not looking at the FLAGS bits). – Peter Cordes Jun 12 '21 at 01:26
  • 1
    @PeterCordes: good point on the "where is it treating it as signed?" question. Have updated the answer accordingly to hopefully make it clearer. – paxdiablo Jun 12 '21 at 02:25