csapp다
오늘은 3.4랑 3.7가능하면 3.8을 할 예정이다
나머지보다 이것들이 이번 주차 주요 단원이라니
중요한것부터 끝내고 시간나면 나머지 보는 느낌으로 말이다
레지스터 구조와 이름 체계 이해가 중요하다
예전 8086의 16비트 레지스터 → 32비트로 (%eax
등) → 64비트로 확장됨 (%rax
등)
새로운 8개 레지스터는 %r8
~ %r15
레지스터는 크기별로 나누어 접근 가능하다
%al
), 2바이트(%ax
), 4바이트(%eax
), 8바이트(%rax
) 등레지스터 값을 덮어쓸 때의 규칙이 있다
1, 2바이트 쓰기: 나머지 바이트는 그대로 둠
4바이트 쓰기: 상위 4바이트는 0으로 자동 초기화
호출 규약(Calling Convention) 에 따라
어셈블리 코드 분석이나 시스템 수준의 최적화, 디버깅을 위해 알아둬야 할 내용을 다루는 듯 하다
대부분의 명령어는 소스 값과 목적지 값을 지정하는 하나 이상의 피연산자를 가진다
피연산자는 세 가지 유형으로 분류 된다
$-577
또는 $0x1F
)종류 | 문법 형식 | 의미 | 명칭 |
---|---|---|---|
Immediate | $Imm |
상수 값 | 즉시 값 |
Register | ra |
R[ra] , 즉 레지스터 값 |
레지스터 |
Memory | Imm |
M[Imm] |
절대 주소 참조 |
Memory | (ra) |
M[R[ra]] |
간접 참조 |
Memory | Imm(rb) |
M[Imm + R[rb]] |
기준 + 오프셋 |
Memory | (rb,ri) |
M[R[rb] + R[ri]] |
인덱스 주소 |
Memory | Imm(rb,ri) |
M[Imm + R[rb] + R[ri]] |
인덱스 + 오프셋 |
Memory | (,ri,s) |
M[R[ri] * s] |
스케일 인덱스 |
Memory | Imm(,ri,s) |
M[Imm + R[ri] * s] |
스케일 + 오프셋 |
Memory | (rb,ri,s) |
M[R[rb] + R[ri] * s] |
스케일 인덱스 |
Memory | Imm(rb,ri,s) |
M[Imm + R[rb] + R[ri] * s] |
완전 일반형 |
여기서
s
(스케일 값)는 반드시1
,2
,4
,8
중 하나여야 하며,rb
,ri
는 모두 64비트 레지스터여야 한다.
mov
클래스 : 기본 데이터 복사변환 없이 소스 위치에서 목적지 위치로 데이터를 그대로 복사
mov
클래스 명령어명령어 | 설명 | 동작 |
---|---|---|
mov |
일반 복사 | D ← S |
movb |
1바이트(byte) 복사 | |
movw |
2바이트(word) 복사 | |
movl |
4바이트(double word) 복사 | |
movq |
8바이트(quad word) 복사 | |
movabsq |
64비트 즉시값 복사 | R ← I |
mov
명령어 조합 예시예시 명령어 | 의미 |
---|---|
movl $0x4050, %eax |
즉시값 → 레지스터 (4바이트) |
movw %bp, %sp |
레지스터 → 레지스터 (2바이트) |
movb (%rdi, %rcx), %al |
메모리 → 레지스터 (1바이트) |
movb $-17, (%esp) |
즉시값 → 메모리 (1바이트) |
movq %rax, -12(%rbp) |
레지스터 → 메모리 (8바이트) |
movabsq
: 64비트 즉시값 복사일반적으로 movq
명령어는 즉시값을 32비트의 2의 보수로 해석하고 이를 부호확장(sign-extend) 해서 64비트로 만든다
하지만 정확한 64비트 즉시값을 사용할 필요가 있을 때에는 movasbsq
를 사용한다.
즉시값은 64비트 전체를 사용 가능
목적지는 반드시 레지스터만 가능
movz
클래스 : 제로 확장 (Zero-extension)레지스터 또는 메모리에서 값을 읽고, 레지스터에 복사할 때 남은 상위 바이트를 0으로 채운다
명령어 | 설명 |
---|---|
movzbw |
바이트 → 워드 (1 → 2바이트) |
movzbl |
바이트 → 더블워드 (1 → 4바이트) |
movzwl |
워드 → 더블워드 (2 → 4바이트) |
movzbq |
바이트 → 쿼드워드 (1 → 8바이트) |
movzwq |
워드 → 쿼드워드 (2 → 8바이트) |
movs
클래스 : 부호 확장 (Sign-extension)상위 비트는 소스의 최상위 비트(sign bit)를 복제하여 채운다
명령어 | 설명 |
---|---|
movsbw |
바이트 → 워드 |
movsbl |
바이트 → 더블워드 |
movswl |
워드 → 더블워드 |
movsbq |
바이트 → 쿼드워드 |
movswq |
워드 → 쿼드워드 |
movslq |
더블워드 → 쿼드워드 |
cltq |
%eax → %rax (부호 확장) |
cltq
는movslq %eax, %rax
와 동일한 의미이지만, 더 짧은 인코딩을 가진다
C 코드와 어셈블리 코드로 데이터 이동 예제가 나온다
함수 인수는 레지스터를 통해 전달되며, 반환 값은 %rax
레지스터에 저장된다는 걸 확인 가능하다
스택과 푸시, 팝이다
여기에 대강 정리해 놨으니 대충만 설명하겠다
pushq
명령어기능: 8바이트(quad word)를 스택에 추가
동작:
%rsp
를 8만큼 감소
해당 위치에 값을 저장
예시
pushq %rbp
는 아래의 두 명령어와 동일
subq $8, %rsp ; 스택 포인터 감소
movq %rbp, (%rsp) ; 값을 스택에 저장
차이점이라면 puqsh
는 1바이트 인코딩이고 위 두 명령어는 총 8바이트 인코딩이다
popq
명령어기능: 스택에서 8바이트 값을 꺼내어 레지스터에 저장
동작:
%rsp
가 가리키는 위치에서 값을 읽어옴
%rsp
를 8만큼 증가
예시
popq %rax
는 아래와 같다
movq (%rsp), %rax ; 스택에서 값 읽기
addq $8, %rsp ; 스택 포인터 증가
명령어 | 동작 요약 |
---|---|
pushq S |
%rsp -= 8 → [rsp] = S |
popq D |
D = [rsp] → %rsp += 8 |
스택은 아래 방향으로 증가 (주소 감소)
%rsp
는 항상 현재 top을 가리킨다
스택 접근은 메모리 참조 방식으로 직접 지정도 가능