C51指針與A51匯編接口之間關(guān)系研究
最近在研究單片機(jī)C51對匯編的接口問題。char和int等都比較簡單,使用寄存器或固定地地址傳值都是可以的,具體可以參考keil的C51 user‘s guide。本篇短文主要重點討論一下A51下如何遵循C51的接口標(biāo)準(zhǔn)來實現(xiàn)C51的指針。主要原因是,現(xiàn)在用C51的人越來越多,大家都圖省事和方便。網(wǎng)上面有關(guān)A51的資料少得可憐,知道用匯編來實現(xiàn)代碼優(yōu)化的少之又少。本人是一直堅持用匯編寫東西的。在嵌入式領(lǐng)域,很多東西都與硬件有關(guān),多知道點底層?xùn)|西還是有好處。
使用工具主要為keil,在windows 7環(huán)境下。C51測試程序如下:
#include
unsignedpos;
bitabc(unsigned*pos){
*pos=100;
return0;
}
voidmain(){
while(1){
abc(&pos);}
這是測試用源程序,很明顯程序中使用了int型指針 pos。為了能夠生成匯編代碼,加入編譯器控制:
#pragmaSRC
#pragmaSMALL
#include
unsignedpos;
bitabc(unsigned*pos){
*pos=100;
return0;
}
voidmain(){
while(1){
abc(&pos);
}
}
注意,#pragma必需在文件的開始位置,否則會報錯。另外編譯器可能會跳“ EXCEPTION 0021H: PATH OR FILE NOT FOUND:main.obj”,沒有關(guān)系,我們的目標(biāo)是生成匯編的src文件。編譯后生成src如下:
;main.SRCgeneratedfrom:main.c
;COMPILERINVOKEDBY:
;D:ProgramFilesKeilC51BINC51.EXEmain.cBROWSEDEBUGOBJECTEXTENDTABS(2)
$NOMOD51
NAMEMAIN
;寄存器及內(nèi)存聲明
P0DATA080H
P1DATA090H
P2DATA0A0H
P3DATA0B0H
T0BIT0B0H.4
ACBIT0D0H.6
T1BIT0B0H.5
T2BIT090H.0
EABIT0A8H.7
IEDATA0A8H
EXF2BIT0C8H.6
RDBIT0B0H.7
ESBIT0A8H.4
IPDATA0B8H
RIBIT098H.0
INT0BIT0B0H.2
CYBIT0D0H.7
TIBIT098H.1
INT1BIT0B0H.3
RCAP2HDATA0CBH
PSBIT0B8H.4
SPDATA081H
T2EXBIT090H.1
OVBIT0D0H.2
RCAP2LDATA0CAH
C_T2BIT0C8H.1
WRBIT0B0H.6
RCLKBIT0C8H.5
TCLKBIT0C8H.4
SBUFDATA099H
PCONDATA087H
SCONDATA098H
TMODDATA089H
TCONDATA088H
IE0BIT088H.1
IE1BIT088H.3
BDATA0F0H
CP_RL2BIT0C8H.0
ACCDATA0E0H
ET0BIT0A8H.1
ET1BIT0A8H.3
TF0BIT088H.5
ET2BIT0A8H.5
TF1BIT088H.7
TF2BIT0C8H.7
RB8BIT098H.2
TH0DATA08CH
EX0BIT0A8H.0
IT0BIT088H.0
TH1DATA08DH
TB8BIT098H.3
EX1BIT0A8H.2
IT1BIT088H.2
TH2DATA0CDH
PBIT0D0H.0
SM0BIT098H.7
TL0DATA08AH
SM1BIT098H.6
TL1DATA08BH
SM2BIT098H.5
TL2DATA0CCH
PT0BIT0B8H.1
PT1BIT0B8H.3
RS0BIT0D0H.3
PT2BIT0B8H.5
TR0BIT088H.4
RS1BIT0D0H.4
TR1BIT088H.6
TR2BIT0C8H.2
PX0BIT0B8H.0
PX1BIT0B8H.2
DPHDATA083H
DPLDATA082H
EXEN2BIT0C8H.3
RENBIT098H.4
T2CONDATA0C8H
RXDBIT0B0H.0
TXDBIT0B0H.1
F0BIT0D0H.5
PSWDATA0D0H
?PR?_abc?MAINSEGMENTCODE
?PR?main?MAINSEGMENTCODE
?DT?MAINSEGMENTDATA
EXTRNCODE(?C?ISTPTR)
EXTRNCODE(?C_STARTUP)
PUBLICpos
PUBLICmain
PUBLIC_abc
RSEG?DT?MAIN
pos:DS2
;#pragmaSRC
;#pragmaSMALL
;#include
;
;unsignedpos;
;
;bitabc(unsigned*pos){
RSEG?PR?_abc?MAIN
_abc:
;SOURCELINE#7
;----Variable'pos?040'assignedtoRegister'R1/R2/R3'----
;*pos=100;
;SOURCELINE#8
;---------關(guān)鍵代碼-------------------
CLRA
MOVB,#064H
LCALL?C?ISTPTR;return0;
;SOURCELINE#9
CLRC;}
;SOURCELINE#10
?C0001:RET
;ENDOF_abc;
;voidmain(){
RSEG?PR?main?MAIN
main:
USING0;SOURCELINE#12
?C0002:;while(1){
;SOURCELINE#13
;abc(&pos);
;SOURCELINE#14
;---------關(guān)鍵代碼-------------------
MOVR3,#00H
MOVR2,#HIGH(pos)
MOVR1,#LOW(pos)
LCALL_abc;}
;SOURCELINE#15
SJMP?C0002
;ENDOFmainEND
對于A51的程序格式,這里不多解釋,有興趣可以自己去Keil官網(wǎng)學(xué)習(xí)。這里主要說一下指針的C51匯編接口。代碼中內(nèi)存和寄存器聲明,這個不重要,可以跳過。主要看標(biāo)記為關(guān)鍵代碼的部分。我們可以看到,在main中,在調(diào)用abc函數(shù)前,主程序初始了三個寄存器,分別是R1R2R3,代碼如下:
MOVR3,#00H
MOVR2,#HIGH(pos)
MOVR1,#LOW(pos)
這里得著重講一下。很明顯,這是寄存器傳值。依據(jù)C51規(guī)定,指針傳遞使用R1R2R3寄存器。其中,Mem type in R3, MSB in R2, LSB in R1。也就是說,R3表指針類型,R1為指針內(nèi)容低位,R2為內(nèi)容高位。從上面三個語句可以看出,程序?qū)㈩愋驮O(shè)為0,將pos地址高位傳給R2,低位給R1。接下來再看abc函數(shù)中的操作
CLR A