RISC-V Assembly Language - Binary to BCD to Binary

Use 32-bit or 64-bit architecture.

Definition: Binary-Coded Decimal (BCD)

A system of writing numbers where each decimal digit (0 through 9) is represented by its own 4-bit binary equivalent
(for example, decimal 51 becomes 0101 0001 in Binary-coded decimal - Wikipedia).

Project #13a

Why does BCD exist? What is it used for?

Project #13b

Write and test several functions:

  1. convert a binary positive integer to packed BCD
  2. convert a positive packed BCD integer to binary
  3. given a positive BCD packed integer, print it on the terminal (in decimal)
    (printing positive binary integers is a RARS syscall)

You will need to create several test values for this project.

Make the displayed information "pretty".

Design Thoughts

At first glance, this problem seems to require lots of bit-pattern masking and shifting.

The BCD Format For This Project...

Packed or Unpacked BCD

Us packed BCD for this project.

Big-endian or Little-endian BCD

Use little-endian for this project to be consistent with RISC-V binary numbers.

Variable Length or Fixed length BCD

Use the variable length, sign terminated BCD format for this project.

For more detailed information about the BCD format to use, click HERE .

BCD Sign Nibble (yes or no)

Each BCD number must have a sign nibble. (See the above tables.)

BCD

This information was extracted from (Wikipedia) and other sources.

Packed vs Unpacked BCD

In byte-oriented systems (i.e. most modern computers), the term unpacked BCD usually implies a full byte for each digit (often including a sign), whereas packed BCD typically encodes two digits within a single byte by taking advantage of the fact that four bits are enough to represent the range 0 to 9.

As an example, a 4-byte value consists of 8 nibbles, wherein the upper 7 nibbles store the digits of a 7-digit decimal value, and the lowest nibble indicates the sign of the decimal integer value. Standard sign values are 1100 (hex C) for positive (+) and 1101 (D) for negative (−). Most implementations also provide unsigned BCD values with a sign nibble of 1111 (F).

Because computers deal with data in 8-bit bytes, it is possible to use one of the following methods to encode a BCD number:

For example, in packed BCD the number 127 is represented by 0001 0010 0111 1100 (127C) and −127 is represented by 0001 0010 0111 1101 (127D).

"8421" Encoding
Decimal
Digit
BCD
8 4 2 1
00 0 0 0
10 0 0 1
20 0 1 0
30 0 1 1
40 1 0 0
50 1 0 1
60 1 1 0
70 1 1 1
81 0 0 0
91 0 0 1
"8421" Encoding
Sign
Digit
BCD
8 4 2 1
SignNotes
A1 0 1 0+ 
B1 0 1 1− 
C1 1 0 0+Preferred
D1 1 0 1−Preferred
E1 1 1 0+ 
F1 1 1 1+Unsigned

Fixed vs Variable Length BCD

Variable-length packed BCD (Binary Coded Decimal) is a numeric data format used in computing, databases, and mainframes to store numbers with high precision without rounding errors. Unlike standard fixed width packed BCD, variable-length BCD dynamically scales its size based on the magnitude and precision of the number being stored.

Here is a breakdown of how the format works, its structure, and its trade-offs.

Core Architecture & Layout

In a standard packed BCD format, each byte is split into two 4-bit nibbles, with each nibble representing a single decimal digit (0 through 9) using standard binary encoding (0000 to 1001).

A variable-length implementation adds mechanisms to track the length, the sign, and the decimal point position dynamically. It generally follows one of two primary structural patterns:

  1. Length-Prefixed Format (Common in Databases like Oracle)

    • Byte 1 (Header/Exponent): Stores the length of the data, the sign bit, and an exponent (which determines the decimal point position).

    • Bytes 2 to N (Mantissa): The actual packed BCD digits.

    • Termination: No terminator is needed because the system reads the exact number of bytes specified in the header.

  2. Self-Terminating Format (Common in Data Serialization)

    • Bytes 1 to N-1: Pairs of decimal digits.

    • Final Byte: Contains the last digit in the high nibble and a sign/termination indicator (like 0xC for positive or 0xD for negative) in the low nibble. The system detects the end of the variable-length stream by scanning for this sign nibble.

  3. Length Delimitation: Because the length is variable, systems use one of a few methods to know where the number ends:

    • Length-prefixed: A header byte or count field specifies how many digits or bytes follow.

    • Terminated / Sign-nibble markers: Special trailing nibbles (such as 0xC or 0xF in legacy mainframe/COBOL packed decimals) indicate the sign (positive/negative) and act as an explicit end marker.

    • Dynamic Buffers: APIs (such as compiler built-ins or BCD data types) manage contiguous arrays of variable length dynamically up to a defined ceiling (e.g., 31 digits or unlimited size depending on the runtime).

Direct Comparison: Fixed vs. Variable-Length BCD

Feature Fixed-Length Packed BCD Variable-Length Packed BCD
Storage Size Fixed size (e.g., always 8 or 16 bytes). Dynamic size (grows or shrinks with the number).
Trailing/Leading Zeros Padded with zeros to fill the
fixed buffer.
Stripped away to conserve memory.
Decimal Alignment Fixed scale/precision set at
database/code level.
Floating decimal point managed via an
internal exponent.
Memory Efficiency Low for small numbers; wastes space. High; only uses bytes necessary for the
digits present.
Parsing Speed Faster (fixed offsets, no length checks). Slower (requires checking headers or
looking for termination nibbles).

Why and Where It Is Used

Variable-length packed BCD is heavily used in environments where exact decimal math is required, and memory footprint must be minimized across millions of records.

Links

Binary-coded decimal (Wikipedia)

Binary Coded Decimal (geeks for geeks)

Densely packed decimal (Wikipedia)