1. Windows의 컴퓨터 비트 수 변화
과거에 주류 PC 환경이 (1) 16비트에서 32비트로 바뀌면서 소프트웨어 개발 환경이 크게 바뀌었다.
int와 WPARAM, handle, 포인터가 모두 4바이트 크기로 바뀌었고, 이로 인해 메시지도 몇몇은 스펙이 불가피하게 바뀌었다.
좌표계의 기본 단위도 다들 32비트로 확장됐고, 이로 인해 GDI 함수들이 상당수가 Ex 버전으로 바뀌었다. 왜냐하면 예전처럼 x, y 좌표 둘을 long 하나에다 묶어서 전달할 수가 없어졌기 때문이다.
하지만 선점형 멀티스레드가 지원되고 그 전에 모든 프로세스들이 자기만의 독립된 주소 공간을 갖는다는 건.. 과거엔 정말 상상도 못 할 혜택이다.
8비트야 거의 임베디드 급의 열악한 환경이니 멀티태스킹 따위는 별나라 얘기였다. 16비트 시절엔.. 어정쩡하게 아주 불편하고 힘들게 가능했던 반면.. 32비트가 되니 주소 공간도 넉넉하고 이제 좀 그럭저럭 할 만해진 것이다.
그리고 32비트에 와서는 예전에 깐깐하게 구분해야 했던 게 이제는 구분이 필요 없어지고(예: HINSTANCE vs HMODULE, far vs near), 예전에는 꼭 할당하고 해제해 줘야 했던 게 지금은 그럴 필요가 없는 등(resource 관련 API, MAKEPROC 따위).. 프로그래밍 하기가 전반적으로 더 간편해지고 편리해지기도 했다.
그에 비해 (2) 32비트에서 64비트로의 변화는 뭐.. int와 포인터의 크기가 달라진 것으로 인한 자잘한 충돌과 이식성 문제가 고작이다. 4GB 한계가 없어지기만 했을 뿐, 체감되는 변화는 아주 미미하다.
Windows의 경우, int는 물론 long조차도 여전히 32비트 크기로 유지된다. 그러나 WPARAM은 64비트로 확장됐다.
전에도 한번 얘기했듯이 게임기는 1990년대 후반, PC는 2000년대 후반, 스마트폰은 2010년대 후반이 돼서야 슬슬 64비트 시대에 들어섰다.
이런 곳은 비트 수가 점진적으로 늘어났기 때문에 기존 코드와의 호환성이 중요했다. 그렇기 때문에 포인터만 빼고 int나 long은 4바이트로 할지 8바이트로 할지 고민이 많은 편이었다.
그 반면.. 슈퍼컴퓨터 전용 아키텍처가 있던 시절 말이다. 197, 80년대에 처음부터 64비트로 시작했던 컴터 환경에서는 레거시 고민 따위 없었다. Cray 같은 플랫폼에서는 쿨하게 처음부터 int고 포인터고 몽땅 다 무식하게 64비트 모델을 채용한 곳도 있었다고 한다. 물론 오늘날이야 int까지 8바이트인 컴퓨팅 환경은 없다고 봐도 되지만..
그리고 저런 옛날 컴퓨터들은 데이터를 취급하고 연산하는 단위만 64비트였다. 아무리 슈퍼컴이라 해도 자기네 메모리 용량이 4GB에 미치지는 못했기 때문에 64비트 컴퓨팅이 곧 64비트 addressing을 의미하지는 않았다고 한다. addressing까지 다 되는 64비트 CPU는 1990년대가 돼서야 등장했다. (MIPS, DEC Alpha 따위) 아하~
얘기가 좀 옆길로 샜는데.. 아무튼 Windows는 16비트에서 32비트로 넘어갈 때 변화가 좀 있었고, 32에서 64비트로의 변화는 미미한 편이었다. 그럼 Windows의 역사상 16비트에서 32비트로의 전환만이 대격변이었던 것일까?
꼭 그렇지는 않았다. 오히려 더 옛날, (3) Windows 1 (+2)과 3 사이는 플랫폼 SDK의 변화, C 컴파일러의 변화 등의 단절이 더 심했다.
Windows 1과 2는 아직도 리얼 모드 내지 끽해야 286 표준 모드에서 멀티태스킹을 구현하던 정말 암울한 시절이다.
Windows의 오랜 역사를 좀 아는 guru라면, 20세기에 Windows에서 가장 혁신적인 변화는 바로 95나 NT도 아니고 3.0에서 "386 확장(enhanced) 모드"가 정식 도입되었던 사건이라고 말할 정도이다. (☞ 링크)
그랬기 때문에 Windows 1과 3은 같은 16비트 기계어에 같은 NE 포맷임에도 불구하고 1용 프로그램이 후대의 3 내지 9x에서 제대로 실행되지 않을 가능성이 매우 높았다.
게다가 저 1980년대의 구닥다리 C 컴파일러는 함수를 정의하는 문법조차 ANSI가 아닌 기괴한 K&R 방식이었다니.. 소스 레벨의 호환성도 기대하기 어렵겠다. 더 자세한 건 여기 글을 참고하시라. (☞ 링크)
2. 마소의 16비트 P-code 기술
마소와 관련된 옛날 이야기가 계속 이어진다. 이 블로그에서 본인이 지금까지 이 얘기를 한 번도 꺼낸 적이 없었다니 놀랍다.;;
네이티브 기계어가 아니라 다른 중립적인 바이트코드 기반으로 돌아가는 '가상 기계 프로그램'이라 하면 흔히 Java (JVM)나 C# (.NET, CLR) 같은 것만 떠올리기 쉽다. 이런 건 최소 32비트 이상의 컴퓨팅 환경에서 등장한 런타임 환경이다. 고유한 클래스 라이브러리도 갖고 있고 쓰레기 수집기도 제공한다.
하지만 마소는 창립하자마자 그 허접한 197, 80년대 8비트 컴퓨터로 제일 먼저 만들었던 게 BASIC 인터프리터였다. 현대적인 가상 머신 정도로 거창하지는 않지만, 그래도 고유한 바이트코드 가상머신 기술을 보유해서 16비트 컴퓨팅 시대까지 잘 써먹었다.
마소에서는 그 바이트코드를 스스로 P-code라고 불렀다. P는 pseudo-, portable, packed(조밀) 등을 뜻했다고 한다. 그리고 그걸 Basic뿐만 아니라 C/C++ 언어 컴파일러에다가도 접목했었다. 아니, 베이식은 그렇다 치지만 기계어 직통 컴파일이 당연시되는 언어이던 C/C++에다가는 성능(= 실행 속도) 희생까지 감수하면서 도대체 왜..?
이 바이트코드는 크기가 작았기 때문이다. 이게 packed의 의미이다.
같은 프로그램 소스를 비슷한 최적화 수준으로 컴파일 했을 때, 네이티브 x86 기계어 코드보다 훨씬 더 작은 크기로 표현할 수 있었다. 심지어 P-code를 해독하는 가상머신 코드의 오버헤드(9K 남짓?)를 포함시키더라도 수지맞는 장사였을 정도라니.. 이건 뭐 실행 파일 압축 기능까지 약간이나마 겸한 셈이었다.
컴퓨터 역사의 관점에서 볼 때 x86 자체도 골수 CISC 구조로서, 현대적인 아키텍처 대비 기계어 코드가 조밀하고 크기가 아주 작은 축에 드는 아키텍처라고 여겨진다. (그 대신 읽어들이고 디코딩하는 난이도가 쥐약이고, 저전력 모바일과 상극)
그런데 마소의 P-code는 그 악명 높던 x86 기계어보다도 더 조밀하고 작다니.. 그 시절에 얼마나 메모리가 비싸고 귀했고 메모리를 어떻게든 아껴야 했는지가 실감이 간다. PC에서도 386 486 같은 32비트 CPU는 진작에 등장하고 값도 내려갔지만.. 메모리가 아직 병목이었다. 이게 더 싸지고 풍부해진 뒤에야 본격적으로 Windows 95/NT가 쓰일 수 있었다.
Visual Basic이야 exe를 생성한다 해도 런타임 dll이 따로 필요하고 내부 코드는 P-code 기반이었다. 1997년에 출시된 5.0.. 최초로 32비트 전용으로 출시된 이 버전에 이르러서야 네이티브 코드 컴파일 기능이 도입됐다.
C/C++의 경우, MS C/C++ 7.0과 Visual C++ 1.x 시절.. 16비트 한정으로 이런 기능이 있다가 32비트부터는 폐기됐다. 그 대신, 16비트이기만 하면 플랫폼은 DOS와 Windows를 모두 지원했다.
따지고 보면 Windows NT의 32비트 PE (portable executable)는 저런 P-code와는 접점이 없었던 셈이다. 32비트 Visual Basic 5나 6을 쓰지 않는 한 말이다
자세한 것은 이 링크의 설명을 참고하시라. 마소의 전설적인 P-code에 대해서 구체적으로 소개한 글은 "Microsoft P-Code Technology" by Andy Padawer이 유일한 것 같다.
QuickBasic이나 GWBASIC은 소스 코드를 고유한 바이너리 포맷으로 저장하는 기능이 있었다. 이건 세상 그 어느 프로그램 개발 환경에서도 없는 기능이었지 싶다.
그 반면, 저 P-code는 소스 코드가 아니라 나름 기계어를 표방하고 컴파일된 코드였다는 차이가 있다.
3. 마소와 볼랜드 프로그래밍 툴의 Windows 지원 내력
(1) 아마 예전에 이 얘기를 한 적이 있었을 텐데..
1980년대 말부터 마소와 볼랜드에서는 주요 프로그래밍/개발툴을 내놓으면서 뭔가 교육용 저가 보급형 제품군에다가는 각각 Quick과 Turbo라는 스피디한 브랜드명을 붙였고, 기업용 기함급 모델에다가는 그냥 자기 회사 이름을 붙였었다.
(2) 1990년대 초엔 C 컴파일러에는 C++의 지원이 추가되었다. 그래서 지원 언어 표기가 C/C++이라고 바뀌었다.
마소의 경우, QuickC는 Microsoft C를 먼저 만들다가 곁다리로 병행하며 잠깐 만들었던 제품이다. 이건 C++ 지원 없이 겨우 2.0에서 맥이 끊겼다. 그 대신 이전부터 만들어 오던 MS C 6의 다음 버전이 MS C/C++ 7이 되었다(1992). 그리고 이거 다음 버전부터는 그 이름도 찬란한 Visual 브랜드가 시작됐고, C는 떼어낸 채 Visual C++ 1로 넘어갔다.
저 때는 1993년 무렵이었다. Visual C++은 Windows NT와도 역사를 함께한다. 이게 마소에서 최초로 내놓은 32비트 C/C++ 컴파일러이며, Windows NT 내부의 각종 프로그램들을 빌드하는 용도로, 즉 자체적으로도 쓰였기 때문이다.
물론 Visual C++도 1.5까지는 16비트 버전이 같이 나오긴 했었다. 그리고 대외적인 버전 번호는 1로 리셋됐지만 얘 역시 MS C를 계승한 제품이라는 흔적은 MSC_VER이던가 그 매크로 상수의 번호에 남아 있다.
(3) 한편, 볼랜드 진영에서는 Turbo C 2.0의 다음 작품이 Turbo C++ 1.0이 되었다. 제품명과 버전이 다 리셋됐다니 좀 이례적이다.
그리고 그 다음 버전인 Turbo C++ 2때부터 같은 버전의 Borland C++도 나란히 나오기 시작했다고는 하는데.. 실질적으로 Turbo와 Borland의 구분이 생겼다고 일반인들이 존재감을 인지하는 첫 버전은 3이다.
Turbo C++은 3인가 3.1에서 맥이 끊겼다. 그 뒤 적어도 4~5 버전부터는 Borland C++만 나오다가 RAD 툴인 C++ Builder 1로 넘어갔다.
(4) 그 시절 C/C++ 컴파일러 업계에서는 C++ 지원뿐만 아니라 Windows 플랫폼의 지원도 중요한 이슈였다.
마소는 DOS에 이어 Windows를 만들던 본가였고, C는 어셈블리어와 더불어 자기들 제품을 만들 때 사용되는 주력 언어이기도 했다. 그러니 MS C는 처음부터 Windows를 지원하는 게 너무 당연한 일이었다.
1980년대 중반, 정말 구닥다리 MS C 4~5 시절부터.. 그야말로 전설적인 Windows 1.x, 2.x 프로그램을 만들 수 있었다. 단, QuickC는 DOS용 버전 2.x대와 별개로 QuickC for Windows 1.0이 딱 한 번만 나오고 말았던 듯하다. 요컨대 마소는 QuickC의 Windows 버전만이 버전 리셋을 했고, 볼랜드는 C++ 컴파일러를 구현할 때 버전 리셋을 했다.
그에 비해 볼랜드 제품에서 Windows 지원이 추가된 건 버전 3.x부터로, C++까지 지원되고 난 이후의 일이다. 심지어 Win32의 지원은 Windows 95가 출시되고 4.x 정도는 된 뒤부터다. 후발주자 3rd-party 업체이니 이런 것 수용은 한 발 늦을 수 있다지만.. Windows용 32비트 extender까지 미리 만들었던 Watcom 같은 업체하고는 개발 방향이 많이 달랐던 것 같다. 그 대신 볼랜드에서는 OWL이라고 꽤 잘 만든 객체지향 프레임워크를 연구 개발했다.
이렇듯, Windows 지원과 관련해서는 볼랜드와 마소 개발툴 간에 이런 내력의 차이가 있었던 셈이다.
(5) 자, 그럼 C/C++ 다음으로 파스칼의 세계로 가면..
볼랜드에서 Turbo Pascal을 내놓으면서 1980년대를 호령하고 재미를 봤다. 도스 아니면 기껏해야 OS/2에서 말이다. 그러다가 1990년대 초, Turbo Pascal 6 타이밍 때 TP for Windows를 1.0과 1.5 두 차례 내놓았다. 아마 5.x던가 6이던가..
이때 ObjectPascal이라는 객체지향 문법이 언어에 도입되기도 했지만 이건 TP의 버전에 영향을 주지 않았다. 그 대신 Windows용을 1.0부터 다시 내놓았다는 점이 Turbo C++과는 다르다.
그러다가 Turbo Pascal 버전 7이 Borland Pascal 7과 나란히 출시됐으며.. 이 BP7은 TP for Windows 2를 통합· 포함한 형태가 됐다. 제품 라인업 한번 복잡하네..;;
TPW는 about 대화상자에 수학자 파스칼 얼굴이 그려져 있는 반면, BPW는 그렇지 않다는 차이가 있다.;;;
1992년에 출시된 Borland C++ 3.1, 그리고 Borland Pascal 7이 도스와 Win16을 풍미했던 장수만세 안정판으로 여겨진다.
Borland C++은 C++ Builder로 넘어가기 전 1993~1995년 사이에 자체적으로 버전이 4~5까지 올라가기도 한 반면, BP는 델파이로 넘어가기 전에 딱히 버전업이 없었다.
심지어 Delphi도 1995년의 첫 버전 1은 Win16, 16비트용이었고 버전 2부터 Win32로 넘어갔으니, 32비트화도 C++보다 늦은 셈이다.
한편, 마소는?? 처음에 Microsoft Pascal을 1980년대에 4.x 버전까지 개발했었다. 하지만 이건 Turbo Pascal과의 경쟁에서 승산이 없다고 판단했는지 접었다. 그렇게 접기 직전에 경쟁사 제품처럼 뽀대나는 IDE를 얹은 QuickPascal 1.0을 최후의 발악 차원에서 한번 내놓았을 뿐이다. Windows 지원 같은 것도 당연히 없었고 제품의 맥이 끊겼다.
볼랜드에서는 Turbo Basic을 만들었다가 반대로 마소의 QuickBasic 대비 승산이 없다고 생각해서 포기해 버렸으니.. 행보가 서로 정반대인 셈이다.
Posted by 사무엘