The next code throws segmentation fault:
.global	compute_char_repeats, parse_lines

.section .text
compute_char_repeats:
	# %rdi: char* buffer, %esi (rsi 32 bit): int line_length, %dl (rdx 1 byte): char special_character
	
	# TODO backup rdi, rsi???

	push %rbp
	mov %rsp, %rbp

	# %r9d: int amountOfAppearances = 0;
	movl $0, %r9d
	# %r10d: int index = -1; (first iter will set it to 0)
	movl $-1, %r10d
	# %r11b: char in curr index
	
	GET_CHAR_HW3:
		inc %r10d
		# Exit loop if index >= length asm Copy Edit
		cmp %esi, %r10d
		jge GET_CHAR_LOOP_END_HW3
		movb (%rdi, %r10, 1), %r11b
		cmp %dl, %r11b
		jne GET_CHAR_HW3
		inc %r9d
		jmp GET_CHAR_HW3

	GET_CHAR_LOOP_END_HW3:
	
	# set return value in eax (32 bit of rax)
	mov %r9d, %eax
	pop %rbp
	ret


find_next_newline:
	# %rdi: char* start_of_buffer, %rsi long max_length
	# return: %rax: min{length_to_closest_newline, max_length}

	# TODO backup rdi, rsi???

	push %rbp
	mov %rsp, %rbp

	# lengthFromNewline (%r11) = 0
	movq $0, %r11
	cmpq $0, %rsi
	jle FOUND_NEWLINE_HW3
	# %r10b: current char
	READ_LINE_CHAR_HW3:
		# read from index i
		movb (%rdi, %r11, 1), %r10b
		# length after read from i is i+1
		inc %r11
		# Check if current char is newline
		cmpb $'\n', %r10b
		je FOUND_NEWLINE_HW3
		# Stop if lengthFromNewline reached max_length
		cmpq %rsi, %r11
		# lengthFromNewline = max_length
		cmovge %rsi, %r11
		jge FOUND_NEWLINE_HW3
		
		jmp READ_LINE_CHAR_HW3

	FOUND_NEWLINE_HW3:
		mov %r11, %rax
		pop %rbp
		ret
	

parse_lines:
	# %rdi: char* path, %rsi: int* line_max_length, %rdx: int* line_max_repeat
	push %rbp
	mov %rsp, %rbp
	push %rbx # callee-saved

	# *line_max_length = 0;
	movq $0, (%rsi)
	# *line_max_repeat = 0;
	movq $0, (%rdx)

	# save caller-saved rdx
	subq $32, %rsp
	movq %rdx, -24(%rbp)

	# %bl (%rbx first byte): char special_character = get_the_special_char();
	call get_the_special_char
	mov %rax, %rbx

	movq -24(%rbp), %rdx

	# now stack has 128 bytes allocated
	subq $96, %rsp

	push %rsi
	push %rdx

	movq $2, %rax # sys_open
	# %rdi already has path to file
	movq $0, %rsi # (O_RDONLY)
	movq $256, %rdx # (S_IRUSR = 00400q)
	syscall

	# %rax now has the fd of the file
	# TODO error handling?
	pop %rdx
	pop %rsi

	# %r12 = file_desc
	mov %rax, %r12

	# oldLength (%r13) = 0
	movq $0, %r13
	# oldCharAppear (%r15) = 0
	movq $0, %r15

	# length (%rcx) = 0
	movq $0, %rcx
	# charAppear (%r11) = 0
	movq $0, %r11

	# totalLines (%r14) = 1
	# This is because an empty file is considered to have one (empty) line
	# Each '\n' adds 1 to the amount of lines in the file
	movq $1, %r14

	READ_CHUNK_HW3:
		push %rdi
		push %rsi
		push %rdx
		push %rcx
		push %r11

		# top of stack before reg backup - stackPointer + length_of_reg_backup (40) 
		mov %rsp, %r11
		addq $40, %r11

		movq $0, %rax # sys_read
		mov %r12, %rdi # file_desc
		mov %r11, %rsi # dest_addr = stack_top (not including backup) 
		movq $128, %rdx # read 128 bytes (at most)

		syscall

		# %rax now is the amount of bytes actually read

		pop %r11
		pop %rcx
		pop %rdx
		pop %rsi
		pop %rdi

		# on end-of-file jump to end of func
		cmpq $0, %rax
		je PARSE_END_HW3

		# startOfLine (%r9) = 0
		movq $0, %r9

		READ_LINE_HW3:
			# oldLength = length
			mov %rcx, %r13
			# oldCharAppear = charAppear
			mov %r11, %r15

			# length (%rcx) = 0
			movq $0, %rcx
			# charAppear (%r11) = 0
			movq $0, %r11

			push %rdi
			push %rax
			push %rsi
			push %r11

			# start_of_line_in_stack = stackPointer + length_of_reg_backup (32) + startOfLine
			mov %rsp, %rdi
			addq $32, %rdi
			add %r9, %rdi
			# lineMaxLength = 128 - startOfLine
			movq $128, %rsi
			sub %r9, %rsi
			call find_next_newline

			# length (%rcx) = %rax
			mov %rax, %rcx
			
			pop %r11
			pop %rsi
			pop %rax
			pop %rdi


			push %rdi
			push %rax
			push %rdx
			push %rsi
			push %r9
			
			# start_of_line_in_stack = stackPointer + length_of_reg_backup (40) + startOfLine
			mov %rsp, %rdi
			addq $40, %rdi
			add %r9, %rdi
			# lineLength = length (%rcx)
			mov %rcx, %rsi
			# param special_character = %rbx
			mov %rbx, %rdx
			call compute_char_repeats


			# charAppear (%r11) = %rax (ret value)
			mov %rax, %r11

			pop %r9
			pop %rsi
			pop %rdx
			pop %rax
			pop %rdi

			
			# If this is the first line in a chunk
			# (therefore, prev line was fully read, not cut off at middle of chunk)
			
			# check if last char in line is \n (otherwise we got to end of file or we got split by a chunk)
			
			# char *lastLineCharPosition (%r8) = stack_p + length - 1
			mov %rsp, %r8
			add %rcx, %r8
			dec %r8

			# char lastLineChar (%r8b) = *lastLineCharPosition (old %r8)
			movb (%r8), %r8b
			cmpb $'\n', %r8b
			jne IS_NOT_NEWLINE_HW3

			# endWithNewline (%r8) = true
			movq $1, %r8
			jmp LENGTH_LOGIC_HW3
			IS_NOT_NEWLINE_HW3:
				# endWithNewline (%r8) = false
				movq $0, %r8
			
			LENGTH_LOGIC_HW3:
			# in that case, skip the merge chunk logic
			cmpq $0, %r13
			je CHECK_MAX_HW3


			# merge chunk length and appearances

			# charAppear += oldCharAppear
			add %r15, %r11
			# length += oldLength
			add %r13, %rcx

			

			CHECK_MAX_HW3:
				# Update line_max_repeat if charAppear is larger
				cmp (%rdx), %r11
				mov (%rdx), %r8       # temp register to hold old line_max_repeat
				cmp %r8, %r11
				cmovge %r11, %r8
				mov %r8, (%rdx)
				# Update line_max_length if length is larger
				cmp (%rsi), %rcx
				mov (%rsi), %r8       # temp register to hold old line_max_length
				cmp %r8, %rcx
				cmovge %rcx, %r8
				mov %r8, (%rsi)

			# Reset length and charAppear if line ends with newline
			cmp $0, %r8
			je READ_CHUNK_HW3

			inc %r14
			# length (%rcx) = 0
			movq $0, %rcx
			# charAppear (%r11) = 0
			movq $0, %r11

			jmp READ_CHUNK_HW3
	
	PARSE_END_HW3:

	push %rdi
	push %rcx
	push %rsi
	push %r11

	mov $3, %rax # sys_close
	mov %r12, %rdi # %rdi = file_desc
	syscall

	pop %r11
	pop %rsi
	pop %rcx
	pop %rdi

	mov %r14, %rax
	pop %rbx # callee-saved
	pop %rbp
	ret