Cetak daftar string dalam perakitan
Bagaimana tampilan program berikut untuk mencetak daftar string? Tempat apa yang bisa saya tingkatkan? Apakah ada cara yang lebih mudah untuk mencetak sesuatu seperti pemisah baris setelah setiap string daripada melakukan hardcode \nke dalam string itu sendiri?
# 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
Jawaban
Apakah ada cara yang lebih mudah untuk mencetak sesuatu seperti pemisah baris setelah setiap string daripada melakukan hardcode \ n ke dalam string itu sendiri?
Saluran baru yang disematkan tentu merupakan cara termudah untuk melakukan ini, tetapi jelas bukan cara yang paling serbaguna. Menyematkan jenis baris baru mendorong Anda ke arah string yang hanya akan digunakan untuk keluaran. Anda mungkin ingin melakukan banyak hal lain dengan mereka juga.
Saya menganjurkan agar string tetap murni dan menambahkan penggalan baris, atau awalan atau sufiks lainnya, nanti. Karena Anda sudah harus menghitung karakter dalam string, Anda dapat pada saat yang sama menyalin string ke buffer (setiap program non-sepele memiliki buffer tujuan umum yang siap). Setelah Anda membaca terminator nol, Anda menyimpan baris baru di buffer. Kemudian Anda siap untuk mencetak konten buffer yang sekarang Anda ketahui panjangnya.
Dalam kode di bawah ini PrepStringForOutput adalah fungsi daun yang berarti Anda dapat melakukan apa saja yang Anda suka di dalamnya. Anda tidak harus mengikuti konvensi pendaftaran apa pun.
# 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
Tempat apa yang bisa saya tingkatkan?
Anda akan dengan mudah melihat ini dalam kode di atas ...
Lihat tata letak tabel yang bagus?