Copy Link
Add to Bookmark
Report

NULL mag Issue 07 30 Assembly tutorial 7

eZine's profile picture
Published in 
null magazine
 · 26 Dec 2020

  




Linefeeds are essential to console programs like our 'hello world' program.
They become even more important once we start building programs that
require user input. But linefeeds can be a pain to maintain. Sometimes you
will want to include them in your strings and sometimes you will want to
remove them. If we continue to hard code them in our variables by adding
0Ah after our declared message text, it will become a problem. If there's
a place in the code that we don't want to print out the linefeed for that
variable we will need to write some extra logic remove it from the string
at runtime.

It would be better for the maintainability of our program if we write
a subroutine that will print out our message and then print a linefeed
afterwards. That way we can just call this subroutine when we need the
linefeed and call our current sprint subroutine when we don't.

A call to sys_write requires we pass a pointer to an address in memory of
the string we want to print so we can't just pass a linefeed character
(0Ah) to our print function. We also don't want to create another variable
just to hold a linefeed character so we will instead use the stack.

The way it works is by moving a linefeed character into EAX. We then push
EAX onto the stack and get the address pointed to by the Extended Stack
Pointer. ESP is another register. When you push items onto the stack, ESP
is decremented to point to the address in memory of the last item and so it
can be used to access that item directly from the stack. Since ESP points
to an address in memory of a character, sys_write will be able to use it to
print.


functions.asm
;------------------------------------------
; int slen(String message)
; String length calculation function
slen:
push ebx
mov ebx, eax

nextchar:
cmp byte [eax], 0
jz finished
inc eax
jmp nextchar

finished:
sub eax, ebx
pop ebx
ret


;------------------------------------------
; void sprint(String message)
; String printing function
sprint:
push edx
push ecx
push ebx
push eax
call slen

mov edx, eax
pop eax

mov ecx, eax
mov ebx, 1
mov eax, 4
int 80h

pop ebx
pop ecx
pop edx
ret

;------------------------------------------
; void sprintLF(String message)
; String printing with line feed function
sprintLF:
call sprint

push eax
; push eax onto the stack to preserve it while we use the eax register
; in this function
mov eax, 0Ah
; move 0Ah into eax - 0Ah is the ascii character for a linefeed
push eax
; push the linefeed onto the stack so we can get the address
mov eax, esp
; move the address of the current stack pointer into eax for sprint
call sprint
; call our sprint function
pop eax
; remove our linefeed character from the stack
pop eax
; restore the original value of eax before our function was called
ret
; return to our program


;------------------------------------------
; void exit()
; Exit program and restore resources
quit:
mov ebx, 0
mov eax, 1
int 80h
ret


helloworld-lf.asm
; Hello World Program (Print with line feed)
; Compile with: nasm -f elf helloworld-lf.asm
; Link with (64 bit systems require elf_i386 option):
; ld -m elf_i386 helloworld-lf.o -o helloworld-lf
; Run with: ./helloworld-lf

%include 'functions.asm'

SECTION .data
msg1 db 'Hello, brave new world!', 0h
; NOTE we have removed the line feed character 0Ah
msg2 db 'This is how we recycle in NASM.', 0h
; NOTE we have removed the line feed character 0Ah

SECTION .text
global _start

_start:

mov eax, msg1
call sprintLF
; NOTE we are calling our new print with linefeed function

mov eax, msg2
call sprintLF
; NOTE we are calling our new print with linefeed function

call quit



~$ nasm -f elf helloworld-lf.asm
~$ ld -m elf_i386 helloworld-lf.o -o helloworld-lf
~$ ./helloworld-lf
Hello, brave new world!
This is how we recycle in NASM.

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT