일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 파이썬
- 자료구조
- 스플릿키보드
- GraphQL
- 부동소수점
- 도커
- 42서울
- adminbro
- 스타트업
- 프라이빗클라우드
- 엣지컴퓨팅
- 텍스트북
- Cloud Spanner
- 창업
- uuid-ossp
- enable_if
- 42seoul
- 쿠버네티스
- 레이캐스팅
- c++
- raycasting
- 동료학습
- 어셈블리
- 정렬
- SFINAE
- psql extension
- mistel키보드
- 이노베이션아카데미
- 어셈블리어
- schema first
- Today
- Total
written by yechoi
[어셈블리어] ___error 함수로 에러 처리하기 본문
** 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을 넣어둔다.
참고로 그냥 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을 넣고 반환한다.
**잘못된 정보가 있으면 댓글 주십셔**