Page 1 of 1
Print Immediate String NASM
Posted: Thu Aug 21, 2008 10:02 am
by Troy Martin
Hey,
Is there any way I can print an immediate string in NASM assembly? Like this:
puts "Hello World!"
That assumes puts is a NASM macro that calls os_print_string. Also, can that same macro check for a \n newline code? Thanks!
Here's os_print_string:
Code: Select all
os_print_string:
pusha
mov ah, 0Eh ; int 10h teletype function
; Some BIOS will change DX and/or BP
.repeat:
lodsb ; Get char from string
cmp al, 0
je .done ; If char is zero, end of string
int 10h ; Otherwise, print it
jmp .repeat
.done:
popa
ret
Re: Print Immediate String NASM
Posted: Thu Aug 21, 2008 11:34 am
by Brendan
Hi,
Try something like:
Code: Select all
%macro puts 1+
section .data
%%string:
db %1,0
section .text
push si
mov si,%%string
call printString
pop si
%endmacro
Cheers,
Brendan
Re: Print Immediate String NASM
Posted: Fri Aug 22, 2008 7:34 pm
by Troy Martin
Freakin' sweet.
Now all I need is it to be able to take a \n newline code... But I can work on that, either in the C compiler that it's used in or in the macro itself.
Re: Print Immediate String NASM
Posted: Fri Aug 22, 2008 8:00 pm
by xyjamepa
Hi,
I have a question,can we use macros when writing an os ?
sure we can use it when writing normal applications, but is it the same when
it comes to os development?
Thanx.
Re: Print Immediate String NASM
Posted: Fri Aug 22, 2008 8:19 pm
by Dex
Yes you can, but remember, a macro is placed where you use the macro name, so if you used the macro 20 time's, it will add 20 times the size of your macro to your code.
This is not the same with a proc.
You can also use it as a simple language eg: basic
Code: Select all
macro PRINT String{
local .Printer
local .Nextchar
local .Done
local .a
.Printer:
mov si, .a
mov ah, 0Eh
jmp .Nextchar
.Nextchar:
lodsb
or al, al
jz .Done
int 10h
jmp .Nextchar
jmp .Done
.a db String,10,13,0
.Done:
}
macro SCREEN mode
{
push ax
if mode = 0
mov ah,0h ;SCREEN 0; Default DOS screen mode
mov al,3h
int 10h
else if mode = 13
mov ah,0h ;SCREEN 13; VGA
mov al,13h
int 10h
end if
pop ax
}
macro SLEEP
{
;Output:
;ah = BIOS scancode of key pressed
;al = ASCII character of key pressed
;Could have also used...
; mov ah,8h
; int 21h
mov ah,0h
int 16h
}
macro END
{
mov ax,4Ch ;\END
int 21h ;/
}
macro LOCATE row,col
{
pusha
mov ah,2 ;Function 2
mov bh,0 ;Use page 0
mov dh,row ;row
mov dl,col ;col
int 10h
popa
}
And then you can do this:
Code: Select all
SCREEN 0
LOCATE 5,5
PRINT "Hello World"
SLEEP
END
Re: Print Immediate String NASM
Posted: Sat Aug 23, 2008 10:43 am
by Troy Martin
Dex, before I reqested the macro, I had already known that it would increase the size, so I'm substituting the big fat loops with "call syscall".
Abu, yeah, you can use macros in your kernel. Even in a bootloader, but even I think that's not really worth it. Remember what Dex said (and I added on to) that if you use 20 copies of the macro, the code for 20 copies of the macro will be put in. It's best to just define a system call to do the grunt work, then a small macro to set up what's needed and call the syscall. Very efficient for things like printing strings, getting input, listing the root directory, etc.
As I said in the OP, I'm using this to write out the intermediate assembly code from my C compiler. It then links to flat binary WITH MikeOS system calls,
Re: Print Immediate String NASM
Posted: Sat Aug 23, 2008 11:15 am
by Brendan
Hi,
Troy Martin wrote:Dex, before I reqested the macro, I had already known that it would increase the size, so I'm substituting the big fat loops with "call syscall".
Even if you are using the macro to call another function it can increase code size. For an example, consider the "puts" macro I posted earlier - it always pushes and pops SI even when it isn't necessary, and if you're printing several strings you'll end up with something like:
Code: Select all
push si
mov si,first_string
call printString
pop si
push si
mov si,second_string
call printString
pop si
push si
mov si,third_string
call printString
pop si
Instead of:
Code: Select all
push si
mov si,first_string
call printString
mov si,second_string
call printString
mov si,third_string
call printString
pop si
However, there are some macros that never increase code size - here's some that I always use:
Code: Select all
%macro clr 1
xor %1,%1
%endmacro
%macro pushes 1-*
%rep %0
push %1
%rotate 1
%endrep
%endmacro
%macro pops 1-*
%rep %0
%rotate -1
pop %1
%endrep
%endmacro
Also, (if you're still wondering) there is no way that I can think of to get NASM to support embedded newlines in strings (e.g.
"foo\nbar" instead of
"foo",0x13,"bar"). As an alternative your code to print strings could do it, but then "/n" would cost 2 bytes instead of one (because the language doesn't convert it into "db 0x13" at compile time).
Cheers,
Brendan
Re: Print Immediate String NASM
Posted: Sat Aug 23, 2008 12:27 pm
by Troy Martin
Hey,
I'm going to take out the push si & pop si, since the syscall does pusha & popa for me for me.
About the newlines, I've embedded some newline code into the compiler, so I can have a newline at the end of the string. Voila!