Show
This procedure doesn't conform to any particular calling convention. It is designed specifically to work with other subroutines designed by me. Any of my examples won't be using and standard library functions either. Not because I think they are inadequate, but rather give me complete independence and easier porting I think to an OS less app relying only on BIOS functions.
The purpose behind this design was to facilitate a very tight loop involving multiple NULL terminated strings
Array db 'One', 0, 'Two', 0, 'Three', 0, 'Four', 0, 0
Prompt db ' times', 10, 0
mov esi, Array
L0 call Show
push rsi
mov esi, Prompt
call Show
pop rsi
cmp byte [rsi], 0
jnz L0
I think you can see the result would be
One times
Two times
Three times
Four times
In any event, it makes for a pretty low overhead loop.
=============================================================================================
Display a null terminated string on monitor or to whever stream is directed.
ENTER: RSI = Pointer to null terminated ASCII string.
LEAVE: RAX = Character count including NULL (terminator)
RSI = Next string (if it exists).
---------------------------------------------------------------------------------------------
0: 57 push rdi
1: 52 push rdx Preserve
2: 51 push rcx
Determine strings length.
3: 48 83 c9 ff or rcx, -1 Should be large enough
7: 31 c0 xor eax, eax Need all bits cleared @ 16 anyway
9: 56 push rsi
a: 5f pop rdi Source buffer
b: f2 ae repnz scasb Find terminator hopefully
d: 48 f7 d9 neg rcx
10: 83 e9 02 sub ecx, 0x2
13: 57 push rdi Need this again @ 1C
Now we can setup for system call.
RDI = STDOUT
RSI = Pointer to string
RDX = Number of characters to display
14: 51 push rcx
15: 5a pop rdx
16: b0 01 mov al, 0x1
18: 50 push rax
19: 5f pop rdi
1a: 0f 05 syscall
I don't think it's really necessary to check for errors here as operator will
probably be aware without prompting.
1c: 5e pop rsi Next string possibly
1d: 59 pop rcx
1e: 5a pop rdx Retrive
1f: 5f pop rdi
20: 48 ff c0 inc rax Bump to include terminator
23: c3 ret