035.多个双字的移位操作

本文深入探讨了8086处理器上使用SHR和RCR指令进行多字节移位操作的过程,通过具体示例展示了如何在连续字节中实现循环移位,特别关注了小端处理器的字节分布特性。
书中这一部分给出的图是结果是有错误的,移位后,正确的结果是从 1001 1001 1001 1001 编程 0100 1100 1100 1100 1100,请注意这里使用的
移位结果产生的过程如下

1001 1001 1001 1001 1001 1001
0100 1100 1001 1001 1001 1001
0100 1100 0100 1100 1001 1001
0100 1100 0100 1100 0100 1100

;Multiple Doubleword Shift            (MultiShf.asm)

;This program demonstrates a multibyte shift operation, 
;using SHR and RCR instructions.

INCLUDE Irvine32.inc

.data
	ArraySize = 3
	array BYTE ArraySize DUP(99h)		; 1001 pattern in each nybble ;nybble n.半字节
										; 十六进制下的99h就是模式为 1001 1001 的二进制数字

.code
	main PROC
		call DisplayArray			; display the array
	
		mov esi,0					; 循环移位的操作是从右向左进行的首先对最左边的一个字节进行携带符号位的移位,其次按顺序对左侧相邻的两个字节进行循环进位的移位操作。
									;8086处理器是小端处理器,应该特别注意连续字节在内存中的分布
		shr array[esi+2],1     		; high byte   
		rcr array[esi+1],1     		; middle byte, include Carry flag
		rcr array[esi],1     		; low byte, include Carry flag

		call DisplayArray			; display the array
		call WaitMsg				;
		exit
	main ENDP

	;----------------------------------------------------
	DisplayArray PROC
	; Display the bytes from highest to lowest
	;----------------------------------------------------
		pushad

		mov ecx,ArraySize
		mov esi,ArraySize-1
	L1:
			mov  al,array[esi]		; AL存放需要显示的字符ASCII码
			mov  ebx,1				; ebx表示字节为以单位显示的大小,这里是用了一个字节
			call WriteBinB			; display binary bits 使用字节格式显示一个二进制整数,接收参数al,ebx,al表示二进制比特数值,ebx标志输出类型
			
			mov  al,' '				;WriteChar使用AL寄存器来传递字符,用于显示在屏幕上
			call WriteChar
			sub  esi,1				;从后向前显示字符,偏移量减少
		Loop L1
	
		call Crlf
		popad
		ret
	DisplayArray ENDP

END main
### 三、双符号数的算术移位操作原理 在计算机系统中,为了提高数值运算的精度控制和溢出检测能力,通常采用**双符号位**的设计。这种设计通过将最高有效位扩展为个相同的符号位来增强数据表示的稳定性,尤其适用于定点数的算术移位操作。 #### 1. 双符号数的基本结构 双符号数指的是在数据表示中,使用个相同的符号位(`SS`)作为前缀,后面跟着实际的数据位(`xxxxxx`)。例如,在一个8位系统中,一个双符号数可能被表示为 `SSxxxxxx`。这样的设计使得在进行移位、加法或减法等操作时,能够更加直观地判断溢出情况并调整运算结果[^1]。 #### 2. 算术右移的操作规则 在执行**算术右移**时,双符号数的核心原则是保持数值的符号不变,同时对数值部分进行适当的移位处理: - **正数**:如果个符号位均为0,则表示该数为正;此时高位补0。 - **负数**:如果个符号位均为1,则表示该数为负;此时高位补1。 具体操作步骤如下: 1. **确定符号状态**:检查当前数据的个符号位,确认其符号属性。 2. **执行右移**:将整个数据序列向右移动一位,最低有效位被丢弃。 3. **填充高位**:根据原符号位的值来决定新空出的最高位应如何填充。 4. **更新符号位**:新的最高位及其相邻位构成了新的双符号位组合。 例如,在引用中的案例中,原始码 `00.001101` 经过多次左移后变为 `01.1010000`,其中低符号位已经发生变化,但高符号位仍然保留不变,从而确保了符号的一致性。 #### 3. 为什么高符号位保留不变? 在双符号数的算术移位过程中,**高符号位保留不变**的原因在于它代表了数值的真实符号信息。即使经过多次移位操作,数值的正负属性应当保持不变。因此,无论进行左移还是右移,高符号位始终被视为真正的符号位,而低符号位则参与具体的移位过程。 这种设计可以有效地防止因移位而导致的符号错误,尤其是在涉及负数的情况下。例如,当一个负数以补码形式存储时,高位补1可以保证其仍然表示负数,避免了符号反转的问题。 #### 4. 为什么低符号位要参与移位? 低符号位之所以需要参与移位,是因为它实际上属于数值的一部分。在某些情况下,如定点数乘以2的幂次方时,低符号位可能会被移出或重新分配到其他位置。例如,引用中的例子显示,随着左移次数增加,低符号位逐渐向右移动,并最终被替换为新的数值位。这种机制允许数值在保持符号一致性的前提下,动态调整其大小。 #### 5. 实现示例与代码演示 以下是一个简单的 Python 函数,用于模拟双符号位的算术右移操作: ```python def arithmetic_right_shift(value, bits=8): """ 模拟双符号位算术右移操作 :param value: 输入的整数值(假设已经是以补码形式存在的) :param bits: 数据宽度(默认为8位) :return: 经过算术右移后的结果 """ # 确保输入值处于指定的位宽范围内 mask = (1 << bits) - 1 value &= mask # 获取符号位 sign_bit = (value >> (bits - 1)) & 1 # 执行算术右移 shifted = (value >> 1) # 如果是负数,则高位补1 if sign_bit: shifted |= (1 << (bits - 1)) return shifted # 测试案例 print(bin(arithmetic_right_shift(0b11110000))) # 应输出 '0b11111000' print(bin(arithmetic_right_shift(0b00001111))) # 应输出 '0b00000111' ``` 在这个函数中,首先确保输入值符合给定的位宽要求,然后提取出符号位并执行标准的右移操作。最后,根据符号位的值决定是否需要在高位补充1,以此达到保持符号一致性的目的。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值