1. 레거시 부동소수점 MBF

컴퓨터에서 쓰이는 2진법 기반의 부동소수점이라는 개념이야 컴공· 전산에서 기본 중의 기본에 속하는 내용이며 본인 역시 이에 대해서 거의 7년 전에 글을 한번 쓴 적이 있다.
본인은 GWBASIC으로 프로그래밍에 처음 발을 내디딘 세대이다. 그런데 베이직이 PC와는 따로 노는 고유한 부동소수점 체계를 갖춘 언어였다는 사실을 30대 나이가 될 때까지 전혀 모르고 있었다.

쉽게 말해 같은 컴퓨터에서 실행한 다음 프로그램의 실행 결과가 GWBASIC과 QuickBasic이 서로 동일하지 않다는 것이다. 참고로 MKS$, MKI$는 해당 숫자들의 binary representation을 문자열 형태로 되돌리는 저수준 함수이다. C++라면 reinterpret_cast<char *>(&num) 한 방이면 끝났을 일이다.

10 INPUT A!
20 IF ABS(A!)<.01 THEN END
30 C$ = MKS$(A!)
40 FOR I = 1 TO 4: PRINT ASC(MID$(C$, I, 1)): NEXT
50 GOTO 10

사용자 삽입 이미지

하긴, 옛날에 베이직은 DEFINT A-Z 같은 걸 하지 않으면 변수의 기본 자료형이 정수가 아니라 실수였다. 언어를 설계할 때 성능보다 인간적인 면모를 더 추구해서 그렇다. (5/3을 구하면 매정하게 1이 아니라 알아서 1.6666..이 나오게..) 그러니 구조적으로 실수를 지원하는 건 필수였다.

때는 무려 1975년, 빌 게이츠가 폴 앨런과 함께 알테어 베이직을 개발하던 시절에 동료들과 함께 뚝딱 해서 2진법 기반의 부동소수점 표기 방식을 만든 게 Microsoft Binary Format, 일명 MBF라는 스펙이 됐다. 32비트와 64비트 두 형태로 말이다.
이 부동소수점은 알테어뿐만 아니라 BASICA, GWBASIC 등 온갖 플랫폼에서 돌아가는 베이직 인터프리터에 두루 쓰이기 시작했다. 지금도 인터넷에 굴러다니는 GWBASIC은 IEEE754가 아닌 MBF 고유 방식으로 부동소수점을 처리한다.

그랬는데 훗날 1984년경에 IEEE754라고 공신력이 더 높은 표준이 등장하면서 판도가 급격히 그쪽으로 기울었다. 게다가 PC에서는 인텔 80x87이라고 오늘날로 치면 하드웨어 가속에 해당하는 수치 연산 보조 프로세서(코프로세서)도 응당 IEEE754를 기반으로 만들어졌다.

마소는 일찍부터 자체적인 부동소수점 포맷을 먼저 제정해서 이를 퍼뜨려 왔지만 이런 시국에서는 자기도 대세를 거스를 수 없게 되었다. GWBASIC의 후신인 QuickBasic도 80년대 중반에 나왔던 1, 2까지는 MBF를 사용했지만 3.0부터는 IEEE 방식으로 갈아탔다. 그 대신 기존 MBF 방식은 별도의 옵션을 줬을 때에만 지원하게 동작이 바뀌었다. (/MBF) MBF 형태로 저장된 부동소수점을 읽어들이는 레거시 프로그램들과의 호환성도 중요하니까 말이다.

그럼 IEEE와 MBF는 어떤 차이가 있었는가? 몇 가지가 있다.
똑같은 32비트 또는 64비트 공간에다 지수와 유효숫자와 부호 비트를 어느 순서대로 어떻게 분배할지 문제는 한 마디로 그냥 정하기 나름이고 대동소이하다. 마치 철도 궤간을 정하는 문제와 비슷하다.

수 전체의 부호 1비트는 IEEE나 MBF든 공통일 수밖에 없고, 32비트의 경우는 지수 8비트, 유효숫자(mantissa) 23비트라는 비율 역시 동일했다. 다만,

(1) IEEE는 2의 보수 기반인 정수의 관행을 존중해서 부호 비트가 수 전체의 최상위 비트에 있는 반면, MBF는 지수와 유효숫자 사이에 존재했다. 다시 말해 mantissa의 최상위 비트에 있는 셈이다. 이렇게 배치를 함으로써 MBF는 IEEE와는 달리 지수와 유효숫자가 딱 8비트와 24비트로 byte padding이 맞춰지게 했다.

(2) 64비트 실수의 경우 이 비율도 달라진다. IEEE는 지수의 공간도 딱 3비트 더 늘어서 11비트이지만, MBF는 여전히 8비트이다. 그래서 32비트 single 실수를 쓰다가 64비트 double 실수를 쓰면 정밀도는 왕창 심지어 IEEE보다도 더 올라가지만 수의 표현 가능 자리수가 늘어나지는 않는다. 그 대신 바이트 경계는 여전히 1:7 비율로 지켜진다.

(3) 다음으로, MBF는 IEEE처럼 denormal number나 NaN, 무한대/무한소 같은 개념도 없다. denormal이야 숫자 표현과 관련된 내부 디테일이니 그렇다 치더라도 베이직 언어로 수학 함수를 사용하면서 NaN이나 무한대/무한소 같은 걸 접한 경험은 없다. 그런 숫자가 생성될 상황이라면 그냥 "Illegal function call" 에러가 나고 말지.
어쩐지 이런 것들은 본인이 훗날 C/C++로 갈아타면서 처음으로 접했다. 이게 엄밀히 말하면 언어 차이가 아니라 이런 부동소수점 표현 방식 때문에 생긴 차이점이다.

세계적으로 문자들은 언어와 문화권마다 제각각이지만 아라비아 숫자만은 세계 공통이다. 컴퓨터 세계도 사정이 얼추 비슷했는데 그나마 유니코드라는 규격 덕분에 동일한 문자는 세계 어디서나 동일한 방식으로 통용 가능해졌다. 그에 반해 숫자가 부동소수점 한정으로 표현 방식이 파편화돼 있었다는 건 개인적으로 무척 흥미롭게 와 닿는다.

C, 파스칼 같은 언어 이름은 함수 호출 규약 명칭에 등장하는데 베이직은 MBF라는 레거시를 보유하고 있구나. IEEE754의 등장 이전에는 MBF 말고 다른 부동소수점 표현 방식은 존재하지 않았나 하는 의문이 남으며, 파스칼에만 있던 6바이트 실수가 규격이 어떠했는지도 다시 보게 된다. 스펙을 검색해 보니 파스칼도 지수부는 8비트이고 나머지가 부호부(1비트)와 가수부(39비트)이다.

2. MOTOR의 정체는?

이 블로그에서 GWBASIC에 대한 추억들 중에서 지금까지 이걸 거론한 적은 없었던 것 같다.
GWBASIC의 대화식 환경에는 코딩 중에 자주 사용하는 키워드들을 곧바로 입력하는 일종의 키매크로가 있었다. F1부터 F10까지 기능키에 배당된 매크로는 LIST, RUN, LOAD...의 순으로 화면 밑줄에 표시되었으며 KEY라는 키워드(?)를 이용해 사용자가 재정의도 할 수 있었다. 후대의 QuickBasic 계열에서는 없어지기도 할 법도 한 키워드인데 KEY에 그 기능만 있는 건 아니기 때문에 없어지지 않고 남아 있긴 하다.

그리고 매크로가 거기에만 있는 게 아니라 Alt+알파벳에도 있었다. A부터 Z 중 J, Q, Y, Z를 제외한 나머지 22개 알파벳에는 AUTO, BSAVE, COLOR ... WIDTH, XOR까지.. 키워드가 즉시 입력되었다. 이 키워드들은 딱히 재정의 가능하지 않았다. RUN과 SCREEN은 Alt에도 있고 F 기능키에도 있었다. (후자는 엔터까지 자동으로 입력된다는 차이가 있음)

그런데 본인이 주목한 것은 M 자리에 배당되어 있던 MOTOR라는 단어였다. 이거 도대체 뭘까? 경험상 숫자 인자를 하나 받는 것 같던데 도대체 하는 일이 뭘까? 두툼한 GWBASIC 매뉴얼/키워드 레퍼런스를 뒤져봐도 의외로 딱히 제대로 설명돼 있지 않았다. 그러니 궁금증은 더욱 커질 수밖에 없었다.

이 역시 전세계에 존재하거나 존재했던 모든 것들에 대한 정보가 손끝 하나로 검색되는 세상이 온 뒤에야 그게 그런 용도였다는 것을 뒤늦게 알 수 있었다.
MOTOR는 카세트 테이프 장치의 헤더를 올리거나 내리는 명령문이었다. 0부터 255 사이의 숫자를 인자로 받긴 하는데 실질적인 의미는 그냥 zero냐 non-zero냐, 쉽게 말해 그냥 bool이었다. 카세트 테이프가 퇴출된 16비트 이상의 IBM-PC급용 베이직에서는 이 명령은 구현되지 않고 아무 동작도 안 하는 레거시 잉여가 되었다.

옛날에 카세트 테이프에다 소스 코드 저장을 SAVE"FILE" 한 뒤 '녹음' 버튼을 눌러서 쭈루룩 하고, 불러오려면 저장되었던 위치로 정확하게 되감기를 하고 LOAD"FILE"한 뒤, '재생' 버튼을 눌러서 했다던데.. MOTOR는 그런 호랑이 담배 피우던 시절에나 유의미한 기능을 했다는 뜻 되겠다.

그런데 왜 이런 잉여가 한때에는 그 시절에는 자주 쓰이기라도 했는지 Alt+M 매크로에 떡 등재돼 있었다. 현실에서는 모터 따위보다는 MOD 연산자 또는 부분문자열을 구하는 MID$ 함수가 훨씬 더 자주 쓰일 텐데 말이다. 그러고 보니 실제로 Alt+M에 MOTOR 대신 쿨하게 MID$가 배당돼 있던 GWBASIC 구현체가 있기도 했던 것 같다. 베이직은 바리에이션 구현체가 워낙 많으니.. 아니면 그건 그냥 내 기억력의 한계로 인한 착각이었는지는 모르겠다.

※ 기타

(1)
이 외에도 GWBASIC은 그러고 보니 소스 코드의 저장도 고유 방식으로 했고 심지어 후대의 QuickBasic에도 비슷한 관행이 있었다(디폴트 옵션). 베이직 언어들은 그 옛날에도 일종의 가상 기계나 독자적인 개발 환경까지 다 짬뽕으로 추구했던 것 같다.
비주얼 베이직의 중후반대(4정도?) 넘어가서 COM 기반의 BSTR 방식으로 갈아타기 전에는 베이직은 문자열도 자기만의 독자적인 이중 포인터 참조 방식으로 구현돼 있었다. 일단 null-terminate 방식이 아니기 때문에 C와는 다름. 이것도 아마 MBF만큼이나 역사가 왕창 오래 된 독자적인 관행이 아닐까 싶다. (문자열에 대해서도 옛날에 한번 글을 쓴 적이 있다.)

(2)
난 C/C++ 파스칼 같은 타 언어로는 도스에서 텍스트 모드에서 색깔을 바꾸고 표준 VGA 그래픽, 특히 mode 13h를 바꾸는 코드를 작성해 본 적이 없다. 베이직에서는 COLOR 내지 SCREEN으로 곧장 됐을 일이 타 언어에서는 표준 라이브러리에서 지원해 주지 않았기 때문이다.
GWBASIC에서 Q(uick)Basic 계열로 바뀌면서 정말 좋은 것 중 하나가 본격적인 VGA 그래픽이 지원된다는 것이었는데, 16진수를 10진수로 바꿔 버릴 생각을 어째 했나 모르겠다. 실제로는 0x13인데 그걸 그냥 13만 써도 되게..;; 그것까지 초보자를 배려한 것이었나 궁금해진다. 그 초보자가 숙련자로 등급이 바뀌는 순간부터 문화 충격을 경험할지도 모르는데..

(3)
베이직이라는 언어 자체는 다트머스 대학의 컴공 교수가 고안한 것이지만, 저런 구현체는 빌 게이츠 같은 괴짜가 아니면 생각해 낼 사람이 별로 없을 물건이다.마소에서는 처음에는 다양한 8/16비트 컴퓨터를 대상으로 베이직 인터프리터를 개발했지만, 사실 IBM PC용으로는 베이직 컴파일러도 DOS 1980년대부터 만들어 오고 있었다.
그래서 Quick이라는 브랜드를 붙여서 QuickBasic 1.0을 1985년에 내놓았다. 이때 퀵베이직은 지원하는 문법은 GWBASIC과 별 차이가 없지만 대화식 환경이 아닌 명령줄에서 컴파일 + EXE 생성만 가능한 베이직일 뿐이었다.

그러다가 1년 주기로 버전 2와 3을 내놓으면서 기존의 구닥다리 행번호 위주가 아닌 구조화 문법이 차근차근 도입되었다. 베이직이라는 언어가 이때(1980년대 중반) 1차로 마개조된 셈이다. 그리고 4.0에 와서야 비로소 함수의 재귀호출이 가능해지고, 즉석 문법 체크와 실행이 지원되는 IDE가 추가되었다. 사실, IDE 자체는 2에서부터 도입됐고 그때 이미 퀵라이브러리도 도입됐다고 하지만, 그때는 지금과 같은 IDE가 아니었다.

그 뒤 1988년 가을에 출시된 QB 4.5가 장수만세 안정판이 되었다. 퀵베이직은 1990년에 어쩐 일인지 버전 5와 6을 건너뛰고 QuickBasic Extended 내지 MS Basic PDS (전문 개발 시스템)이라는 이름으로 7과 7.1 버전까지 개발된 뒤, Visual이라는 브랜드로 바뀌었으며 이때부터 플랫폼도 Window로 바뀌었다. 5, 6을 건너뛴 이유는 퀵베보다 먼저 개발되어 온 그 전신 컴파일러의 버전 번호를 맞췄기 때문이다. (참고로 Visual C++도 IDE의 버전보다 컴파일러의 버전이 더 높음. 전신인 MS C 의 버전을 계승하기 때문이다.)

이 와중에 1991년에 출시된 MS-DOS 5.0에서는 QuickBasic에서 컴파일 기능을 떼어낸 QBasic이라는 물건을 만들고, 이 엔진으로 MS-DOS 4.0까지 내장하고 있던 GWBASIC과, EDLIN 텍스트 에디터를 동시에 대체했다. 무척 흥미로운 점이다. MS-DOS가 전체 화면 형태로 제공하던 유틸리티는 4.0에서 도입됐던 DOS Shell 이후로 이게 둘째가 아닌가 싶다.

Posted by 사무엘

2017/04/28 08:38 2017/04/28 08:38
, ,
Response
No Trackback , No Comment
RSS :
http://moogi.new21.org/tc/rss/response/1354

오늘은 오랜만에 옛날 GWBASIC 추억 얘기를 또 늘어놓아 보겠다. 예전에 했을 법도 해 보이는데 여러 키워드로 검색을 해 보니 안 한 것 같다. 베이직 얘기를 전문적으로 하는 건 한 2년 만의 일이다.

GWBASIC은 초딩이었던 본인을 프로그래밍의 세계로 이끈 추억의 장난감이다.
본인은 어릴 때부터 컴퓨터가 다른 전자 기기와는 뭔가 차원이 다른 대단한 물건이라는 걸 실감했다.
텔레비전은 오로지 일방적으로 전달만 하는 물건인 반면, 컴퓨터는 내가 직접 명령을 내려서 모니터에 찍히는 글자의 색깔을 바꿀 수 있고, 내가 원하는 화면을 구성할 수 있고, 그림도 그릴 수 있고 소리도 내고 파일로부터 정보를 읽고 쓰면서 뭔가 '나만의 능동적인 세계'를 표현할 수 있기 때문이다.

본인은 딱히 머리가 빨리빨리 잘 돌아간다거나 수학 덕후 최적화 덕후 기질이 있지는 않았다. 단지, 새로운 세계를 표현하는 것 자체에 집착했다. 그래서 정보 올림피아드도 경시에서는 영 재미를 못 보고 그 대신 공모 부문에서 다 입상했다.

GWBASIC은 결과를 즉시 확인할 수 있는 대화식 구조라는 게 굉장히 인상적이다. 행번호에 GOTO문 남발은 굉장히 기괴하고 거추장스러운 개념이긴 하지만, 행번호가 없는 명령은 곧장 실행되고, 행번호가 붙은 명령은 메모리에 등록되어서 나중에 행번호 순으로 한꺼번에 실행된다는 그런 발상은... 참 아무나 할 수 있는 게 아닌 듯하다. RUN, MERGE, DELETE, CHAIN처럼 기억된 프로그램 자체를 확장하거나 바꾸는 명령이 있다는 것도 기괴하고 말이다.

GWBASIC에는 프로그램을 불러오거나 저장하는 명령으로 LOAD, SAVE가 있다. 그런데 GWBASIC은 좀 특이한 게, 여느 프로그래밍 툴처럼 소스 코드를 plain text로 저장하는 게 아니라 내부 바이너리 바이트코드로 저장하는 게 기본 옵션이다. 바이트코드는 같은 소스를 저장했을 때 plain text보다 크기가 작고, 로딩/저장 속도도 더 빠르다는 이점이 있다.

세월이 워낙 많이 흘렀기 때문에 지금은 그 바이트코드의 포맷이 다 알려져서 인터넷에 굴러다닌다. 포맷이 정식으로 공개된 건지 아니면 해커들이 리버스 엔지니어링을 해서 알아낸 건지는 잘 모르겠다.
다른 프로그램에서도 소스 코드를 볼 수 있게 저장하려면 SAVE"파일이름", A라고 뒤에 A를 덧붙여야 한다.

그리고 한편으로 P라는 옵션이 있다. P 옵션은 A와는 반대로 소스 코드를 내부 바이너리 코드로 저장하되 그걸 XOR 기반의 간단한 암호화까지 해서 저장한다.
P 옵션으로 저장된 소스는 불러와서 실행은 가능하지만, LIST로 내용을 열람하거나 코드를 수정할 수 없다. 따라서 비록 GWBASIC에 소스 코드를 EXE로 컴파일하는 기능은 없지만, 다 만든 프로그램을 남에게 인계할 때는 P 옵션으로 저장된 프로그램 파일을 전해 주면 소스 코드 유출을 막을 수 있다. 이론적으로는 말이다.

그러나 그 시절의 GWBASIC에 무슨 전문적인 코드 암호화나 난독화 기능이 있었던 것도 아닌데, 겨우 그 정도의 허접한 보호 기능은 당연히 뚫리고도 남았다.
P 옵션의 암호화 방식도 다 알려져 있고, GWBASIC의 버그를 이용하여 보호 기능 자체를 뚫어 버리는 방법도 존재한다. 이것은 아주 오래 전부터 베이직 프로그래머들 사이에 나돌던 공공연한 비밀 테크닉이었다.

자, 0xFF 문자 2개로 구성된 2바이트짜리 파일(가칭 UN.BAS)을 만든다. 간단하지만 키보드로 바로 입력할 수 없는 문자이긴 한데.. 헥사 에디터를 쓰든지 아니면 GWBASIC 자체를 이용해서 이런 파일을 생성하는 프로그램을 짜서 돌려도 된다.

그 뒤, P 옵션이 붙은 임의의 소스를 LOAD한 뒤, 그 상태에서 UN.BAS를 뒤이어 LOAD하고 나면..
기존 소스의 프로텍션이 풀리고 LIST 열람이 가능해지는 걸 볼 수 있다. 마법과 같은 일이 벌어진다.

사용자 삽입 이미지

그 뿐만이 아니다.
NEW를 입력해서 기억되어 있던 소스를 다 지운 뒤에도 UN.BAS를 LOAD하면.. 방금 지워졌던 소스가 되살아난다.

사용자 삽입 이미지

이게 도대체 어째서 가능할까? (UN.BAS는 0xFF 0xFF일 뿐, 저 소스 코드 자체가 들어있는 거 절대 아님.. -_-)
사실, GWBASIC은 내부적으로 기억하고 있는 바이트코드를 디코딩해서 LIST로 출력하고 소스 코드를 고치는 것을 허용할지 여부를 간단한 boolean 변수 하나로만 판단하는 듯하다. 저장할 때 XOR 인코딩 여부 역시 그 변수로 판단하며, 불러올 때의 XOR 디코딩 여부는 파일 앞부분에 있는 헤더로 판단한다.
그러니, 그 메모리 주소의 값만 바꿔 버리면 프로텍션을 곧바로 풀 수 있다. GWBASIC의 보안 체계는 근본적으로 허술했던 것이다.

그리고 GWBASIC의 고유 파일 포맷에 따르면, 프로텍션이 걸리지 않은 파일은 0xFF로 시작하고, 걸린 파일은 0xFE로 시작한다.
그러므로 0xFF 0xFF 2바이트짜리 파일은 GWBASIC으로 하여금 프로텍션 플래그는 해제하지만 그 뒤에 거의 즉시 파일이 끝나 버리기 때문에 메모리 상의 다른 소스 코드는 건드리지 않는 역할을 하는 듯하다.

원래는 그렇게 파일이 갑작스럽게 끝났을 때의 처리를 GWBASIC이 깔끔하게 해야 하지만 그렇지 못하기 때문에 졸지에 프로텍션만 풀어 버리는 게 가능한 듯하다.
NEW를 한 것까지 어떻게 undo를 하는지까지는 잘 모르겠지만 말이다.

아무튼, 이런 게 오늘날의 소프트웨어 보안 용어로 치자면 일종의 버그이고 exploit이다.
만약 GWBASIC이 Windows, Office, Visual Studio처럼 오늘날까지 살아 있는 제품이고 GWBASIC이 세계 기업들의 돈줄을 좌지우지하는 솔루션이었다면 이건 뭐 당장 긴급 업데이트/패치감이 됐을 것이다. 회사의 자산인 소스 코드가 간단한 해킹으로 죄다 유출되게 생겼으니 말이다.

업데이트 명분으로 맨날 귀가 따갑도록 나오는 “악의적으로 조작된 파일을 열 경우 임의의 코드가 실행... 까지는 아니어도 뭐가 어찌될 수 있는 보안 취약점이 Microsoft 모 제품에서 발견되었습니다” 문구가 가리키는 게 바로 이런 거다.
자그맣게 조작된 파일이 GWBASIC의 저장 프로텍션을 풀어 버리니, 이 꼼수가 보안의 관점에서 오늘날 시사하는 바가 크다고 생각되어서 문득 글을 써 보았다.

옛날에, 286 XT/AT를 갖고 '교육용 컴퓨터' 이러던 시절에는 단색 그래픽 모드에서 동작하는 여러 '교육용 소프트웨어'들도 있었다. CAI라고 들어 보셨는가?
'약수와 배수', '컴퓨터 개론' 같은 타이틀이 있었는데, 개중에는 정말 놀랍게도 GWBASIC으로 개발된 것도 있었다.
물론 런타임인 GWBASIC.EXE와 소스 코드들은 다 파일 이름과 확장자를 교묘하게 바꿨고, 실행은 CAI.BAT라는 파일로 했다.

소스 코드를 열어 보니 당연히 프로텍션이 걸려 있었다. 그러나 본인은 저 테크닉을 이용하여 프로텍션을 풀고 코드를 열람해 보기도 했다. 분량이 상당히 방대했으며 지금 다시 봤으면 여러 재미있는 아이디어들을 발견했을 법도 해 보지만, 본인은 그 당시엔 프로그래밍 실력의 부족으로 인해 그다지 충분한 재미를 못 봤다.

그 느리고 허접한 GWBASIC으로 자체 한글 출력과 그것도 모자라서 입력까지 구현했는데 과연 어떻게 구현했을지가 궁금해지지 않는가?

GWBASIC의 후신인 QBasic이야 고릴라 내지 NIBBLES 같은 예제 게임 프로그램이 MS-DOS 5.0에 같이 곁들여 제공되기도 했다.
순수 GWBASIC으로 근성으로 만들어진 프로그램은? 먼 옛날에 무슨 허접한 자동차 경주 게임 같은 걸 본 게 마지막이다. 각 스테이지의 이름은 태양계의 행성 이름이었는데... 기억하는 분이 있으려나 모르겠다.

상용 제품인 QuickBasic도 GWBASIC의 전통을 이어받아 소스 코드를 자기 고유 포맷으로 저장하는 기능이 있었다. 물론 GWBASIC과 호환되는 포맷은 아니었다. 그리고 축소판인 QBasic은 그런 기능이 없다.
지금은 '큐베'라고 하면 음악 DAW 프로그램인 큐베이스(Cubase)가 먼저 떠오르는 세상이 됐으니 이것도 격세지감이다.

* 그리고 GWBASIC과 관련된 추가 여담.
IBM PC(=도스)용으로 이식된 GWBASIC이야 기본 프롬프트가 Ok이지만, 더 구닥다리 8비트 롬 베이직 같은 걸 보면 프롬프트가 READY인 경우가 있다. 빌 게이츠 아저씨가 GWBASIC을 최초로 만들 때 원래 의도했던 메시지는 ready였다고 한다.
그 사고방식은 오늘날 같은 Windows+GUI 시대에까지도 남아 있다. Excel이나 Visual Studio, 심지어 MFC 기본 어플이.. 내부적으로 더 처리할 메시지가 없이 사용자의 입력만 기다리는 idle 상태로 진입했을 때 아래의 상태 표시줄에 나타나는 메시지는 바로 Ready이며, 우리말로는 그냥 '준비'이다.

그랬는데 ready가 ok로 바뀐 이유는.. 메모리를 단 3 바이트라도 더 확보하기 위해서였다고 한다. 뿌우우... 묵념.

단, Ok도 다 대문자 OK도 아니고, 대문자 O에 소문자 k로 정해진 이유는 본인으로서는 지금도 알 길이 없다.

Posted by 사무엘

2014/10/15 08:23 2014/10/15 08:23
, ,
Response
No Trackback , 6 Comments
RSS :
http://moogi.new21.org/tc/rss/response/1018

살다 보니 C#이나 파이썬도 아니고 비주얼 베이직으로 작성된 코드를 C++로 포팅해야 할 일이 있었다. C/C++로 갈아탄 뒤로는 베이직 코드는 다시는 볼 일이 없을 줄 알았는데 이거 정말 몇 년 만이냐.

들여다봐야 하는 코드는 닷넷도 아니고 비주얼 베이직 6으로 만들어진 코드였다. 하지만 GUI가 아니라 계산 알고리즘을 포팅하는 것이기 때문에 포팅이 크게 어려운 건 없었다. VB6에서 닷넷으로 넘어가면서 완전히 뒤집어엎어진 건 API 체계이지, 언어 자체가 그렇게 많이 바뀐 건 우려한 것만치 많지 않아 다행이었다. 자바와 자바스크립트의 관계에 필적하는 이질감은 아닌 것 같다.

언어가 바뀐 것은,
- 첫째, statement이던 것이 C 언어의 영향을 받아 다 일관된 함수 호출 형태로 바뀜. 그래서 매개변수 전체를 괄호로 싸야 됨. (파이썬도 3.0에서는 print가 statement에서 함수로 바뀜)

- 둘째, 타입이 예전보다 더 엄격해지고, 모든 변수는 반드시 사용 전에 선언을 해 줘야 함. 베이직은 원래 그런 걸 안 하는 언어이다가 하는 걸로 바뀌었다 보니, 변수를 선언하는 키워드가 Var이 아니라 Dim...이다. 원래는 배열을 선언할 때만 쓰는 키워드였지.
이런 추세를 정면으로 역행하는 GWBASIC의 잔재인 DefINT A-Z 같은 명령문은 당연히 퇴출이다.

- 셋째, 그리고 객체지향 패러다임에 맞춘 API의 전면 재구성이다. 예전엔 그냥 global 단위로 곧바로 호출하던 함수도 다 분야가 나뉘어서 클래스나 namespace에 소속된 메소드로 바뀌었다. 그래서 수학 함수도 바로 Sqrt라고 하면 안 되고 Math.Sqrt라고 써 줘야 하며, Math를 자주 쓴다면 Using 선언을 한 뒤에 생략해야 한다. 하긴, 비베에는 예전부터 With 키워드는 있긴 했다만.

이 정도.
요즘 언어들은 C/C++ 영향을 받아서 다들 대소문자 구분을 하는 게 유행이기 때문에, 혹시 비주얼 베이직도 그렇게 바뀌지 않았으려나 생각했다만...
의외로 명칭에 대소문자 구분을 안 하는 건 VB6이나 닷넷이나 마찬가지이다.

베이직은 원래 좀 가볍고 동적인 언어였는데, MS의 닷넷 입맛대로 대수술을 거치다 보니 그냥 C#의 표현력에 필적하는 전형적인 절차형 언어가 된 것 같은 느낌이 든다. 예전의 베이직 같은 느낌은 파이썬이 더 잘 간직하고 있는 듯.

배열 첨자도 ()로 싸고, 함수 호출 인자도 ()로 싸는 건 베이직의 특징이다. 언뜻 보기에 굉장히 혼동될 것 같은데 C++처럼 [] () 따로 연산자 오버로딩이라도 해야 하는 게 아니라면 의외로 둘이 문법 차원에서 혼동될 일은 없다. 참고로 본인은 ::와 .의 구분이 없는 객체지향 언어들에 대해서도 의아해한 적이 있었는데 이 구분 역시, 포인터만 없다면 거의 필요하지 않다.

그러고 보니 베이직은 대입도 =, 동등 비교도 =이다. A=B=1이라고 하면 C언어 식으로 치자면 A=B==1처럼 해석된다. 원래 베이직의 대입문은 Let A=1 처럼 써 줘야 맞는데 Let이 C언어의 auto만큼이나 캐잉여로 전락하는 바람에 지금 같은 꼴이 된 것이다. 그러고 보니 Let을 Dim처럼 변수 선언 키워드... 아니 C++0x의 auto처럼 쓰는 것도 괜찮을 것 같다?

Dim A as Double
Dim I as Integer

뿐만 아니라

Let A = 0.52 '자동으로 실수 확정
Let I = 5    ' 자동으로 정수 확정

이렇게도 되게 말이다. 타입이 이랬다저랬다 바뀌는 Variant가 아님. 기발하지 않은지? ㄲㄲ

베이직처럼 구문 분석이 쉬운 언어는 IDE의 인텔리센스나 코드 자동 완성 같은 기능이 C++의 그것과는 비교할 수 없이 안드로메다급으로 훨씬 더 빠르고 똑똑하고, 돌아가는 게 손에 착착 달라붙는다. 도스 시절의 퀵베이직이 이미 인텔리센스만 없을 뿐이지 그런 꿈의 프로그램 개발 환경을 어느 정도 제공하고 있었다. 빌드 속도는 두말 할 나위도 없음.

그러나 C++ 코드는 실시간으로 코드 변경 사항을 IDE가 따라잡으려면, 비주얼 스튜디오든 Source Insight든, 어쨌든 background에서 소스를 다 까 보는 작업을 하지 않으면 안 된다. 그래서 어떻게든 처리 속도를 올리려고 덕지덕지 남기는 부가 정보 데이터가 많다. 함수 이름을 바꾼 게 C/C++은 복잡한 절차를 거쳐 최소한 수 초 뒤에 IDE의 ClassView에 반영되는 반면, 베이직은 ‘즉시’이다.

이런 생산성과, C++ 특유의 졸라 가볍고 효율적인 네이티브 코드라는 두 마리 토끼를 모두 잡은 프로그래밍 언어 + 개발 환경은 정녕 없는 것일까.
하긴, 윈도우 환경에서 베이직 언어로 네이티브 코드를 생성하는 컴파일러는 MS 제품 중에는 없고 파워베이직이라는 브랜드가 있다. 하지만 인지도가 안습한 수준.

Posted by 사무엘

2012/01/26 08:45 2012/01/26 08:45
,
Response
No Trackback , 6 Comments
RSS :
http://moogi.new21.org/tc/rss/response/632


블로그 이미지

그런즉 이제 애호박, 단호박, 늙은호박 이 셋은 항상 있으나, 그 중에 제일은 늙은호박이니라.

- 사무엘

Archives

Authors

  1. 사무엘

Calendar

«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

Site Stats

Total hits:
3041213
Today:
840
Yesterday:
1700