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.

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.

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.

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.

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?

`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.

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.

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