I'm learning x86 assembly language and have no idea how to print negative integer using Irvine32 library.
INCLUDE Irvine32.inc
.data
arry SWORD 10, -20, 30
.code
main PROC
mov eax, 0
mov esi, OFFSET arry
mov ax, SWORD PTR [esi]
add esi, TYPE arry
add ax, SWORD PTR [esi]
call WriteInt
exit
;call DumpRegs
main ENDP
end main
The result I was expecting is -10 but the console printed +65526. I don't know how WriteInt functions works but seems like it recognizes the value in ax as unsigned value.
If I modify my code like this, then WriteInt function gives me proper result.(-10)
...
mov eax, 10
sub eax, 20
call WriteInt
...
I want to read data from memory and add or subtract integers. If I want to print as signed integer how can I?
movsx eax, SWORD PTR [esi]
to sign-extend it into a dword register for WriteInt.WriteInt always looks at the whole 32 bits, and the 32-bit number you gave it (with bit-pattern
0x0000fff6
), interpreted as 32-bit 2's complement, represents a positive number.If there was a WriteShort function, you could call it and it would look at bit #15 instead of bit #31 to decide if the number was negative, but there's no need for one when we can just sign-extend up to a full register.
Notice the
mov eax,0
you used before loading AX: you are explicitly zero-extending by doing that, as an inefficient way to emulatemovzx eax, word ptr [esi]
. (If you didn't do that, the high 16 bits of EAX would hold whatever garbage was there from the code that called main.)There are other ways to do 2's complement sign-extension, i.e. copy the sign-bit of a number to higher bits of the full register. For example,
cwde
after already loading into AX, or evenshl eax, 16
/sar eax, 16
. But MOVSX is the most efficient when you don't already have the narrow value in a register.Or with a 16-bit add result in AX,
cwde
is just a more efficient way to writemovsx eax, ax
.(Fun fact: CWDE is the 32-bit version of an instruction that dates back to 8086. Before 386, you could only sign-extend efficiently with your number in AL or AX, not from anywhere to any register.)
To avoid the possibility of signed overflow in the add, you may want to
movsx
both inputs before add. e.g. this makes it possible to get 0x7fff + 0x7fff = 0x0000fffe, 65534.Not 0xfffffffe, aka -2, which you'd get if you sign-extended after a 16-bit add of two positive numbers overflowed to produce a negative result.
(The sum or difference of two n-bit numbers takes at most n+1 bits to represent exactly, so widening at all makes overflow impossible. To overflow a 32-bit sum, you'd have to add about 2^16 words.)