아 힘들다 시팔
아 선형주소 이해안되
익명(122.32)
2015-05-14 22:55
추천 0
댓글 25
다른 게시글
-
__fastcall 이 이형 C 컴파일러끼리 호환된다고 믿고 있는 애들 [45]codesafer(codesafer) | 15.05.14추천 0
-
김치맨들 스마트포인터 안쓰는 이유가 뭐냐? [2]익명(211.58) | 15.05.14추천 0
-
한국은 스택오버플로우 없음????????? [2]ㅇ(125.177) | 15.05.14추천 0
-
햄드라 이거 왜 오버플로우 안생김?????????? [2]겸둥(125.177) | 15.05.14추천 0
-
중딩 때 생각했던 프로그래머로써 이런 식으로 살면 부러움. [2]익명(59.21) | 15.05.14추천 0
-
int a,b,c,d; [2]섹서(125.177) | 15.05.14추천 0
-
프로그램을 업그레이드 하지만않으면 유지보수 할필요없는거야? [4]ㅁㄴㅇㄻㄴ..(121.164) | 15.05.14추천 0
-
클록 사이클 어떻게 뜻을 받아들여야하지? [5]익명(122.32) | 15.05.14추천 0
-
loop to recursion [1]츄럴(218.54) | 15.05.14추천 0
-
코딩이랑 결혼한 프갤러 있음? [1]익명(59.21) | 15.05.14추천 0
세그멘테이션을 거쳐서 나온 가상 주소가 선형 주소잖아. 세그멘테이션을 거치기 전의 세그먼트:가상 주소 꼴은 논리 주소고.
세그멘테이션이 가상주소를 다루는 기법맞져? 이렇게말해야하나
세그먼테이션은 실제 물리 메모리에 매핑된 memory mapped IO와 여러 서비스콜들, 벡터들 따위로 이루어진 단절 구조 그 자체지
32비트 이후로 세그멘테이션은 별로 유의미한 가치를 지니지 않아. 그저 보호 모드에서 코드 권한 관리하는 것과 초기에 태스크 스위칭 시 스와핑(swapping)을 위해 사용되긴 했는데, 지금은 대부분의 OS에서 메모리 관리에 스와핑 개념을 쓰지 않고 페이징 개념을 쓰고 있으니까. 아 한 가지 더 있긴 하네. Windows나 이런 OS에서 남아도는 FS(F's Segment), GS(G's Segment) 같은 세그먼트에 특수 목적의 시스템 구조체 영역을 가리키게 해서 프로세스가 편하게 시스템 구조체를 참조할 수 있게 해 놓은거. 가령 윈도우의 경우 FS 세그먼트(64비트에서는 GS)에 TEB(Thread Environment Block)의 영역으로 매핑시켜 놨지.
음 뭐랄까 똥덜싼느낌이네여... 아무래도 페이징기법이랑 세그멘테이션 다시보고와야할듯 ㅠㅠ
그러니 간단히 말해서 세그멘테이션은 16비트 시절의 잔재임. 인텔의 4가지 특권 계층(Ring Privilege)을 공부할 때 이외에는 그냥 세그먼트는 그냥 붙이는 거라고 이해해도 큰 문제는 없어.
CS:XXX, DS:XXX, SS:XXX. 모두 대다수의 현대의 32비트 OS에서는 동일한 선형 가상 주소 XXX로 매핑한다.
8086때 멀티태스킹안됬었죠?
아니? 이론적으로는 얼마든지 가능한데 구현한 OS가 적었을 뿐이지. 애초에 멀티태스킹이라는 게 GUI적 개념인데 그 당시엔 다 콘솔(터미널) 기반이었잖아.
프로세스마다 Context(문맥: 레지스터들의 값)를 보관하고 타이머 인터럽트 이용하면 얼마든지 구현할 수 있는 게 태스크 스위칭 개념이야.
8086때 세그먼트라는게 등장했다는데 이때 세그먼트에는 예를들어 cs라면 현재 명령어위치를 가르키고있었나요?
현재 프로그램의 코드 영역의 시작 주소를 가리켰지. 정확하게는 시작 paragraph(16byte 단위) 위치. 왜냐면 물리 주소의 변환이 Segment * 16 + Offset이므로 Segment는 실제 주소의 /16한 값을 넣어야 하니깐.
그래서 프로그램 코드에서 현재 프로그램이 어디에 로딩될지는 신경쓰지 않고(OS가 담당하는 영역이니) 그저 CS:1234, DS:3333 식으로 접근하면 됐'었'지. 과거형인 이유는 32비트에서는 프로세스마다 개별 메모리 공간이 할당돼서 그냥 컴파일러가 프로그램이 메모리 상에 어디에 로딩될지 정해주고(예: 0x400000) 그 주소대로 접근하면 되니까(예: 0x401234) 과거형임. C언어에서 printf("%s\n", 0x400000); 해보면 MZ라는 문자열을 볼 수 있을텐데 exe 파일을 메모장으로 열어보면 MZ로 시작할 거다. 실행파일의 내용을 그대로 메모리에 올려준 거지. 이걸 로딩이라고 불러.
8086에서 실제주소만들때 4비트 shl된 16비트 세그먼트+ 16비트오프셋이라던데 그러면 여기서 오프셋은 뭘가르키는거죠? 세그먼트의 오프셋인가요?
말 그대로 목적별 메모리 영역 속의 내가 원하는 위치를 가리키는 상대 위치를 말하는 거지. 파일이든 메모리든 offset이라는 개념이 어떤 base 주소를 기준으로 차이값(delta)을 뜻하는 개념이야. 파일의 offset이라고 하면 파일 시작으로부터의 위치를 말하는 거고 메모리 offset은 메모리 시작으로부터의 위치, 여기서는 세그먼트 시작으로부터의 위치를 말하는 거지.
음 다행히 그건 제가생각했던거랑 맞네요 페이징하고 세그먼테이션좀 공부하고오면 좀더 쉽게이해될거같네요 감사합니다
16비트에서 세그멘테이션 개념이 등장하게 된 것도 웃겨. 당연한 말이지만, 당시 레지스터 크기가 16비트 밖에 안 됐었는데 이게 문제가 뭐냐면 2^16 해보면 64KB 메모리 밖에 가리킬 수가 없다는 거임. 그래서 인텔이 고민하다가 고민 끝에 궁여지책으로 내놓은 꼼수가 세그멘테이션임. 16비트 세그먼트 레지스터를 추가해서 세그먼트 레지스터:오프셋 식으로(예: DS:1000h) 32비트 논리 주소로 메모리 위치를 표현하는 것이지. 실제 메모리 주소는 세그먼트 주소 * 16 + 오프셋 주소로 계산되고 16은 2^4 즉 4비트 shift left된 거니까 계산해 보면 20비트 주소 밖에 안돼. 그래서 1MB까지 메모리를 표현할 수 있었는데 이게 세그멘테이션 때문에 가능해진 거.
근데 왜 주소를 지정할 수 있는 ESI, EDI, EBP 같은 Index/Base 레지스터의 크기를 16비트에서 32비트로 늘리지 않고 세그먼트 레지스터라는 걸 굳이 추가했냐면 여러 프로그램을 메모리 상에 동시에 로딩할 수 있도록 하기 위함이야. 어, 뭔가 이상하지? DOS 시절에는 멀티 태스킹이라는 개념이 없었는데. 맞아. 멀티 태스킹 개념은 그 때 당시엔 없었어. 하지만 메모리에 여러 프로그램을 올릴 필요는 있었지. 프로그램A가 syste\0m 함수 같은 걸로 프로그램B를 실행했다고 할 때 프로그램A는 프로그램B가 끝날 때까지 작업이 중단되고 프로그램B의 코드가 실행되는데 이런 상황에서는 메모리에 프로그램A, 프로그램B가 모두 로딩되어 있지.
이런 식으로 DOS 시절에도 메모리 상에는 프로그램이 여러 개가 동시에 메모리에 올려져 있었다. 그래서 프로그램은 내 프로그램이 어느 메모리에 로딩될 지(다시 말하지만 로딩은 그냥 CPU가 실행 파일의 명령을 수행하기 위해 실행 파일을 읽어서 메모리에 올려두는 작업을 말해. 어셈이든 뭐든 컴퓨터에서 "load"라는 개념은 데이터를 처리하기 위해 느린 메모리에서 휘발성의 빠른 메모리로 옮기는 것을, store라는 개념은 그 역을 말해. 인터넷에서 말하는 upload/download라는 용어도 인터넷 선이라는 느린 매체를 통해 주고 받는 거라 load라는 말을 쓰는 거야)
모르기 때문에(로드될 위치를 컴파일러가 주면 안되냐고? 그럼 예를 들어 프로그램 A와 프로그램 B가 모두 0x100000에 로딩될 거라 컴파일러가 예상해서 프로그램이 짜여져 있다면 어떻게 될까?) 프로그램이 로딩되는 위치는 운영체제가 결정하도록 운영체제의 자유에 맡기고 운영체제가 목적별 메모리를 적당히 할당해서 CS, DS, SS 세그먼트 레지스터에 가리키면 프로그램은 CS:1234h 식으로 운영체제가 할당한 공간 안에서 상대 위치 가지고 메모리를 가지고 노는거야.
아 괄호 속 예시를 잘못 들었다. 0x100000이 아니라 0x1000. 16비트 시절이었지 참.
아 또 잘못 든게 있네. ESI, EDI, EBP가 아니라 SI, DI, BP. ESI, EDI, EBP는 32비트 모드의 레지스터지.
감사합니다
음 좀 이해가되네영
ST7 7 8.℃ ○M 16pnskvd