(질문이 여러개입니다. 모두 연관된 질문입니다.)
질문1.
(64bit로) __int64로 할당할 때와
char b;__int32 a=0; long c; float d;
//--------------------------------------------------
char: 12ff7c //32bit<-기준
__int64: 12ff74 //64
long: 12ff70 //32
float: 12ff6c //32
(32bit로) int로 할당할 때를 \'동등한 시점\'에서 비교해 보았습니다.
char b;__int32 a=0; long c; float d;
//--------------------------------------------------
char: 12ff7c //32bit<-기준
int32: 12ff78 //32
long: 12ff74 //32
float: 12ff70 //32
보시다시피, 12ff7c->부터 시작해서 낮은 쪽으로 메모리가 내려가면서 할당되고 있습니다. 자동메모리는 Stack메모리인데, 위와 같이 되기 위해서는 Stack Pointer(레지스터)가 12ff7c서부터 내려가면서 저장해야 하는데, 그것이 실재로 일어나는 일입니까? 이말은 다시 거꾸로 말하면, Pop으로 Stack에서 자료를 읽어올때마다 StackPointer의 값이 내려가는 것이 아니라 올라간다는 것입니까?
어딘가에서 읽은 듯 한데요. Stack메모리영역은 프로그램영역 위에 있고 Static하고 Dynamic영역은 그 아래쪽에 있다고 합니다. 위쪽으로 갈 수록 주소가 낮아지기 때문에, 제가 처음에 생각하기로는 Stack이 쌓이는 방향은 아마도 Stack영역(그러니까 프로그램의 위) 가장 위쪽에서 시작해서 아래쪽으로 쌓이겠다라고 생각했었습니다. 그런데, int, __int64 실험을 한 뒤로 어쩌면 Stack영역(그러니까 프로그램의 위)의 가장 낮은 부분(즉 Stack영역에서 주소가 높은 쪽)에서 시작해서 위로 쌓아올려지는 것은 아닐까 하고 저의 지식을 의심하게 되었던 것입니다. 그런데 그렇게 생각하자니 모순이 발생합니다. CPU가 이해하는 기계명령 중에 PUSH는 스택에 저장할때마다 SP(Stack Pointer:Register)의 값을 올린다고 배웠는데, Stack영역의 아랫쪽에서 위로 쌓아올려진다면, 정 반대로 PUSH할때마다 SP의 주소가 낮아져야 하는 것이 아니겠습니까? 패러독스가 아닐 수 없습니다. 저의 고민은 바로 이것에서 시작하는 것입니다.
질문2.
C,C++에서 자동변수를 할당하면 메모리 주소가 정말로 이상하게도!! Char형, Int형, Float형, Pointer형까지 모조리! 모조리! 다 4Byte씩 할당되던데 왜 그래야만 하는 것입니까?(__int64는 제외) 다시 말하면, Char형으로 1Byte만 사용할 것이면서 주소공간을 4Byte나 할당한다면 1/3은 버리는 것입니까? 확인해 보았지만 나머지 1/3에 다른 data를 저장한다던가 하는 일은 발견하지 못했습니다. 32bit system에서 모든 자료형의 변수가 6Byte 주소공간에 할당된다면 64bit System에서는 8Byte주소공간에 할당될 것이 아닙니까? 그렇게 된다면 메모리가 너무 낭비 아닙니까?
질문3.
제가 \"소문\"으로 들어 알기로는 범용레지스터에는 다양한 모드가 있는 것으로 알고 있습니다. 32bit system을 기준으로 할때 Enhanced AX(32bit),EAL(16bit),EAH(16bit), AX(16bit), AL(8bit), AH(8bit)으로 Mode가 구분된다고 알고 있습니다. (64bit System에 대해서는 모르겠습니다) 질문의 요지는, 이러한 레지스터의 여러가지 모드를 통해서 메모리에 Access하는 것이 가능한가 입니다. //제어버스(아마도)의 회선을 디멀티플랙싱(신호분배)하여 일부 DataBus의 회선으로만 저장할 수 있게 국한시키는 일이 이론적으로는 가능할 것으로 생각됩니다. 그것이 가능하다면 1Byte씩도 읽고 쓸 수 있지 않을까요? (위의 \"소문\"에 대해 잘못이 있다면 지적해 주세요.)
질문4.
배열변수를 선언하면 자동변수와는 정 반대로 낮은 주소에서 높은 주소로 변수가 할당되는 것일 발견하였습니다. 즉 [0] -> [max]로 갈 수록 주소(&)가 증가하게 됩니다. 그런데 그러한 배열 자체를 질문1에서의 자동변수 이후에 선언할 경우, 배열마지막번지의 주소는 자동변수가 할당된 주소보다 더 낮은 곳에 있게 됩니다. 즉 질문 1에서 12ff6c보다 낮은 주소에 배열의 가장 마지막 번지가 존재하게 됩니다. 이에 대한 제 추론은, 배열 마지막 번지부터 메모리에 할당되기 시작하는 것이 아닌가 하는 것입니다.(생략)
질문5.
C와 C++에서 Pointer 값이 32bit/64bit system에 따라서 달라진다고 들었습니다. 또한 눈에 보여지는 주소 출력 그대로가 pointer 값이 될 수 없다는 사실을 포함하고 생각하면, 순수한 Pointer값은 실제 시스템주소에 더하는 간접주소지정에 불과한 것이 아닌가 하고 생각되었습니다. 정말 그런가요? 그렇다면, 32bit/64bit의 실주소에 더하기 위해서 필요한 pointer변수를 C와 C++에서는 각각 몇바이트로 할당합니까.
질문6.(질문3에서 연결됩니다.)
CPU의 처리과정에서 스택포인터가 특정 메모리 번지에서 자료를 읽어올때, 한번에 무조건 32bit/64bit(시스템 버스 폭)씩 읽어들입니까? 그런 것이라면 push AX 하였을때, AX가 \'64bit\'라면 한번에 무조건 8번지 만큼의 주소를 차지하게 된다는 의미이겠지요.
하지만 만약!(가정입니다.) Push Al이라고 명령하면, AX의 절반에 해당하는 4번지만큼의 주소영역만을 차지하고 남아있는 4번지에는 Bh를 저장할 수 있는 것이 아닙니까? 물리적으로 가능한 일일 것으로 생각합니다. 왜 그렇게 하지 않나요? 혹은 그런 기능이 있습니까?
가능하다면, 데이타 버스의 2 CYCLE에 걸쳐서 2Byte+2Byte의 반토막씩 스택에서 읽어오는 일도 발생하지 않을까 싶습니다.
질문7.
물리적 동작으로, 범용레지스터 AX가 32bit라 할때, AL(16bit)을 BH에 넣는 Direct로 저장하는 것이 가능합니까? 어셈블리 명령으로는 Mov BH, AL 라고 해야 할 텐데요. 가능한 일입니까? (저는 물리적 동작으로 Direct로 저장하는 것을 의미하는 것입니다. Compile동작으로 수행하는 조합명령어를 의미하는 것이 아닙니다. 이에 유의해 주세요.)
------------------
여기까지 읽어주셔서 매우 감사드립니다. 1~7까지의 질문에 약소하게라도 답변해주시는 분께 모든 영광을 돌리겠으며, 대대 손손 번창하시기를 기원해드리겠습니다. 그럼 마지막으로 인사드립니다...
------------------History
xxx터 1. 내려간다 2007/10/27
xxx터 2.포인터형은 무조건 4바이트다 2007/10/27
xxx터 4.배열 크키만큼 스택에 푸쉬 해놓고 스택 포인터가 올라간다 2007/10/27
xxx터 5.16비트컴터 씀? 요즘은 integer은 32비트 4바이트다 2007/10/27
답변 2. 아마 최적화랑 관련이 있지 않나 싶다. 32비트 CPU가 개인용 컴퓨터의 대다수를 차지하고 있다는 사실과 연관시켜 생각해 볼 것
답변 5. OS와 상담하세요.
답변 2. 주소는 CPU 비트 수를 따라가지효. 32비트 어드레싱. 하지만 포인팅하는 메모리 공간이 char형이라면 1씩 커질테고, int32라면 2씩 커질테고, double이면 4씩 커질테고.