Real mode assembly II: Difference between revisions
[unchecked revision] | [unchecked revision] |
m (Add tone note at top) |
No edit summary |
||
(4 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
{{FirstPerson}} |
{{FirstPerson}} |
||
{{You}} |
|||
⚫ | |||
{{Rating|1}} |
{{Rating|1}} |
||
''In this second installment of the [[real mode assembly bare bones]] series we will cover hex functions and NASM directives and their usefulness.'' |
''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== |
==Hexadecimal to ASCII== |
||
Line 10: | Line 10: | ||
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. |
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. |
||
< |
<syntaxhighlight lang="asm"> |
||
cmp al,10 |
cmp al,10 |
||
sbb al,69h |
sbb al,69h |
||
das |
das |
||
</syntaxhighlight> |
|||
</source> |
|||
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: |
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: |
||
< |
<syntaxhighlight lang="asm"> |
||
shr al,4 ; Shift right four places to put upper nybble in lower spot |
shr al,4 ; Shift right four places to put upper nybble in lower spot |
||
cmp al,10 |
cmp al,10 |
||
Line 26: | Line 26: | ||
mov ah,0Eh ; Print out upper nybble |
mov ah,0Eh ; Print out upper nybble |
||
int 10h |
int 10h |
||
</syntaxhighlight> |
|||
</source> |
|||
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: |
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: |
||
< |
<syntaxhighlight lang="asm"> |
||
mov [.temp],al |
mov [.temp],al |
||
</syntaxhighlight> |
|||
</source> |
|||
And restore it after to do the second: |
And restore it after to do the second: |
||
< |
<syntaxhighlight lang="asm"> |
||
mov al,[.temp] |
mov al,[.temp] |
||
</syntaxhighlight> |
|||
</source> |
|||
Now we rotate and shift to do the conversion for the low nybble: |
Now we rotate and shift to do the conversion for the low nybble: |
||
< |
<syntaxhighlight lang="asm"> |
||
ror al,4 |
ror al,4 |
||
shr al,4 |
shr al,4 |
||
Line 51: | Line 51: | ||
mov ah,0Eh |
mov ah,0Eh |
||
int 10h |
int 10h |
||
</syntaxhighlight> |
|||
</source> |
|||
===The code=== |
===The code=== |
||
Line 57: | Line 57: | ||
Now put that all together: |
Now put that all together: |
||
< |
<syntaxhighlight lang="asm"> |
||
print_hex_byte: |
print_hex_byte: |
||
mov [.temp],al |
mov [.temp],al |
||
Line 81: | Line 81: | ||
.temp db 0 |
.temp db 0 |
||
</syntaxhighlight> |
|||
</source> |
|||
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! |
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! |
||
Line 89: | Line 89: | ||
[[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: |
[[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: |
||
< |
<syntaxhighlight lang="asm"> |
||
%macro name operands |
%macro name operands |
||
; code code code |
; code code code |
||
%endmacro |
%endmacro |
||
</syntaxhighlight> |
|||
</source> |
|||
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 [[printing to the screen without a db|here]]. |
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 [[printing to the screen without a db|here]]. |
||
Line 99: | Line 99: | ||
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. |
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. |
||
< |
<syntaxhighlight lang="asm"> |
||
%define D_SIGNATURE 0xCAFEF00D |
%define D_SIGNATURE 0xCAFEF00D |
||
%define D_INFO 0x29A3B83D |
%define D_INFO 0x29A3B83D |
||
Line 106: | Line 106: | ||
push D_INFO |
push D_INFO |
||
jmp 0x2000:0 |
jmp 0x2000:0 |
||
</syntaxhighlight> |
|||
</source> |
|||
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. |
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. |
||
Line 118: | Line 118: | ||
Have fun developing your OS! |
Have fun developing your OS! |
||
[[Category:Assembly]] |
|||
[[Category:Real mode assembly]] |
[[Category:Real mode assembly]] |
||
<- [[Real mode assembly I]] | [[Real mode assembly III]] -> |
<- [[Real mode assembly I]] | [[Real mode assembly III]] -> |
Latest revision as of 08:30, 17 June 2024
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 ->