|
HotC51 發(fā)表于 2009-3-3 22:28 裸奔式實時操作系統(tǒng)HotTask51 ←返回版面 |
樓主: HotC51共產兒童團第十二課:匯編是藝術是享受,而非技巧可以攀比 |
開課:
菜農“逆潮流”而創(chuàng)辦的“HotC51共產兒童團”就是要讓更多的“紅色腦漿”
流淌在地球的各個角落,讓更多的“團員”和那些自認為“老大”的PK~~~
菜農就是要培養(yǎng)千千萬萬的“混小子”、“二愣子”和“天不怕、地不怕”的
“小菜農”~~~
只要他舉起紅旗,他就不怕任何地球人~~~
A人(擅長匯編之人)和C人(擅長高級語言之人)本無貧賤之分,更無高低之別。
就菜農個人而言,可謂學盡了天下的各種計算機語言~~~至少在MCU這個
圈子里俺可以這么說~~~
至少俺敢說單片機并非俺之最強項~~~
但俺所編的每一句匯編語言自己都要“審美”一遍,直到“陶醉”為止~~
這是很多人不能理解的~~~
若有人說俺匯編“檔次地”,俺可以“高點”,但俺絕不會單獨用C語言!
為什么???若C語言是“最高境界”,那么Delphi、BC、CVI、VC、VB
Java、C#、VB.Net等為什么要再“造”呢???
匯編是一切語言之母!!!不會匯編的C語言“高手”永遠都是自己封的
“高手”~~~編譯器的任何小bug都會雷翻他~~~
高級語言一個問題可能有多種編程方法,但匯編可能又有一個唯一之解。
有時是無法“PK”的~~~
舉例:
天雨粟 發(fā)表于 2008-10-19 14:59 侃單片機 ←返回版面 舉報該貼 |
一個精巧的兩字節(jié)除法子程序
條件: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,現在我們將其看作一個普通的單字節(jié)數,則相當于將其除以了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 發(fā)表于 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”~~~
在菜農發(fā)布近6000多行的“匯編數組”前,讓俺自己先“陶醉”一下~~~
至于什么是“匯編數組”?它和匯編語言、嵌入匯編、腳本語言等有何區(qū)別?
“匯編數組”的過去、現在和將來,這要在團課中做專題才能說清楚。
先陶醉“匯編數組”Demo包里的一個經典的匯編例程---軟件中斷。
HotC51 發(fā)表于 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);//永遠不能執(zhí)行!!!
}
|
|
哈哈~~~估計有很多C高人一生用過的C51中斷函數也不超過5個吧~~~
咱們“HotC51共產兒童團”的團員們以后都用滿32個氣暈他們~~~
現在來陶醉吧~~~
HotC51 發(fā)表于 2009-3-3 18:39 侃單片機 ←返回版面 |
樓主: 菜農正式發(fā)布“匯編數組”完整版前再暈大家一次(不暈做中隊長) |
/*---------------------------------------------
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 */
這些都可以由硬件觸發(fā)的中斷,其他都是無對應硬件中斷而“保留的”軟件中斷。
他們必須由軟件來觸發(fā)即調用。
故必須編寫一個“軟中斷函數”,這在ARM/DSP上都是芯片自帶的,而51必須自己
編寫,效率肯定不如硬件中斷觸發(fā)的高。
既然是軟件中斷,即為擴展中斷,那么可能就會有不存在的軟件中斷。
這一般有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人編程的思路講解完畢。
最后注意“匯編數組”是動態(tài)編譯指令,而匯編和嵌入匯編是靜態(tài)編譯指令。
要說“檔次”肯定不能在一起PK的~~~
“匯編數組”若是在RAM運行的話,可以向PC的動態(tài)鏈接庫DLL一樣~~~
課畢:
HotC51@126.com 2009.3.3于菜地。
團部:http://group.ednchina.com/1623/ |
|
|
|