C H A P T E R 4 ::: 주소 지정 방식 :::
공부할 내용
★ 주소 지정 방식 (addressing)
★ 세그먼트와 세그먼트 레지스터
★ 스택의 구현
★ 직접 주소 지정
★ 간접 주소 지정
★ 인덱싱
★ 인덱스 레지스터, 베이스 레지스터
★ 주소를 지정하는 일반적인 규칙
★ 코드세그먼트내에서의 주소 지정
기초적인 PC 주소 지정 방식
★ 기계어 명령이 사용하는 주소의 길이 = 16비트
- 16비트를 사용하여 만들 수 있는 주소 = 0000H부터 FFFFH까지
따라서, 메모리의 크기 <= 64K 바이트 (이는 지나친 제약임)
★ 더 나은 방법은?
움직이는 팔을 가진 로보트가 있다고 하자.
그 로보트의 팔은 64인치만큼 들락날락하며 움직일 수 있다고 하자.
(1) 로보트가 방안의 어떤 곳에 고정되어 있는 경우
그 팔은 64인치 이내의 거리에 있는 물건만을 잡을 수 있다.
(2) 로보트가 방안을 돌아다닐 수 있다면 그 팔로 방안의
어느 곳에 있는 물건도 잡을 수 있다.
★ 인텔 프로세서는 이런 방식으로 주소를 지정함.
인텔 프로세서의 주소 지정 방식
★ 어셈블리 언어 프로그램에 사용되는 주소
= 세그먼트 주소 (segment address) + 오프셋(offset)
★ 세그먼트 주소 = 20 비트 크기 =>
방안에서의 로보트의 위치에 해당
오프셋 = 16비트 크기 => 로보트 팔에 해당
★ 실효 주소(effective address) : 바이트의 실제 주소
= 세그먼트 주소 + 오프셋
예) 세그먼트 주소가 50000H이고 오프셋이 62A3H라고 하자.
실효 주소 = 50000H + 62A3H
= 562A3H
예) 세그먼트 주소를 50000H로 고정한 상태에서 오프셋만을 변경
시켜가면서 접근할 수 있는 바이트들은?
실효주소의 범위 = 50000H ~ 5FFFFH (64K바이트 분량)
예) 세그먼트 주소가 50000H일 때, 실효주소 8726BH번지의 자료를
엑세스할 수 있나? no
해결책: 8726BH가 64K바이트 이내에 들어오도록 세그먼트
주소를 변경시켜야만 한다.
★ 하드웨어는 실효 주소를 계산하여 항상 20비트짜리 숫자로 만든다.
즉, 실효 주소는 00000H ~ FFFFFH까지 될 수 있고,
이제 1 메가바이트 크기의 메모리를 가질 수 있다.
세그먼트와 세그먼트 레지스터
★ 모든 프로그램은 세그먼트(segment) 단위로 나뉘어져야 한다.
즉, 큰 프로그램을 작성할 때는 프로그램을 적당한 크기로
나누어서 각 조각이 한 세그먼트에 들어갈 수 있도록 해야 한다.
★ 한 세그먼트의 최대 크기는 64K바이트이다.
★ 프로그램안에는 각 세그먼트의 시작 주소와 끝 주소를 어셈블러에게
알려주는 특정 명령들이 있다.
★ 프로그램이 실행되는 동안에 프로세서는 각 세그먼트의
세그먼트 주소를 CS, DS, ES 또는 SS라고 불리는 세그먼트 레지스터
(segment register)에 저장하여 두고 관리한다.
★ 한 프로그램이 가질 수 있는 세그먼트의 개수는 4개 이상일 수 있지
만 동시에 활성화될 수 있는 세그먼트의 개수는 4개뿐이다.
(이유: 프로세서에 들어있는 세그먼트 레지스터의 개수 = 4)
★ 4개의 표준 세그먼트
(1) 코드 세그먼트(code segment)
- 기계어 명령이 있는 곳
(2) 데이터 세그먼트(data segment)
- 자료가 저장되어 있는 곳
(3) 엑스트라 세그먼트(extra segment)
- 자료가 저장되는 곳 (필요시에 이 세그먼트를 둘 수 있음)
(4) 스택 세그먼트(stack segment)
- 스택이 있는 공간
★ 각 세그먼트의 주소가 저장되어 있는 레지스터
CS: 코드 세그먼트의 주소
DS: 데이터 세그먼트의 주소
ES: 엑스트라 세그먼트의 주소
SS: 스택 세그먼트의 주소
★ 모든 프로그램마다 4개의 표준 세그먼트가 있는가?
아니다.
- 모든 프로그램에는 최소한 (명령이 있을 곳인) 코드 세그먼트와
스택 세그먼트가 있어야 한다. (COM파일에는 스택이 없음)
- 데이터 세그먼트와 엑스트라 세그먼트는 꼭 있을 필요는
없으나 대부분의 프로그램에는 적어도 한 개의 데이터
세그먼트가 있다.
세그먼트 레지스터의 용도
★프로그램에서의 주소 표시법
[세그먼트 레지스터 이름] : [오프셋]
예) 데이터 세그먼트의 시작점으로부터 6AH 바이트 떨어져 있는
곳의 자료의 주소는?
DS:6AH
예) 엑스트라 세그먼트의 시작점으로부터 1A5H 떨어져 있는 곳의
자료의 주소는?
ES:1A5H
★ 프로그램이 실행될 때 프로세서는 오프셋을 해당 세그먼트 레지스터
의 값에 더하여 실효 주소를 얻는다.
즉, 주속 DS:6AH라면, 프로세서는 6AH를 DS의 값에 더한다.
★ 각 세그먼트 레지스터에는 어떻게 해당 세그먼트의 시작주소가 저장
되는가?
- 프로그램이 실행되기 전에 운영체제가 프로그램을 기억장치에
로드(load)한다. 이 때에 프로그램의 각 세그먼트의 주소가 결정됨
- CS, SS:운영체제가 초기화함.
ES, DS: 프로그리머 자신이 (프로그램안에서) 초기화해야 함.
세그먼트 레지스터가 갖는 값
★ 세그먼트 레지스터에는 세그먼트 주소가 들어 있다.
그렇다면, 16비트 크기의 레지스터에 20비트 크기의 세그먼트 주소가
어떻게 저장되는 것일까?
해결책: 주소의 20비트 중에서 레지스터에는 최상위 16비트만을 저장
남은 4비트는 모두 0으로 간주함.
예) 운영체제가 코드 세그먼트를 217A0H번지에,
스택 세그먼트를 1F8A0H에 로드하였다고 하자.
이 때: CS 레지스터가 갖는 값 = 217AH이고
SS 레지스터가 갖는 값 = 1F8AH가 된다.
★ 프로그램의 각 세그먼트는 0H로 끝나는 주소에 자동적으로 load됨.
(즉, 세그먼트는 항상 패러그래프 경계에 정돈된다.)
스택의 구현
★ SS(stack segment) 레지스터: 스택 세그먼트의 주소가 저장됨
- 프로그램이 로드될 때 운영체제가 이 값을 설정해 준다.
★ SP(stack pointer) 레지스터: 스택의 탑의 오프셋이 저장됨
★ 스택 탑의 실효주소 = SS:SP
★ 스택에 저장되는 항목(entry)의 크기 = 16비트 (2바이트)
★ SS 레지스터: 스택 영역의 가장 낮은 주소를 가리킨다.
SP 레지스터의 초기값: 스택의 크기
- 첫째 푸쉬 명령은 자료를 스택영역의 최상위 주소에 저장함
- 그 다음 푸쉬 명령이 저장하는 자료는 그 다음 최상위 주소의
엔트리에 저장된다.
- SP 레지스터: 항상 자료가 마지막으로 저장된 곳을 가리킨다.
(즉, 스택의 탑을 가리킨다.)
★ 스택은 최상위 주소로부터 시작하여 스택의 베이스를 향하여 아래
방향으로 자란다.
★ 일반적으로 한 항목이 푸쉬될 때는 아래와 같은 일이 이루어진다.
1. SP는 다음의 빈 공간을 가리키기 위하여 그 값이 2 만큼 감소한다.
(각 항목이 차지하는 공간은 2 바이트임을 잊지 말자.)
2. 푸쉬할 항목이 SP가 가리키는 곳에 복사된다.
★ 자료가 팝될 때는 아래와 같은 일이 이루어진다.
1. SP가 가리키는 곳의 항목이 적당한 다른 곳에 복사된다.
2. 팝된 후에 스택의 탑에 있는 항목을 가리키기 위하여 SP는 그 값
이 2만큼 증가된다.
★프로그램이 로드될 때, SP 레지스터는 첫째 항목이 저장될 장소보다
두 바이트 위에 있는 주소로 초기화된다. 첫째 푸쉬 명령은 SP를 2
감소시켜서 첫째 항목이 저장될 곳의 오프셋을 얻는다.
직접 주소 지정 방식
(1) 데이터 세그먼트안의 오프셋이 10AH인 곳을 지칭하려고 할 때
DS:10AH
(2) 숫자대신 이름을 오프셋으로 사용 (고급언어의 변수에 해당)
예) SUM이라는 이름이 데이터 세그먼트의 오프셋이 10AH인 곳을
나타낸다고 하자. 이 곳을 참조할 때는
DS:SUM
(3) 메모리 영역을 참조할 때, 그 주소가 데이터 세그먼트에 있으면
세그먼트 레지스터의 이름을 생략할 수 있다.
SUM
(4) 데이터가 다른 세그먼트에 있는 경우 (예. ES)
ES:SUM
간접 주소 지정 방식
★ 오프셋이 레지스터에 저장되어 있는 경우
예) SI 레지스터의 값이 1000H라고 하자.
MOV AX, SI (1000H를 AX에 복사)
MOV AX, [SI] (오프셋 1000H에 저장된 자료를 AX에 복사)
★ 간접 주소 지정 방식에 사용될 수 있는 레지스터
= SP, BP, BX, SI와 DI 임
★ 간접 주소 지정할 때, 대부분의 경우에 세그먼트 레지스터를 명시할
필요는 없다.
(이유: 프로세서가 적당한 것을 이미 가정하고 있기 때문이다.)
예) 데이터 세그먼트 내의 어떤 자료의 오프셋이 BX에 들어
있다고 하자. 이 자료는 참조할 때는 다음과 같이 한다.
[BX]
예) BX의 값이 엑스트라 세그먼트 자료의 오프셋인 경우
ES:[BX]
[예외] 이 규칙을 따르지 않는 중요한 예외가 하나 있다.
스트링을 MOV 하는 명령을 사용할 때, 프로세서는 DI 레지스터
의 값이 엑스트라 세그먼트에 있는 오프셋임을 가정한다.
인덱싱(indexing)
★ 인덱싱: 1차원 배열 또는 2차원 배열과 같은 자료를 나타내는데 사용
★ 즉, 배열 전체에 이름을 1개 주고 배열 내의 각 항목(item)은
첫째 자료 항목으로부터의 상대거리를 사용하여 참조함.
★ 베이스 주소(base address): 배열의 첫째 항목의 주소
예) 100개의 원소를 갖는 배열이 데이터 세그먼트에 있고, 그 원소들은
연속된 100개의 바이트에 저장되어 있다고 하자. 각 원소는 한
바이트를 차지한다. 배열의 이름은 LIST라고 하자.
(1) 첫째 바이트를 엑세스할 때: LIST
(2) 두번째 바이트를 엑세스할 때: LIST+1
★ 베이스 주소에 더해지는 수를 변위량(displacement)이라 함.
예) 100개의 워드로 구성된 배열 BIGLIST를 생각하여 보자. 각 워드가
2바이트를 차지하므로 원소들의 변위량은 다음과 같이 된다.
첫째 원소 ← BIGLIST
둘째 원소 ← BIGLIST+2
셋째 원소 ← BIGLIST+4
100번째 원소 ← BIGLIST+198
인덱스 레지스터
★ 배열의 원소를 엑세스할 때 사용되는 변위량을 레지스터에 저장하여
두고 사용할 수 있음. 이 때 사용되는 레지스터를 인덱스 레지스터
(index register)라고 한다.
★ 인덱스 레지스터로 사용될 수 있는 레지스터: SI, DI
예) 100바이트로 구성된 배열 LIST를 고려하여 보자. 프로그램이 이 배
열의 원소를 처음부터 끝까지 순서대로 참조한다고 하자. 이 때 SI
레지스터의 값을 0부터 99까지 변화시키면서 LIST[SI] 를 사용함.
★ LIST[SI]의 의미: SI에 들어 있는 값(value)을 LIST의 오프셋에
더하여 얻은 주소에 있는 자료를 참조하라.
예) 100개의 워드로 된 배열 BIGLIST를 고려하여 보자. 인덱스를 주기
위하여 DI 레지스터를 사용한다면
- 원소를 엑세스할 때: BIGLIST[DI] 를 사용
- 첫째 원소를 참조하려면 DI = 0
둘째 원소를 참조하려면 DI = 2
셋째 원소를 참조하려면 DI = 4
.........
n 번째 원소를 참조하려면 DI = (n-1)★ 2
★ 배열의 원소가 더블워드인 경우의 인덱스는 4의 배수이어야 하고,
쿼드워드인 경우는 8의 배수이어야 한다. 어셈블리 언어를 사용할
때는 프로그래머가 이를 직접 처리하여야 한다
(고급언어에서와는 달리).
베이스 레지스터: BX 레지스터
★ 베이스 주소 역시 레지스터에 저장될 수 있다. 데이터 세그먼트에서
는 BX가, 스택에서는 BP가 이런 용도로 사용된다. 이 레지스터들은
베이스 레지스터(base register)라고 불린다.
예) 배열 LIST는 다음과 같이 인덱스될 수 있다: LIST[DI]
LIST의 오프셋을 BX 레지스터에 넣어 두었다면
LIST[DI] <==> [BX][DI]
★ 베이스 주소를 레지스터에 넣어 두면 1개의 명령문을 사용하여 여러
개의 자료 구조를 액세스할 수 있다.
★ 더 복잡한 형식: TABLE[BX][DI]
두 레지스터의 값이 자료 항목의 오프셋에 더해진다.
예) BX에 20 들어 있고, DI에 4가 들어 있다면
TABLE[BX][DI] <==> TABLE + 24 이다.
★ 이중 인덱싱(double-indexing)을 사용하여 얻는 점
- 자료구조 안에서 베이스 주소를 설정할 수 있다는 것이다.
예) TABLE을 1바이트짜리 원소로 30행 100열짜리 테이블이라고 하자.
- BX : 특정 행을 가리키도록 하자.
- DI나 SI: 그 행의 원소를 인덱스할 수 있다.
첫째 행: 0번째 바이트부터 99번째 바이트
둘째 행: 100번째 바이트로부터 199번째 바이트
18번째 행의 57번째 원소: BX = 1700, SI = 56를 저장한 후에
아래와 같이 함
TABLE[BX][SI] <==> TABLE + 1756
베이스 레지스터: BP 레지스터
★ 스택의 주소 지정: 대부분의 경우에 SS, SP 레지스터를 사용
SS : 세그먼트 주소, SP: 스택 탑의 오프셋
★ 가끔은 스택 내부에 있는 정보를 액세스할 필요가 있을 때도 있다.
이 때는 BP 레지스터에 스택 내에서의 베이스 주소를 저장한다.
예) 프로시저 A가 프로시저 B를 호출할 때 스택을 통하여 어떤 정보를
프로시저 B에게 전달한다고 하자.
- 프로시저 B가 프로시저 A로부터 제어권을 넘겨받은 순간에
스택 탑의 오프셋을 BP 레지스터에 저장하여 두면 나중에
어떠한 정보가 스택에 푸쉬되어도 프로시저 A로부터 전달받은
자료는 BP의 값을 베이스 주소로 하여 액세스할 수 있다.
예) 프로시저 A가 10개의 워드를 스택에 푸쉬하였다고 하자.
- 프로시저 B의 실행이 시작되면, 프로시저 B가 가장 먼저 하는 일
은 SP의 값을 BP에 복사함으로써 스택 탑의 오프셋을 저장함.
- 프로시저 B는 언제라도 10개의 워드를 다음과 같이 엑세스함
SS:BP
SS:BP+2
SS:BP+4
.....
SS:BP+18
★ BP가 베이스 주소로 사용되면 SS가 묵시적으로 가정됨.
SS:BP+2 <==> BP+2
주소를 지정하는 일반적인 규칙
★ 직접 주소를 지정할 때
TABLE
TABLE[SI]
TABLE[DI]+8
TABLE[BX][SI]+8
★ 간접 주소를 지정할 때
- SP, BP, BX, SI 또는 DI를 사용한다.
- BP나 BX가 사용될 때는 SI나 DI가 인덱스로 사용된다.
[BP]
[SI]
[BX][DI]
[SI]+4
[BP][DI]+4
★ 간접 방식이든 직접 방식이든 하나의 주소에는 2개 이상의 베이스
레지스터가 사용될 수도 없고 2개 이상의 인덱스 레지스터가
사용될 수도 없다.
★ 인덱스의 값을 지정할 때 어셈블러는 다음의 규칙을 따른다.
인덱스의 값에는 특정 순서가 없다.
레지스터의 이름은 대괄호에 싸여 있어야 한다.
레지스터의 이름들과 한 개의 상수 변위량을 모두 하나의 대괄호
안에 넣어 사용할 수 있는데, 이 때 이들은 각각 + 부호로 분리되
어 있어야 한다.
레지스터의 이름 앞에 상수 변위량을 쓸 수도 있는데 이 때는 이
두 값 사이에 + 부호가 있을 필요가 없다.
예) TABLE[BX][SI]+8
TABLE[BX+SI+8]
TABLE[8+SI+BX]
[BP][SI]+12
12[BP][SI]
12[BP+SI]
★ 아래의 패턴을 추천함
(1) 직접 주소의 표현: 이름[베이스][인덱스]+상수
예) TABLE[BX][SI]+8
(2) 간접 주소의 표현: [베이스][인덱스]+상수
예) [BP][DI]+8
코드 세그먼트 내에서의 주소 지정 방식
★ 코드 세그먼트로의 주소 지정:
프로세서가 CS 레지스터와 IP 레지스터를 사용해 자동 해결
★ CS: 코드 세그먼트의 세그먼트 주소가 있음
IP:바로 다음에 수행될 명령의 오프셋이 있음
★명령을 실행할 때마다 IP 는 그 다음 명령을 가리키도록 수정됨.
★ 다음에 실행될 명령이 분기 명령, 프로시저 호출 등이면
프로세서는 IP 레지스터의 값을 그에 맞게 바꾼다.
★ 코드 세그먼트로의 주소 지정은 자동적으로 이루어지므로
대부분의 경우에 CS 레지스터와 IP 레지스터의 값은 잊고 지내면 됨
[출처] C H A P T E R 4 ::: 주소 지정 방식 :::|작성자 현미찹쌀
'Algorithm' 카테고리의 다른 글
선점,비선점 스케쥴링 (1) | 2008.08.19 |
---|---|
병행프로세스와 상호배제 (0) | 2008.08.19 |
RISC 기본원리 (0) | 2008.08.19 |
deadlock 4가지 (0) | 2008.08.01 |
B-, B+ Tree (0) | 2008.08.01 |