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