4
\$\begingroup\$

How does the following program look to print a list of strings? What places can I improve? Are there easier ways to print something like a linebreak after each string rather than hardcoding the \n into the string itself?

# Program, print out a list of strings, one per line
.data
SYS_EXIT = 60
SYS_WRITE = 1
SYS_STDOUT = 1
# Empty string means end of strings
strings: .asciz "Once\n", "upon\n", "a\n", "time\n", "...\n", ""
.text
.globl _start
get_string_length:
 mov 0,ドル %eax
 .L1_loop:
 movzbl (%edi, %eax), %ecx
 cmp 0,ドル %cl
 je .L1_exit
 inc %eax
 jmp .L1_loop
 .L1_exit:
 ret
_start:
 mov $strings, %rbx
 print_loop:
 mov %rbx, %rdi
 call get_string_length # (rdi=file_descriptor, rsi=starting_address, rdx=size)
 cmp 0,ドル %eax
 jz exit
 mov $SYS_STDOUT,%edi
 mov %rbx, %rsi
 mov %eax, %edx
 mov $SYS_WRITE, %eax
 syscall
 lea 1(%eax, %ebx,), %ebx
 jmp print_loop
 exit:
 mov 0,ドル %edi
 mov $SYS_EXIT, %eax
 syscall
asked Sep 18, 2020 at 5:07
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Are there easier ways to print something like a linebreak after each string rather than hardcoding the \n into the string itself?

Embedded newlines are certainly the easiest way to do this, but definitively not the most versatile way. Embedding the newlines kind of pushes you in the direction that the strings will be used for outputting only. You might want to do lots of other stuff with them too.
I advocate keeping the strings pure and adding the linebreaks, or any other prefix or suffix for that matter, later on. Since you already have to count the characters in the string, you can at the same time copy the string to a buffer (every non-trivial program has some general purpose buffer at the ready). Once you read the zero terminator you store the newline in the buffer. Then you're ready to print the buffer contents for which you now know the length.

In below code PrepStringForOutput is a leaf function which means you can do pretty much anything you like in it. You don't have to follow any register conventions per se.

# Program, print out a list of strings, one per line
.data
SYS_EXIT = 60
SYS_WRITE = 1
SYS_STDOUT = 1
# Empty string means end of strings
Strings: .asciz "Once", "upon", "a", "time", "...", ""
Buffer: .ascii "12345"
.text
.globl _start
; IN (%rbx is asciz) OUT (%rsi is buffer, %rdx is length) MOD (%al) 
PrepStringForOutput:
 mov $Buffer, %rsi # Destination
 xor %edx, %edx # Length
 .L1_loop:
 mov (%rbx, %rdx), %al # Character from asciz string
 test %al, %al
 jz .L1_exit
 mov %al, (%rsi, %rdx) # Store in buffer
 inc %edx
 jmp .L1_loop
 .L1_exit:
 mov 10,ドル (%rsi, %rdx) # Adding newline
 inc %edx
 ret
_start:
 mov $Strings, %rbx
 PrintLoop:
 cmpb 0,ドル (%rbx) # End of list ?
 je Exit
 call PrepStringForOutput # -> %rsi is address, %rdx is length
 add %rdx, %rbx # Advancing in the list
 mov $SYS_STDOUT, %edi
 mov $SYS_WRITE, %eax
 syscall
 jmp PrintLoop
 Exit:
 xor %edi, %edi
 mov $SYS_EXIT, %eax
 syscall

What places can I improve?

You'll easily spot these in above code...
See the nice tabular layout?

answered Sep 25, 2020 at 22:59
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.