有符号和无符号数字


17

微处理器中的ALU如何区分1111表示的有符号数-7和1111表示的无符号数15?


3
请参阅相关问题的答案:cs.stackexchange.com/a/30047/28999。顺便说一下,带符号的-7不会表示为1111。这是-1。然后,例如,在有符号和无符号的情况下(112 vs. 1111-0001 = 1110)
Albert Hendriks

2
公平地讲,@ AlbertHendriks,某些较旧的计算机确实使用“符号幅度表示”(一个符号位和幅度位),并且我们仍将这种样式用于例如IEEE浮点数。与二进制补码相比,它们只是笨拙且难以使用。n1
Draconis

1
主要区别在于大于或小于运算符的行为方式以及右移是否填充了最高位。当您实际相乘和相除时,结果是相同的。
罗布


2
@Rob并不完全正确。无符号和二进制补码之间的加法,减法和乘法都相同-假设您的输入和输出大小相同。除法不相同6/2是3,但-2/2是-1。而且许多CPU都有乘法指令,其中两个输入的大小相同,但输出的大小是其两倍,在这种情况下,无符号和二进制补码也不相同。
卡巴斯德(Kasperd),

Answers:


14

简短而简单的答案是:否。没有现代主流CPU ISA可以像您想象的那样工作。

对于CPU,这只是一种模式。程序员,要由您自己来确定该位模式的含义。

通常,在存储方面,ISA不会区分不同的数据类型。(忽略FPU中的浮动寄存器之类的专用寄存器。)这对CPU而言只是毫无意义的位模式。但是,ISA 确实有不同种类的指令,它们可能以不同的方式解释位模式。例如,算术指令,例如MULDIVADDSUB解释的位模式为某种数量的,而逻辑指令如ANDORXOR它解释为布尔值的阵列。因此,由程序员(或如果使用高级语言,则由解释器或编译器的作者)选择正确的指令。

例如,对于带符号和无符号的数字,可能会有单独的说明。一些ISA还具有二进制编码的十进制算术指令。

但是,请注意,我在上面写了“现代主流ISA”。实际上,非主流或历史性ISA的工作方式有所不同。例如,IBM AS / 400的原始48位CISC ISA和现在称为IBM i的系统的当前基于POWER的64位RISC ISA都可以区分指针和其他值。指针始终被标记,并且包括类型信息和权限管理。CPU知道一个值是否是一个指针,并且只有特权的i / OS内核才允许自由操作指针。用户应用程序只能使用少量安全指令来操纵其拥有的指针,以指向其拥有的内存。

也有一些历史悠久的ISA设计,其中至少包括一些有限形式的类型意识。


请注意,Java字节码也算作ISA。它几乎确实在乎数据类型...
John Dvorak

从某种意义上说,Java字节码确实是作为ISA实现的,因此它可以算作ISA。但是,这种基本类型检查是由类加载器执行的,因此在运行时大多数类型都可以忽略。当然,Java字节码首先没有无符号类型。
别名

@Pseudonym:从技术上讲,它确实具有char16位无符号类型。当然,在Java字节码中仍然没有无符号的算术指令,因为任何char值都会自动提升为int(32位带符号的)算术。
Ilmari Karonen

42

简短版:不知道。没有办法说。

如果1111表示-7,则您具有符号幅度表示,其中第一位是符号,其余位是幅度。在这种情况下,算术有些复杂,因为无符号加法和有符号加法使用不同的逻辑。因此,您可能会有一个SADD和一个UADD操作码,如果选择了错误的操作码,则会得到无意义的结果。

不过,更常见的是1111表示-1,即所谓的二进制补码表示形式。在这种情况下,ALU根本不在乎数字是带符号的还是无符号的!例如,让我们进行操作1110 + 0001。在带符号算术中,这表示“ -2 + 1”,结果应为-1(1111)。在无符号算术中,这表示“ 14 +1”,结果应为15(1111)。因此,ALU不知道您要签名还是未签名的结果,因此它不在乎。它只是像没有符号一样执行加法运算,如果您以后要将其视为有符号整数,则取决于您。

编辑:正如Ruslan和Daniel Schepler在注释中正确指出的那样,即使在二进制补码机上,某些操作数仍需要单独的有符号和无符号版本。加法,减法,乘法,等式等在不知道数字是否带符号的情况下都可以正常工作。但是除法和任何大于/小于比较必须具有单独的版本。

编辑编辑:还有其他一些表示形式,例如一个人的补语,但是基本上不再使用它们,因此您不必担心它们。


啊,知道了 谢谢你:)
noorav

10
在二进制补码表示形式中,三个算术运算符与符号无关,即加法,减法和乘法(乘积的长度与操作数相同)。对于带符号的操作数,只需要对除法进行不同的处理。
罗斯兰

4
还有一个比较:< <= >= >有符号和无符号操作数是不同的,而==!=是不可知的。
Daniel Schepler

乘法通常具有带符号和无符号的变体:0xFFFFFFFF * 0xFFFFFFFF如果是无符号则为0xFFFFFFFE00000001,如果是符号则为0x0000000000000001。像Intel这样的处理器会在2个寄存器中返回结果,而有符号和无符号的顶部寄存器的确有所不同。在两种情况下,底部寄存器均为1。
Rudy Velthuis

9

所有现代体系结构都使用的二进制补码数学的一大优点是,有符号和无符号操作数的加法和减法指令完全相同。

许多CPU甚至没有乘法,除法或模数指令。如果这样做,它们必须具有分开的带符号和无符号形式的指令,并且编译器(或汇编语言程序员)选择适当的形式。

CPU通常还对签名或未签名的比较使用不同的指令。例如,如果比较应该签名,则x86可能跟CMPJL(小于时跳转),或者如果比较没有签名,则后跟x86 JB。同样,编译器或程序员将为数据类型选择正确的指令。

其他一些指令通常带有有符号和无符号变体,例如右移或将值加载到更宽的寄存器中(带或不带符号扩展名)。


1
只要您不需要结果的位数多于input的位数,甚至无符号和有符号(二进制补码)整数的乘法也相同。但是,如果要执行8×8→16位(或16×16→32位等)乘法,则需要对输入进行符号扩展(或中间结果)
Ilmari Karonen

@IlmariKaronen这是事实;ARM A32 / A64是有多种形式的乘法指令,包括手无关乘加写入仅低阶位,而且指令集smulh,并umulh认为只返回乘法的高位和符号和无符号指令将结果返回到寄存器中,其宽度是源操作数的两倍。
戴维斯洛

6

没有。处理器依靠指令集来告诉它正在查看的数据类型以及将数据发送到何处。操作数本身中没有1和0可以固有地向ALU发出信号,即数据是否为char,float,int,signed int等。如果1111进入了一个预期2s补码的电路,它将被解释为2s补码。


char在硬件级别没有这样的东西。也许曾经是机械电传打印机的时代。但今天,一个char只是一个号码就硬件而言。不同数字对应屏幕上不同字母形状的原因是,这些数字用于从大表(即从“字体”)中选择不同的位图或不同的绘制例程。
所罗门慢

3

我想补充一下已经做出的答案:

在大多数其他答案中,请注意,在二进制补码算法中,有符号和无符号数字的结果相同:

-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

也有不同的“条件”指令(条件跳转,按条件设置位)以及有符号和无符号算术的乘法指令。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.