C declaration / intel data type / suffix / Size
1. char / Byte / b / 1
2. short / Word / w / 2
3. int / Double word / l / 4
4. long / Quod word / q / 8
5. char* / Quad word / q /8
6. float / Single precision / s / 4
7. double / Double precision / d / 8
Operand Types
- immediate : $0x11..
- register : %rax
- Memory : (%rax)
- src, Dest : 둘중 하나 이상은 register가 들어가야함
D(Rb, Ri,S)
D : displacement
Rb : Base register
Ri : Index register
S : Scale
- (Rb + Ri * S) + D
- FIFO
- 높은 주소(%rbp) -> 낮은 주소(%rsp)
- pushq Src : %rsp - 8 이후 스택에 적재
- pop Dest : %rsp 가 가리키는 값 추출 후 %rsp + 8
call label
1.자동 push (call 다음 명령어 주소 = 복귀 주소)
2.이후 label로 jump
ret
자동으로 pop
- rip가 ret 주소에 도착할 경우 저절로 스택에 저장된 주소값으로 복귀한 후 %rsp + 8
First 6 arguments
- 1st arg : %rdi
- 2nd arg : %rsi
- 3th : %rdx
- 4th : %rcx
- 5th : %r8
- 6th : %r9
- 추가 arg는 스택에 저장
return values = %rax에 저장
Stack Frames
각 함수별 스택의 공간 할당되고 이를 stack frames라 한다
%rbp는 Framepointer로써 제일 상단의 주소를 가짐
함수내의 함수 선언할 경우 %rsp의 값을 %rbp로 바꾼후 차례대로 push...
caller, callee saved : 함수 호출된후 해당 레지스터의 값의 변조를 예방하기 위해 스택에 저장
1.caller saved
- %r10, %r11
2.callee saved
- %rbx, %r12, %r13, %r14
- %rbp: frame pointer지만 callee-saved로도 사용가능
array T A[L]
연속적으로 메모리에 할당됨
접근
-A[i][j], k = sizeof(datatype) c = columns)
- A + (i * c+ j) + k


- 포인터 이용과 비교
- 유연성 측면에서는 포인터로 구현하는 것이 유리
- 포인터로 구현할시 메모리를 2번 읽어야하므로 효율성 측면에서는 연속적하당이 유리


- 정렬되지 않은 data들에 대해 정렬하기 위한 패딩값이 생기게됨
- 기준은 가장큰 byte값을 가지는 자료형을 기준 : double = 8bytes
- 위 그림에서는 8바이트 기준으로 정렬 이루어져야 함 -> 8 / 8 / 8
- 즉 내림차순으로 정렬하여 선언하는 것이 중요하다
- 구조체 배열 접근 : 구조체 하나 크기 * Index + 접근하고자 하는 element
- stack : 8MB limit
- Heap : 동적할당
- Data : 전역, static
- Text, Shared Libraries : read only

버퍼의 용량을 초과한 Index값에 접근하는 경우
- 위의 그림은 사용량을 체크하지 않았다.
- 취약한 라이브러리 : gets, strcpy, scanf(%s)...
- 보완 : gets -> fgets, strcpy -> strncpy, %s -> %ns)
- Stack addr를 랜덤값으로 변경
- Stack Canaries : 사이즈 이외의 값에 침범하지 못하도록 설정
- 카나리 값과 일치하는지 확인한다
- Shadow Stack
- memory Tag