2007. 8. 15. 01:52
# What is it?
 수를 표현하는데는 많은 방법이 존재합니다. 고대엔 사람들이 숫자를 표현하기 위해서 막대기를 사용
했습니다. 그후엔 막대를 그려서 표현하는 방법을 터득했습니다.(종이나 땅바닥에....)
예를 들면 수치 5를 표현하기 위해서는 | | | | |  이런식으로 표현을 하였습니다.

로마시대에 와서는 막대를 써서 수치를 표현하는데 다른 심볼 두개를 추가합니다. 바로 V 와 X입니다.
각각 5와 10을 나타내었습니다.  각각의 전과 후에 막대가 표현됨에 따라 하나작은 혹은 하나많은으로
표현을 합니다. (IV -> V -> VI .... iX -> X -> XI......)

그당시까지만 해도 이런 막대표현방식은 굉장한 아이디어에 속했습니다. 실제 숫자에 해당하는 막대
대신에 심벌(기호)을 이용해서 표현하는 것에 대한 이야기였습니다.

이제는 컴퓨터에서 표현가능한 숫자표현에 대하여 알아보도록 하겠습니다. 수학시절로 되돌아가는
것은 아닙니다. 저또한 수학엔 잰뱅이라서..... 단지 이런이런것이 있구나를 알아두시고, 추가로
이어지는 장을 학습하시면서 자연스럽게 사용하게 됩니다. 억지로 외우시면 역효과가.......


# Decimal System (10진수)
대부분의 사람은 수를 표현하는데 10진수를 사용합니다. 10진수는 수를 표현하는 기호 10개를 사용해서
10진수라고 부릅니다. (0,1,2,3,4,5,6,7,8,9,0 -> 자리올림 후 다시 0)
어떠한 양의 수를 어떤진수로 표현하든지 양은 동일합니다. 단지 표현방법만 다를 뿐입니다.
사람은 손가락이 10개라서 10진수에 익숙하다는 속설도.......

754 라는 숫자를 곰곰히 들여다 보십시요. 칠백 오십 사   를 뜯어보면 X백 X십 사  라고  표현됩니다.
수학적으로는 기수(Radix)의 자승으로 크기가 늘어나서 양적표현을 합니다.
즉, 우측에서 부터 기수인 10의 0승 10의 1승 10의 2승..........  7X100 + 5X10 + 4X1  = 754라고
부릅니다. 시시한가요? 바로 이러한 기본에서 부터 파생되어 갑니다. 저또한 이런것을 보면
다배운거라고 무시하고 넘어가는 버릇이 있었습니다. 하지만 어셈블리 할때는 이러한 기본들로
아무리 복잡한  표현이라도 다 표현합니다.  10진법의 구조를 알았으니 단지 Radix인 기수만
변경하면 어떠한 진법으로도 다 표현 할 수 있습니다...

참고로 , 왜 컴퓨터 기초책에서 이런 진법얘기가 안빠지고 나올까요??

컴퓨터는 누가 쓰느냐에 따라서 입니다.  기계는 혼자는 다 잘 합니다. 문제는 사람이 개입해서입니다.
사람이 편하게 쓰기위해서 만들다 보니, 두종족(??)인 사람과 기계와의 대화수단이 생겨나겠지요...
컴퓨터는 숫자에 강하고 사람은 문자에 강합니다. 그래서 수치만으로 모든걸 표현하는 컴퓨터가
움직이는 방식을 사람이 이해할려면 숫자->문자로 변환해야겠지요?? 이것을 코드라고 부릅니다.
들어들 보셨을 겁니다. ASCII / EBCDIC .........  즉 1을 A라고 약속해놓고 컴퓨터에서는  1이란
숫자만 보면 VGA카드에게 1이라고 그려주면 사람은 컴퓨터가 1을 이해하는것 처럼 보이지만 실제론
숫자에 해당하는 신호로 처리할 뿐입니다... 이래서 컴퓨터는 단순하느니 무식하느니 하는 것입니다.
단지 이진수로 움직이지만 그 움직이는 속도가 무지막지하게 빠르다는게 사람과 차이점이지요....

자 여기까지 컴퓨터는 이진수 사람은 10진수라고 했지요....  그런데 왜 8진수 더더구나 16진수는
몸에 익어야하는데 왜일까요? 바로 프로그래밍 언어가 들어오면서 부터입니다.
컴퓨터가 쓰는 2진수를 사람이 주로 2진수로 입출력하지는 않겠죠? 그래서 당연히 변환을 합니다.
느려지겠네요.... 컴퓨터에서 모든 행동은 시스템 클럭을 소모합니다.. 그래서 중간지점을 찾습니다.
2진수   -> 8진수 -> 16진수  부분이 시스템이 좋아하는 진법입니다.  10진법은 사람이 좋아합니다.
그래서 고급언어들은 주로 10진수를 그대로 사용하고, 저급언어에서는 16진수 8진수 등을 사용합니다.
8진수는 자주 안보셨다구요? 아까 위에서 언급한 한문자를 표현하는데는 코드를 사용한다고 했습니다.
그 코드는 8비트로 되어있구요. 8비트는 표현가능한것이 8개므로 8진법입니다...... 이해되셨나요?
그런데 한글자씩 표현하기엔 좀 번거롭고해서 16비트로 처리합니다. (이것은 16비트컴퓨터에서...)
그것을 워드(WORD)라고 표현합니다.. 요즘은 32비트 컴퓨터를 주로 사용하지요???
8비트 컴퓨터 16비트 컴퓨터 32비트 컴퓨터는 한번에 데이터를 몇바이트를 처리하느냐로 결정됩니다.
또한가지, 이러한 것은 바로 고급언어에서의 "정수형" 이라고 부르는 Integer형입니다.
왜 Int형을 가장많이 쓰고 효율적이라는 지 답이 나왔네요.   이러한 진법은 자칫 혼동스러울수 있습니다만
억지로 외우지 마시길 바랍니다. 그냥~~~~ 쓰다보면 익혀집니다.. 처음엔 손가락으로 세지만 나중엔
자기도 모르게 암산까지 하시는 여러분들이라면 누구나 다 이해됩니다. 걱정마시기 바랍니다....

다시 본론으로....
사용자 삽입 이미지

base가 바로 기수인(Radix) 진법의 기본이 되는 수입니다. 위는 당연히 10진수입니다.
각각의 자릿수는 그 수의 크기를 나타냅니다.
한가지 혼동하시면 안될 것이 있습니다.
사용자 삽입 이미지

바로 기수의 0승입니다. 모든진법의 0승은 1이 나옵니다..(맞나요???)  ㅎㅎ



# Binary System (2진수)
컴퓨터는 사람과 같이 영리하지 않습니다. 단순하지만 상당히 빠르다는 것외에는......
그단순함은 스위치와 동일합니다. 최초의 컴퓨터라는 애니악이 왜 크기가 교실만했을까요?
요즘같이 트랜지스터가 없을때는 진공관으로 스위치 역활을 했습니다. 당연히 크기가 커지겠죠..
이게 바로 교실의 부피만큼 스위치가 가득했던 이유입니다. 전구를 몇천개를 손톱크기의 칩에
넣어버렸죠.. 그래서 집적(모아서 쌓는다)회로라고 하고 IC칩이라 부르죠...
여하튼 스위치 한개로 2가지 표현을 할 수 있습니다. 꺼짐 / 켜짐  이것을 2진수로는 0 / 1 로 표현
되겠네요. 바로 이러한 꺼짐과 켜짐으로 컴퓨터는 모든것이 시작됩니다.  위에서 수치를 표현하는데
여러가지 방법이 존재할 뿐 어떠한 수는 같다고 했습니다. 그래서 2진수로도 수치를 표현할 수
있겠네요..... 하지만 표현수단이 2개 뿐이니 754정도 되는것을 표현할려면 자릿수가 상당하겠죠?
그래서 2진수 3자리를 끊어서 8진수로 만들고 2진수 4자리를 끊어서 16진수를 만들어서 사용하는
것입니다.  8진수 16진수는 왜 쓰는지 위에서 간략히 설명했었지요...... 그런데 왜 3자리씩 끊고 4자리씩
끊어서 8진수 16진수로 표현할까요? 2진수 3자리는 000 / 111 입니다. 각각 기수인 2의 0승 1승 2승으로
표현되고 제일 큰수가 7입니다. 0부터 시작하니 8개네요.. 그럼 기수가 8이므로 8진수입니다. 8진수는
문자표현수단인 아스키(ASCII)코드와 일치하구요..... 그럼 사람이 편하게 쓰는 10진수로는 각자리
수는  4 / 2 / 1 이 됩니다. 다 합치면 7이죠.....   16진수는 8 / 4 / 2 /1 이 됩니다...   다합치면..15겠죠.
그런데 자릿수가 나오면서 16진수는 문제가 좀 생깁니다. 9다음으로 6개가 더있는데 숫자기호론 표현이
안되서 알파벳을 사용합니다....... 이것은 조금있다가 16진수 놀이에서 밝혀드립니다....

다시 본론으로 이진수는 컴퓨터가 주력으로 사용하는 진법이다가 보니 자세히 알아두셔야합니다.
이진수 한자리를 Bit라고 부르며, 4자리는 Nibble이라 부르며 8자리는 Byte  16자리는 Word 32자리는
Double Word라고 부릅니다..  자 여기서 자리수 1 / 2 / 4 / 8 / 16 / 32.... 눈에 익은 숫자네요......
사용자 삽입 이미지


이제부터 몇가지 약속을 해야겠습니다.수를표현하는 여러가지가 있다는 것을 알았으니 어느수인지를
표현하는지에 대한 약속입니다....  11001b 라면 아 2진수네...... 라고 알수있는 법칙입니다.....
이표현은 C에서도 사용합니다. C언어는 어셈블리언어의 사용하기 쉬운버전일 뿐입니다........

수치의 우측에 아래의 b  / o Q / h가 붙으면 각각 2 / 8 / 16진수라는 의미입니다.
그리스어에서 파생한 말입니다.   쏠로 / 듀엣 / 트리오 / 테트 / 펜타.../옥탈....... 헥사........
b는 Binary      o / Q 는 Octal   h 는 Hexa 의 의미입니다....... 
다아시다치피 컴퓨터는 이런거 모릅니다. 무조건 2진수만 알죠.. 사람이 이해하기 쉽게 나눈것입니다.
코드표현할때는 8진수로 자주쓰고, 8진수 2자리는 16진수한자리니까 그냥 16진수를 주구장창 쓰게
됩니다. 16진수를 2진수로 만들게 되면 몇자리에서 끊느냐에 따라 10진수나 8진수로 혹은 16진수로
변환하기도 편하니까요..........


사용자 삽입 이미지

상기의 그림은 10진수 165를 이진수로 표현한 것입니다. 자세히 들여다 보시면 이해하시게 됩니다.
이해안되도 상관없습니다... 컴퓨터가 좋아할 뿐 앞으론 16진수와 10진수만 사용하게 되니까요.
MASM / TASM은 이러한 기본이 되는 진수를 변경할 수있으며, 아무런 표기가 없으면 그냥 10진수로
사용합니다. 변환은 어셈블러가 어셈블링 할때 처리해주니까요............


# Hexadecimal System (16진수)
이제 가장중요한 16진수 이야기가 나오는 군요.. 아까 위에서 문제점이 한가지 있다고 했었습니다.
바로 자리수에 대한것인데요.. 16진수는 한자리에 16가지 기호가 필요합니다. 아시다 시피 숫자는
0부터 9까지 10개밖에 없네요... 그래서 A / B / C / D / E / F를 동원하기에 이릅니다....
한자리에 숫자2개를 쓸수없기 때문입니다......... A를 10진수에 10에 해당합니다. B는 11 이구요..
당연히 16진수 한자리의 가장큰 수는 15이므로 F가 해당합니다.........
여기서 또한가지 진법이 커짐으로 얻는 이득이 있네요.... 커진 진법 한자리는 밑의 진법보다 표현
범위가 커지네요.....  
컴퓨터는 2진수만 좋아하고, 사람은 10진수 그리고 프로그래밍할때는 16진수로 쓴다... 입니다.
사용자 삽입 이미지

2진수 4자리는 16진수 한자리고 이것을 니블(Nibble)이라 부른다고 했습니다. 그냥 그런게 있구나..
라고 알아두시면 됩니다.  16진수임을 나타낼때는 수치의 오른쪽에 Hexa의 첫글자인 h를 붙여서
이것이 16진수이다. 라고 표현합니다.


사용자 삽입 이미지

상기의 그림은 10진수 4660을 16진법의 기수방식으로 표현한 것입니다.....



# Converting form Decimal System to Any Other (10진수에서의 변환)
10진수에서 어떤 진수의 숫자로 변환할려면 수학적으로는 나눗기를 사용해야합니다.
즉 10진수에서 8진수로 변환할려면 10진수의 값을 8로 계속 나누어서 몫과 나머지로 이용해서
8진수로 변환합니다.... 역시 수학적으론 맞아도 상당히 번거롭고 난해합니다.. 변환할때마다
메모지와 필기구가 필요하겠군요....
본 가이드에서는 이러한 방법은 사용하지 않습니다. 가장 편하게 사용하는 방법을 씁니다.
위의 내용을 이해하셨던 분이라면 자연스럽게 이해하시게 됩니다.
예를 들어서 10진수로 13을 각각 2진수 / 8진수 / 16진수 표현하면 어찌될까요?
진법변환은 가장먼저 2진수로 만들면 가장 쉽습니다..... 니블(4비트)를 사용해서 표현합니다.
니블은 4비트입니다. 각각 자리수는 10진수의  8 / 4 / 2 / 1에 해당합니다. 각각 더해서 13을
만들면 됩니다. 즉 ,   13을  8, 4, 2, 1로 만들려면 8 + 4 + 1 하면 되죠?  사용하지 않는것은 2네요
그럼 벌써 답이 나왔습니다....     1101 은 10진수로 13입니다....  사용하는 수를 1로 놓고 덧셈에
사용하지 않는건 0으로 만들면 됩니다...........  2진수로 만들었다면 3자리씩 끊어서 더하면??
8진수가 됩니다.....   반대로  1111b 는 10진수로 얼마일까요?  안보고도 아시는분 게시죠? 가장크니까
16진수의 가장큰수인 15가 되겠네요... 32진수로도 만들수 있겠죠???  저는 이방법을 사용합니다.
무조건 2진수로 만들고, 자리씩 끊어서 계산합니다..   니블은 BCD연산에 사용하고 바이트로
끊어서 쓸땐  그냥 일반적인 4칙연산에 쓰고, 16진수 2자리로 10진수 2자리를 표현할때는 Pack방식
의 BCD연산을 사용합니다. 어셈블리언어로는 AAA AAS AAD SBB .. 등의 4비트용 처리명령이
존재합니다.......    조금 난해할 수 있지만, 그냥 있다는 것만 알아두시면 됩니다.........
수치만 봐도 10진수로 척척 바꾸실 자신을 발견하게 되도록 계속 쓰게되니까요..........
사용자 삽입 이미지

참고로 15진수 AB5C를 이진수 각자리로 만드는 방법입니다. 왜인지는 아시겠죠??


# Signed Numbers (부호표현)
자 이제까지는 모두 양수에 대해서만 얘기했습니다. 하지만 실제로 사용할려면 음수도 있어야겠지요?
2진법만 사용하는 컴퓨터에서느 음수는 어찌 표현되는지를 알아야 합니다.
결론부터 말씀드리겠습니다.  Neg + 1 이 음수입니다...   

0FFH는 양수일까요? 음수일까요?   역시 결론부터 말씀드리쟈면 양수로 보면 255가 되고 음수로 표현
하면 -1 이 됩니다..  컴퓨터는 양수인지 음수인지 상관하지 않습니다..  이것은 프로그래머가
사용하기 나름입니다.....  세부적으로 사칙연산을 하는데 수학에서는 컴퓨터에서는 4칙연산을
하지 않습니다.. 무조건 덧셈(Adder)회로로만 다합니다. 곱하기는 숫자만큼 더하고 뺄샘은 보수를
더해서 처리하고 뺄샘을 여러번하면 나누기가 되지요........  여기서 얼핏 보수얘기가 나왔네요....
무식한 저도 이러한 수학놀이가 싫습니다......   아까 위에서 프로그래머가 음수인지 양수인지를
정한다고 했지요?? 그렇다면 어떠한 약속을 했다는 얘기입니다.........  최상우부분에서 8비트를
바이트로 사용한다고 했습니다. 16비트 32비트........  각 비트의 가장 좌측의 1비트를 바로 부호표시기
로 사용합니다. (MSB라고합니다). 그렇다면 각비트의 가장 우측부분한비트를 양음수 표시기로
쓴다면, 표현할 수 있는 숫자의 양이 절반으로 떯어지겟네요..... C를 하셨던 분들은 왜 int 와 uint의
범위표현이 다른지 이제 아시겠습니까? 어셈블리에서는 이게 기본입니다. 외울필요도 없죠...
즉 예전 16비트 컴퓨터에서는 2의 16승 인 10진수로 65535까지 표현할 수있습니다. 가장 좌측비트를
부호비트로 소모해버리면 -32768 ~ 0 ~ 32767로 줄어들게 됩니다..... 요즘은 32비트니까 4억을
절반까지 잘르겠네요.. 여하튼 최좌측비트는 MSB라 부르고 음 / 양 수 표시기로 사용할 수있고,
이것은 프로그래머 마음이라고 생각하시면 됩니다.......

빠르신 독자분들은 CBW라는 명령어에 대해서 잠시 생각해보시기 바랍니다..... Convert Byte Word의
약자입니다. 바이트면 8비트 워드면 16비트 인데 .  FFh를 16비트로 변환하면 어찌될까요?
양수는 아~무 문제없습니다만 음수라면 무조건 최상위비트를 1로 설정해야겠지요? 해당명령에서
자세히 설명하겠지만 바로 부호비트도 같이 확장해주는 명령입니다.......  이처럼 어셈블리의 각 명령에
해당하는 니모닉은 바로 이러한 최소한의 명령어를 제공해줍니다. 고급언어는 이것들을 조합해서 하나의
루틴으로(프로시져)만들어놓고 인자를 줘서 곱하기도 하고 더하기도 하고 하는 것에 지나지 않습니다.

# Emu8086 Tools
자 우리의 공부터전인 Emu8086에서는 이와같이 기수와 진법을 변화이 잦아서 아예 유틸리티를 제공
합니다. 저같은 경우도 그냥 숫자만 보면 자연스럽게 2진수로 보여집니다만, 그래도 도구를 사용하는
동물이 인간인지라...............
emu8086의 메뉴중에 Math에 보시면 base Converter라는 메뉴가 있지요? Base는 기수라 했으니
머하는 프로그램인지는 이제는 설명안해도 아실거라 생각됩니다.........
사용자 삽입 이미지



이상으로 처음부터 조금 지루하고 난해해 보이는 진법과 컴퓨터의 수치표현에 대해서 알아보았습니다.
컴퓨터 혼자는 아주 잘 처리하는 것을 사람이 이해할려고 하니 나타나는 증상들입니다. 컴퓨터는
회로의 집합이고, 이 회로는 정해진 길이 있고, 이길은 법칙입니다. 이법칙을 외워가는것이 바로
어셈블리입니다. 이것이 복잡해보이는 가장 큰 이유겠지요.. 하지만 단순한 컴퓨터!! 라는 것을 잊지
마시기 바랍니다. 중요부분은 사람이 이해하고 단지 실제 컴퓨터는 처리속도가 무지막지하게 빠르
다는것 외에는 없습니다..   이러한 기초적인 진법변환부터 변수처리 배열처리 클래스등의 처리를
보다 편하게 해놓은게 바로 고급언어들입니다.. 당연히 뭉쳐서 만들어놓았기때문에 더좋은 알고리즘을
자신이 개발하면 획기적으로 속도를 빠르게 만들 수도 있습니다. 기성복과 맞춤복 .......세단과 스포츠카
의 비유가 적절한 이유가 그것입니다...... 어셈블리로 하면 난해하고 유지보수가 힘들다!!!
대부분의 유저들이 인정합니다만, 아닐 수 있습니다...... 이것이 어렵게 쓰는지 쉽게 쓰는지는 바로
만드는 사람 마음이니까요....... 하지만, 적어도 왜 이것이 실행되는지와 실제 어찌 작동되는지를
정확하게 알기에..... 크랙같은것도 우습게 처리됩니다..... 당연한 거겠지요... 영화에 나오는 해커와
크랙커들은 대충 엔터키만 치면 다 처리하죠??  불가능은 아닙니다만 본인은 불가능입니다.
모든것을 다 알아야 활용할 수 있습니다.......  진법은 바로 기본중의 기본입니다.

다시금 요약하면 컴퓨터는 무조건 2진법이고, 코드표현하기 편하게할려고 8진법을 쓰고 (바이트)
가장많이 쓰는 정수형을 표현하기위해서 16/32진법을 사용하며, 16진수의 자릿수를 늘려서
그것을 표현한다!! 입니다...... 진법변환은 툴을 이용하거나 제가 사용하는 방법대로 먼저 이진수로
만든후 자릿수를 끊어서 처리하셔도 됩니다... 왜하는지만 알면 됩니다............
Posted by openserver