flat assembler
Message board for the users of flat assembler.

 Index > Main > Signed integers?
Author
Tabaci

Joined: 26 Apr 2018
Posts: 6
Location: Sweden
Tabaci
As far as I've understood it, integers are unsigned by default; I haven't managed to get around that yet. What I remember from an x86 Assembly class, is that a signed integer is the "two's complement?" of any given unsigned integer. Then, once you have that signed integer, you would use the `imul` and `idiv` instructions to multiply and divide it, howbeit `add` and `sub` would work like they normally do.

After doing some research on the web, I've seen some people stating that no conversion is necessary at all. But when I attempt to write a number preceded by a `-` and then print it out with the C interface's `printf` function utilizing the `%d`, `-1` turns into `255`. Frankly, for an unsigned integer that would make impeccable sense.

Code:
```; I'm making a very basic compiler; that's why it's pushed onto the stack first
; the `-12` might need to be treated in the form of an equation
push -12
pop eax
```

Is there an instruction to convert an unsigned integer into a signed integer? Is it already a signed integer; do I need to treat it differently in the code if I'm to use it as a signed integer?

Best regards,

_________________
My sandwich: it was reduced to dust, I tell you. It was pulverized!
15 May 2018, 07:48
revolution
When all else fails, read the source

Joined: 24 Aug 2004
Posts: 18629
revolution
In assembly all register values are just numbers. There is no notion of signed or unsigned. It is up to the program to determine how that number is treated. Some instructions can treat a number as signed (like imul and idiv) and others treat it as unsigned (mul & div). And other instructions are agnostic (add & sub).

When you want to convert a number to decimal as a string, then you have to tell printf how to treat the number. Something like %d/%u/%i will tell printf how you want the number printed.
15 May 2018, 08:20
Furs

Joined: 04 Mar 2016
Posts: 1820
Furs
Tabaci wrote:
Is there an instruction to convert an unsigned integer into a signed integer? Is it already a signed integer; do I need to treat it differently in the code if I'm to use it as a signed integer?
255 is a signed 8-bit integer, but printf expects a 32-bit arg (or 64-bit if x64).

-1 as 32-bit is not 0x000000FF -- that's 255, as you got. You need to "propagate" the sign bit of the 8-bit int over all the higher bits, this is called "sign extension", and there is an instruction to do it:
Code:
`movsx eax, al    `
Converts 0x000000FF to 0xFFFFFFFF, which is -1.

There's also zero extension (for unsigned numbers) where the higher bits are simply set to zeros, not the former sign bit's value. That's movzx.

Of course, nothing stops you from using movzx on a "signed" integer, you just won't get what you expect, but it's perfectly valid, there's no such thing as "signed" integer type for the CPU, just instructions performing sign-extension, zero-extension, or whatever.
15 May 2018, 12:20
DimonSoft

Joined: 03 Mar 2010
Posts: 1029
Location: Belarus
DimonSoft
revolution wrote:
In assembly all register values are just numbers.

A tiny correction: any values are not even numbers but just sets of bits grouped/accessed together. Signed/unsigned, number/character/handle/color/float — all of these are just ways to interpret values formed by such bits.
15 May 2018, 19:01
rugxulo

Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo
Tabaci wrote:
As far as I've understood it, integers are unsigned by default;

Sometimes the term "integer" is misused.

Wikipedia wrote:

An integer (from the Latin integer meaning "whole") is a number that can be written without a fractional component. For example, 21, 4, 0, and −2048 are integers, while 9.75, ​5 1⁄2, and √2 are not.

Old K&R C didn't barely have unsigned (except for int?), but eventually that was allowed for various ordinal types. J&W Pascal was only integer and subranges thereof. Modula-2 added CARDINAL (unsigned) because it was originally a 16-bit implementation, and that was needed for addressing. But it complicated type compatibility, so when Oberon was introduced, since it was 32-bit, they went back to INTEGER (also SHORTINT, LONGINT) "type inclusion" to simplify things again. I think newer Oberon-07 might sometimes have some unsigned stuff in SYSTEM pseudo-module.

Tabaci wrote:

After doing some research on the web, I've seen some people stating that no conversion is necessary at all. But when I attempt to write a number preceded by a `-` and then print it out with the C interface's `printf` function utilizing the `%d`, `-1` turns into `255`. Frankly, for an unsigned integer that would make impeccable sense.

Probably some b.s. regarding unary operator or such. Make sure you're using the right format string syntax (see here).

(Frankly, this is one of several things that Pascal and derivatives don't have a problem with, their data typing is stricter.)

Tabaci wrote:

Is there an instruction to convert an unsigned integer into a signed integer? Is it already a signed integer; do I need to treat it differently in the code if I'm to use it as a signed integer?

old NASM 0.98.39 doc wrote:

B.4.181 `MOVSX', `MOVZX': Move Data with Sign or Zero Extend

MOVSX reg16,r/m8 ; o16 0F BE /r [386]
MOVSX reg32,r/m8 ; o32 0F BE /r [386]
MOVSX reg32,r/m16 ; o32 0F BF /r [386]

MOVZX reg16,r/m8 ; o16 0F B6 /r [386]
MOVZX reg32,r/m8 ; o32 0F B6 /r [386]
MOVZX reg32,r/m16 ; o32 0F B7 /r [386]

`MOVSX' sign-extends its source (second) operand to the length of
its destination (first) operand, and copies the result into the
destination operand. `MOVZX' does the same, but zero-extends rather
than sign-extending.
15 May 2018, 21:07
Furs

Joined: 04 Mar 2016
Posts: 1820
Furs
Ok, my previous post is a bit confusing when you think about C's "types", so here's a more detailed explanation.

When you use an unsigned char type (8-bit unsigned integer), the compiler assumes that the value stored in there is unsigned. So 0xFF means 255, not -1.

When you pass it to printf, it needs to convert it to 32-bit because that's what printf expects. So it converts it with movzx because it assumes 0xFF means 255, since you told it it's unsigned. Even if you place -1 in that variable, it is 0xFF, but the compiler will assume it's unsigned so 0xFF = 255, therefore convert it with movzx (i.e. 0x000000FF, zero extended).

It's all about what the compiler does with the type you gave it. The type is just information to the compiler about the uses for that variable.

The only difference if you make it signed, in this case, is the compiler will use movsx instead. You can also cast it on the spot, i.e. printf("%d", (signed char)x); will print -1 if x was 0xFF, because compiler will now generate movsx instead.

BTW, same with comparisons where sign matters: a < b converts to signed comparison only if a's type is signed.
16 May 2018, 20:21
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First

 Jump to: Select a forum Official----------------AssemblyPeripheria General----------------MainTutorials and ExamplesDOSWindowsLinuxUnixMenuetOS Specific----------------MacroinstructionsOS ConstructionIDE DevelopmentProjects and IdeasNon-x86 architecturesHigh Level LanguagesProgramming Language DesignCompiler Internals Other----------------FeedbackHeapTest Area

Forum Rules:
 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot vote in polls in this forumYou cannot attach files in this forumYou can download files in this forum