打印

疑问再提:C与汇编的问题(提高C编译器效率,扬长避短)

[复制链接]
8360|43
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
谈的元|  楼主 | 2009-12-27 21:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 谈的元 于 2009-12-29 19:18 编辑

大家有一个共识:C写的效率高,可读性好。但无用的操作多。就是运行效率低点
                       汇编写的效率低,可读性差。就是运行效率高点

而我觉得C编译器除了那些限制,(比如无法带标志移位,)

效率应该比汇编高才对啊

但对于:
比如  int  SS;
ss>>8;

象这种编译,C编译器为何移动8次呢?


而不是作为一种特例直接变换呢?

让人无法理解啊

请大家来讨论一下,

有例证最好了。

那样对C与汇编的理解就深刻多了。

谢谢!

相关帖子

来自 2楼
HWM| | 2009-12-28 08:45 | 只看该作者
C和ASM不是一个层次的东西(层次不等于贵贱)。在高级语言(高低级之分也没贵贱什么事)范畴中,C是“细节”干预能力最强的语言。再加上C++面向对象描述的拓展,可以说C/C++是目前跨度最大,描述能力最强的语言。但由于C/C++毕竟是一高级语言(通常也有称其为中级语言的),原则上不可能达到指令级描述。虽然可以加入一些特许处理,但这不是C的准,对移植和更新不利。

相反,ASM本身是基于某一特定CPU的指令级(也称低级)语言,其描述和处理能力完全取决于具体CPU之指令系统的描述和处理能力。如同楼主所举的例子,如果存在一次移动八位的指令,则用一条指令就可以完成移位,反之则必须用多条指令来实现同样的移位。

虽然C/C++语言可读性和移植性优于ASM,但实际上,每个具体的C/C++的实现(或称编译)都是建立在某个具体的CPU之上的。换句话说,就是每个具体的C/C++都是存在于某个具体的ASM之上的。不仅是C/C++,可以说所有的高级语言的基础都是ASM——或称指令系统。回到楼主的例子,ss >> 8。虽然在几乎所有的C/C++中,都能用此语句表达右移八位的语义,但具体实现起来还得要看C/C++的基础ASM的处理能力。若上所叙,如果存在一次移动八位的指令,则用一条指令就可以完成移位,反之则必须用多条指令来实现同样的移位。

由于C/C++的编译设计者通常是C/++和相关CPU的指令系统的“双重专家”,所以一般由C/C++编译系统得到的代码就平均意义上讲比直接用ASM编出的代码质量要高,再加上C/C++的可读性和移植性,所以通常人们更愿意使用C或C++。但要注意的是,这里讲的是平均意义,不排除有特殊能人和特殊要求,致使ASM更适合其使用。

总之要认识到,C/C++和ASM不是一个层次的东西,它们没有可比性,所以也没有好坏贵贱之分。这就象分子是由原子组成的一样,化学家不会去鄙视物理学,而物理学家也同样不会去鄙视化学家。一个最为理想的情况就是,把自己培养成为既是物理家同样也是化学家。

使用特权

评论回复
板凳
chunyang| | 2009-12-27 22:56 | 只看该作者
楼主又想掀起一场江湖风雨?
C并非“无用的操作”多,而是为保持兼容性的结果。

使用特权

评论回复
地板
chunyang| | 2009-12-27 22:56 | 只看该作者
俺跳出圈外,不争论……

使用特权

评论回复
5
chunyang| | 2009-12-27 22:57 | 只看该作者
想起了所长,怀念一下……

使用特权

评论回复
6
古道热肠| | 2009-12-28 00:01 | 只看该作者
“C哥只是个传说”,哈哈,现学来的。

使用特权

评论回复
7
yixuanyuxiao| | 2009-12-28 00:20 | 只看该作者
特例多了,语句就不精简了,兼容性也会变差的。比如在51上这个特例可以实现,到arm或其他的cpu上就无法实现了,而一次一次的一位似乎可以兼容任何cpu吧。应该是兼容性问题

使用特权

评论回复
8
ejack| | 2009-12-28 06:34 | 只看该作者
编译器需要在最大程度上贯彻编程者的意图。
你自己要移位而不是移字节,怨谁?

使用特权

评论回复
9
aozima| | 2009-12-28 13:13 | 只看该作者
月经贴

使用特权

评论回复
10
yewuyi| | 2009-12-28 14:31 | 只看该作者
呵呵,这要给分的。

使用特权

评论回复
11
ZALIN| | 2009-12-28 15:18 | 只看该作者
就楼主的例子,应该是编译器把SS作为有符号处理了

使用特权

评论回复
12
冷漠| | 2009-12-28 17:06 | 只看该作者
本帖最后由 冷漠 于 2009-12-28 19:28 编辑

我还当是真的呢。把下面程序编译一下,看看结果:
#include <reg52.h>
sfr16 DPTR=0X82;

void mian()
{
int  ss=0X1234;

DPTR=ss>>8;

while(1);
}

使用特权

评论回复
13
冷漠| | 2009-12-28 17:11 | 只看该作者

哪里移动8次了?还能化简吗?(这是0级优化。

本帖最后由 冷漠 于 2009-12-28 17:18 编辑

NAME        C1234
?PR?mian?C1234       SEGMENT CODE
?DT?mian?C1234       SEGMENT DATA
        PUBLIC        mian

        RSEG  ?DT?mian?C1234
?mian?BYTE:
         ss?040:   DS   2
; #include <reg52.h>
;
; sfr16 DPTR=0X82;
;
; void mian()

        RSEG  ?PR?mian?C1234
mian:
        USING        0
; {
;  int  ss=0X1234;
        MOV          ss?040,#012H
        MOV          ss?040+01H,#034H
;  DPTR=ss>>8;
        MOV          A,ss?040
        MOV          R7,A
        RLC          A
        SUBB         A,ACC
        MOV          R6,A
        MOV          DPH,R6
        MOV          DPL,R7
?C0001:
; while(1);
        SJMP         ?C0001
?C0002:
; }
?C0003:
        RET         
; END OF mian

        END

使用特权

评论回复
14
冷漠| | 2009-12-28 17:16 | 只看该作者

这是6级优化。上面是0级优化。

本帖最后由 冷漠 于 2009-12-28 17:18 编辑

; void mian()

        RSEG  ?PR?mian?C1234
mian:
; {
;  int  ss=0x1234;
                        ; SOURCE LINE # 8
;---- Variable 'ss?040' assigned to Register 'R6/R7' ----
;  
;  DPTR=ss>>8;
        MOV          A,#012H
        RLC          A
        SUBB         A,ACC
        MOV          DPH,A
        MOV          DPL,#012H
?C0001:
;
; while(1);
                        ; SOURCE LINE # 12
        SJMP         ?C0001
; END OF mian

        END

使用特权

评论回复
15
谈的元|  楼主 | 2009-12-28 19:56 | 只看该作者
本帖最后由 谈的元 于 2009-12-28 19:58 编辑
特例多了,语句就不精简了,兼容性也会变差的。比如在51上这个特例可以实现,到arm或其他的cpu上就无法实现了,而一次一次的一位似乎可以兼容任何cpu吧。应该是兼容性问题 ...
yixuanyuxiao 发表于 2009-12-28 00:20

回6楼:

    可以这样理解吗?汇编是方言,C是普通话。

    C编译器是将普通话翻译为方言,

    不同的C编译器就是将一句话翻译成不同地方语言。

    我们移植的是C,

     因此不存在兼容性问题啊。

使用特权

评论回复
16
谈的元|  楼主 | 2009-12-28 20:14 | 只看该作者
本帖最后由 谈的元 于 2009-12-28 20:19 编辑

还有一个问题:

假如 int  代表  8;short  代表 16 ;long 代表  32位。


   unsigned   long   n1, n2,n3;

   n1=(int)n2/n3;

   目的:求商的低字节;

   没除法指令的C编译器基本上都是要做32次移位减法来完成的。


  我认为C编译器可以扫描到INT这个关键词后,对N2,N3做一些变换,然后再做8次移位减法就可以了。

(少了24次循环,无疑是时间上的优化)

同样n1=(short)n2/n3;只需要16次循环就可以了。

  我们知道一种C编译器是为特定的一类单片机服务的。而除法是比较耗时的。

  而能做优化就是很有必要的。
  

  大家说说我的想法可以在C编译器中实现吗?

使用特权

评论回复
17
谈的元|  楼主 | 2009-12-28 20:21 | 只看该作者
编译器需要在最大程度上贯彻编程者的意图。
你自己要移位而不是移字节,怨谁?
ejack 发表于 2009-12-28 06:34


你好!

   请教    移字节         用C语言     怎么描述?

    请给个例子。

    谢谢!

使用特权

评论回复
18
zenwall| | 2009-12-28 20:40 | 只看该作者
我只是来看看的。

使用特权

评论回复
19
huergang| | 2009-12-28 20:43 | 只看该作者
瞅个热闹啊~~

使用特权

评论回复
20
airwill| | 2009-12-28 21:29 | 只看该作者
程序到一定规模, C 的效率 未必不如 ASM 的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

98

主题

3872

帖子

6

粉丝