NASM Forum > Example Code

My own 64-bit `puts' instruction (No length required)

(1/4) > >>

MediocreVeg1:
So I've been having a bit of difficulty regarding procedures, and the people on this forum helped a lot (and helped me understand 64-bit assembly in general). So in return, I want to help others who may be having difficulty like me too with the `puts' procedure i made. But the main advantage of the procedure - not having to enter the length - requires another procedure `strlen', which calculates the length of the string (not including the terminating 0 character). It takes rdi (which should hold the string) as a parameter and returns the length in rax. So here it is:

--- Code: ---strlen:
    xor rax, rax ; Return value, will count string length
    dec rdi
.cntloop:
    inc rax
    inc rdi
    cmp byte [rdi], 0 ; Terminating character
    jnz strlen.cntloop

    dec rax ; So that it does not include the last terminating character
    ret
--- End code ---
Thanks to this, the actual printing procedure is really simple. It also takes rdi as a parameter and prints the string in the register:

--- Code: ---puts:
    mov rsi, rdi
    call strlen
    mov rdx, rax
    mov rax, 1
    mov rdi, rax
    syscall
    ret
--- End code ---

Note that the string doesn't need to have a 0 character at the end for this to work, but it would be better if you did put it.

This isn't as advanced as the `puts' macro I made, which didn't require the argument to be a variable and could take an infinite amount of arguments, but it couldn't print variables of .bss and too macros is probably a bad idea. Anyway, do give me any suggestions to improve the code if you feel it could be better.

MediocreVeg1:
UPDATE: I realised an issue with the procedure related to the way section .data works. From what I can tell, if you do this:

--- Code: ---achar db "H"
bchar db "F"
--- End code ---
the variables will be stored in the memory side-by-side with no space in-between, so no terminating character in-between. This means that if you print achar, it'll print bchar right after that. Due to this, I HIGHLY RECOMMEND YOU PUT THE NULL CHARACTER YOURSELF AT THE END OF EACH STRING. Apart from that, the rest is fine.

Frank Kotler:
Looks as if you've reinvented "gets". No protection against overflow.  Take it away!

Best,
Frank

MediocreVeg1:
What do you mean by that? I actually haven't tried to make a `gets' without specifying the size because I'm not sure if that is possible with how I'm getting length currently.

MediocreVeg1:
Oh right, if you are talking about the going to the other vairable thing, yeah, it is a bit annoying. If you really can't put the 0 at the end, you can override db to automatically put a 0 with this macro:

--- Code: ---%macro db 1+
    db %1, 0
%endmacro

--- End code ---
(The plus will make it a greedy parameter so %1 will include all args)
if you don't want to override db or dont want to do this with every dx instruction you can rename it to something else too.

Navigation

[0] Message Index

[#] Next page

Go to full version