Binary Coded Decimal

z80 » Variables

As I explained in the Variable Manipulation section, the OP_ Registers are also used to store Binary Coded Numbers (BCD) for use with math routines.

The OP_ Registers are 11 bytes long. They store what are called Floating Point Numbers (the decimal point is not in a fixed position). When you are putting variable's names into the OP_ Register, you usually use all 11 bytes; however, when you are using the OP_ Registers for BCD numbers, you only use the first 10. The last byte doesn't matter.

The first 10 bytes are broken up into three different parts:

	.db type/sign
	.dw exponent relative to $fc00
	.db BCD number for 7 bytes

Type and Sign

The first byte is broken up into two things.
  1. If bit 7 is set the number is negative,
  2. if bit 7 is reset the number is positive.
  3. If bit 0 is set the number is complex,
  4. if bit 0 is reset then it's a real number
So there are only 4 possible combinations of numbers and what they look like.
  1. $00 positive real number
  2. $80 negative real number
  3. $01 positive complex part of a number
  4. $81 negative complex part of a number

Exponent

The next two bytes (second and third) of the OP_ Register are the exponent bytes. Remember that the z80 works by storing an address, say for example $1234, backwords as $3412 in the memory. This is called Little Indian or something. This applies to these next two exponent bytes. They are stored $fc00 as $00fc. This is kinda weird and took me a while to get used to how the number $fc00 has anything to do with the exponent. When you consider exponents ([number]*10^[exponent]) you have to probably switch to Scientific Mode on your calculator to refresh yourself on how numbers are represented in Scientific Notation. The number 1,234,567 would be 1.234567E6 in Scientific Notation.

Let's do a quick review of Scientific Notation. When you have a number that is normal, you move the decimal point to the left or right until you've only got one digit before the decimal point (which has to be between 1 and 9), then you count how many decimal places you had to move it over to get there...that number is positive if you moved the decimal place to the left...negative if you moved it to the right. The number of places you moved the number to the right or two the left is the exponent on the 10. The remaining decimal number is put before the 10 to the [exponent] power.

Normal Scientific
12345 1.2345E4
1.2345 1.2345E0
12.345 1.2345E1
0.12345 1.2345E-1
0.012345 1.2345E-2
5364 5.364E3
-0.6562 -6.562E-1
0.00090009 9.0009E-4
90009000 9.0009E7

The decimal number that is before the E is called the mantissa, the part on the other side is called the exponent or the power. $fc00 is used as the "zero" for the exponent, everything is relative to that. You add whatever exponent you want to $fc00. Here's the simple formula where X is the number relative to $fc00 and P is the power you are wanting to use:

$fc00+P=X

So, a power of 1 is $fc01, a power of 0 is $fc00, a power of -1 is $fbff, a power of 3 is $fc03, and a power of -3 is $fbfd. Practice with that or something. Remember that it is stored backwards, so $fbfc as a result would be stored in memory $fcfb.

Binary Coded Decimal

The next 7 bytes of the OP_ Register (remember the 8th byte which isn't used) are used to store a number in BCD. This is simpler than it sounds. The number 123456 is stored as $12,$34,$56 (or 12 34 56). The number 4521345323 (or broken up as 45 21 34 53 23) would be stored as $45,$21,$34,$53,$23 in memory. It's so simple that I don't think you need specific examples for this.

Now that you know all the components of the Floating Point Number, let's put it all together in some examples in yet another table!

Sign Type Exponent BCD BCD BCD BCD BCD BCD BCD Normal Style
$00 $fc00 $12 $34 $56 $00 $00 $00 $00 1.23456
$00 $fc05 $12 $34 $56 $00 $00 $00 $00 123456
$00 $fc00 $12 $34 $56 $78 $90 $12 $34 1.2345678901234
$80 $fc01 $32 $98 $97 $40 $00 $00 $00 -32.98974
$80 $fc05 $56 $45 $89 $32 $33 $40 $12 -564589.32334012
$00 $fc00 $00 $00 $00 $00 $00 $00 $00 0
$00 $fc00 $10 $00 $00 $00 $00 $00 $00 1
$80 $fc00 $10 $00 $00 $00 $00 $00 $00 -1
$00 $fc0e $99 $99 $59 $99 $95 $99 $99 99995999959999
$00 $fbfc $23 $00 $00 $00 $00 $00 $00 0.00023
	.db $80
	.dw $fc00
	.db $10,$00,$00,$00,$00,$00,$00	; = -1

Real numbers take up 10 bytes to represent, complex numbers take up 20 bytes: the first 10 are for the real part of the number and the next 10 are for the complex part of the number. They use the same format that the ones above do for each part. The only difference is that if bit 0 is set it is complex. Bit 0 of the first byte of the real part and the first byte of the complex part will both be set if the number is complex. Remember that the TI86 displays Complex numbers in parenthesis: (Real part, Complex part). Here's how a complex number would be displayed like the above numbers.

Sign
Type
Exponent BCD BCD BCD BCD BCD BCD BCD Final Number
Real part $01 $fc00 $12 $34 $56 $00 $00 $00 $00 (1.23456,1.23456)
Complex part $01 $fc00 $12 $34 $56 $00 $00 $00 $00  
Real part $01 $fc01 $23 $46 $50 $00 $00 $00 $00 (23.465,-0.234)
Complex part $81 $fbff $23 $40 $00 $00 $00 $00 $00  
Real part $81 $fc02 $30 $04 $50 $00 $00 $00 $00 (-300.45,-0.03234)
Complex part $81 $fbfe $32 $34 $00 $00 $00 $00 $00  
	.db $01
	.dw $fc00
	.db $10,$00,$00,$00,$00,$00,$00
	.db $81
	.dw $fc00
	.db $10,$00,$00,$00,$00,$00,$00	; = (-1,1)

A good exercise you can do is to make a routine that will take a string pointed to be hl with length b and convert it into a BCD number in OP1. I saw an example of this by Joshua Seagoe called AtoF. It will help solidify your understanding of the format of these numbers. The AtoF routine takes a string with length b and changes it into a Floating Point BCD number in OP1.

  1. Find where the decimal point is and count left or right until you have the decimal in the right place.
  2. Add the number of places moved to $fc00 and store that.
  3. Put the digits in BCD through the rest of the OP1 register (any digits over the allowed 14 are left out).


More from z80 » Variables
Absolute Addressing // Binary Coded Decimal // Creating Variables // External Levels // _FindSym // Messing with Variable Data // OP Math // TI-OS Variable Manipulation // Variable Name Format // VAT Searches