查看: 5127|回复: 4

HotC51共产儿童团第十二课:汇编是艺术是享受,而非技巧可以攀比

[复制链接]
发表于 2009-4-2 22:40:14 | 显示全部楼层 |阅读模式
关键词: 儿童团 , 汇编 , 技巧 , 攀比 , 艺术
HotC51 发表于 2009-3-3 22:28 裸奔式实时操作系统HotTask51 ←返回版面

楼主: HotC51共产儿童团第十二课:汇编是艺术是享受,而非技巧可以攀比


开课:
菜农“逆潮流”而创办的“HotC51共产儿童团”就是要让更多的“红色脑浆”
流淌在地球的各个角落,让更多的“团员”和那些自认为“老大”的PK~~~
菜农就是要培养千千万万的“混小子”、“二愣子”和“天不怕、地不怕”的
“小菜农”~~~
只要他举起红旗,他就不怕任何地球人~~~
A人(擅长汇编之人)和C人(擅长高级语言之人)本无贫贱之分,更无高低之别。
就菜农个人而言,可谓学尽了天下的各种计算机语言~~~至少在MCU这个
圈子里俺可以这么说~~~
至少俺敢说单片机并非俺之最强项~~~
但俺所编的每一句汇编语言自己都要“审美”一遍,直到“陶醉”为止~~
这是很多人不能理解的~~~
若有人说俺汇编“档次地”,俺可以“高点”,但俺绝不会单独用C语言
为什么???若C语言是“最高境界”,那么Delphi、BC、CVI、VC、VB
Java、C#、VB.Net等为什么要再“造”呢???
汇编是一切语言之母!!!不会汇编的C语言“高手”永远都是自己封的
“高手”~~~编译器的任何小bug都会雷翻他~~~
高级语言一个问题可能有多种编程方法,但汇编可能又有一个唯一之解。
有时是无法“PK”的~~~

举例:
天雨粟 发表于 2008-10-19 14:59 侃单片机 ←返回版面 举报该贴

一个精巧的两字节除法子程序

条件:8个unsigned char型数据相加,高位在R2中,低位在R3中
出口:将此数除以8,余数四舍五入

MOV    A,R2        ;(R2,R3)/8
SWAP    A
RL    A
XCH    A,R3
SWAP    A
RL    A
ADD    A,#80H        ;四舍五入
ANL    A,#1FH
ADDC    A,R3
RET                    ;结果在A中

下面是具体分析:由于被操作数是8个无符号字符型数据相加,固其高位(R2)里D3位及其以上必为0。
现在将其分为三部分别想办法:R2的低四位,R3的高四位,R3的低四位。

将R2的低四位换到高四位,相当于把低四位乘以16,左移一位,又相当于乘以2,则原数被乘以了32。R2的真实意义是(R2)*256,现在我们将其看作一个普通的单字节数,则相当于将其除以了256。先乘以32再除以256,则等于将原数除以8。

将R3的高四位移到低四位,完成除以16,左移一位,相当于乘以2,最终完成除以8。

R3的低四位,其中的D3位,其权值正好为8,通过左移,移到新数的D0位(形成商加1——D3=1时;或不加——D3=0时)。R3的D2~D0位是余数,如为4~7时要五入;如为0~3时要四舍。分析可知,当D2为1时,余数为4~7;D2为0时,余数为0~3。在对R3进行左移操作时,D2已移到最高位,现对移位的结果加#80H,D2为1时,必置位CY,通过ADDC指令加进位形成五入,否则四舍。
ANL A,#1FH,因为R3/8,商的有效位为D4~D0,其它位在运算时要使用,但取结果时必须屏蔽掉。


俺随手即抛出一个“终极PK”,是人无法逾越~~~或很难逾越。
不算“精巧”吧~~~俺这个要少3条语句~~~[/B]
hotpower 发表于 2008-10-19 17:12 侃单片机 ←返回版面 举报该贴

;R2=00000YYY R3=xxxxxXXX
MOV  A,R3;xxxxxXXX
ADD  A,#4;XXX+4 四舍五入(CY)
ANL  A,#0F8H;xxxxx000
ADDC A,R2;xxxxxYYY+CY
SWAP A;xyyyxxxx
RL   A;yyyxxxxx
RET;结果在A中yyyxxxxx

现在也可以有人来“PK”~~~
在菜农发布近6000多行的“汇编数组”前,让俺自己先“陶醉”一下~~~
至于什么是“汇编数组”?它和汇编语言、嵌入汇编、脚本语言等有何区别?
“汇编数组”的过去、现在和将来,这要在团课中做专题才能说清楚。
先陶醉“汇编数组”Demo包里的一个经典的汇编例程---软件中断。
HotC51 发表于 2009-3-3 18:42 侃单片机 ←返回版面

3楼: main.c

#include "hottask51.h"

void TimerISR2() interrupt TF2_VECTOR using 3
{
    TF2 = 0;
    _nop_();
    _nop_();
    _nop_();
}

void UserISR0f() interrupt 0x0f using 3
{
    _nop_();
    _nop_();
    _nop_();
}

void UserISR1f() interrupt 0x1F using 3
{//所有非法软中断被拦截到此~~~
    _nop_();
    _nop_();
    _nop_();
}


void main()
{
    comFunction.Vtbl.STARTex();

    comFunction.Vtbl.START();
    comFunction.Vtbl.ISR(TF2_VECTOR);//软中断到Timer2Isr()
    comFunction.Vtbl.ISR(0x1f);//软中断0x1f
    comFunction.Vtbl.ISR(0x20);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0x30);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0x40);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0x50);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0x60);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0x70);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0x80);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0x90);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0xa0);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0xb0);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0xc0);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0xd0);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0xe0);//非法软中断被拦截到0x0f
    comFunction.Vtbl.ISR(0xff);//非法软中断被拦截到0x0f

    comFunction.Vtbl.TEST();
    comFunction.Vtbl.RESET();//软件复位
    while(1);//永远不能执行!!!
}


哈哈~~~估计有很多C高人一生用过的C51中断函数也不超过5个吧~~~
咱们“HotC51共产儿童团”的团员们以后都用满32个气晕他们~~~
现在来陶醉吧~~~
HotC51 发表于 2009-3-3 18:39 侃单片机 ←返回版面

楼主: 菜农正式发布“汇编数组”完整版前再晕大家一次(不晕做中队长)

/*---------------------------------------------
    HotTask51软中断函数
    void __HotASM_ISR__(unsigned char isrNum)
入口: R7   D4D3 中断向量组号  D2D1D0 中断向量号
出口: R7   isrNum
结果: 跳入对应的中断地址 isrNum * 8 + 3
-----------------------------------------------*/
HotASM (__HotASM_ISR__)//(unsigned char isrNum)
{//DPTR保存的是汇编数组函数的首地址__HotASM_ISR__
#define lable__HotASM_ISR__Error (-(size_CPL_C() + size_MOV_A() + size_JNC()))
    asm_CJNE_R7(0x20, size_CPL_C() +size_MOV_A() - 1),//mov a,R7
//lable__HotASM_ISR__Error:
    asm_CPL_C(),
    asm_MOV_A(0xEF),//mov a,0xef//
    asm_JNC(lable__HotASM_ISR__Error),//非法软中断号>(0~0x1f)
    asm_RL_A(),
    asm_RL_A(),
    asm_RL_A(),
    asm_ORL_A(0x03),
    asm_CLR_ACC_2(),
    asm_PUSH_ACC(),//压入中断地址低8位
    asm_CLR_A(),
    asm_PUSH_ACC(),//压入中断地址高8位
    asm_RET()//跳入对应的中断地址 isrNum * 8 + 3
};


菜农一句一句地“陶醉”:
在51中,中断向量一个有4组,每组8个,共32个。
每个中断向量地址的公式为: N*8 +3. 其中:N=0~31
在Regx52.h头文件里,有几个定义:
/*------------------------------------------------
Interrupt Vectors:
Interrupt Address = (Number * 8) + 3
------------------------------------------------*/
#define IE0_VECTOR 0  /* 0x03 External Interrupt 0 */
#define TF0_VECTOR 1  /* 0x0B Timer 0 */
#define IE1_VECTOR 2  /* 0x13 External Interrupt 1 */
#define TF1_VECTOR 3  /* 0x1B Timer 1 */
#define SIO_VECTOR 4  /* 0x23 Serial port */
#define TF2_VECTOR 5  /* 0x2B Timer 2 */
#define EX2_VECTOR 5  /* 0x2B External Interrupt 2 */

这些都可以由硬件触发的中断,其他都是无对应硬件中断而“保留的”软件中断。
他们必须由软件来触发即调用。
故必须编写一个“软中断函数”,这在ARM/DSP上都是芯片自带的,而51必须自己
编写,效率肯定不如硬件中断触发的高。
既然是软件中断,即为扩展中断,那么可能就会有不存在的软件中断。
这一般有2中:其一为越界的中断(>0x1f),界内但未声明的中断(以后团课讲)
HotTask51软中断函数例程有几个“精华”之处:
1.越界的中断(>0x1f)的判别:
入口向量号在R7寄存器中
      cjne r7,#0x20,next-1//实际跳入mov a,r7,这句是“反逆向技术”
//r7=0x20在此入口
err:
      cpl c//因为cjne语句用jnc判断即>=判断,故R7>=0x70时CY=0,此语句是欺骗敌人
      mov a,#0xef;上句实际应该setb c.主要为了通过下句的封锁。
next:
      jnc err//r7>0x20在此回跳!进行错误拦截!在菜农的OS中为狗任务
//以下做N*8+3运算
rl a
rl a
rl a//N*8
orl #0x03//N*8+3
clr acc.2//去掉非法中断向量中被拦截到0x0f后的错误,因为0xef会得到0x0f*8+7的错误
//下面是A人最经典的“跳转”,它令人陶醉地模拟了LCALL过程~~~
push acc//压入中断地址低8位
clr a//因为0x1f*8+3不可能超过0x100,即高位地址恒为0
push acc//压入中断地址高8位
ret//跳入对应的中断地址 isrNum * 8 + 3

到此,一个精妙的A人编程的思路讲解完毕。
最后注意“汇编数组”是动态编译指令,而汇编和嵌入汇编是静态编译指令。
要说“档次”肯定不能在一起PK的~~~
“汇编数组”若是在RAM运行的话,可以向PC的动态链接库DLL一样~~~
课毕:
HotC51@126.com   2009.3.3于菜地。
团部:http://group.ednchina.com/1623/
发表于 2009-6-12 13:23:30 | 显示全部楼层
我原来用汇编,现在很少用了,最多c和汇编结合起来用
发表于 2009-6-16 15:22:21 | 显示全部楼层
不懂啊只能看熱鬧
发表于 2010-7-15 22:44:53 | 显示全部楼层
不懂C 只懂一点汇编 凑个热闹
发表于 2010-7-28 21:17:48 | 显示全部楼层
好, 菜农加油啊
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们  -  服务条款  -  使用指南  -  站点地图  -  友情链接  -  联系我们
电子工程网 © 版权所有   京ICP备16069177号 | 京公网安备11010502021702
快速回复 返回顶部 返回列表