과제/libasm
[libasm] 01. 기초지식 - 리눅스의 호출 규약과 어셈블리코드 정리
Pearan
2021. 2. 24. 22:28
1. 호출규약
윈도우와 리눅스의 호출규약은 서로 다르다.

출처: Paul A. Carter의 [PC 어셈블리어]에서 1.3.4
출처: nasm 어셈블리 산술 연산
출처: movsx, movzx
| MOV | MOV dest, src -> src에 있는 데이터를 dest에 복사 | |
| ADD | 정수 a, b 일때 a + b | |
| SUB | 정수 a, b 일때 a - b | |
| INC | INC dest -> dest를 1 증가 시킨다. dest++ | 기계코드 크기가 ADD, SUB보다 더 작다. |
| DEC | DEC dest -> dest를 1 감소 시킨다. dest– | 기계코드 크기가 ADD, SUB보다 더 작다. |
| MUL | MUL multiplier 부호 없는 데이터를 곱합니다. | |
| IMUL | IMUL multiplier Integer mul. 부호 있는 데이터를 곱합니다. | |
| DIV | ||
| IDIV | ||
| movzx | dst가 src보다 큰 공간이어도 복사가 되고, 남는 공간은 0으로 채워진다. | 부호가 없는 정수에만 사용 |
| movsx | 남는 공간이 1로 채워진다. | 부호가 있는 정수에만 사용한다 |
| *참고: 부호비트 자리가 1이라는 것은 컴퓨터에게 ‘음수거나 부호가 있는 정수’라는 뜻이다. | ||
| 그니까 왜냐면.. 음수(부호가 있는 수)계산은 사실은 항상 보수처리해서 더하기로 진행하니까..? |

64bit NASM Assembly Register
| Name | Notes | Type | 64-bit long |
32-bit int |
16-bit short |
8-bit char |
| rax | Values are returned from functions in this register. | scratch | rax | eax | ax | ah and al |
| rcx | Typical scratch register. Some instructions also use it as a counter. | scratch | rcx | ecx | cx | ch and cl |
| rdx | Scratch register. | scratch | rdx | edx | dx | dh and dl |
| rbx |
Preserved register: don't use it without saving it! | preserved | rbx | ebx | bx | bh and bl |
| rsp |
The stack pointer. Points to the top of the stack (details coming soon!) | preserved | rsp | esp | sp | spl |
| rbp |
Preserved register. Sometimes used to store the old value of the stack pointer, or the "base". | preserved | rbp | ebp | bp | bpl |
| rsi | Scratch register used to pass function argument #2 in 64-bit Linux. In 64-bit Windows, a preserved register. | scratch | rsi | esi | si | sil |
| rdi | Scratch register and function argument #1 in 64-bit Linux. In 64-bit Windows, a preserved register. | scratch | rdi | edi | di | dil |
| r8 | Scratch register. These were added in 64-bit mode, so they have numbers, not names. | scratch | r8 | r8d | r8w | r8b |
| r9 | Scratch register. | scratch | r9 | r9d | r9w | r9b |
| r10 | Scratch register. | scratch | r10 | r10d | r10w | r10b |
| r11 | Scratch register. | scratch | r11 | r11d | r11w | r11b |
| r12 |
Preserved register. You can use it, but you need to save and restore it. | preserved | r12 | r12d | r12w | r12b |
| r13 |
Preserved register. | preserved | r13 | r13d | r13w | r13b |
| r14 |
Preserved register. | preserved | r14 | r14d | r14w | r14b |
| r15 |
Preserved register. | preserved | r15 | r15d | r15w | r15b |
위 표는 어떨때 쓰냐면, 여기 과제에서는 대부분 char 형(8-bit) 를쓰기 때문에, 내가 만약에 rax가 가르키는 주소에서 char를 읽어서 다른 레지스터에 넣는다 하면
mov rcx, BYTE [rax] 이런식으로 쓰면 rcx 는 64bit 기 때문에 에러가 난다. 따라서 rcx 에 넣고 싶으면 저 위 표를 보고
mov cl, BYTE [rax] 이런식으로 넣어야 한다.
syscall 와 ___error 를 통한 에러처리 (write 를 예로)
section .text
global _ft_write
extern ___error
_ft_write:
mov rax, 0x2000004 syscall을 사용하기 위해 rax 에 syscall 번호를 넣어줌
syscall rax에 write 의 리턴값을 저장
jc err 만약 에러가 났다면 carry flag = 1 로 바뀌므로 jc 로 체크해서 점프
ret 아니라면 그대로 리턴
err:
push rax write 는 에러가 났을경우 에러번호를 rax에 그대로 담아두기에 일단 푸쉬함
call ___error errno 을 담을 주소값을 rax에 리턴해줌
pop rcx write 가 push 해둔 rax의 값을 rcx 로 pop함
mov [rax], rcx rax 가 가르키는 주소의 값에 rcx값을 넣어줌
mov rax, -1 rax (리턴값) 에는 -1 을 넣어줌
ret
처음에
err:
함수 부분에서
push rax
call ___error
pop rcx
하지말고
mov rcx, rax
call ___error
하면 되는것 아닌가? 했는데 ___error 에서 rcx 값에다가 무슨짓을 할지 모른다. 따라서 push 한 후 함수호출이 끝나면
pop 하는 것이 안전하다 (라고 나는 생각했다)