提问人:YB1925 提问时间:10/22/2023 最后编辑:YB1925 更新时间:10/22/2023 访问量:69
运行“sorter.s”时出现分段错误(核心转储)
Segmentation fault (core dumped) when running "sorter.s"
问:
在我们的练习中,我们将编写一个程序,当给定 (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 ──────────────────────────────────────────────────────────────────────────────
答: 暂无答案
上一个:C 缓慢的缓冲区访问 [已关闭]
评论
r13
getFileSize
fd
rdi
fd
r9
r8
read
fd
r11
rcx
syscall
.LstartSort
rdi
rsi