반응형
3.4 정보 접근하기
- x86-64 주처리장치 cpu는 64비트 값을 저장할 . 수있는 16개의 범용 레지스터를 보유하고 있다.
- 레지스터는 '정수 데이터'와 '포인터'를 저장하는데 사용된다.
- 레지스터 각각은 특정한 목적을 가졌으며, 따라서 이들은 이들이 사용되는 방법을 반영하는 이름이 붙여졌다.
- 인스트럭션들은 16개의 레지스터 하위 바이트들에 저장된 다양한 크기의 데이터에 대해 연산 할 수있다.
- 16비트 → 2바이트
- 32비트 → 4바이트
- 64비트 → 레지스터 전체에 접근
- 인스트럭션들이 레지스터들을 목적지로 할 때, 8바이트보다 작은 바이트를 생성하는 인스트럭션들의 레지스터에서 남는 바이트들에 대해 어떻게 처리할 것인가는 2가지로 선택할 수 있다.
- 1 또는 2바이트를 생성하는 경우는 나머지 바이트들은 변경 없이 그대로 유지한다.
- 4바이트 길이의 값을 생성하는 경우는 상위 4바이트를 0으로 설정한다.
오퍼랜드 식별자
- 레지스터: CPU 내부의 작은 저장 공간으로, 데이터를 임시로 저장하고 빠르게 처리하기 위해 사용됩니다. 레지스터는 보통 8바이트(64비트) 크기입니다.
- 인스트럭션: CPU가 수행하는 명령어로, 특정 연산을 지시합니다.
- 대부분의 인스트럭션은 하나 이상의 오퍼랜드를 가진다.
- 오퍼랜드 : 연산을 수행할 소스값과 그 값을 저장할 목적지의 위치를 명시한다. ⇒ 작업을 수행할 때 사용하는 데이터나 데이터의 위치
- 소스 값: 상수로 주어지거나 레지스터나 메모리로부터 읽을 수 있다.
- 결과 값: 레지스터나 메모리에 저장
- 오퍼랜드 : 연산을 수행할 소스값과 그 값을 저장할 목적지의 위치를 명시한다. ⇒ 작업을 수행할 때 사용하는 데이터나 데이터의 위치
종류
- 즉시값(immediate) : 명령어 자체에 포함된 '고정된 상수값'. 이 값은 실행 시에 변경되지 않으며, 명령어가 실행될 때 바로 사용.
- 특징:
- ATT형식의 어셈블리 코드로서, 상수는 $기호 다음에 c표준 서식을 사용하는 정수로 $-577과 $0x1F같이 나타낸다.
(ATT 형식의 어셈블리에서는 즉시값을 '$' 기호 다음에 숫자로 표시한다.)
[‘-577’이라는 값을 즉시값으로 표현할 때는 ‘$-577’로 쓴다] - C표준 서식을 적용하여 정수 표기한다. ⇒ C언어에서 숫자 표한하는 방식
- 어셈블러는 해당 값을 인코딩하는 가장 컴팩트한 방법을 자동으로 선택한다.
- ATT형식의 어셈블리 코드로서, 상수는 $기호 다음에 c표준 서식을 사용하는 정수로 $-577과 $0x1F같이 나타낸다.
- 특징:
ex
MOVL $0x1F, %eax ; 0x1F (31)를 레지스터 EAX에 이동
ADDQ $-577, %rbx ; -577을 레지스터 RBX에 더함
- 레지스터(Register) : 레지스터의 내용을 오퍼랜드로 사용
- 각각 16개의 64비트, 32비트, 16비트, 8비트 레지스터들의 하위 일부인 8,4,2,1 바이트 중 하나의 레지스터를 가리킨다.
- 특징:
- 레지스터는 CPU 내부에 있어 접근 속도가 매우 빠르다.
- 레지스터를 사용하는 명령어는 메모리 접근을 피할 수 있어 효율적이다.
- 메모리 참조(Memory Regerence) : 유효주소라고 부르는 계산된 '주소에 의해' 메모리 위치에 접근한다.
- 메모리는 거대한 '바이트의 배열'로 생각할 수 있음 ⇒ M_b[Addr]과 같이 표시하여 메모리 내 특정 주소(Addr)부터 저장된 b 바이트를 참조한다
- 여러가가지 유형의 메모리 참조를 가능하게 하는 많은 주소지정방식이 존재한다. 일반적인 형태는 'Imm(r_b, r_i, s)'다. 이 형태의 참조는 네 개의 구성요소를 갖는다.
- 상수 오프셋(Imm):
- 명령어에 포함된 고정된 값.
- 메모리 주소를 계산할 때 기본값으로 사용.
- 베이스 레지스터(r_b):
- 유효 주소를 계산할 때 사용하는 기본 레지스터.
- 주로 배열이나 구조체의 시작 주소를 가리키는 데 사용됌.
- 인덱스 레지스터(r_i):
- 배열의 특정 원소에 접근할 때 사용. 배열의 인덱스 역할을 하며, 배율(s)과 함께 사용.
- 배율(s):
- 인덱스 레지스터의 값을 몇 배로 늘릴지 결정. 일반적으로 1, 2, 4, 8의 값을 가짐.
- 이는 배열의 요소 크기(예: 4바이트 정수 배열에서는 s=4)를 나타냄.
- 상수 오프셋(Imm):
- 유효 주소 계산
- 일반적인 형태는 배열의 원소를 참조할 때 종종 볼 수 있다. 다른 형태들은 모두 이들 구성요소의 일부가 생략된 특별한 경우이다.
ex)
MOV RAX, 8(RBX, RCX, 4)
- 8: 상수 오프셋 'Imm'
- RBX: 베이스 레지스터 'r_b'
- RCX: 인덱스 레지스터 'r_i'
- 4: 배율 's'
⇒ 유효주소: 8 + R[RBX] + R[RCX] * 4 ⇒ 이 주소에서 데이터를 읽어와 ‘RAX’레지스터에 저장
데이터 이동 인스트럭션
정의
- '데이터 이동 명령어'는 데이터를 한 위치에서 다른 위치로 복사하는 작업을 수행한다.
- 이 명령어들은 소스 오퍼랜드(Source Operand)에서 데이터를 읽고, 목적지 오퍼랜드(Destination Operand)에 그 데이터를 쓴다.
- 설명하는 여러 개의 인스트럭션 클래스로 구분하고, 클래스의 인스트럭션들은 동일한 동작을 다른 오퍼랜드 크기를 사용하여 수행한다.
- 소스 오퍼랜드 : 상수, 레지스터 저장 값, 메모리 저장 값을 표시한다.
- 상수(Constant): 예를 들어, 즉시값(Immediate value)과 같은 값이 명령어에 포함될 수 있다.
- 레지스터(Register): CPU 내부에 있는 저장소로, 매우 빠르게 접근할 수 있는 위치
- 메모리 위치(Memory Address): 메모리 내의 특정 주소로, 데이터를 읽어올 수 있는 위치
- 목적 오퍼랜드 : 레지스터 또는 메모리 주소의 위치를 지정한다.
- 레지스터(Register): 데이터를 저장할 CPU 내부의 저장소
- 메모리 주소(Memory Address): 메모리 내의 특정 위치`
인스트럭션 클래스
- 인스트럭션들은 소스 위치에서 데이터를 목적지 위치로 어떤 변환도 하지 않고 복사한다.
- 이 클래스는 오퍼랜드 크기에 따라 네 개의 인스트럭션으로 구성된다: movb, movw, movl, movq
- movb: 1바이트(8비트)를 이동
- movw: 2바이트(16비트)를 이동
- movl: 4바이트(32비트)를 이동
- movq: 8바이트(64비트)를 이동
x86-64의 메모리 참조 제한
- x86-64 : 데이터 이동 인스트럭션에서 두 개의 오퍼랜드 모두가 메모리 위치에 올 수 없도록 제한하고 있다.
- → 이러한 제한 떄문에 메모리에서 다른 메모리 위치로 직접 이동할 수 없다.
- 하나의 메모리 위치에서 다른 위치로 어떤 값을 복사하기 위해서는 두 개의 인스트럭션이 필요하다.
- 소스 값을 레지스터에 적재하는 인스트럭션
ex
'movq [source_address], %rax'는 메모리의 'source_address'에서 8바이트 데이터를 읽어와 레지스터 'RAX'에 저장한다. - 이 레지스터의 값을 목적지에 쓰기 위한 인스트럭션
ex
'movq %rax, [destination_address]'는 레지스터 'RAX'에 있는 데이터를 'destination_address'에 저장한다.
- 소스 값을 레지스터에 적재하는 인스트럭션
- 일반적인 MOV 명령어 동작
- MOV 인스트럭션의 조합의 소스와 목적지 유형
- 소스 오퍼랜드가 먼저 나오고 다음에 목적 오퍼랜드가 나온다
- MOVQ와 MOVABSQ 명령어와 MOVABSQ 인스트럭션
- 확장 이동 명령어 (MOVZ, MOVS)
- 0으로 확장하는 데이터 이동 인스트럭션
스택 데이터의 저장과 추출
스택의 개념
- 두 개의 데이터 이동 연산은 프로그램 스택에서 데이터를 저장('push')하거나 스택에서 데이터를 추출('pop')하기 위해 사용
- 스택은 프로시저 호출을 처리하는데 중요한 역할을 함
- 'push' 연산으로 스택에 데이터를 추가하고 'pop'연산으로 제거하되, 제거하는 값이 가장 최근에 추가된 값(last -in, first-out)이어야 하며, 그 값은 스택에 여전히 남아있다.
- 스택은 배열로 구현될 수 있으며, 배열에서 원소들을 배열의 한쪽 끝에서만 추가하거나 제거함. 이 끝부분을 스택의 'top'이라고 함.
- 스택의 top 원소가 모든 스택 원소 중에서 가장 낮은 주소를 갖는 형태로, 스택은 아래방향으로 성장한다. →새로운 데이터를 추가할 때 스택 포인터는 감소한다.
스택 포인터 (%rsp)
- 스택의 맨 위(top)를 가리키는 포인터입니다. 스택에 데이터가 추가될 때마다 %rsp는 감소하고, 데이터가 제거될 때마다 증가합니다.
- 'popq '인스트럭션이 데이터를 추출하는 반면, 'pushq' 인스트럭션은 데이터를 스택에 추가하는 기능을 한다. 이들 인스트럭션은 한 개의 오퍼랜드를 사용한다-추가할 소스 데이터와 추출을 위한 데이터 목적지
- 쿼드워드 값을 스택에 추가하려면, 먼저 스택 포인터를 8 감소시키고, 그 값을 스택 주소의 새로운 탑(top)에 기록하는 것으로 구현된다. 그러므로 pushq %rbp 인스트럭션의 동작은 다음과 같은 한 상의 인스트럭션과 동일하다.
- 그러나 위의 두 개의 인스트럭션은 총 8바이트가 필요하지만, pushq 인스트럭션은 한 바이트의 기계어 코드로 인코딩된다는 점이 다르다. 첫 두열은 %rsp가 0x108이고 %rax가 0x123일 때 pushq %rax를 실행한 결과를 보여준다. 먼저 %rsp는 8 감소해서 0x100이 되고, 0x123이 메모리 주소 0x100에 저장된다.
- 쿼드워드 팝pop하는 것은 스택 탑 위치에서의 읽기 작업 후에 스택 포인터를 8 증가시키는 것으로 구현된다. 그러므로 popq %rax 인스트럭션은 다음 한 쌍의 인스트럭션과 동일하다
- pushq 실행 직후에 popq %rdx 인스트럭션을 실행한 결과를 보여준다. 값 0x123을 메모리에 읽어서 레지스터 %rdx에 기록한다. 레지스터 %rsp는 다시 0x108로 복구되었다. 값 0x123은 다른 값이 덮어써질 때까지 메모리 주소 0x100에 여전히 남아있다. 그렇지만 스택 탑은 언제나 %rsp가 가리키는 주소를 의미한다. 스택 탑보다 윗부분에 저장된 값은 모두 무효인 값들이다.
- 스택이 프로그램 코드와 다른 형태의 프로그램 데이터와 동일한 메모리에 저장되기 때문에 프로그램들은 표준 메모리 주소지정 방법을 사용해서 스택 내 임의의 위치에 접근할 수 있다. 일례로, 스택 최상위 원소가 쿼드워드라고 가정하면, movq 8(%rsp), %rdx 인스트럭션은 스택의 두 번째 쿼드워드를 레지스터 %rdx에 복사해준다.
반응형
'CS > Computer System' 카테고리의 다른 글
2. RBTREE 트리 생성, 삭제 (0) | 2024.09.15 |
---|---|
1. RBTREE란? (0) | 2024.09.15 |
[CS:APP] 1-7 운영체제는 하드웨어를 관리한다 (1) | 2024.08.27 |
[CS:APP] 1-5~1-6) 캐시 메모리, 저장장치의 계층 구조 (2) | 2024.08.27 |
[CS:APP] 1-4 프로세서의 작동 원리 (3) | 2024.08.21 |