基于MSP430FR5739的16位无符号整数右循环移位实现求助
16位无符号整数循环右移的C实现(适配MSP430FR5739)
首先纠正一个误区:你提到的RRA指令是算术右移,会保持符号位,并不适合无符号整数的循环右移——它没法自动把最低位移到最高位,还需要配合进位操作,这也是你内嵌汇编出错的主要原因之一。纯C实现不仅更易维护,还能避免汇编语法适配问题,以下是两种可行方案:
方案1:逐位循环实现(贴合你的代码框架)
这个版本和你给出的框架结构一致,每次循环完成1位的循环右移,逻辑清晰:
void rotate_bits_right_16bit(unsigned int *address, unsigned char num_rotates) { // 16位数据循环移位超过16次等价于取模后的次数,避免无效循环 num_rotates %= 16; if (num_rotates == 0) return; unsigned char i; unsigned int temp; for(i = 0; i < num_rotates; i++) { temp = *address; // 核心逻辑:最低位移到最高位,其余位右移1位 *address = (temp >> 1) | ((temp & 0x0001) << 15); } }
方案2:单次计算实现(更高效)
直接通过位运算一次完成指定次数的移位,省去循环开销,性能更优:
void rotate_bits_right_16bit(unsigned int *address, unsigned char num_rotates) { num_rotates %= 16; if (num_rotates == 0) return; unsigned int temp = *address; // 右移指定位数,同时把被移出的低位补到高位 *address = (temp >> num_rotates) | (temp << (16 - num_rotates)); }
验证你的示例
输入值0x70DD(二进制0111 0000 1101 1101),调用函数传入num_rotates=1:
- 右移1位得到
0x386E,原数最低位(1)左移15位得到0x8000 - 两者按位或结果为
0xB86E(二进制1011 1000 0110 1110),和你预期的结果完全一致。
如果你坚持要用内嵌汇编
如果一定要用MSP430汇编实现,需要注意CCS的内嵌汇编语法规范,以及RRC(带进位循环右移)指令的正确用法(RRA不适合无符号循环移位),示例如下:
void rotate_bits_right_16bit(unsigned int *address, unsigned char num_rotates) { num_rotates %= 16; if (num_rotates == 0) return; unsigned char i; for(i = 0; i < num_rotates; i++) { __asm volatile( "MOV %[val], R15\n" // 将目标值加载到寄存器R15 "CLRC\n" // 清除进位位,避免干扰 "BIT #1, R15\n" // 将最低位状态写入进位位C "RRC R15\n" // 带进位循环右移:C进入最高位,最低位进入C "MOV R15, %[val]\n" // 将结果写回原地址 : [val] "+m" (*address) // 输入输出操作数:修改内存地址的内容 : : "R15", "C" // 告知编译器被修改的寄存器和进位位 ); } }
内容的提问来源于stack exchange,提问作者user19402326
相关产品推荐
相关产品推荐

