0. 프로젝트 목표
- nasm을 이용해서 libc 함수 구현하기
-> ft_strlen, ft_strcmp, ft_strcpy
-> ft_write, ft_read
-> ft_strdup
1. 학습
nasm을 설치하고 HelloWorld찍기
calling convention에 대해서 얄팍하게 알아보기
1. 함수 반환은 rax에 저장
2. 매개변수는 순서대로 [ rdi, rsi, rdx, rcx, r8, r9 ] 라고 함 ("최대가 6개다.."라는 글을 어디서 봄)
3. 즉, 매개변수가 있는 함수를 호출 할 때는 위의 레지스터에 값을 설정하고 호출하면 됨
4. ret만나면 caller로 돌아감
-> 모두 알 필요는 없음
cs.lmu.edu/~ray/notes/nasmtutorial/
문법 공부해보기
-> HelloWorld를 출력하는 예제를 실행해보면 각종 구문이 많이 나옴
-> 깊이는 알 필요없지만 어느정도는 알고 가야 함
1
2
3
4
5
|
global _symbol ; 심볼 만들기, _필요
section .text ; 코드 영역
extern _malloc ; 외부 함수
_symbol : ; 레이블 붙이기 (like goto format)
label... :
|
cs |
- global은 함수심볼을 외부에 던지기 위함
- underscore는 macOS에서는 강제된다고 함
- section .text 는 실제 코드를 위한 섹션 (cf, section .data 는 상수나 초기화 값을 위한 섹션)
- 외부 함수는 extern 으로 가져와서 call함
필요한 syscall 에서의 고민들 (ft_write, ft_read에서)
- write, read함수가 error를 만날 때 어느 상황이 일어나는가
-> 즉, error를 만나면 우리는 errno을 설정해주어야 하는데 어떻게 해야 할까
-> error를 나는 어떻게 캐치하는가
-> ___error 함수는 무엇이고 무엇을 리턴하는 가
1. rax에 syscall code를 넣고 syscall을 함
2. syscall이 error라면 carry flag가 활성화 됨 (참고는 아래)
3. 그와 동시에 errno을 양수로 반환 (rax에는 errno이 담겨있음)
4. 그럼 나는 carry flag가 활성화 되어있으면 error label로 넘겨줌
5. error label에서는 errno가 담긴 rax을 잠시 저장하고 ___error를 호출해서 &errno을 받아옴
6. errno에 값을 넣어주고
7. mov rax, -1 후 ret하면 됨
2. 참고 글
cf) 레지스터를 잠시 저장할 때는 안쓰는 레지스터에 넣는다는 생각보다는 그냥 push해놓고 필요할 때 pop하는 게 좋음
-> ___error를 사용하거나 다른 외부함수를 사용할 때 에러를 발생할 때, 임의로 사용 중인 레지스터를 push 해버리면 에러가 안남...
-> slack에서 ryukim님 말로는 매개변수로 인식하는 경우가 있다고 함
cf) syscall중에 error에 대한 글 (jc 분기문으로 잡는 근거)
www.freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/x86-return-values.html
stackoverflow.com/questions/15304829/how-to-return-errno-in-assembly
>>> errno, ___error에 관한 stackoverflow
cf) syscall에 0x02000000에 대한 글
stackoverflow.com/questions/48845697/macos-64-bit-system-call-table
cf) syscall number
opensource.apple.com/source/xnu/xnu-1504.3.12/bsd/kern/syscalls.master
cf) 구조체에 대한 글
-> 어셈블러는 구조체가 뭔지모름 -> 그냥 메모리 참조임
stackoverflow.com/questions/6549708/in-assembly-how-do-you-deal-with-c-struct
cf) 매개변수나 call로 리턴받은 rax레지스터의 정수 음수검사
-> 무조건 cmp rax, 0 로 검사하는 것이 아님
-> 자료형에 따라 다르게 계산해야 함
-> 리턴 값이 int라면 4byte라서 eax로 검사해야 함
-> 그렇지 않으면 앞의 4바이트의 부호비트는 0이라서 항상 양수임
cf) intel VS AT&T 의 어셈블리 차이
cf) syscall 사용
3. 마무리
Windows의 32bit를 올리디버거로 까본 적이 있기 때문에 수월했음
-> 그렇지 못한 사람은 기초적인 문법, 명령어 부터 공부를 해야 할 듯
-> 그 후에 기본적인 함수를 작성 후 libasm에 도전하는 것이 맞는 듯
함수 호출 규약에 대해서는 깊게 공부하는 거 아닌 이상 특정한 상황에 대한 예외를 알아차리기 힘듦
libasm하면서 64bit로 처음 봄
-> 큰 차이는 없음
asm -> .c 로 변환하는 과정은 많이 해봤으나
.c -> asm로 하는 과정이 좀 더 어려운 듯
기본적인 내용을 알고 작성하니 정말 재밌는 서브젝트였음
'42cursus' 카테고리의 다른 글
ft_services - 가이드 및 참고자료 정리하기 (42seoul) (0) | 2021.01.07 |
---|---|
Kubernetes(쿠버네티스) 개념 정리하기 (0) | 2021.01.07 |
cub3d - mlx사용법 위주로 정리하기 (42seoul) (2) | 2020.11.03 |
ft_server - 가이드 및 참고자료 정리하기 (42seoul) (2) | 2020.10.19 |
ft_printf - 초간단 정리 (42seoul) (3) | 2020.10.11 |