对于PIC16芯片中有符号扩展的优化

本文探讨了在PIC16芯片中如何优化有符号扩展操作,由于该芯片缺乏算数右移指令,作者提出了使用两条指令模拟算数右移的方法,详细分析了不同扩展方式所需的指令条数,并给出了优化后的五条指令解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题来源

举个小栗子

市面上有很多种芯片,其中对应的指令集也很丰富,可是不同的指令集对于各种基本功能的支持力度是不同的,以PIC16芯片和X86芯片相比较,举出一个很简单的例子,就是乘法,比如实现c = a * b
在X86中,实现如下:

movl b, %eax
mul b

这里不敢说乘法指令的全部操作只需要一条指令,但是乘法的本身还是只需要一条指令的,即mul b,但是在PIC16中会变成什么样子呢,代码如下:

movf a, w
movf mul.atmp, f
movf b, w
movf mul.btmp, f
call mul.i8
movf mul.result, w
movf c, 1

这里可能写的不规范,但是总体的意思是,将变量ab 分别放到乘法库函数定义的符号mul.atmpmul.btmp的符号里面,然后调用乘法库函数mul.i8,最后从库函数预先设定的符号里面取值,放到符号c中,如果觉得不好理解,可以先看成下面的高级函数形式的声明:

char mul.i8(char mul.atmp, char mul.btmp);

然后用户调用这个函数:

mul.result = mul.i8(a, b);
c = mul.result;

小栗子的结论

从上面的小栗子可以看出,不同的芯片对于每种基本基本操作的支持力度真的是不一样的,所以本文题目中的操作—有符号扩展,在两个芯片中的支持力度也不同,下面开始分析

分析过程

所需要的指令集

指令名称指令作用
rlf mem, w将符号mem的值循环左移一位,最高位进入进位位,最终的值写入寄存器,不写入f
rlf mem, f将符号mem的值循环左移一位,最高位进入进位位,原本符号位进入mem的最低位,写回到f
clrf memmem处的值清零
decf mem, fmem的值减一,并进行回写
comf mem, fmem的值取反,并进行回写
bcf mem, bmem的第b为清零

本芯片中如何用两条指令完成一次算数右移

先告诉你们一个不幸的消息,PIC16芯片中关于移位只有循环右移和循环左移,没有算数右移算数左移和逻辑右移。而且PIC16里面也没有相应的标志位寄存器,对于标志位,PIC16的策略是保存在一个内存符号里面,好在PIC16有一条指令bcf,这条指令可以将某个内存符号中的特定位置0,对应的也有bsf指令,可以将特定的内存位置的特定位置1,那么如何使用两条指令进行模拟呢。下面直接说结论吧,。
算数右移:

rlf mem, w
rrf mem, f

算数左移/逻辑左移:

bcf flags, 3 // 这里不一定是3,这里假设状态位的第三位是进位位,即这里是把进位位清零
rlf mem, f

逻辑右移:

bcf flags, 3 // 这里不一定是3,这里假设状态位的第三位是进位位,即这里是把进位位清零
rrf mem, f

两种没有经过优化的方式

使用库函数的方式

就像第一部分所说的,如果使用库函数,那么是8位扩展为16位,需要7条指令,因为可以指定移位次数是7,代码如下:

movf a, w
movf srashift.atmp, f
movl 7
movf srashift.btmp, f
call srashift.i8
movf srashift.result, w
movf c, f

同样可以看成高级语言函数声明:

srashift.result = srashift(char srashift.atmp, char srashift.btmp);

用户可以调用这个函数:

srashift.result = srashift(a, 7);
c = srashift.result;

而PIC16中的最高位宽是32位,最低位宽是8位,所以这里存在三种有符号扩展,分别为i8->i16i8 -> i32i16 -> i32,这三种有符号扩展分别所需要的指令条数为7条,至少11条,和13条。这是统计数据,相信我,没骗你们。

重复生成移位指令

这个小题目看起来神秘莫测的,但是其实非常2,所谓的重复生成移位指令就是一条一条的移位指令的写,这里以8位扩展为16位为例,可以看出位宽只差为8位,可是本平台每移动一次就需要两条指令,所以如果是8位扩展为16位需要16条指令。同理8位扩展32位需要48条指令,16位扩展32位需要32条指令。

本博客提出的方法

直接说出方法吧,这里以8位扩展16为例,设低位保存在mem + 0,值为00000000,高位保存在mem + 1中,由于申请这个符号的时候值是未知的,所以设置为xxxxxxxx,完成有符号移位只需要五条指令:

clrf mem + 1, f
rlf mem + 0, w
rlf mem + 1, f
decf mem + 1, f
comf mem + 1, f

让我们来看看这五条指令的执行效果:

指令名称执行效果
高位初始值xxxxxxxx
clrf mem + 1, f00000000
rlf mem + 0, w00000000
rlf mem + 1, f00000001
decf mem + 1, f00000000
comf mem + 1, f11111111

可以看出,最后的高位是11111111,与mem + 0的最高位相等。容易证明,对于正数来说也是如此,最后的结果是00000000

结语

从这篇博客里面也可以得知,不管一条指令有多么简单,都不要把这条指令的实现当成理所当然的,就比如乘法,在PIC16里面是没有对应的指令来实现的,再退一步,加法,也是通过各种位运算实现的呀。对于不同的芯片的相同指令,有不同的代码生成方法,这正是编译的乐趣所在,嘻嘻~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值