开课: 菜农“逆潮流”而创办的“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/
|
|
文章评论(0条评论)
登录后参与讨论