Print Hex

Make the bytes in your computer show up on screen!

This page shows you how to take a byte of data and display its value as two hexadecimal characters on the screen. This lets you see the contents of memory or registers in a human-readable way. (Printing, itself, was covered by the previous page.)

Each hexadecimal digit is 4 bits (1 nibble), so to print AL, which is 1 byte, we'll print the left nibble and then the right nibble. Here's the plan:

  1. Set AH to 0x0E for printing
  2. Copy AL to BL so that we don't lose what's in it when putting the hex chars we wanna print in AL,
  3. Print the left nibble:
    1. Right-shift AL by 4 so that it stores just the value of the left nibble,
    2. Check if AL is between 0 and 9 or between 10 and 15; if it's between 0 and 9, we'll print an ASCII number, otherwise we'll print a letter (between A and F),
    3. ADD the appropriate number so that AL now stores the right ASCII character to print,
    4. Print AL (call BIOS print interrupt \cdDle)
  4. Copy BL back to AL, then
  5. Print the right nibble:
    1. AND AL with 0xF so that it stores just the value of the right nibble,
    2. Same steps as printing left nibble: (1) Check if AL is between 0-9 or higher, and (2) calculate the ASCII char to print automatically!

Quick Example

StepDescriptionALBL
1Set AH to 0x0E.0x??0x??
2If AL stores the value 0x48, then we want 48 to appear on the screen.0x480x??
3Copy AL to BL.0x480x48
4Shift AL to the right by 4 bits.0x040x48
5Convert the number in AL to a hex character.0x34 (ASCII character 4)0x48
6Call BIOS print.0x340x48
7Copy BL back to AL (now it has the original value again).0x480x48
8Do a logical and operation on AL to get rid of the upper nibble.0x080x48
9Convert the number to a hex char again.0x38 (ASCII character 8)0x48
10Call BIOS Print.0x380x48

Walkthrough

Setting Up

Setting up is pretty straightforward: AH needs to be set to Sho for printing, which can be done with \b4Sho, and then \8a\da to copy AL into BL:

\b4Sho\8a\d8

Next comes the code for printing the left nibble.

Printing Nibble 1

Our goal is to isolate one nibble, figure out which printable character it should become, and then put the corresponding ASCII code into AL.

Right now, the byte in AL has two nibbles jammed together: high nibble and low nibble. We want just the high nibble first, so we shift right by 4 bits. Example:

The effect of shifting a number right by 4 bits. Top: Hexadecimal, Bottom: Binary

But we can't just print this; we need to convert the number now in AL to the ASCII character corresponding to its hex digit. Luckily, the numerals in ASCII are sequential:

What gets printedByte in AL
00x30
10x31
20x32
...
90x39

So if the number in AL is between 0 and 9 then adding 0x30 to it will convert it to its ASCII character:

Eot0
Machine code for adding 0x30 to AL. Eot is the opcode for ADDing to AL, and 0 is the byte 0x30.

This works for each number from 1 through 9, but not for letters A through F; the letters A–F aren’t packed right after the digits 0–9 in ASCII. They're farther up, starting at 0x41 for A. What that means is that if you add 0x30 to the value 10 (0x0A), you won't get the ASCII value for A (you'll get 0x3A which is :).

The ASCII value for A is 0x41, so if the register has 0x0A in it, we need to add 0x37 to it, since:

0x0A + 0x37 = 0x41

Adding 0x37 moves values 10–15 (0x0A0x0F) into the correct spot in ASCII, starting from A at 0x41.

Distinguishing Between Digits and Letters

Since we need to handle 0–9 and A–F differently, I typically use a comparison (to check if it's 0–9 or A–F) and a conditional jump. The way that I implement this is:

This way, for values between 0–9, execution goes to the +0x30 instruction, whereas for values between A–F, execution goes to the +0x07, and then also runs the +0x30 instruction next.

Essentially, it's set up like this:

  1. Start off the idea that we'll need to add at least 0x30 to AL,
  2. But for A–F, first add 0x07 to "push" it up to where the letters are in ASCII,
  3. then add the 0x30 afterwards.

We use the condtional jump to skip the ADD AL, 0x07 if the value is already in the 0–9 range. In effect: