Real mode assembly II

From OSDev.wiki
Jump to navigation Jump to search
This article refers to its readers or editors using I, my, we or us.
It should be edited to be in an encyclopedic tone.
This article refers to its readers using you in an unencyclopedic manner.
It should be edited to be in an encyclopedic tone.
WARNING: Please see the Real Mode OS Warning page before continuing.
Difficulty level

Beginner

In this second installment of the real mode assembly bare bones series we will cover hex functions and NASM directives and their usefulness.

Hexadecimal to ASCII

This is where things get fun. We're going to convert a value in al to two characters and print them out. The following code snippet from http://www.df.lth.se/~john_e/gems/gem003a.html shows how to convert the low nybble of al to an ASCII character.

 cmp al,10
 sbb al,69h
 das

Simple, but doesn't do that much. After all, it only converts the low nybble and can do weird things occasionally. So we need to shift (and rotate for the low nybble). Here's how I do it:

 shr al,4        ; Shift right four places to put upper nybble in lower spot
 cmp al,10
 sbb al,69h
 das
 
 mov ah,0Eh   ; Print out upper nybble
 int 10h

Sure, it works, but it's only printing out the upper nybble and the low nybble disappears! Oh noes! So we have to store a copy of al in a variable first:

 mov [.temp],al

And restore it after to do the second:

 mov al,[.temp]

Now we rotate and shift to do the conversion for the low nybble:

 ror al,4
 shr al,4
 cmp al,10
 sbb al,69h
 das
 
 mov ah,0Eh
 int 10h

The code

Now put that all together:

 print_hex_byte: 
   mov [.temp],al
   shr al,4
   cmp al,10
   sbb al,69h
   das
 
   mov ah,0Eh
   int 10h
 
   mov al,[.temp]
   ror al,4
   shr al,4
   cmp al,10
   sbb al,69h
   das
 
   mov ah,0Eh
   int 10h
 
   ret
 
 .temp db 0

And that function is now callable! Using what you've learned, you can also write your own call to print all of ax and not just al. Try it, it's not that hard!

NASM: Lord of Open-Source Assemblers

NASM has some great macro abilities, including automating tasks such as writing your db statements for you. Simple, multi-line macros go something like this:

 %macro name operands
    ; code code code
 %endmacro

You can use %1, %2, etc. to represent the contents of arguments passed to your macro. You can even emulate BASIC statements with macros, like discussed here.

Even simpler macros are the single-line macros, or %define statements. They create assemble-time statements to be inserted, but they are more like constants than functions.

 %define D_SIGNATURE 0xCAFEF00D
 %define D_INFO 0x29A3B83D
 
 push D_SIGNATURE
 push D_INFO
 jmp 0x2000:0

Now, that's just example code, it could mean anything, but it depends on what's at 0x2000:0, of course. But the principle is the same, %define is used to create constants and the like.

NASM's macro features are discussed in a lot more detail in the manual: http://www.nasm.us/doc/nasmdoc4.html

Continuing on

This tutorial was more of a theory lesson and less of a water pipe spitting out gushes of source code. Future tutorials will have more application, but less copy-and-paste code.

Have fun developing your OS!

<- Real mode assembly I  |  Real mode assembly III ->