Cetak daftar string dalam perakitan

Sep 18 2020

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

3 SepRoland Sep 26 2020 at 05:59

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?