written by yechoi

[어셈블리어] ___error 함수로 에러 처리하기 본문

Born 2 Code/Assembly

[어셈블리어] ___error 함수로 에러 처리하기

yechoi 2020. 8. 6. 13:28
반응형

** macos, intel syntax 기준 ** 

section .text
	global _ft_read
	extern ___error

_ft_read:
	mov rax, 0x2000003
	syscall
	jc _err
	ret

_err:
	push rax
	call ___error
	pop rdx
	mov [rax], rdx
	mov rax, -1
	ret

 

read()를 재구현해놓은 어셈블리 코드다. 위 코드를 바탕으로 에러를 처리하는 방법을 정리한다. 

 

 

syscall로 read 함수 호출하기 

_ft_read:
	mov rax, 0x2000003
	syscall

 

rax에 넣어놓는 값에 따라 syscall로 호출되는 함수가 다르다. 1은 exit, 4는 write. 여기선 read() 함수를 호출하기 위해, rax에 3을 넣어둔다.

출처 : https://opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master

 

참고로 그냥 3이 아닌 0x200003인 이유는 macos에선 syscall에 클래스를 두기 때문. macosx나 bsd는 system call 번호를 여러 ‘class'로 나눠뒀다. read나 write는 syscall_class_unix에 속하기 때문에 upper bits 를 2로 설정한다. 즉 unix system call 의 system call 은 (0x2000000 + unix syscall #)가 된다.

 

 

에러 처리 구문으로 넘어가기 

	jc _err
	ret

 

syscall 함수는 rax에 error value를 리턴한다. 오류가 있을 경우 작은 음수 (-1 ~ -4095)를 내뱉는다고 한다. 이는 unsigned int 값을 벗어나는 연산 결과이므로, carry flag가 참이 된다. 따라서 jc(carry flag가 1일 때 점프)를 활용하면 에러 처리 구문(_err)로 넘어갈 수 있다.

 

 

___error 이용해 에러 처리 하기

_err:
	push rax
	call ___error
	pop rdx
	mov [rax], rdx
	mov rax, -1
	ret

 

먼저 rax에 담겨있는 error value를 push해 스택에 백업해둔다. 그 다음에 ___error 함수를 호출하면 에러 주소값이 rax에 담긴다. rdx에 스택에 저장시켜 놨던 error value를 팝해온다. 

 

rdx에 담긴 error value를 에러 주소를 변경하지 않고 고대로 집어 넣기 위해 `mov [rax], rdx` 해준다. rax에 []를 씌워주면 주소는 건들지 않고 값만 바꿀 수 있다.

 

그리고 마지막으로 return value는 -1이 돼야 하므로 rax에 -1을 넣고 반환한다. 

 

**잘못된 정보가 있으면 댓글 주십셔**

반응형