|
메뉴릿
카테고리
최근 등록된 덧글
감사합니다. shell scrip..
by Mr.Carbin at 07/17 아.. 정말 감사드립니다.. by 송진영 at 03/15 조금 거리가 있는 주제.. by sio4 at 03/11 안녕하세요? 덧글 달아.. by 송진영 at 02/14 펄이나 파이썬은 진입장.. by kirrie at 02/13 최근 등록된 트랙백
Allergy to codeine s..
by Source of codeine. Online phentermine. by Lowest price for phen.. Tramadol ultram medic.. by Ultram addiction. Ephedra weight loss .. by Ephedra. Canada overnight am.. by Ambien manufacturer. Calico film music des.. by Zoo sex. Lexapro-ultracet-int.. by Extracting acetanin.. Ambien. by Ambien verses temac.. Scat eating shit sex. by Shit sex photos per.. Ordering adderall. by Adderall. 포토로그
이전블로그
이글루링크
이글루 파인더
|
2009년 05월 15일
원문 : http://www.drpaulcarter.com/pcasm/
번역 : 송진영( caddsjy@gmail.com ) 2.1 정수 작업(Working with Integers) 2.1.1 정수에 대한 설명 정수는 2가지 형태로 표현합니다. : 부호가 없거나 부호가 있는 정수. 부호가 없는 정수는( 양의 정수 ) 아주 똑바른 바이너리 방식입니다. 숫자 200을 1바이트의 부호없는 정수로 표현하면 11001000( 16진수로 C9 )이 됩니다. 부호가 있는 정수(양의 정수 혹은 음의 정수)는 복잡한 방법으로 표현할 수 밖에 없습니다. 예를 들어 -56. +56은 00111000으로 표현해야하는데 종이위에 글로 표현할때는 -56을 -111000으로 적으면 되지만 메모리상에서는 이 -를 표현할 방법이 없습니다. 어떻게하면 마이너스 기호를 메모리에 기록할수 있을까요? 컴퓨터 메모리에 부호를 기록하는 일반적인 3가지의 기술이 있습니다. 모든 방법들은 정수에 부호비트를 갖게 하는 것입니다. 양수이면 이 비트의 값이 0이고 만약 음수라면 이 비트의 값은 1이 됩니다. Signed magnitude 첫번째로 signed magnitude라고 불리는 간단한 방법이 있습니다. 이 방식은 정수를 두 부분으로 표현합니다. 첫번째 부분은 부호비트로 두번째 부분은 정수의 크기를 나타냅니다. 56이라는 수는 00111000(맨 앞의 밑줄이 그려진 비트가 부호비트입니다.)으로 표현합니다. 그리고 -56은 10111000으로 표현합니다. 1 바이트로 표현할 수 있는 가장 큰값은 01111111 또는 +127이고 가장 작은 수는 1111111 또는 -127입니다. 음수의 표현을 위해 부호비트가 사용됩니다. 이 방식은 쉽게 표현이 가능하지만 문제점을 가지고 있습니다. 첫번째로 두가지의 0의 표현이 생깁니다. +0(00000000)과 -0(10000000). 두번째로 일반 연산에서도 문제가 생깁니다. 만약 10에 -56을 더하면 10에서 56을 빼게되는데 CPU의 로직에서는 복잡해집니다. One's complement (1의 보수 ) 두번째 방식으로 one's complement라는 것이 있습니다. 이 방식은 각각의 비트를 반전시키는 방법을 사용합니다. 예를 들어 00111000 (+56)의 1의 보수는 11000111이 됩니다. 1의 보수법은 1의 보수가 대응하는 음수값이 됩니다. 그러므로 -56은 11000111으로 표현됩니다. 첫번째 방식에서 0은 00000000(+0)과 11111111(-0)으로 2가지가 나타납니다. 1의 보수또한 연산이 복잡합니다. 2진수로 바꾸지않고 16진수로 1의 보수값을 찾는 방법이있습니다. hex값 F에서 숫자를 뺍니다.(또는 십진수 15에서) 예를들어 +56은 hex로 38입니다. 이 수에서 1의 보수를 찾는 방법은 각 비트값들을 F에서 뺀값으로 바꾸면됩니다. F-3 = C, F-8=7이므로 0x38의 1의 보수값은 0xC7이 됩니다. Two's complement (2의 보수) 앞의 두가지 방식은 예전의 컴퓨터에서 사용했던 방식들입니다. 현대의 컴퓨터는 2의 보수로 표현됩니다. 2의 보수는 두가지 단계로 계산해낼 수 있습니다.
11000111 2의 보수 표현 방식으로는 2의 보수에 해당하는 음수를 계산 할 수 있습니다. 그러므로 11001000은 -56의 2의 보수로 표현됩니다. 한번 더 반복하면 원래의 숫자로 돌아옵니다. 2의 보수로 계산된 11001000의 1의 보수를 다시 구하면 00110111이 되고 여기에 1을 더하면 00111000이 됩니다. 2의 보수에서 덧셈을 할 경우 가장 왼쪽 비트에는 캐리가 발생하게 됩니다. 이 캐리는 사용되지 않습니다. 컴퓨터의 모든 데이터들은 어느정도의 고정된 크기를 가지고 있다는 것을 기억하세요. ( 비트의 수.. ) 이 점은 2의 보수 표현에 있어서 중요한 부분입니다. 예를 들어 0의 2의 보수를 계산하면 0이 됩니다. 00000000의 1의 보수는 11111111이고 여기에 1을 더하면 캐리(자리올림)가 발생하는데 이 캐리를 무시하면 00000000만 남게 되므로 0이 됩니다. 11111111 c가 위치한 곳에 캐리가 발생합니다. (후에 여기에서 발생한 캐리를 확인하는 방법을 보여줄 것입니다. 그러나 결과값에는 캐리를 저장하지 않습니다. ) 그러므로 2의 보수의 표현에서 0은 항상 1가지만 존재합니다. 이 것은 2의 보수를 사용함으로써 앞의 방식들보다 간단하게 수학연산을 가능하게 했습니다. 2의 보수 표현법을 사용하여 -128~+127까지의 부호있는 수를 표현가능합니다. 표 2.1에서 가능한 몇가지의 수를 나타내고 있습니다. ----표 2.1 : 2의 보수 표현---- 수 | hex 0 | 00 1 | 01 127 | 7F -128 | 80 -127 | 81 -2 | FE -1 | FF ---------------------------- 만약 16비트를 사용하게 되면 부호있는 수는 -32,768~32,767까지 표현가능 합니다. +32,767은 0x7FFF이고 -32768은 0x8000으로 표현합니다. -128은 0xFF80, 그리고 -1은 0xFFFF가 됩니다. 32비트에서 2의 보수로 표현가능한 수의 범위는 -20억에서 +20억까지 가능합니다. CPU는 byte에 대해 (또는 word나 double word) 아는 바가 없습니다. 어셈블리도 고급언어에서 가지고있는 타입에 대해서도 모릅니다. 데이타가 해석되는 것은 데이터가 사용되는 부분의 명령에 의존적입니다. hex값 FF가 부호있는 -1인지 부호없는 +255로 해석될지는 프로그래머에게 달려있습니다. C언어는 signed와 unsigned 정수 형이 정이되어져 있습니다. 이 것으로 C컴파일러는 명령어가 사용하는 데이터를 정확하게 알 수 있도록 해줍니다. 2.1.2 Sign extension 어셈블리에서 모든 데이터는 크기를 가지고 있습니다. 데이터의 크기 줄이기 데이터의 크기를 줄이기 위해서 간단하게 데이터에서 중요한 비트만 남기고 삭제하면 됩니다. 아래에 예가 있습니다. mov ax, 0034h ; ax = 52( 16비트로 저장됩니다. )만약 숫자가 작은 크기에서는 정확히 표현을 할 수 없다면 크기를 줄이는 작업을 할 수가 없습니다. 예를 들어 만약 AX의 값이 0134h였다면 위의 코드에서 CL에는 34h가 될 것입니다. 이 동작은 signed나 unsigned 모두 동작은 합니다. signed번호로 가정하고 만약 AX의 값이 FFFFh( word로 -1 )라면 CL의 값은 FFh( byte로 -1 )가 될 것입니다. 하지만 AX가 unsigned 일때는 이 값이 정확하지 않게 될 것입니다! 부호없는 숫자를 위한 규칙은 삭제될 모든 비트가 0일때만 정확하게 계산됩니다. 부호있는 숫자의 경우 삭제될 숫자가 모두 1이거나 모두 0일 경우에 정확하게 계산됩니다. 추가적으로 삭제될 비트와 삭제되지 않을 비트의 값이 동일한경우에도 같은 값을 가지게 됩니다. 이 비트는 작은 값의 새로운 부호 비트가 될 것입니다. 이 점은 원본의 부호비트와 동일하게 하기 위한 중요한 내용입니다. 데이터의 크기 늘리기 데이터의 크기를 늘리는 것은 줄이는 것보다 더 복잡합니다. hex byte FF를 word로 늘렸다면 어떤 word값으로 바뀌었을까요? 이것은 FF를 해석하는 것에 따라 달라집니다. 만약 FF가 부호없는 바이트라면(10진수 255) word값 00FF로 될 것입니다. 그러나 만약 부호있는 바이트라면( 십진수 -1 ) 이 값은 FFFF가 될 것입니다. 일반적으로 부호없는 수를 확장하면 확장되는 새로운 수들은 0으로 채워집니다. 그러므로 FF는 00FF가 됩니다. 그러나 부호있는 수를 확장하기 위해서 부호비트를 확장해야만 한다. 이 뜻은 새로운 비트는 부호비트의 사본이된다. FF의 부호비트가 1이므로 새로운 비트들은 반드시 1이 되게 되며 FFFF로 만들어진다. 만약 부호있는 5A의 경우는 확장되면 005A가 된다. 80386이 수의 확장을 위해 제공하는 몇개의 명령어가 있습니다. 컴퓨터는 숫자가 signed 인지 unsigned인지 모른다는 점을 기억하세요. 이 것은 프로그래머가 정확한 명령을 사용하여 결정됩니다. 부호없는 수를 위해서 mov명령어를 사용하여 상위비트를 0으로 만듭니다. 예를 들어 AL의 바이트를 확장하여 부호없는 AX의 word로 바꿔보겠습니다. : mov ah, 0 ; 상위 8비트들을 0으로 만듭니다.하지만 mov명령어를 사용하여 AX의 unsigned word값을 unsigned double word인 EAX로 바꾸는 것은 불가능합니다. 왜 안될까요? 이유는 mov명령어로는 EAX의 상위 16비트들을 정의할 수 있는 방법이 없기 때문입니다. 80386은 이 문제를 해결하기 위해 MOVZX라는 새로운 명령어를 제공합니다. 이 명령어는 2개의 오퍼랜드들을 가집니다. 첫번째 오퍼랜드는 목적지(destination)이고 반드시 16또는 32비트의 레지스터여야 합니다. 두번째 오퍼랜드는 소스(source)로써 8또는 16비트의 레지스터나 byte 또는 메모리의 word값이여야 합니다. 또 다른 제약사항으로는 destination은 반드시 source보다 커야합니다.(많은 명령어들은 source와 destination은 같은 크기를 요구합니다.) 아래에 몇가지 예가 있습니다. : movzx eax, ax ; ax를 eax로 확장 signed 숫자를 위해서는 MOV 명령어를 쓰는것이 쉽지 않습니다. 8086은 signed 수를 확장하기 위한 몇가지 명령어들을 제공합니다. CBW( Convert Byte to Word ) 명령어는 부호있는 AL을 AX레지스터로 확장하는 명령입니다. 오퍼랜드는 암묵적입니다. CWD( Convert Word to Double ) 명령어는 AX를 DX:AX로 확장합니다. DX:AX의 뜻은 DX를 32비트 레지스터의 상위 16비트로, AX레지스터를 하위 비트들로 사용한다는 의미를 가집니다. ( 8086은 어떠한 32비트 레지스터도 없다는 것을 기억하십시요! ) 80386은 몇개의 새로운 명령어들이 추가되었습니다. CWDE( Convert Word to Double word Extended )명령은 AX를 EAX로 확장하고, CDQ( Convert Double word to Quad word) 명령어는 부호있는 EAX를 EDX:EAX형태의 64비트로 확장하는 명령입니다. 마지막으로 MOVSX 명령어는 MOVZX명령과 비슷한 기능을 가지며 signed 숫자를 위한 명령입니다. Application to C programming unsigned와 signed정수를 확장하는 일은 C 언어에서도 발생합니다. C언어의 변수들은 signed나 unsigned( int는 signed )로 선언됩니다. Figure 2.1의 코드의 3번째줄에서는 MOVZX명령을 사용하게 되며 unsigned 값을 확장하는 것입니다. 그러나 4번째 줄은 MOVSX를 사용하여 signed 규칙을 사용한 것입니다. ----Figure 2.1----- unsigned char uchar = 0xFF; signed char schar = 0xFF; int a = (int)uchar; /* a = 255 ( 0x000000FF ) */ int a = (int)schar; /* b = -1 ( 0xFFFFFFFF) */ ----------------------- --------Figure 2.2------- char ch; while( (ch = fgetc( fp ) ) != EOF ){ /* do something with ch */ } ------------------------- 시간상 다음에 계속....
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
| |||||