專注差異化嵌入式產(chǎn)品解決方案 給智能產(chǎn)品定制注入靈魂給予生命
提供開發(fā)工具、應(yīng)用測(cè)試 完善的開發(fā)代碼案例庫(kù)分享
從全面的產(chǎn)品導(dǎo)入到強(qiáng)大技術(shù)支援服務(wù) 全程貼心伴隨服務(wù),創(chuàng)造無(wú)限潛能!
提供新的芯片及解決方案,提升客戶產(chǎn)品競(jìng)爭(zhēng)力
提供最新的單片機(jī)資訊,行業(yè)消息以及公司新聞動(dòng)態(tài)
當(dāng)前,大多數(shù)單片機(jī)編程都是使用C語(yǔ)言完成的,如果不是C,則是另一種高級(jí)語(yǔ)言,如C++。但真實(shí)情況并非總是如此,在使用單片機(jī)的早期,所有代碼都是用匯編語(yǔ)言編寫的,在那時(shí)這是唯一的選擇。記得在那時(shí)候,內(nèi)存是極其有限的,因此必須非常嚴(yán)格地控制它的使用。而且除此之外,沒(méi)有可用的高級(jí)語(yǔ)言工具。
隨著計(jì)算機(jī)技術(shù)的發(fā)展,程序開發(fā)語(yǔ)言變得更多,單片機(jī)的功能也變得越來(lái)越強(qiáng)大(16位、32位,再到64位),價(jià)格變得更便宜,集成度更密集,應(yīng)用程序也變得更復(fù)雜。
那么,為什么現(xiàn)在還需要學(xué)會(huì)匯編語(yǔ)言?單片機(jī)開發(fā)人員應(yīng)具有閱讀匯編語(yǔ)言的能力,這其中有兩個(gè)原因。
首先,單片機(jī)中的代碼效率幾乎總是至關(guān)重要的?,F(xiàn)代編譯器通常在優(yōu)化代碼方面做得非常出色。但是,了解編譯器工作原理很重要。否則,開發(fā)人員在做調(diào)試時(shí)可能會(huì)造成混亂。
此外,編譯器也可能不夠完美的運(yùn)行,比如用C語(yǔ)言編寫代碼時(shí),不是以最清晰的方式編寫的,開發(fā)人員需要能夠理解出了什么問(wèn)題。檢查編譯器生成的代碼應(yīng)該是開發(fā)過(guò)程中的日常工作,這提供了機(jī)會(huì)來(lái)確保編譯器的輸出確實(shí)能夠達(dá)到程序員的預(yù)期。
有些開發(fā)人員需要能夠讀懂匯編的第二個(gè)原因是,在做“硬件開發(fā)”進(jìn)行編程時(shí),這是必不可少的。如今,驅(qū)動(dòng)程序不一定是100%匯編的,但是某些匯編語(yǔ)言的內(nèi)容幾乎是不可避免的。為了最有效地使用驅(qū)動(dòng)程序并進(jìn)行故障排除,必須能夠詳細(xì)了解驅(qū)動(dòng)程序在做什么。
為什么要學(xué)會(huì)編寫匯編語(yǔ)言
編寫匯編語(yǔ)言呢?如今,用匯編語(yǔ)言編寫整個(gè)應(yīng)用程序是非常少見的,至少大多數(shù)代碼都是用C編寫的。因此,C編程技能是單片機(jī)開發(fā)的關(guān)鍵要求。但是,一些開發(fā)人員需要掌握匯編語(yǔ)言編程。當(dāng)然,此技能是針對(duì)特定處理器的。但是,如果設(shè)計(jì)人員已經(jīng)掌握了一個(gè)CPU的匯編語(yǔ)言,則遷移到另一個(gè)CPU并不會(huì)太有挑戰(zhàn)性。
編寫匯編語(yǔ)言有兩個(gè)原因。第一個(gè)也是最重要的原因是實(shí)現(xiàn)一些用C語(yǔ)言無(wú)法表達(dá)的功能。一個(gè)簡(jiǎn)單的例子:禁用中斷功能。這可以通過(guò)編寫匯編語(yǔ)言子例程并像調(diào)用C函數(shù)一樣調(diào)用它來(lái)實(shí)現(xiàn)。為此,必須知道正在使用的C編譯器的調(diào)用/返回協(xié)議,但這通常很容易弄清楚。例如,你可以只看編譯器生成的代碼。
實(shí)現(xiàn)匯編語(yǔ)言代碼的另一種方法是,通常使用asm擴(kuò)展關(guān)鍵字將其內(nèi)聯(lián)插入C代碼中。當(dāng)需要單個(gè)或僅幾個(gè)匯編程序指令時(shí),這特別有意義,因?yàn)橄苏{(diào)用/返回開銷。此擴(kuò)展的實(shí)現(xiàn)因編譯器而異,但通常,asm語(yǔ)句采用以下形式:
asm(" trap #0");
通常,唯一需要用C語(yǔ)言表示的功能的地方是啟動(dòng)代碼和設(shè)備驅(qū)動(dòng)程序。嵌入式軟件應(yīng)用程序開發(fā)的這一部分涉及少量開發(fā)人員。因此,如上所述,對(duì)匯編編寫技能的需求僅限于一組選定的工程師。
一些開發(fā)人員認(rèn)為,他們需要知道如何編寫匯編語(yǔ)言,才能以比編譯器“更有效”的方式實(shí)現(xiàn)代碼。在極少數(shù)情況下,這可能是正確的。因?yàn)?,現(xiàn)在大多數(shù)現(xiàn)代編譯器在優(yōu)化和生成高效代碼方面,已經(jīng)做得非常出色。
這是一個(gè)例子:
#define ARRAYSIZE 4
char aaa[ARRAYSIZE];
int main()
{
int i;
for (i=0; i<ARRAYSIZE; i++)
aaa[i] = 0;
}
這看起來(lái)像一個(gè)簡(jiǎn)單的循環(huán),將數(shù)組的每個(gè)元素設(shè)置為零。如果你在激活了合理數(shù)量的優(yōu)化的情況下進(jìn)行編譯并嘗試調(diào)試代碼,你將得到一個(gè)奇怪的結(jié)果:它將直接跳入循環(huán)(即,表現(xiàn)得好像根本沒(méi)有循環(huán))。這是因?yàn)榫幾g器確定將零移動(dòng)32位到數(shù)組中比循環(huán)更有效。
結(jié)果代碼如下所示:
mov r3, #0
ldr r2, .L3
mov r0, r3
str r3, [r2]
bx lr
.L3:
.word .LANCHOR0
調(diào)整ARRAYSIZE的值會(huì)產(chǎn)生一些有趣的結(jié)果。將其設(shè)置為5可得到以下效果:
mov r3, #0
ldr r2, .L3
mov r0, r3
str r3, [r2]
strb r3, [r2, #4]
仍然沒(méi)有循環(huán)。使它繼續(xù)進(jìn)行下去是8:
然后,為64位CPU構(gòu)建此代碼將變得更好:
mov w0, 0
str xzr, [x1, #:lo12:.LANCHOR0]
因此,它可以繼續(xù)運(yùn)行。較大的數(shù)組大小會(huì)導(dǎo)致有效的循環(huán),或者可能只是調(diào)用諸如memset()之類的庫(kù)函數(shù),這是可以從匯編中調(diào)用的標(biāo)準(zhǔn)C庫(kù)函數(shù)。
最重要的是,匯編語(yǔ)言技能遠(yuǎn)不是過(guò)時(shí)的,單片機(jī)開發(fā)人員不應(yīng)該僅限于會(huì)閱讀匯編語(yǔ)言。