无专用移位指令时如何实现逻辑右移
用指定汇编指令实现右位移位
右位移位分为无符号逻辑右移和有符号算术右移两种场景,以下基于你提供的指令集分别实现:
一、无符号逻辑右移(左补0)
逻辑右移的核心是将所有位向右移动一位,最高位补0,等价于无符号数整除2。以下以8位字长为例,实现寄存器A的逻辑右移1位:
代码实现
; 功能:A = A >> 1(无符号逻辑右移) mv B, 0 ; B存储最终结果 mv C, A ; C暂存原始数值 ; 逐位判断并构建结果 cmp C, 128 ; 检查原始值第7位(最高位)是否为1 jnz skip7 add B, 64 ; 结果第6位设为1 sub C, 128 skip7: cmp C, 64 ; 检查原始值第6位 jnz skip6 add B, 32 sub C, 64 skip6: cmp C, 32 ; 检查原始值第5位 jnz skip5 add B, 16 sub C, 32 skip5: cmp C, 16 ; 检查原始值第4位 jnz skip4 add B, 8 sub C, 16 skip4: cmp C, 8 ; 检查原始值第3位 jnz skip3 add B, 4 sub C, 8 skip3: cmp C, 4 ; 检查原始值第2位 jnz skip2 add B, 2 sub C, 4 skip2: cmp C, 2 ; 检查原始值第1位 jnz skip1 add B, 1 sub C, 2 skip1: mv A, B ; 将结果存回A
说明
通过cmp和jnz判断原始值的每一位是否为1,若是则将结果的对应高位设为1,本质是把原始值的第n位移到结果的第n-1位,最高位补0。若字长不是8位,只需对应调整各次幂的数值(如16位字长用32768、16384等)。
二、有符号算术右移(左补符号位)
算术右移需要保留符号位:正数右移补0,负数右移补1(最高位保持为1)。以下以8位字长为例实现:
代码实现
; 功能:A = A >> 1(有符号算术右移) mv SIGN, 0 ; SIGN标记符号:0为正,1为负 mv B, A ; 暂存原始值 ; 判断并记录符号位 cmp B, 128 ; 8位中最高位对应数值128 jnz skip_sign mv SIGN, 1 sub B, 128 ; 去掉符号位,转为无符号数处理 skip_sign: ; 执行无符号右移(复用逻辑右移的位判断逻辑) mv C, 0 mv D, B cmp D, 128 jnz skip7a add C, 64 sub D, 128 skip7a: cmp D, 64 jnz skip6a add C, 32 sub D, 64 skip6a: cmp D, 32 jnz skip5a add C, 16 sub D, 32 skip5a: cmp D, 16 jnz skip4a add C, 8 sub D, 16 skip4a: cmp D, 8 jnz skip3a add C, 4 sub D, 8 skip3a: cmp D, 4 jnz skip2a add C, 2 sub D, 4 skip2a: cmp D, 2 jnz skip1a add C, 1 sub D, 2 skip1a: ; 若原始值为负数,恢复符号位 cmp SIGN, 1 jnz skip_set_sign add C, 128 ; 将结果最高位设为1 skip_set_sign: mv A, C ; 结果存回A
说明
先判断原始值的符号,负数则先剥离符号位转为无符号数处理;完成无符号右移后,若原始为负数,给结果加上符号位对应的数值,确保最高位保持为1,保留负号。
适配不同字长的注意事项
如果你的自制计算机字长不是8位,只需将代码中的数值替换为对应字长的幂次即可:
- 16位字长:符号位阈值为32768,右移对应位的数值依次为16384、8192...1
- 32位字长:符号位阈值为2147483648,对应位数值依次为1073741824、536870912...1
内容的提问来源于stack exchange,提问作者Kestrel
相关产品推荐
相关产品推荐

