พิมพ์รายการสตริงในชุดประกอบ

Sep 18 2020

โปรแกรมต่อไปนี้มีลักษณะอย่างไรในการพิมพ์รายการสตริง ฉันสามารถปรับปรุงสถานที่ใดได้บ้าง มีวิธีที่ง่ายกว่าในการพิมพ์สิ่งต่างๆเช่น linebreak หลังจากแต่ละสตริงแทนที่จะเข้ารหัส\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

คำตอบ

3 SepRoland Sep 26 2020 at 05:59

มีวิธีที่ง่ายกว่าไหมในการพิมพ์สิ่งต่างๆเช่น linebreak หลังจากแต่ละสตริงแทนที่จะฮาร์ดโค้ด \ n ลงในสตริงเอง

บรรทัดใหม่แบบฝังเป็นวิธีที่ง่ายที่สุดในการทำเช่นนี้ แต่ไม่ใช่วิธีที่หลากหลายที่สุด การฝังขึ้นบรรทัดใหม่จะผลักคุณไปในทิศทางที่จะใช้สตริงสำหรับการส่งออกเท่านั้น คุณอาจต้องการทำสิ่งอื่น ๆ อีกมากมายด้วยเช่นกัน
ฉันสนับสนุนการรักษาสตริงให้บริสุทธิ์และเพิ่มการแบ่งบรรทัดหรือคำนำหน้าหรือคำต่อท้ายอื่น ๆ สำหรับเรื่องนั้นในภายหลัง เนื่องจากคุณต้องนับอักขระในสตริงอยู่แล้วคุณจึงสามารถคัดลอกสตริงไปยังบัฟเฟอร์ได้ในเวลาเดียวกัน (ทุกโปรแกรมที่ไม่สำคัญจะมีบัฟเฟอร์สำหรับวัตถุประสงค์ทั่วไปพร้อมกัน) เมื่อคุณอ่านศูนย์เทอร์มิเนเตอร์คุณจะเก็บบรรทัดใหม่ไว้ในบัฟเฟอร์ จากนั้นคุณก็พร้อมที่จะพิมพ์เนื้อหาบัฟเฟอร์ซึ่งคุณทราบความยาวแล้ว

ในโค้ดด้านล่างPrepStringForOutputเป็นฟังก์ชัน leaf ซึ่งหมายความว่าคุณสามารถทำอะไรก็ได้ที่คุณชอบ คุณไม่จำเป็นต้องปฏิบัติตามอนุสัญญาการลงทะเบียนใด ๆ ต่อ 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

ฉันสามารถปรับปรุงสถานที่ใดได้บ้าง

คุณจะเห็นสิ่งเหล่านี้ได้อย่างง่ายดายในโค้ดด้านบน ...
ดูเค้าโครงตารางที่ดี?