I'm on day 3 of Learn ASM in 28 Days and I'm confused when it says this:

Storing negative numbers, however, is legal, but the number will get "wrapped" to fit. For example, if you assign -1 to A, it will really hold 255. If you assign -2330 to BC, it will really hold 63206. Adding one plus the maximum value the register will hold gives you the value that will be stored.

I understand the wrap part, but the last sentence doesn't make any sense. If A can hold 255, then one more is 256. But if you have -3 for instance, it stores 253, which is not 256. Why does it say that?

If you were making a CPU, how would you store negative numbers? The way preferred on the Z80 (and most other CPUs you'll find today) is called

two's complement.

The way the wrapping works, 0 = 256.

So -1 = 255, -2 = 254, -3 = 253.

This is obvious if you write them out in binary. 256 = 100000000b, which has the 9 bits, however the register only has 8 bits, so it is truncated to 00000000b.

for 256 wouldn't you need two registers though?

And, unless I'm very confused, I don't think you see what i was inquiring about. It says it wraps but then it contradicts itself and says it's always the value a register can store + 1.

**MrIdrik wrote:**

for 256 wouldn't you need two registers though?

Yes, that's why I said "truncated to 00000000b".

**Quote:**

And, unless I'm very confused, I don't think you see what i was inquiring about. It says it wraps but then it contradicts itself and says it's always the value a register can store + 1.

The formula for 2s complement negative numbers is that to negate a number, n, you store it is (~n)+1, where ~ is the bitflipping operation. (i.e. ~1001 = 0110). Everything is modulo 256 when you have an 8 bit register, which is "the largest number it can store + 1", but modulo that means you all numbers must be less than it.
It means add one plus the max value [to the value you're storing]. -3+1+255=253.

If it helps, negative numbers in z80 ASM are entirely a function of how you interpret them. $FF can be -1 or 255, depending on what you want it to be.

Yeah, it's confusingly written. It's saying that if you write "LD A,-3", the value stored in A is -3 plus (255 + 1), which is 253. But this addition is done by your assembler, not in the Z80 CPU itself - as far as the Z80 is concerned, -3 and 253 are the same number.

Fixing the way that ASM in 28 Days discusses negative numbers is one of the things at the top of my list for if (when?) I ever get around to making a 3.0 of the guide, after fixing the interrupt chapter, adding TI-84+ and TI-84+CSE information, updating the assembler/editor instructions, and tossing in a lot more sample code and programs.

Thanks to everyone for all the replies. It's more clear to me now. So basically, I don't even have to convert negative numbers to positive myself?

And one more thing, could someone explain this to me:

It turns out that there are many signed numbering schemes, but the only one we're interested in is called the two's complement. When we have a signed value in two's complement, the most significant bit of the number is termed the sign bit and its state determines the sign of the number. The existence of the sign bit naturally imposes a restriction on the number of bits a number may be composed of. With this, the amount of bits at our disposal to represent the number is reduced by one; for a string of eight bits, we can have a numeric range of -128 to +127. For a string of sixteen, it's -32, 768 to 32, 767, etc.

So the most significant bit is the leftmost one, but I don't see how the sign bit restricts us. Does it take the place of the most significant bit? What even IS a sign bit (like, what does it look like). Someone above put a ~ to show it, so LD A,-3 would be 253, which is 11111100, and to show it is signed it would be ~11111100b? And if the assembler does it, when would I ever need to use it anyway?

~ for bitwise logic means invert. When you do ~1 in 8 bit, you get 254 (0b11111110), which is the 1's complement. Two's complement is: If the number is negative, invert then add one.

-3 is 253, but it is not 0b11111100 in 2's complement, that is one's complement.

For your confusion on the sign bit, look at a two's complement 8-bit number:

S|NNNNNNN

You have 7 bits worth to make numbers, essentially. For positive, you have 0 (0000000) to 127(1111111). This is when the sign bit is 0.

When the sign bit is 1, then you have negative numbers (essentially flips and shifts a number line). -1 is (1111111) (two's complement of -1 goes ~0000001 -> 1111110+1 -> 1111111) and -128 (1111111).

<edit> Made post about numbers and not very nice bits

So the sign bit is just a number?

If a 1 is the most significant bit, it's negative, and when 0 is the most significant bit, it's positive?

-3 is 253, but it is not 0b11111100 in 2's compliment, that is one's compliment.

Why is there is a 0 in front, is that the sign bit? Wouldn't the b go at the end? And how is it not Two's Complement? It says this on the site which is what I did:

Calculate zero minus the number (like negative numbers in the Real World). If you're confused how to do this, you can consider 0 and 256 (or 65536 if appropriate) to be the same number. Therefore, -6 would be 256 - 6 or 250: %11111010.

0b is just notation saying that you have a binary number, just as 0x is for hex and 0 is for octal.

About the 253, the binary number is wrong, 253 is 11111101

Oh, right, so %11111101 is indeed -3?

So I accidentally wrote it wrong and it happened to be one's complement?

I'm still confused about what a sign bit actually is:

**Quote:**

So the sign bit is just a number?

If a 1 is the most significant bit, it's negative, and when 0 is the most significant bit, it's positive?

More asm learners!

One's complement is essentially an "xor $FF", meaning every bit in the byte is inverted. The one's complement of 1 would be:

%0000 0001

%1111 1111 (XOR)

----------------

%1111 1110

This is equivalent to -2. Two's complement adds one to this value: %1111 1111 (or -1).

Think about it this way, an 8-bit number can only hold values from 0-255. If you're at 0 and subtract 1, it will wrap to 255. So 0-1 = -1=255=%1111 1111.

The sign bit is the leftmost bit. Every negative number (represented in binary) will have a 1 in the very leftmost bit, so negative numbers go from %1111 1111 (-1 aka 255) to %1000 0000 (-128 aka 128). Positive numbers go from %0000 0000 to %0111 1111.

I think I've got it now, thanks everyone.