안드레아의 포스 소개

+ 성부와 성자와 성신의 이름으로, 아멘! 안녕하세요? 김찬홍 안드레아입니다. 흐~ 우리 동아리 짱께서 제 강좌가 올라오고 있다는 소식을 공지해 주셨 네요. 애고, 감사합니다. 그런데, 포스는 흔히 말하는 '인기 있는 언어'에 속하지는 못합니다. 포스가 널리 알려지지 못햇고, 쓰는 사람이 적었기 때문에 C언어와 같은 주류 언어에 속하지는 못햇지만, 포스는 우 리가 흔히 쓰는 주류 언어들보다는 훨씬 뛰어난 특징을 많이 가지고 있습 니다. 포스가 많이 알려지지 못한 이유는, 다른 언어들과 바탕 개념이 많이 다 르기 때문입니다. 바로, 그것 때문에 포스가 강력하고, C나 파스칼과 같 은 ALGOL계 언어들의 단점을 벗어던지는 길이지요. 만약 필립 칸이 Turbo Pascal 대신에 Turbo Forth를 만들었다면 모든 것이 달라졌겠지만,... :) 지금은 너무 늦었지요. 그러나, 포스는 꼭 배울 필요가 있다고 생각합니 다. 특히 하드웨어를 제어하는 데에는 C 따위에 비길 수가 없습니다. 포 스를 쓰면 실시간(Real Time)으로 굳은모를 제어할 수 있습니다. 나중에 제가 가라사대 카드를 구입하고, Sori.Sys를 어느정도 이해한 다음에는, 포스에서 대화식으로 가라사대에 접근하는 법을 연구해 보려고 합니다.... 그 어떤 언어라도, 굳은모와 내장 제어 시스템을 설계할 때에 는 포스를 따라오지 못합니다. 포스가 C와 같은 주류 언어가 아니라고 해서 그 기능이 결코 떨어지는 것이 아닙니다. 지금의 C 언어 번역기(compiler)에 들어있던 통합 환경, 인라인 어셈블러는, Chalres H. Moore에 의해서 포스가 개발된 1971년부 터 있었습니다. 더구나 포스만의 특징으로 인해서, 포스 프로그램은 같은 일을 하는 조립어(assembly language) 프로그램보다 코드 크기가 작습니 다. 믿어지지 않습니까? 그럼 제가 자료실에 올린 hForth를 보십시오. 거기에 들어있는 SAVE.EXE 파일에는, 포스의 번역기(compiler), 통역기 (interpreter), 조립기(assembler)와, 동시에 여러 작업을 진행하고 통제 할 수 있는 다중 작업기(multi tasker), 그리고 포스의 기본 사전이 들어 있으며, 그 사전에는 기억 공간을 조정하는 것부터 파일을 읽고 쓰는데 이르기까지의 많은 낱말(C에서의 '함수'와 비슷하죠)들이 들어있습니다. 그 모든 것이 들어간 실행 파일의 크기가 30KB도 체 안 됩니다. 이 SAVE.EXE에 그래픽 모드에서 한글 입출력을 구현하는 낱말을 덧붙여 만든 SAVE2.EXE 역시 60KB도 안 됩니다. 놀라운 것은, 이 한글을 쓸 수 있는 SAVE2.EXE 안에 한글과 영문자의 글꼴(Font)도 내장되어 있으며, 두벌식 과 세벌식 자판을 모두 지원합니다. 또한 VGA와 허큘레스도 자동 판독하 여 지원합니다. 만약 글꼴 처리 방법을 바꾸어서 늘 외부 글꼴을 사용하 게 만든다면, 글꼴이 차지하는 약 10KB의 용량마저 줄일 수 있습니다. 또한 이렇게 만든 SAVE2.EXE에 LOGO 언어의 거북 그림(turble graphic) 기능을 집어넣어 만든 HTurtle.Exe 파일 역시 약 65KB 정도밖에 되지 않 는다는 겁니다. 놀랍지 않습니까? 사람들은 C가 UNIX라는 운영 체계를 만드는데 쓰였기 때문에 강력하다고 합니다. 네. 맞는 말입니다. C 언어 또한 매우 훌륭한 언어입니다. 다만 너무 지저분하고 비논리적이며 체계가 없는 문법 때문에 욕을 먹고 있는 언어이지만 말입니다. 그러나, 포스는 그 자신이 바로 운영 체계입니다. 소형 컴퓨터 중에는 부팅을 하면 자동으로 ROM에 있는 포스 시스템이 시작되는 것도 있습니 다. 앞에서 말한바와 같이 포스는 그 크기가 매우 작아서, 16KB의 기억 공간이면 기본적인 기능은 넉넉히 쓸 수 있고, 8KB에서도 돌아간답니다. 또한 더욱 더 놀라운 사실은, Forth 언어를 기계어로 삼는 CPU도 있다는 것입니다. 따라서, 포스 언어도 C언어와 같이 매우 강력하다고 말할 수 있습니다. C가 굳은모(hardware)를 잘 제어한다고 하지만, 감히 포스 앞에 내세울 수는 없습니다. 가령 기억 장소 B800:0000h 번지에 41h 라는 값을 넣는다 고 할 , C라면.. *((char far *)0xB8000000L) = 0x41; 처럼 해야 합니다. 그러나 포스라면, HEX 41 B800 0000 LC! 라고만 해 주면 됩니다. 간단하지 않습니까? 그리고, C로는 도저히 불가능한 일도 포스로 할 수 있습니다. 제가 아직 가라사대 카드를 잘 모르지만, 한 번 가정을 해 봅시다. 가라사대가 연결 된 나들목(I/O port) 210h 번지에 0이 들어가면 소리를 끄고, -1이 들어 가면 소리가 켜진다고 한번 가정해 보십시오. C를 쓰고 있으면 일일이 바 탕글(source code)을 작성하고 편집 -> 번역 (compiling) -> 연결 (linking) -> 실행(Run)의 과정을 거쳐야 합니다. 즉 소리를 끄고 켤 때 마다 그래야 하고, 그렇지 않다면 이미 번역되어 있는 프로그램의 실행 파일을 실행해야 합니다. 그러나 여러분이 포스에서 프로그램을 한다면 다음 몇 줄을 추가함으로 써 쉽게 가라사대의 음성을 제어할 수 있습니다. (다시 말하지만 아래에 서 쓴 주소는 __가정__입니다.) HEX 210 CONSTANT 가라사대 : 켜 ( p_addr -- ) -1 SWAP PC! ; : 꺼 ( p_addr -- ) 0 SWAP PC! ; 이제 포스는 '가라사대', '켜', '꺼', 이렇게 새 낱말을 배웠습니다. 여 러분이 가라사대를 켜고 싶다면 포스에게 언제든지 가라사대 켜 라고 시키면 되고, 끄고 싶을 때에는 가라사대 꺼 라고 시키면 됩니다. 이 모든 것이 실시간과 대화식으로 이루어집니다. 매우 효율적이고 우리 사람이 생각하는 것과 가깝지 않습니까? 포스에는 사전이 있고, 이 사전에 들어있는 낱말을 포스는 알아듣습니 다. 그러므로 여러분이 필요한 낱말을 포스에게 가르쳐 줄 수 있고, 따라 서 여러분이 원하는 데로 포스를 부릴 수 있습니다. 다른 어떤 언어도, 포스의 이런 특징과 유연성을 가지지 못했습니다. 물론 포스와 사촌인 TeleScript 등의 언어에서 포스의 이런 특징을 수용했다고는 하지만, 원 조만큼 수용하지는 못햇습니다. - 프로그램이 어렵게만 느껴지십니까? - C의 복잡한 문법과 포인터의 장벽에 막혀 계십니까? - 여러분이 스스로 언어를 고쳐서 여러분의 구미에 맞도록 바꾸어 보고 싶습니까? - 컴퓨터의 깊은 곳을 속속들이 알고 싶습니까? => 그렇다면 지금 곧 포스를 시작하십시오. 위에서 보여드렷듯이, 포스로 기억 공간을 건드린다 하더라도 포인터에 대해서 전혀 신경 쓸 필요가 없습니다. 물론 포스에도 포인터 개념이 있 습니다. 그러나 그것은 C언어처럼 배워서 익히는 것이 아닙니다. 포스를 쓰다 보면 저절로 터득하게 되는 것입니다. 포스는 매우 단순합니다. 일주일만 포스와 친해지신다면, 어느 정도 포 스를 갖고 놀 수 잇게 될 것입니다. 우리 동아리에 자료실이 있기는 하지만, 그래도 여러 사람이 포스를 쓰 게 하기 위해서 공개 자료실에 올렸습니다. 꼭 한번 받아보십시오. 그리 고 잘 모르겟드면 __반드시__ 질문을 해 주십시오. 여러분이 포스를 하다 가 막히는 것이 있으면, 그것은 결코 포스의 잘못이 아닙니다. 바로 __여 러분__ 스스로의 탓입니다. 포스를 만든 챨스 무어는 아래와 같이 말햇습 니다. "좋은 프로그래머는 포스로 놀라운 일을 해 내고, 나쁜 프로그래머는 포스로 끔찍한 일을 해 낸다." 여러분이 포스를 익히고, 또 좋은 프로그래머가 되려고 노력한다면 틀림 없이 놀라운 일을 할 수 있을 것입니다. 참고로 여러 가지 짧은 일을 하는 포스 프로그램 바탕글을 올려드리겠습 니다. 포스가 얼마나 간결한지, 그리고 강력한지를 대중해서 짐작해 보십 시오. 물론 포스를 처음 접한 여러분은 대부분 이해하지 못하실 것입니 다. 그러나 일단 여러분이 포스를 시작하게 되면 하나 하나씩 그 배일이 벗겨집니다. 절대로 바탕글을 뭉쳐서 보지 마십시오. 포스에서는 모든 것이 낱말입니다. 이 하나하나의 낱말이 모여서 문법을 형성하고 있습니 다. 그러므로 포스 낱말이 하는 행동(=낱말의 의미)만 바꾼다면 우리가 문법을 만들 수 있습니다. 그럼 우리 맹인들 중에 훌륭한 포스 프로그래머가 나오기를.... -------------------------------------------------------------------- \ prime.f -- 수를 입력 받아 그 수 까지 존재하는 모든 소수를 찾아 출 력함. \ \ 만든이: 김찬홍(andrea92). \ 한글 낱말을 제대로 보기 위해서 hiomult?.f 를 쓰세요. \ \ 1995. 11. 1. 고원용이 고침 \ 주어진 수의 제곱근까지만 나누어 떨어짐을 확인하도록 '소수인 가?'를 고침. MARKER ~PRIME : 소수인가? ( n -- flag ) DUP 1 = IF DROP FALSE EXIT THEN DUP 2 = IF DROP TRUE EXIT THEN DUP 2 DO I I * OVER > IF DROP TRUE UNLOOP EXIT THEN DUP I MOD 0= IF DROP FALSE UNLOOP EXIT THEN LOOP ; : 까지,소수봐 ( x -- ) CR 2 ?DO I 소수인가? IF I . THEN LOOP ; -------------------------------------------------------------------- \ 10sum.f -- 기억 공간의 칸 10 개의 내용을 더하는 낱말. : 10SUM ( a-addr:시작주소 -- n:결과 ) 0 OVER 10 CELLS + ROT DO I @ + 1 CELLS +LOOP ; : ENTER-DATA ( a-addr -- a-addr ) 11 1 DO I 2DUP 1- CELLS + ! LOOP ; CREATE DATA 10 CELLS ALLOT DATA ENTER-DATA 10SUM . ------------------------------------------------------------------- \ Fact.f -- 펙토리얼 구하기. : FACT! ( x -- x! ) DUP 1 = IF EXIT ELSE DUP 1- RECURSE * THEN ; \ 위의 낱말을 입력한 후 \ 3 FACT! . \ 라고 시켜보십시오. 위에서 RECURSE 낱말은 제귀 호출을 하는 낱말. ---------------------------------------------------------------- \ RANDOM.F -- pseudo-Random numbers generator for hForth \ by ChanHong Kim(andrea92@hitel.kol.co.kr) \ \ Bug Fixed by WonYong Koh(wykoh@pado.krict.re.kr) \ \ 난수를 만들어 내는 낱말들이 들어있습니다. 1971년에 만들어진 \ 포스에, 이미 인라인 어셈블러가 잇엇으며, 어셈블러도 식은 죽 \ 먹기처럼 쓸 수 있습니다. BASE @ GET-ORDER GET-CURRENT NONSTANDARD-WORDLIST SET-CURRENT HEX VARIABLE W1 VARIABLE W2 \ SRAND ( -- ) Seeds the random number generator. CODE SRAND CLI, 40 # AL IN, AL AH MOV, STI, 40 # AL IN, AX AX OR, 1 L# JNZ, 1A INT, DX AX MOV, 1 L: 0 # W1 ) MOV, AX W2 ) MOV, NEXT, END-CODE \ RANDOM ( -- u ) Computes a pseudo-random number CODE RANDOM BX PUSH, 015A # CX MOV, 4E35 # BX MOV, W2 ) DI MOV, W1 ) AX MOV, AX DX MOV, BX MUL, CX AX XCHG, DI MUL, AX CX ADD, DI AX MOV, BX MUL, CX BX ADD, 1 # AX ADD, 0 # DX ADC, AX W2 ) MOV, DX AX MOV, AX W1 ) MOV, 07FF # AX AND, AX BX MOV, NEXT, END-CODE SET-CURRENT SET-ORDER BASE ! --------------------------------------------------------------------