运行“sorter.s”时出现分段错误(核心转储)

Segmentation fault (core dumped) when running "sorter.s"

提问人:YB1925 提问时间:10/22/2023 最后编辑:YB1925 更新时间:10/22/2023 访问量:69

问:

在我们的练习中,我们将编写一个程序,当给定 (x, y) 坐标列表时 它仅在 y 维度上对它们进行排序,然后打印结果。

我们有一些代码片段,我想通过链接它们来使用它们:

  • parsing.s:pastebin.com/Mum2atVN
  • fileHandling.s:pastebin.com/NgxVN5Rg
  • allocate.s:pastebin.com/uMQJj16w
  • insertionSort.s:pastebin.com/fPRzzHaJ

分配 (allocate.s) 此函数要求操作系统更改 数据段在运行程序中,从而获得更多空间。 作为参数,您只需在 %rdi 中传递所需的字节数。一个 指向已分配内存的指针以 %rax 形式返回。 请注意,内存永远不会被释放,因此实际上没有太多的内存管理,如果将内存分配到 递归函数。

getFileSize (fileHandling.s) 当你打开一个文件时,你可以得到 它的大小(以字节为单位)与此函数。传递 file 作为参数。

getLineCount (parsing.s) 当您将文件的内容读入 一个缓冲区,这个函数可以计算其中有多少个坐标(通过 计算换行符的数量)。这将允许您 为解析的坐标分配适当的内存量。 • 第一个参数必须是内存的地址,其中 数据。 • 第二个参数必须是该段内存的长度。

parseData (parsing.s) 此函数转换 将坐标分成成对的数字。 • 第一个参数必须是要解析的文本缓冲区的地址。 • 第二个参数必须是该文本缓冲区的长度。 • 第三个参数必须是指向一段内存的指针 将解析后的坐标写入。

我决定使用插入排序,然后制作了一个“主排序器”。 我的分拣机。

.section .data
input_buffer:
    .space 1000                               # Reserve a larger buffer, adjust as needed
    
.section .text
.globl _start
_start:

   # Get the number of command-line arguments and the arguments themselves
    pop %r8             # number of arguments
    pop %r8             # program name
    pop %r8             # first argument after program name (this should be the filename)

    # Use the filename obtained from the command line
    movq %r8, %rdi     # Load address of filename into rdi

    # Open the file
    movq %r8, %rdi
    movq $0, %rsi 
    movq $2, %rax
    syscall
    test %rax, %rax     # Check if open was successful
    js .LError          # Jump to error handling if the result was negative

    movq %rax, %r9      # Store file descriptor in r9
    
    # Step 2: Get the file size
    call getFileSize           # call the function
    movq %rax, %r9             # store file size in r9

    # Step 3: Allocate buffer to read the file
    movq %r9, %rdi             # set size as argument to allocate
    call allocate              # call the function
    movq %rax, %r10            # store buffer address in r10

    # Step 4: Read the file into the buffer
    movq $0, %rax              # syscall number for read
    movq %r8, %rdi             # file descriptor
    movq %r10, %rsi            # buffer address
    movq %r9, %rdx             # file size
    syscall                    # read() call

    # Step 5: Count the number of coordinates in the file
    movq %r10, %rdi            # buffer address
    movq %r9, %rsi             # file size
    call getLineCount          # call the function
    movq %rax, %r11            # store line count in r11

    # Step 6: Allocate space for the coordinates
    movq %r11, %rdi
    shlq $4, %rdi              # 2 * 8 * line count bytes
    call allocate              # call the function
    movq %rax, %r12            # store coordinates address in r12

    # Step 7: Parse the coordinates into the allocated space
    movq %r10, %rdi            # buffer address
    movq %r9, %rsi             # file size
    movq %r12, %rdx            # coordinates address
    call parseData             # call the function

    # Step 8: Sort and print the coordinates
    call printCoordinates

    # Close the file
    movq $3, %rax       # syscall number for close
    movq %r9, %rdi      # file descriptor
    syscall

    # Exit the program
    movq $60, %rax      # syscall number for sys_exit
    xor %rdi, %rdi      # exit status (0)
    syscall

# Function to print a number to stdout
printNumber:
    # Check if the number is 0
    test %rdi, %rdi
    jz .LprintZero

    # Convert the number in rdi to ASCII and print it
    movq $10, %rbx          # divisor
    leaq .Lbuffer(%rip), %r8 # buffer to store ASCII characters
    leaq .LbufferEnd(%rip), %r9 # End of buffer
    addq $15, %r8           # point to the end of the buffer

    # Convert number to ASCII
.LconvertLoop:
    xorq %rdx, %rdx         # clear any previous remainder
    divq %rbx               # divide rdi by 10, quotient in rax, remainder in rdx
    addb $0x30, %dl         # convert remainder to ASCII

    # Check if we're still within buffer bounds
    cmpq %r8, .Lbuffer(%rip)
    jl .LError              # If we've gone out of bounds, jump to error

    decq %r8                # move buffer pointer back
    movb %dl, (%r8)         # store ASCII character in buffer

    test %rax, %rax         # check if quotient is zero
    jnz .LconvertLoop       # if not, continue loop

    # Print the number
    movq $1, %rax           # syscall number for write
    movq $1, %rdi           # file descriptor for stdout
    movq %r8, %rsi          # buffer containing ASCII number
    movq $16, %rdx          # maximum possible length for the number
    subq %r8, %rdx          # actual length
    syscall                 # write() call
    ret
    
.LprintZero:
    movq $1, %rax           # syscall number for write
    movq $1, %rdi           # file descriptor for stdout
    leaq .Lzero(%rip), %rsi # address of the zero character
    movq $1, %rdx           # length of the character
    syscall                 # write() call
    ret
    
.Lbuffer:
    .space 16               # buffer to store ASCII representation of the number
.LbufferEnd:
.Lzero:
    .byte 0x30              # ASCII representation of zero

    # Print newline
    leaq .Lnewline(%rip), %rsi
    movq $1, %rdx            # length of newline character
    syscall                  # write() call
    
    ret

# Print the sorted coordinates
printCoordinates:
    movq %r11, %rcx           # rcx will be our counter for the number of coordinates

    # Step 8: Sort the coordinates
    movq %r12, %rdi            # Starting address of the coordinates
    movq %r11, %rsi            # Number of coordinates
    call insertionSort         # Call the sorting function

    # Step 9: Print the sorted coordinates
    movq %r11, %rcx            # rcx will be our counter for the number of coordinates

.LprintLoop:
    test %rcx, %rcx           # Check if counter is zero
    jz .LprintEnd             # If yes, printing is complete

    # Print x-value
    movq (%r12), %rdi         # Load x-value of the coordinate into rdi
    call printNumber          # Call the function to print it

    # Print tab
    movq $1, %rax             # syscall number for write
    leaq .Ltab(%rip), %rsi    # Load address of the tab character
    movq $1, %rdx             # Size of tab character
    syscall                   # write() call

    # Print y-value
    movq 8(%r12), %rdi        # Load y-value of the coordinate into rdi
    call printNumber          # Call the function to print it

    # Print newline
    movq $1, %rax             # syscall number for write
    leaq .Lnewline(%rip), %rsi # Load address of the newline character
    movq $1, %rdx             # Size of newline character
    syscall                   # write() call

    addq $16, %r12            # Move to the next coordinate
    dec %rcx                  # Decrement counter
    jmp .LprintLoop           # Continue with the loop

.LprintEnd:
    ret

.Ltab:
    .byte 0x09                # Tab character
.Lnewline:
    .byte 0x0A                # Newline character

.LError:
    # Handle the error or simply exit
    movq $60, %rax     # syscall number for exit
    movq $1, %rdi      # status code 1
    syscall            # exit() call
    
    # Exit with an error status
    movq $60, %rax      # syscall number for sys_exit
    movq $1, %rdi       # exit status (1 for error)
    syscall

如何解决此问题?

我试着跑遍gdb:

组装它们然后将它们连接在一起是没有问题的。当我尝试运行该程序时,它给了我一个分段错误:

─── Output/messages ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Program received signal SIGSEGV, Segmentation fault.
0x00000000004011d6 in insertionSort ()
─── Assembly ──────────────────────────────────────────────────────────────────────────────
 0x00000000004011d6  ? mov    0x8(%r13),%r15
 0x00000000004011da  ? cmp    %r14,%r12
 0x00000000004011dd  ? jl     0x4011f4 <insertionSort+62>
 0x00000000004011df  ? mov    (%r14),%rdi
 0x00000000004011e2  ? mov    %rdi,0x10(%r14)
 0x00000000004011e6  ? mov    0x8(%r14),%rdi
 0x00000000004011ea  ? mov    %rdi,0x18(%r14)
 0x00000000004011ee  ? sub    $0x10,%r14
 0x00000000004011f2  ? jmp    0x4011da <insertionSort+36>
 0x00000000004011f4  ? mov    0x0(%r13),%rdi
─── Breakpoints ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[1] break at 0x0000000000401000 for *_start hit 1 time
─── Expressions ──────────────────────────────────────────────────────────────────────────────
─── History ──────────────────────────────────────────────────────────────────────────────
─── Memory ──────────────────────────────────────────────────────────────────────────────
─── Registers ──────────────────────────────────────────────────────────────────────────────
      rax 0x0000000000403000      rbx 0x0000000000000000      rcx 0x0000000000000305         rdx 0x0000000000403000      rsi 0x0000000000000306      rdi 0x0000000000403000      rbp 0x0000000000000000
      rsp 0x00007fffffffdfc0       r8 0x00007fffffffe326       r9 0x0000000000000000         r10 0x0000000000403000      r11 0x0000000000000306      r12 0x0000000000403000      r13 0x0000000000403010
      r14 0x0000000000403000      r15 0x0000000000000000      rip 0x00000000004011d6      eflags [ PF IF RF ]             cs 0x00000033               ss 0x0000002b               ds 0x00000000        
       es 0x00000000               fs 0x00000000               gs 0x00000000        
─── Source ──────────────────────────────────────────────────────────────────────────────
─── Stack ──────────────────────────────────────────────────────────────────────────────
[0] from 0x00000000004011d6 in insertionSort
[1] from 0x0000000000000000
─── Threads ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[1] id 14906 name sorter from 0x00000000004011d6 in insertionSort
─── Variables ──────────────────────────────────────────────────────────────────────────────
程序集 x86 64 位

评论

0赞 Jester 10/22/2023
您没有显示段错误。您刚刚显示了程序在您设置的断点处停止。此外,这是很多代码。将其简化为最小的可重现示例
0赞 YB1925 10/22/2023
我不太擅长组装,所以我想我做到了......我的错。这也是我的分拣机,我试图写...对不起,时间太长了。我希望你能使用它,在“gdb”中运行“stepi”:我已经更新了它
1赞 Jester 10/22/2023
这意味着你是无效的。逆向工作以了解原因。此外,您似乎没有发布排序代码,并且您显示的代码格式不正确,请使用工具栏上的按钮进行修复。r13
0赞 YB1925 10/22/2023
嗨,小丑,感谢您的反馈 - 希望它现在看起来更干净哈哈。:D
1赞 Jester 10/22/2023
您甚至无法加载数据。已经失败了,因为你没有传入。将 保存到 而不是 并立即用大小覆盖它,并最终将需要 .稍后你尝试使用和跨越哪个 clobbers 两者。此外,调试打印不会打印任何数字,只会打印制表符和换行符。当你到达两者时,已经被你无用的调试打印破坏了。所有这些都在你开始分类之前。getFileSizefdrdifdr9r8readfdr11rcxsyscall.LstartSortrdirsi

答: 暂无答案