Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Storing numbers and text as bits

After this lesson: I can store numbers and text as bits.

55 min lesson11 commandsCompilers and computer architecture lab: gcc, flex, bison and RISC-V in one VM

The shelf that held 255 boxes

A warehouse program counts the boxes on each shelf. One evening a worker takes a box from a shelf the program thinks is empty.

The screen now says the shelf holds 255 boxes. Nothing is broken. The program stored -1 the only way it could, as eight bits, and the screen read those bits as a plain number.

By the end of this lesson

Note

I can store numbers and text as bits.

Key words

WordWhat it meansExample
Bitone binary digit: 0 or 1
Byteeight bits, the unit memory is counted in
Binarywriting numbers with only the digits 0 and 111001000
Hexadecimalbase 16, one digit for every four bits0xc8
Two's complementthe usual way to store negative whole numbers in bits
Character codethe number that stands for one letter or sign65 for A

The cells students fill in are left blank in this preview.

Binary counts in twos

In ordinary numbers each place is worth ten times the place to its right. In binary each place is worth twice as much.

Eight places, one byte, are worth 128, 64, 32, 16, 8, 4, 2 and 1. Add the places that hold a 1. So 11001000 is 128 + 64 + 8, which is 200.

Worked example: 200 in one byte

Place value1286432168421
Bit11001000
Counts12864008000

The cells students fill in are left blank in this preview.

Go to the architecture folder

Command
cd ~/arch

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Ask Python for three conversions

Command
python3 -c "print(bin(13), hex(255), int('1101', 2))"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

The shell writes hexadecimal too

Command
printf '%d %x\n' 200 200

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

One hex digit is four bits

Hexadecimal has sixteen digits: 0 to 9, then a to f for ten to fifteen. Each hex digit stands for exactly four bits.

So a byte is always two hex digits. 200 is 1100 1000 in bits, which is c then 8, written 0xc8. Tools that show memory or machine code use hex because it is short and still lines up with the bits.

Negative numbers use the top bit

A byte has no minus sign. Two's complement makes the top bit worth -128 instead of 128. The other seven bits keep their usual values.

So 11111111 is -128 + 127, which is -1. And 10000000 is -128 on its own. To write a negative number, add 256 and write the result as a plain byte: -5 becomes 251, which is 11111011.

Worked example: one byte read two ways

BitsRead as unsignedRead as two's complement
0000010155
01111111127127
10000000128-128
11111011251-5
11111111255-1

The cells students fill in are left blank in this preview.

Write a RISC-V program that subtracts

Command
printf '.globl _start\n_start:\n  li a0, 2\n  li a1, 3\n  sub a0, a0, a1\n  li a7, 93\n  ecall\n' > minus.s

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Assemble it

Command
riscv64-linux-gnu-as minus.s -o minus.o

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Link it

Command
riscv64-linux-gnu-ld minus.o -o minus

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Run it on the emulator

Command
qemu-riscv64 ./minus

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Read the exit status

Command
echo $?

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A common mistake

Warning

Many people think the bits themselves say whether a number is negative. They do not. The program worked out 2 - 3 and left -1 in a0. Linux kept the low eight bits, 11111111, and the shell read them as unsigned: 255. The same bits mean -1 or 255 depending on who reads them.

Text is numbers too

A computer stores a letter as its character code. A is 65 and a is 97. The first 128 codes are the same in every common scheme.

UTF-8 stores those 128 in one byte each. Every other character takes two to four bytes. The letter é is code 233, and UTF-8 stores it as the two bytes c3 a9. So a word's length in bytes is not always its length in letters.

Character codes and UTF-8 bytes

Command
python3 -c "print(chr(233).encode('utf-8'), ord('A'), ord('a'))"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Fractions are stored approximately

A fraction such as 0.1 is stored as floating point: a sign, a power of two and a fraction, 64 bits in all. Most decimal fractions cannot be written exactly in powers of two, just as one third cannot be written exactly in decimals.

So 0.1 + 0.2 is very close to 0.3 but not equal to it. Never test money or counts with == on floating point.

Add 0.1 and 0.2

Command
python3 -c "print(0.1 + 0.2)"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

The bytes of 1000, smallest first

Command
python3 -c "print((1000).to_bytes(4, 'little').hex(' '))"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Going further: widening a number

Write -20 in 8 bits by hand. Then write it in 16 bits. Compare the two: what has happened to the eight new bits on the left?

Check both with your to_bits function. Then say what a processor must do when it loads one signed byte into a 64-bit register.

About this lab and its source: Compilers and computer architecture lab: gcc, flex, bison and RISC-V in one VM

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.