마이크로 프로세서의 ALU는 1111로 표시되는 부호있는 숫자 -7과 1111로 표시되는 부호없는 숫자 15를 어떻게 구별합니까?
마이크로 프로세서의 ALU는 1111로 표시되는 부호있는 숫자 -7과 1111로 표시되는 부호없는 숫자 15를 어떻게 구별합니까?
답변:
짧고 간단한 대답은 그렇지 않습니다. 현대의 주류 CPU ISA는 생각대로 작동하지 않습니다.
CPU의 경우 비트 패턴입니다. 비트 패턴의 의미를 추적하는 것은 프로그래머에게 달려 있습니다.
일반적으로 ISA는 스토리지와 관련하여 서로 다른 데이터 유형을 구분하지 않습니다. FPU의 부동 레지스터와 같은 특수 목적 레지스터는 무시합니다. CPU에 대한 의미없는 비트 패턴입니다. 그러나 ISA들은 어떻게 다른 방식으로 비트 패턴을 해석 할 수 있습니다 지침의 다른 종류가있다. 예를 들어, 다음과 같은 산술 명령어MUL
, DIV
, ADD
, SUB
, 숫자 등의 어떤 비트 패턴을 해석하는 등의 논리 지시하는 반면 AND
, OR
, XOR
불리언 배열로 해석한다. 따라서 올바른 지시 사항을 선택하는 것은 프로그래머 (또는 고급 언어를 사용하는 경우 인터프리터 또는 컴파일러 작성자)의 책임입니다.
예를 들어 부호있는 숫자와 부호없는 숫자에 대한 별도의 지침이있을 수 있습니다. 일부 ISA에는 이진 코드 10 진수를 사용한 산술 지침도 있습니다.
그러나 위의 "현대 주류 ISA"를 작성했습니다. 사실 비주류 또는 역사적 ISA는 다르게 작동합니다. 예를 들어, IBM AS / 400의 원래 48 비트 CISC ISA와 현재 IBM i라고하는 시스템의 현재 POWER 기반 64 비트 RISC ISA는 포인터와 다른 값을 구별합니다. 포인터는 항상 태그가 지정되며 유형 정보 및 권한 관리가 포함됩니다. CPU는 값이 포인터인지 여부를 알고 있으며 권한있는 i / OS 커널 만 포인터를 자유롭게 조작 할 수 있습니다. 사용자 응용 프로그램은 적은 수의 안전한 명령을 사용하여 소유 한 메모리를 가리 키도록 소유 한 포인터 만 조작 할 수 있습니다.
또한 제한된 형식 인식 유형이 포함 된 역사적인 ISA 디자인도있었습니다.
char
16 비트 부호없는 형식이다. 물론 Java 바이트 코드에는 부호없는 산술 명령어가 없습니다. 모든 char
값은 int
산술을 위해 (32 비트 부호있는) 로 자동 승격 되기 때문 입니다.
짧은 버전 : 잘 모르겠습니다. 말할 방법이 없습니다.
1111
-7을 나타내는 경우 부호 크기 표현이 있습니다 . 여기서 첫 번째 비트는 부호이고 나머지 비트는 크기입니다. 이 경우 부호없는 추가와 부호있는 추가가 서로 다른 논리를 사용하므로 산술이 다소 복잡합니다. 따라서 아마도 a SADD
와 UADD
opcode 가있을 것이고 , 잘못된 코드를 선택하면 말도 안되는 결과를 얻습니다.
그러나 종종 2의 보수 표현1111
이라고 불리는 -1을 나타냅니다 . 이 경우 ALU는 단순히 숫자에 부호가 있거나 부호가 없는지 신경 쓰지 않습니다! 예를 들어의 작업을 수행해 봅시다 1110 + 0001
. 부호있는 산술에서 "-2 + 1"을 의미하며 결과는 -1 ( 1111
) 이어야합니다 . 부호없는 산술에서 "14 + 1"을 의미하며 결과는 15 ( 1111
) 여야합니다 . 따라서 ALU는 서명 된 결과 또는 서명되지 않은 결과를 원하는지 여부를 알지 못합니다. 그것은 부호없는 것처럼 추가를 수행하고 나중에 부호있는 정수로 처리하려는 경우 그것은 당신에게 달려 있습니다.
편집 : Ruslan과 Daniel Schepler가 주석에서 올바르게 지적했듯이 일부 피연산자는 여전히 2의 보완 시스템에서도 별도의 서명 및 서명되지 않은 버전이 필요합니다. 덧셈, 뺄셈, 곱셈, 평등 및 그와 같은 모든 숫자가 부호가 있는지 여부를 알지 못하면 정상적으로 작동합니다. 그러나 나누기와 비교보다 크거나 작은 비교에는 별도의 버전이 있어야합니다.
편집 편집 : 하나의 보완 과 같은 다른 표현도 있지만 기본적으로 더 이상 사용되지 않으므로 걱정할 필요가 없습니다.
<
<=
>=
>
반면 부호없는 피연산자 대 서명을 위해 다른 ==
과 !=
부호의 불가지론이다.
모든 현대식 아키텍처에서 사용하는 2의 보수 수학의 가장 큰 장점 중 하나는 더하기 및 빼기 명령어가 부호있는 피연산자와 부호없는 피연산자 모두에 대해 정확히 동일하다는 것입니다.
많은 CPU에는 곱하기, 나누기 또는 모듈러스 명령어조차 없습니다. 그러한 경우에는 별도의 서명 및 서명되지 않은 명령어 형식을 가져야하며 컴파일러 (또는 어셈블리 언어 프로그래머)가 적절한 형식을 선택합니다.
CPU에는 일반적으로 부호있는 비교 또는 부호없는 비교에 대한 다른 지시 사항도 있습니다. 예를 들어, 86가에 따라 수 CMP
와 JL
(점프 미만의 경우) 비교가 서명 할 필요가있는 경우, 또는 JB
(점프 아래 경우) 비교 서명해야합니다. 다시 말하지만, 컴파일러 또는 프로그래머는 데이터 유형에 맞는 올바른 명령어를 선택합니다.
몇 가지 다른 명령어는 부호 확장을 사용하거나 사용하지 않고 오른쪽으로 이동하거나 더 넓은 레지스터에 값을로드하는 것과 같이 부호있는 부호있는 부호없는 변형이있는 경우가 많습니다.
smulh
및 umulh
단지 곱셈의 상위 비트 서명과 서명되지 않은 지침이 수익을 그 소스 피연산자보다 두 배 넓은 레지스터에 결과를 반환합니다.
그렇지 않습니다. 프로세서는 명령 세트를 사용하여보고있는 데이터 유형과 전송 위치를 알려줍니다. 피연산자 자체에는 데이터가 char, float, int, signed int 등인지 ALU에 신호를 보낼 수있는 피연산자 자체에는 약 1과 0이 없습니다. 1111이 2의 보수를 기대하는 전기 회로에 들어가면 계속 진행됩니다. 2s 보수로 해석됩니다.
char
하드웨어 수준 에는 그런 것이 없습니다 . 어쩌면 기계식 텔레 프린터 시대로 거슬러 올라갈 수도 있습니다. 하지만 오늘, a는 char
이다 단지 숫자까지 하드웨어에 관한 한. 다른 숫자가 화면의 다른 문자 모양에 해당하는 이유는 그 숫자가 큰 테이블 (예 : "글꼴")에서 다른 비트 맵 또는 다른 그리기 루틴을 선택하는 데 사용되기 때문입니다.
이미 작성한 답변에 추가하고 싶습니다.
대부분의 다른 답변에서 2 보수 산술에서 결과는 부호있는 숫자와 부호없는 숫자에 대해 동일합니다.
-2 + 1 = -1 1110 + 0001 = 1111
14 + 1 = 15 1110 + 0001 = 1111
그러나 예외가 있습니다.
Division:
-2 / 2 = -1 1110 / 0010 = 1111
14 / 2 = 7 1110 / 0010 = 0111
Comparison:
-2 < 2 = TRUE 1110 < 0010 = TRUE
14 < 2 = FALSE 1110 < 0010 = FALSE
"Typical" (*) multiplication:
-2 * 2 = -4 1110 * 0010 = 11111100
14 * 2 = 28 1110 * 0010 = 00011100
(*) 많은 CPU에서 두 개의 n 비트 숫자를 곱한 결과는 (2 * n) 비트입니다.
이러한 작업의 경우 CPU는 부호있는 및 부호없는 산술에 대한 다른 명령어를 갖습니다.
즉, 프로그래머 (또는 컴파일러)는 부호있는 및 부호없는 산술에 다른 명령어를 사용해야합니다.
예를 들어 x86 CPU div
에는 부호없는 구분 idiv
을 수행하기위한 명령과 서명 된 구분을 수행하기위한 명령이 있습니다.
부호있는 및 부호없는 산술에 대한 곱하기 명령어뿐만 아니라 다른 "조건부"명령어 (조건부 점프, 비트 조건 설정)도 있습니다.