当 MSB 为零时,我的教科书中的算术右移示例会移位
Arithmetic right shift examples in my textbook shift in ones when the MSB was zero
我目前正在研究汇编,并在其中转换按位运算的工作原理。特别是算术右移困扰着我。
现在,我正在阅读的书中有几道练习题,其中,我需要对一个字节执行此操作,该字节包括:
0100 0100
现在,看到算术右移填充了最高有效位的值,在我看来这应该是这样的:
00001000
不过书上说应该是
11101000
即从左边开始填入1而不是0。但是最高有效位不是 0 吗?
嗯,还有一个:
0110 0100 >> 3 = 0000 1100
但是,显然这也是错误的,应该是:
11101100
同样,我不明白最有效的位值显然是 0,即最左边的一位,但解决方案告诉我应该填写 1?
所以我这里有最后一个显然是正确的:
0111 0010 >> 3 = 0000 1110
这是我所期望的。那么为什么其他人不正确?
如果不理解这一点,阅读汇编会非常困难,因为很多乘法和除法都被编译为移位运算。
左移是增加基本幂,右移是减少。所以基数 2(二进制)右移是减少 2 的幂,左移是增加。所以右边是除以 2 左边是乘以 2.
问题出在右移和负数上,这意味着假设二进制补码,并且理解处理器不知道或不关心,位就是位,它们对程序员来说意味着什么。
一个负的二进制补码表示msbit的设置你很清楚。
因此,如果我想将 -2 0b11111110 除以 2 得到 -1 0b11111111,那么将其右移会很好,但逻辑右移通常意味着用零填充顶部,因此 0b11111110 逻辑右移变为 0b01111111它不是-1,而是 127。有些处理器有算术右移,它不是移入零,而是复制最高位,因此 0b11111110 ASR 变为 0b11111111。
这是 right/desired 使用移位除以 -2 / 2 的答案。
同样理解0b11111110同时也代表值254,254/2 = 127。所以算术右移得到255,这是错误的答案。到目前为止,对于签名,我们想为未签名的 LSR 做一个 ASR。
你是对的,你的书可能是错的,或者你只给了我们这本书的片段。
0b01000100 ASR is 0b00100010
0b01000100 LSR is 0b00100010
0b10001000 ASR is 0b11000100
0b10001000 LSR 0s 0b01000100
多位算术移位只要把它们看成多个单个位或者只用原始数的msbit填充顶部
0b10001000 ASR 3 = 0bBBB10001 其中 B 是 1 所以 0b11110001
对于 LSR,BBB 为零 0b00010001
请注意,算术左移和逻辑左移是相同的操作,它们只是从右侧填充零。
说到C,这会是书上的错误,根据standard:
- 无符号类型的移位按您预期的方式工作(要移位的位数必须小于要移位的数字的宽度且非负数)。
- 有符号类型的移位不同。如果要移动的数字是负数,则左移未定义,但右移是实现定义的。
因此,无符号数的移位是明确定义的,但有符号数则不是(更好的说,没有通用的定义)。
为了完整起见,标准说:
The result of E1 >> E2is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined ().
因此考虑到 OP 的示例(正数),没有理由填写一个。
谈算术移位(以x86为例):
In an arithmetic shift (also referred to as signed shift), like a logical shift, the bits that slide off the end disappear (except for the last, which goes into the carry flag). But in an arithmetic shift, the spaces are filled in such a way to preserve the sign of the number being slid. For this reason, arithmetic shifts are better suited for signed numbers in two's complement format.
SAR
指令在数字为负数时补1(为了保持符号),例如:
sar 10110011b, 2 #the result is 11101100b
(shr 10110011b, 2 #the result is 00101100b
)
不过,OP 的例子是在谈论正数,所以没有理由用一个来填充。
总而言之,在应用右移时可以用一个填充,但在那些情况下不行。
当输入的 MSB 为 0 时,任何移位都不会填充 1。 请注意,反之则不然(逻辑右移总是填充 0)。
如果这本书没有一些额外的上下文,那么它只是一个错误。那不是旋转或其他任何东西。甚至 1 的补码或 sign/magnitude 都无法解释它(因为所有 3 个表示中的数字都是正数)。
符号位副本中的 2 的补码移位的算术右移。 (因此,例如 sar eax, 31
将符号位广播到 32 位寄存器的所有位。
算术移位结果的符号总是与输入的符号相同。
逻辑右移总是移零。
逻辑和算术的左移是相同的:它们向零移动。 (x86 有 sal mnemonic, but it's just an alternate name for the same opcode as shl. Later x86 extensions don't bother mentioning an arithmetic left shift, e.g. there's a SIMD pslld
(压缩整数逻辑左移)但没有 pslad
。)
在 sign/magnitude 中,算术左移我猜想保持符号位不变。我不确定 1 的补码算术左移是否需要任何特殊处理。
但2的补码算术左移与逻辑相同。 (与 add same,same
相同,左移 1 也就是乘以 2。)
我目前正在研究汇编,并在其中转换按位运算的工作原理。特别是算术右移困扰着我。
现在,我正在阅读的书中有几道练习题,其中,我需要对一个字节执行此操作,该字节包括:
0100 0100
现在,看到算术右移填充了最高有效位的值,在我看来这应该是这样的:
00001000
不过书上说应该是
11101000
即从左边开始填入1而不是0。但是最高有效位不是 0 吗?
嗯,还有一个:
0110 0100 >> 3 = 0000 1100
但是,显然这也是错误的,应该是:
11101100
同样,我不明白最有效的位值显然是 0,即最左边的一位,但解决方案告诉我应该填写 1?
所以我这里有最后一个显然是正确的:
0111 0010 >> 3 = 0000 1110
这是我所期望的。那么为什么其他人不正确?
如果不理解这一点,阅读汇编会非常困难,因为很多乘法和除法都被编译为移位运算。
左移是增加基本幂,右移是减少。所以基数 2(二进制)右移是减少 2 的幂,左移是增加。所以右边是除以 2 左边是乘以 2.
问题出在右移和负数上,这意味着假设二进制补码,并且理解处理器不知道或不关心,位就是位,它们对程序员来说意味着什么。
一个负的二进制补码表示msbit的设置你很清楚。
因此,如果我想将 -2 0b11111110 除以 2 得到 -1 0b11111111,那么将其右移会很好,但逻辑右移通常意味着用零填充顶部,因此 0b11111110 逻辑右移变为 0b01111111它不是-1,而是 127。有些处理器有算术右移,它不是移入零,而是复制最高位,因此 0b11111110 ASR 变为 0b11111111。 这是 right/desired 使用移位除以 -2 / 2 的答案。
同样理解0b11111110同时也代表值254,254/2 = 127。所以算术右移得到255,这是错误的答案。到目前为止,对于签名,我们想为未签名的 LSR 做一个 ASR。
你是对的,你的书可能是错的,或者你只给了我们这本书的片段。
0b01000100 ASR is 0b00100010
0b01000100 LSR is 0b00100010
0b10001000 ASR is 0b11000100
0b10001000 LSR 0s 0b01000100
多位算术移位只要把它们看成多个单个位或者只用原始数的msbit填充顶部
0b10001000 ASR 3 = 0bBBB10001 其中 B 是 1 所以 0b11110001 对于 LSR,BBB 为零 0b00010001
请注意,算术左移和逻辑左移是相同的操作,它们只是从右侧填充零。
说到C,这会是书上的错误,根据standard:
- 无符号类型的移位按您预期的方式工作(要移位的位数必须小于要移位的数字的宽度且非负数)。
- 有符号类型的移位不同。如果要移动的数字是负数,则左移未定义,但右移是实现定义的。
因此,无符号数的移位是明确定义的,但有符号数则不是(更好的说,没有通用的定义)。
为了完整起见,标准说:
The result of E1 >> E2is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined ().
因此考虑到 OP 的示例(正数),没有理由填写一个。
谈算术移位(以x86为例):
In an arithmetic shift (also referred to as signed shift), like a logical shift, the bits that slide off the end disappear (except for the last, which goes into the carry flag). But in an arithmetic shift, the spaces are filled in such a way to preserve the sign of the number being slid. For this reason, arithmetic shifts are better suited for signed numbers in two's complement format.
SAR
指令在数字为负数时补1(为了保持符号),例如:
sar 10110011b, 2 #the result is 11101100b
(shr 10110011b, 2 #the result is 00101100b
)
不过,OP 的例子是在谈论正数,所以没有理由用一个来填充。
总而言之,在应用右移时可以用一个填充,但在那些情况下不行。
当输入的 MSB 为 0 时,任何移位都不会填充 1。 请注意,反之则不然(逻辑右移总是填充 0)。
如果这本书没有一些额外的上下文,那么它只是一个错误。那不是旋转或其他任何东西。甚至 1 的补码或 sign/magnitude 都无法解释它(因为所有 3 个表示中的数字都是正数)。
符号位副本中的 2 的补码移位的算术右移。 (因此,例如 sar eax, 31
将符号位广播到 32 位寄存器的所有位。
算术移位结果的符号总是与输入的符号相同。
逻辑右移总是移零。
逻辑和算术的左移是相同的:它们向零移动。 (x86 有 sal mnemonic, but it's just an alternate name for the same opcode as shl. Later x86 extensions don't bother mentioning an arithmetic left shift, e.g. there's a SIMD pslld
(压缩整数逻辑左移)但没有 pslad
。)
在 sign/magnitude 中,算术左移我猜想保持符号位不变。我不确定 1 的补码算术左移是否需要任何特殊处理。
但2的补码算术左移与逻辑相同。 (与 add same,same
相同,左移 1 也就是乘以 2。)