8

I am reading this wonderful skript on operating system programming

http://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf

On Page 12 there is a simple bootloader.

If I understand correclty, the code shown is what you must write in NASM to get BIOS to print out characters.

What I dont get is this:

It says that

we need interrupt 0x10 and to set ah to 0x0e (to indicate tele-type mode)
and al to the ASCII code of the character we wish to print.

But the first instruction is:

mov ah , 0x0e ;int 10/ ah = 0eh -> scrolling teletype BIOS routine

I don't understand the comment on that line. Why doesn't the first line of code say:

mov ah, 0xeh
int 0x10

if thats what you need to do?

Thanks for help!

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
user3813234
  • 1,580
  • 1
  • 29
  • 44

2 Answers2

13

Although Chrono gave you an answer I'm not quite sure it answers your question. You seem to be asking why the comment says one thing and the code seemingly does another.

Base Prefixes and Suffixes

Decades ago a lot of reference material and some disassemblers used a slightly different default notation to represent decimal, hexadecimal, octal, and binary bases than you might see today. They specified the base as the last character(suffix) of the value. Common suffixes are:

b = binary    10101010b      (decimal 170)    base 2
d = decimal   170d           (decimal 170) \  both d and t mean base 10 
t = decimal   170t           (decimal 170) /
h = hex       0AAh           (decimal 170)    base 16
o = octal     252o           (decimal 170)    base 8

If a number contains no alphabetic characters then it is assumed to be base 10 decimal. So this also applies:

no alphabetic character      170             decimal   170

Most assemblers will accept most of these suffixes, but they also will support the base being defined as a prefix. If a value doesn't end with an alphabetic character but starts with a 0 followed by a letter then the letter denotes the base. Common prefix bases are:

b = binary    0b10101010     (decimal 170)    base 2
d = decimal   0d170          (decimal 170) \  both d and t mean base 10 
t = decimal   0t170          (decimal 170) /
h = hex       0xAA           (decimal 170)    base 16
o = octal     0o252          (decimal 170)    base 8

Most modern assemblers will support the forms specified as a prefix or suffix. Some assemblers may not support some of the prefixes and suffixes like t.

If you specify numbers with a prefix base then stick with prefixes throughout the whole file. If you specify numbers with a suffix base then stick with suffixes throughout the whole file. You can mix them up, but it is best to be consistent in a file.

Interpreting int 10/ ah = 0eh

What does this mean:

int 10/ ah = 0eh -> scrolling teletype BIOS routine
  • int 10 contains no letters so it is decimal 10 (or hexadecimal a).
  • 0eh ends with a letter and doesn't start with 0 and a letter so h is the suffix. h means hexadecimal. So 0ehis hexadecimal 0e (or decimal 14).

If you were to put that into assembler code for the BIOS it would look like (using hexadecimal suffix):

mov ah, 0eh      ; Decimal 14
int 0ah          ; Decimal 10. The 0 in front makes sure the assembler knows we don't mean register ah! 

Using prefixes (hexadecimal in this example):

mov ah, 0xe      ; Decimal 14
int 0xa          ; Decimal 10 

Or if you want to use decimal (no prefix or suffix):

mov ah, 14       ; Decimal 14
int 10           ; Decimal 10

But you may now be saying Hey Wait! that is wrong because the BIOS video interrupt is 0x10 (or 16 decimal) you are correct! We have just learned that the comment is wrong or at best VERY ambiguous. The comment should have said:

int 10h / ah = 0eh -> scrolling teletype BIOS routine

You may wish to contact the author of the comment / code and let them know that their comment is inaccurate. The code they wrote is correct.

If the assembler supports them I prefer prefixes like 0x, 0b, 0o instead of the suffixes h, b, o because it is possible for some suffixes to form register names, or other identifiers and symbols. When using suffixes, if you have a value that must start with a letter (ie: A to F in hexadecimal) add a 0 to the beginning to let the assembler know you are representing a value. As an example AAh would have to be written as 0AAh, and Bh would have to be written as 0Bh.

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • 3
    Ahh, thanks a lot! Now I suddenly feel I'm above the author ;D Thanks for the extensive explanation!! – user3813234 Oct 03 '15 at 20:04
  • 1
    If I had read the comment I would have probably glossed right over the fact that they didn't specify the base properly, only because I'm so accustomed to know that 10 hex is the video interrupt. But for someone new, it definitely can be confusing. I gave a description of suffixes and prefixes mainly because in your code you said `0xeh` which has both a prefix and suffix and like. `h` isn't a hexadecimal value so assemblers will choke on it if you also specify 0x (assembler doesn't know what you really meant) – Michael Petch Oct 03 '15 at 20:13
4

The comment is just for context, stating that AH=0x0e because it denotes the scrolling teletype BIOS routine when invoking INT 0x10.

You could think of the int XXX instruction as an "execute function XXX" instruction for simplicity purposes. In this particular case, if you don't first load the AL register with a byte of your choosing, whatever byte is in that register will be printed each time INT 0x10 appears. That's why AH is initially loaded with 0x0e for the scrolling teletype routine, and AL is then loaded each time with a byte to display before executing the INT 0x10 instruction.

In some simplistic commented pseudocode:

#AH=0x0e is the scrolling teletype BIOS routine when used with int 10h.
AH := 0x0e

#AL is the byte to display.
AL := 'H'

#Execute the scrolling teletype BIOS routine (AH=0x0e), displaying 'H' (AL='H').
INT 0x10