微处理器中的ALU如何区分1111表示的有符号数-7和1111表示的无符号数15?
微处理器中的ALU如何区分1111表示的有符号数-7和1111表示的无符号数15?
Answers:
简短而简单的答案是:否。没有现代主流CPU ISA可以像您想象的那样工作。
对于CPU,这只是一种模式。程序员,要由您自己来确定该位模式的含义。
通常,在存储方面,ISA不会区分不同的数据类型。(忽略FPU中的浮动寄存器之类的专用寄存器。)这对CPU而言只是毫无意义的位模式。但是,ISA 确实有不同种类的指令,它们可能以不同的方式解释位模式。例如,算术指令,例如MUL
,DIV
,ADD
,SUB
解释的位模式为某种数量的,而逻辑指令如AND
,OR
,XOR
它解释为布尔值的阵列。因此,由程序员(或如果使用高级语言,则由解释器或编译器的作者)选择正确的指令。
例如,对于带符号和无符号的数字,可能会有单独的说明。一些ISA还具有二进制编码的十进制算术指令。
但是,请注意,我在上面写了“现代主流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,则您具有符号幅度表示,其中第一位是符号,其余位是幅度。在这种情况下,算术有些复杂,因为无符号加法和有符号加法使用不同的逻辑。因此,您可能会有一个SADD
和一个UADD
操作码,如果选择了错误的操作码,则会得到无意义的结果。
不过,更常见的是1111
表示-1,即所谓的二进制补码表示形式。在这种情况下,ALU根本不在乎数字是带符号的还是无符号的!例如,让我们进行操作1110 + 0001
。在带符号算术中,这表示“ -2 + 1”,结果应为-1(1111
)。在无符号算术中,这表示“ 14 +1”,结果应为15(1111
)。因此,ALU不知道您要签名还是未签名的结果,因此它不在乎。它只是像没有符号一样执行加法运算,如果您以后要将其视为有符号整数,则取决于您。
编辑:正如Ruslan和Daniel Schepler在注释中正确指出的那样,即使在二进制补码机上,某些操作数仍需要单独的有符号和无符号版本。加法,减法,乘法,等式等在不知道数字是否带符号的情况下都可以正常工作。但是除法和任何大于/小于比较必须具有单独的版本。
编辑编辑:还有其他一些表示形式,例如一个人的补语,但是基本上不再使用它们,因此您不必担心它们。
<
<=
>=
>
有符号和无符号操作数是不同的,而==
和!=
是不可知的。
所有现代体系结构都使用的二进制补码数学的一大优点是,有符号和无符号操作数的加法和减法指令完全相同。
许多CPU甚至没有乘法,除法或模数指令。如果这样做,它们必须具有分开的带符号和无符号形式的指令,并且编译器(或汇编语言程序员)选择适当的形式。
CPU通常还对签名或未签名的比较使用不同的指令。例如,如果比较应该签名,则x86可能跟CMP
有JL
(小于时跳转),或者如果比较没有签名,则后跟x86 JB
。同样,编译器或程序员将为数据类型选择正确的指令。
其他一些指令通常带有有符号和无符号变体,例如右移或将值加载到更宽的寄存器中(带或不带符号扩展名)。
smulh
,并umulh
认为只返回乘法的高位和符号和无符号指令将结果返回到寄存器中,其宽度是源操作数的两倍。
没有。处理器依靠指令集来告诉它正在查看的数据类型以及将数据发送到何处。操作数本身中没有1和0可以固有地向ALU发出信号,即数据是否为char,float,int,signed int等。如果1111进入了一个预期2s补码的电路,它将被解释为2s补码。
char
在硬件级别没有这样的东西。也许曾经是机械电传打印机的时代。但今天,一个char
是只是一个号码就硬件而言。不同数字对应屏幕上不同字母形状的原因是,这些数字用于从大表(即从“字体”)中选择不同的位图或不同的绘制例程。
我想补充一下已经做出的答案:
在大多数其他答案中,请注意,在二进制补码算法中,有符号和无符号数字的结果相同:
-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
。
也有不同的“条件”指令(条件跳转,按条件设置位)以及有符号和无符号算术的乘法指令。