-2以2的补码形式存储,即0b1111_1110,该数据块的十进制表示形式为254,对吗?
是的,对于典型的现代系统来说确实如此。
现在,我的问题是,由于ARM处理器的二进制表示形式相同,因此它们将如何区分“ -2”和“ 254”?
处理器没有;编译器可以。
假设您有表达value > 0
。变量value
和常量0
都有一个类型。根据这些类型,编译器选择要使用的CPU指令。因此,有符号和无符号比较可能导致不同的编译器输出。
处理器不知道代码中的类型。它只是执行这些选定的指令。
int icmp(int num) {
return num > 0;
}
int ucmp(unsigned int num) {
return num > 0;
}
Run Code Online (Sandbox Code Playgroud)
icmp:
sub sp, sp, #16
str w0, [sp, 12]
ldr w0, [sp, 12]
cmp w0, 0
cset w0, gt
and w0, w0, 255
add sp, sp, 16
ret
ucmp:
sub sp, sp, #16
str w0, [sp, 12]
ldr w0, [sp, 12]
cmp w0, 0
cset w0, ne
and w0, w0, 255
add sp, sp, 16
ret
Run Code Online (Sandbox Code Playgroud)
查看编译器如何生成略有不同的cset
指令。
大多数处理器(包括 Arm 处理器)不区分有符号数和无符号数。包含 0b1111_1110 的字节可以解释为值为 254 的无符号整数或值为 -2 的有符号整数。或者它可以被解释为其他东西,比如浮点数、定点数、字符等。决定这种解释的是你对其进行的操作。
对于许多指令来说,值是有符号整数还是无符号整数并不重要:有符号整数的表示形式旨在通过对字大小取模来使它们变得轻量级。例如,将两个相同大小的值相加只是一条add
指令;这些值是否有符号并不重要。
对于某些指令,处理器提供不同的指令。例如,有两组指令用于将值复制到更大的寄存器:SXTB(符号扩展字节)及其朋友,以及UXTB(零扩展字节)及其朋友。UXT* 指令将值复制到目标寄存器的低位,并将高位设置为零。SXT* 指令将值复制到目标寄存器的低位,并将高位设置为该值的高位,即它们将此高位解释为符号位。
从 C 的角度来看,编译器的工作是根据操作数使用正确的指令。例如,如果编译器看到
uint8_t x = 0xfe;
uint32_t y = x + 3;
Run Code Online (Sandbox Code Playgroud)
它决定最好的编译方法是将其存储x
在 32 位寄存器的低位中,并且y
作为另一个 32 位寄存器,它将发出一条 UXTB 指令来设置寄存器,y
然后发出0x000000fe
一条ADD
指令来获取的期望值x
。(当然,在实践中,这个片段将被优化掉。)
归档时间: |
|
查看次数: |
164 次 |
最近记录: |