Распечатать список строк в сборке
Как выглядит следующая программа для печати списка строк? Какие места я могу улучшить? Есть ли более простые способы напечатать что-то вроде разрыва строки после каждой строки, а не жестко закодировать \nсаму строку?
# 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
Ответы
Есть ли более простые способы напечатать что-то вроде разрыва строки после каждой строки, а не жестко закодировать \ n в самой строке?
Встроенные символы новой строки, безусловно, являются самым простым способом сделать это, но определенно не самым универсальным способом. Встраивание символов новой строки как бы подталкивает вас к тому, что строки будут использоваться только для вывода. Возможно, вам захочется заняться с ними и другими вещами.
Я выступаю за то, чтобы строки оставались чистыми и позже добавляли разрывы строк или любой другой префикс или суффикс. Поскольку вам уже нужно подсчитать количество символов в строке, вы можете одновременно скопировать строку в буфер (каждая нетривиальная программа имеет наготове какой-то буфер общего назначения). После того, как вы прочитаете нулевой терминатор, вы сохраните новую строку в буфере. Затем вы готовы распечатать содержимое буфера, длина которого вам теперь известна.
В приведенном ниже коде PrepStringForOutput - это листовая функция, что означает, что вы можете делать в ней практически все, что захотите. Вам не обязательно соблюдать какие-либо правила регистрации как таковые.
# 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
Какие места я могу улучшить?
Вы легко заметите их в приведенном выше коде ...
Видите красивую табличную структуру?