算术移位和逻辑移位实现分析

unsigned int i = 8;
int main()
{
i = i<<3;//输出结果i = 64
}
上面的变量i是采用逻辑移位还是算术移位呢?
逻辑移位,简单理解就是物理上按位进行的左右移动,两头用0进行补充,不关心数值的符号问题
算术移位,同样也是物理上按位进行的左右移动,两头用0进行补充,但必须确保符号位不改变

但我们好奇的是“i<<3”和“i>>3”到底采用的是算术还是逻辑移位呢?其实单从C语言本身来看可能没有太多突破,因为C最终会被编译器编译成目标平台的汇编代码,所以必须要结合编译器和汇编程序来分析以上代码,下面主要从反汇编入手分析,对ARM平台下有关移位的指令有:
LSL(逻辑左移)
LSR(逻辑右移)
ROR(循环右移)

ASL(算术左移)
ASR(算术右移)
RRX(带扩展的循环右移)

下面我们来看看上面那段C程序的反汇编结果:

结论:说明无符号数采用的是逻辑左移。
那么经过测试我们发现以下几份代码反汇编结果和上面的情况是一样的,都是逻辑左移:
signed int i = 8;
int main()
{
i = i<<3;//输出结果i = 64
}
signed int i = -8;
int main()
{
i = i<<3;//输出结果i = -64
}
结论:说明不管是否有无符号类型,也不管值的正负,均采用的是逻辑左移。

接下来看看右移:
unsigned int i = 8;
int main()
{
i = i>>3;//输出结果i = 1
}
反汇编结果:

结论:说明无符号数采用的是逻辑右移。

再看看有符号数的右移操作:
signed int i = 8;
int main()
{
i = i>>3;//输出结果i = 1
}
反汇编结果:

结论:说明有符号数采用的是算术右移。
经过测试发现以下代码反汇编结果和上面的情况也是一样的:
signed int i = -8;
int main()
{
i = i>>3;//输出结果i = -1
}
结论:说明只要是有符号数,不管值是正还是负,右移时采用的都是算术右移。

疑问:按照移位补0的原则,为何左移都是逻辑移位呢?
答疑:先看看“-8”和“8”在计算机内存中的值分别是:
0xfffffff8
0x8
由于计算机均按补码保存数值,所以不管符号正负,左移对于符号位并不产生影响,而右移则就不同了,无符号数怎么右移都不影响符号位,但是有符号数逻辑右移时高位补0将改变符号位,所以只能采用算术右移。

总结:只有有符号数右移才采用算术右移,否则其它情况都采用逻辑移位操作(逻辑左移或逻辑右移)。原来只要明白计算机是以补码方式保存数值的,就一切都清楚了。
<think>我们正在讨论汇编语言中的移位操作,特别是算术移位逻辑移位的区别。根据引用[3],我们可以总结如下: - 逻辑移位(不管是左移位还是右移位)都是空缺处补0。 - 算术移位要保证符号位的不改变。具体来说: - 算术左移同逻辑左移(都是空缺处补0)。 - 算术右移移入的位用符号位填充(即保持符号位不变)。 在汇编语言中,通常有以下移位指令: - 逻辑左移:SHL(Shift Left) - 逻辑右移:SHR(Shift Right) - 算术左移:SAL(Shift Arithmetic Left)——实际上与SHL相同 - 算术右移:SAR(Shift Arithmetic Right) 引用[3]中的例子: 1. 逻辑左移(SHL)算术左移(SAL)结果相同: ```assembly mov ax, 1100_0111_0110_1000B mov cl, 3 shl ax, cl ; 或者 sal ax, cl ; 结果 ax = 0011_1011_0100_0000B ``` 这里,最高位的1被移出,左边移出的位用0补充。 2. 逻辑右移(SHR): ```assembly mov ax, 1100_0111_0110_1000B mov cl, 3 shr ax, cl ; 结果 ax = 0001_1000_1110_1101B ``` 右边移出的位用0补充。 3. 算术右移(SAR): ```assembly mov ax, 1100_0111_0110_1000B ; 符号位为1(负数) mov cl, 3 sar ax, cl ; 结果 ax = 1111_1000_1110_1101B ; 移入的位用符号位1填充 mov ax, 0100_0111_0110_1000B ; 符号位为0(正数) mov cl, 3 sar ax, cl ; 结果 ax = 0000_1000_1110_1101B ; 移入的位用符号位0填充 ``` 因此,区别主要在于右移操作: - 逻辑右移(SHR)总是用0填充移出的高位。 - 算术右移(SAR)用符号位(即最高位)填充移出的高位,这样在右移过程中保持了数值的符号不变,适用于有符号数的除法运算(例如,将负数右移,结果仍然是负数)。 而左移操作中,逻辑左移(SHL)算术左移(SAL)是相同的,都是将操作数向左移动,低位用0填充,高位移出。左移操作可以用于无符号数有符号数的乘法(乘以2的幂),但要注意溢出问题。 另外,引用[2]提到循环移位算术移位逻辑移位不同,循环移位分为带进位不带进位,这里不再展开。 总结: | 指令 | 方向 | 填充方式 | 用途 | |------|------|----------|------| | SHL | 左移 | 低位补0 | 无符号数乘法,逻辑操作 | | SAL | 左移 | 低位补0(同SHL) | 有符号数乘法(但注意溢出) | | SHR | 右移 | 高位补0 | 无符号数除法 | | SAR | 右移 | 高位用符号位填充 | 有符号数除法 | 所以,在汇编语言中,算术移位逻辑移位的区别主要体现在右移操作上,左移操作两者相同。</think>### 汇编语言中算术移位逻辑移位的区别 在汇编语言中,移位操作分为算术移位逻辑移位两种类型,它们在**符号位处理****数值意义**上有本质区别: #### 1. **逻辑移位(Logical Shift)** - **操作指令**:`SHL`(左移)、`SHR`(右移) - **核心特点**:空缺位**始终补0**,不考虑符号位 - **二进制示例**: ```assembly ; 原始值:1100_0111_0110_1000B SHR AX, 3 ; 右移3位 → 0001_1000_1110_1101B(高位补0) SHL AX, 2 ; 左移2位 → 0001_1000_1110_1101_00B(低位补0) ``` - **数学意义**:无符号整数乘以/除以$2^n$($n$为移位次数) - **适用场景**:位操作、无符号数运算、数据掩码处理[^3] #### 2. **算术移位(Arithmetic Shift)** - **操作指令**:`SAL`(左移)、`SAR`(右移) - **核心特点**: - 左移(`SAL`)**等同逻辑左移**(低位补0) - 右移(`SAR`)**保留符号位**(高位用符号位填充) - **二进制示例**: ```assembly ; 负数(符号位1):1100_0111_0110_1000B SAR AX, 3 ; 右移3位 → 1111_1000_1110_1101B(高位补符号位1) ; 正数(符号位0):0100_0111_0110_1000B SAR AX, 3 ; 右移3位 → 0000_1000_1110_1101B(高位补符号位0) ``` - **数学意义**:有符号整数乘以/除以$2^n$(保持符号不变) - **适用场景**:有符号数运算、高效除法优化[^3] #### 3. **核心区别对比** | 特性 | 逻辑移位 | 算术移位 | |--------------|------------------------|------------------------| | **符号处理** | 忽略符号位 | 保留符号位(仅右移) | | **填充规则** | 空位恒补0 | 左移补0,右移补符号位 | | **指令** | SHL/SHR | SAL/SAR | | **数值类型** | 无符号数 | 有符号数 | | **数学意义** | 纯倍数缩放 | 带符号的倍数缩放 | #### 4. **关键注意事项** 1. **左移操作统一性**: 算术左移(`SAL`)与逻辑左移(`SHL`)**完全等价**,均低位补0[^3] $$ \text{SAL } x = \text{SHL } x = x \times 2^n $$ 2. **右移本质区别**: 逻辑右移(`SHR`)补0可能改变符号,算术右移(`SAR`)保持符号: $$ \begin{align*} \text{SHR: } & \text{unsigned } x \div 2^n \\ \text{SAR: } & \text{signed } x \div 2^n \end{align*} $$ 3. **溢出风险**: 左移操作可能导致符号位被覆盖(如 `0111_1111B << 1 = 1111_1110B`,正数变负数)[^3] > ⚠️ 循环移位(`ROL/ROR`)是独立机制,通过进位位连接首尾,无算术/逻辑之分[^2]。 --- ### 应用场景示例 ```assembly ; 场景1:快速无符号乘法(逻辑移位) MOV AX, 5 ; AX = 5 (0000_0101B) SHL AX, 3 ; AX = 40 (0010_1000B) → 5×8=40 ; 场景2:有符号数除法(算术移位) MOV BX, -24 ; BX = -24 (1110_1000B) SAR BX, 2 ; BX = -6 (1111_1010B) → -24÷4=-6 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值