부호있는 숫자와 부호없는 숫자


17

마이크로 프로세서의 ALU는 1111로 표시되는 부호있는 숫자 -7과 1111로 표시되는 부호없는 숫자 15를 어떻게 구별합니까?


3
관련 질문에 대한 답변을 참조하십시오 : cs.stackexchange.com/a/30047/28999 . 그건 그렇고, 서명 된 -7은 1111로 표시되지 않습니다. -1입니다. 그런 다음 부호있는 케이스와 부호없는 케이스 모두에서 1111-0001 = 1110 (-2 대 14)
Albert Hendriks

2
@AlbertHendriks 공정하게, 일부 구형 컴퓨터는 "부호 크기 표현"(1 부호 비트 및 크기 비트)을 사용하며, IEEE 플로트와 같은 스타일을 계속 사용합니다. 그것들은 단지 2의 보수와 비교할 때 우아하지 않고 작업하기가 어렵습니다. n1
Draconis

1
주요 차이점은 greatThan / lessThan 연산자의 동작 방식과 오른쪽 시프트가 가장 높은 비트로 채워지는지 여부입니다. 실제로 곱하고 나누면 결과는 같습니다.
Rob


2
@Rob 그것은 완전히 정확하지 않습니다. 덧셈, 뺄셈 및 곱셈은 부호없는 것과 둘의 보수가 동일하며 입력과 출력의 크기가 같다고 가정합니다. 나누기가 같지 않음 6/2는 3이지만 -2/2는 -1입니다. 그리고 많은 CPU에는 두 입력의 크기가 동일한 곱셈 명령어가 있지만 출력의 크기는 두 배입니다.이 경우 부호없는 부호와 2의 보수도 동일하지 않습니다.
kasperd

답변:


14

짧고 간단한 대답은 그렇지 않습니다. 현대의 주류 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 디자인도있었습니다.


Java 바이트 코드도 ISA로 계산됩니다. 그리고 그것은 거의 데이터 유형에 관심이 있습니다 ...
John Dvorak

Java 바이트 코드는 실리콘으로 구현되었다는 점에서 ISA로 분류됩니다. 그러나 이러한 종류의 기본 유형 검사는 클래스 로더가 수행하는 검사이므로 런타임시 유형을 대부분 무시할 수 있습니다. 물론 Java 바이트 코드에는 먼저 부호없는 유형이 없습니다.
가명

@Pseudonym : 음은 기술적으로는 않습니다char16 비트 부호없는 형식이다. 물론 Java 바이트 코드에는 부호없는 산술 명령어가 없습니다. 모든 char값은 int산술을 위해 (32 비트 부호있는) 로 자동 승격 되기 때문 입니다.
Ilmari Karonen

42

짧은 버전 : 잘 모르겠습니다. 말할 방법이 없습니다.

1111-7을 나타내는 경우 부호 크기 표현이 있습니다 . 여기서 첫 번째 비트는 부호이고 나머지 비트는 크기입니다. 이 경우 부호없는 추가와 부호있는 추가가 서로 다른 논리를 사용하므로 산술이 다소 복잡합니다. 따라서 아마도 a SADDUADDopcode 가있을 것이고 , 잘못된 코드를 선택하면 말도 안되는 결과를 얻습니다.

그러나 종종 2의 보수 표현1111 이라고 불리는 -1을 나타냅니다 . 이 경우 ALU는 단순히 숫자에 부호가 있거나 부호가 없는지 신경 쓰지 않습니다! 예를 들어의 작업을 수행해 봅시다 1110 + 0001. 부호있는 산술에서 "-2 + 1"을 의미하며 결과는 -1 ( 1111) 이어야합니다 . 부호없는 산술에서 "14 + 1"을 의미하며 결과는 15 ( 1111) 여야합니다 . 따라서 ALU는 서명 된 결과 또는 서명되지 않은 결과를 원하는지 여부를 알지 못합니다. 그것은 부호없는 것처럼 추가를 수행하고 나중에 부호있는 정수로 처리하려는 경우 그것은 당신에게 달려 있습니다.

편집 : Ruslan과 Daniel Schepler가 주석에서 올바르게 지적했듯이 일부 피연산자는 여전히 2의 보완 시스템에서도 별도의 서명 및 서명되지 않은 버전이 필요합니다. 덧셈, 뺄셈, 곱셈, 평등 및 그와 같은 모든 숫자가 부호가 있는지 여부를 알지 못하면 정상적으로 작동합니다. 그러나 나누기와 비교보다 크거나 작은 비교에는 별도의 버전이 있어야합니다.

편집 편집 : 하나의 보완 과 같은 다른 표현도 있지만 기본적으로 더 이상 사용되지 않으므로 걱정할 필요가 없습니다.


아. 감사합니다 :)
noorav

10
2의 보수 표현에서 3 개의 산술 연산은 부호를 무시합니다. 덧셈, 뺄셈 및 곱셈 (피연산자와 길이가 같은 곱). 부호있는 피연산자에 대해서는 나누기 만 다르게 처리해야합니다.
Ruslan

4
비교도있다는 : < <= >= >반면 부호없는 피연산자 대 서명을 위해 다른 ==!=부호의 불가지론이다.
Daniel Schepler

곱셈은 ​​종종 부호가 있고 부호없는 품종입니다. 0xFFFFFFFF * 0xFFFFFFFF는 부호가 없으면 0xFFFFFFFE00000001이고 부호가 있으면 0x0000000000000001입니다. Intel과 같은 프로세서는 결과를 2 개의 레지스터로 반환하며 최상위 레지스터는 부호있는 것과 부호없는 것에 대해 다릅니다. 하단 레지스터는 두 경우 모두 1입니다.
Rudy Velthuis 2016 년

9

모든 현대식 아키텍처에서 사용하는 2의 보수 수학의 가장 큰 장점 중 하나는 더하기 및 빼기 명령어가 부호있는 피연산자와 부호없는 피연산자 모두에 대해 정확히 동일하다는 것입니다.

많은 CPU에는 곱하기, 나누기 또는 모듈러스 명령어조차 없습니다. 그러한 경우에는 별도의 서명 및 서명되지 않은 명령어 형식을 가져야하며 컴파일러 (또는 어셈블리 언어 프로그래머)가 적절한 형식을 선택합니다.

CPU에는 일반적으로 부호있는 비교 또는 부호없는 비교에 대한 다른 지시 사항도 있습니다. 예를 들어, 86가에 따라 수 CMPJL(점프 미만의 경우) 비교가 서명 할 필요가있는 경우, 또는 JB(점프 아래 경우) 비교 서명해야합니다. 다시 말하지만, 컴파일러 또는 프로그래머는 데이터 유형에 맞는 올바른 명령어를 선택합니다.

몇 가지 다른 명령어는 부호 확장을 사용하거나 사용하지 않고 오른쪽으로 이동하거나 더 넓은 레지스터에 값을로드하는 것과 같이 부호있는 부호있는 부호없는 변형이있는 경우가 많습니다.


1
곱셈도 부호없는 정수와 부호있는 (2의 보수) 정수에 대해 동일 하지만 결과가 입력 값보다 더 많은 비트를 가질 필요가없는 한 . 그러나 8 × 8 → 16 비트 (또는 16 × 16 → 32 비트 등) 곱셈과 같은 작업을 수행하는 경우 입력 (또는 중간 결과)을 확장해야합니다 .
Ilmari Karonen

@IlmariKaronen 이것은 사실입니다. / A64 ARM A32 기호에 얽매이지 만 하위 비트들을 기록 곱셈 - 덧셈, 또한 포함하여 곱셈 명령의 여러 형태로,이 명령어 세트입니다 smulhumulh단지 곱셈의 상위 비트 서명과 서명되지 않은 지침이 수익을 그 소스 피연산자보다 두 배 넓은 레지스터에 결과를 반환합니다.
Davislor

6

그렇지 않습니다. 프로세서는 명령 세트를 사용하여보고있는 데이터 유형과 전송 위치를 알려줍니다. 피연산자 자체에는 데이터가 char, float, int, signed int 등인지 ALU에 신호를 보낼 수있는 피연산자 자체에는 약 1과 0이 없습니다. 1111이 2의 보수를 기대하는 전기 회로에 들어가면 계속 진행됩니다. 2s 보수로 해석됩니다.


char하드웨어 수준 에는 그런 것이 없습니다 . 어쩌면 기계식 텔레 프린터 시대로 거슬러 올라갈 수도 있습니다. 하지만 오늘, a는 char이다 단지 숫자까지 하드웨어에 관한 한. 다른 숫자가 화면의 다른 문자 모양에 해당하는 이유는 그 숫자가 큰 테이블 (예 : "글꼴")에서 다른 비트 맵 또는 다른 그리기 루틴을 선택하는 데 사용되기 때문입니다.
Solomon Slow

3

이미 작성한 답변에 추가하고 싶습니다.

대부분의 다른 답변에서 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을 수행하기위한 명령과 서명 된 구분을 수행하기위한 명령이 있습니다.

부호있는 및 부호없는 산술에 대한 곱하기 명령어뿐만 아니라 다른 "조건부"명령어 (조건부 점프, 비트 조건 설정)도 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.