實時操作系統(tǒng)_第1頁
實時操作系統(tǒng)_第2頁
實時操作系統(tǒng)_第3頁
實時操作系統(tǒng)_第4頁
實時操作系統(tǒng)_第5頁
已閱讀5頁,還剩27頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、寫的不錯本人正在學習中有興趣的頂下我將繼續(xù)補發(fā)后面的 第一篇:函數(shù)的運行                                   第一篇:函數(shù)的運行      在一般的單片機系統(tǒng)中,是以前后臺的方式

2、(大循環(huán)+中斷)來處理數(shù)據(jù)和作出反應(yīng)的。      例子如下:            makefile的設(shè)定:運行WinAvr中的Mfile,設(shè)定如下      MCU Type: mega8      Optimization level: s      D

3、ebug format :AVR-COFF      C/C+ source file: 選譯要編譯的C文件  #include <avr/io.h>  void fun1(void)      unsigned char i=0;    while(1)          P

4、ORTB=i+;      PORTC=0x01<<(i%8);        int main(void)      fun1();        首先,提出一個問題:如果要調(diào)用一個函數(shù),真是只能以上面的方式進行嗎?      相信學習過C語言的各位會回答,No!我們還有一種方式,就是“用函數(shù)指針變量調(diào)用函數(shù)”,如果大家都和

5、我一樣,當初的教科書是譚浩強先生的C程序設(shè)計的話,請找回書的第9.5節(jié)。            例子:用函數(shù)指針變量調(diào)用函數(shù)  #include <avr/io.h>  void fun1(void)      unsigned char i=0;    while(1)         

6、; PORTB=i+;      PORTC=0x01<<(i%8);        void (*pfun)();  /指向函數(shù)的指針  int main(void)      pfun=fun1;    /    (*pfun)();    /運行指針所指向的函數(shù) 

7、;              第二種,是“把指向函數(shù)的指針變量作函數(shù)參數(shù)”          #include <avr/io.h>  void fun1(void)      unsigned char i=0;    while(1)    &

8、#160;     PORTB=i+;      PORTC=0x01<<(i%8);        void RunFun(void (*pfun)()  /獲得了要傳遞的函數(shù)的地址      (*pfun)();            

9、0;    /在RunFun中,運行指針所指向的函數(shù)    int main(void)       RunFun(fun1);            /將函數(shù)的指針作為變量傳遞              看到上面的兩種方式,很多人可能會說,“這的確

10、不錯”,但是這樣與我們想要的RTOS,有什么關(guān)系呢?各位請細心向下看。      以下是GCC對上面的代碼的編譯的情況:            對main()中的RunFun(fun1); 的編譯如下    ldi r24,lo8(pm(fun1)    ldi r25,hi8(pm(fun1)    rcall Ru

11、nFun        對void RunFun(void (*pfun)()的編譯如下                  /*void RunFun(void (*pfun)()*/             

12、    /*(*pfun)();*/  .LM6:    movw r30,r24    icall    ret      在調(diào)用void RunFun(void (*pfun)()的時候,的確可以把fun1的地址通過r24和r25傳遞給RunFun()。但是,RTOS如何才能有效地利用函數(shù)的地址呢?  -第二篇: 人工堆棧  

13、0;     在單片機的指令集中,一類指令是專門與堆棧和PC指針打道的,它們是      rcall   相對調(diào)用子程序指令      icall   間接調(diào)用子程序指令      ret     子程序返回指令      reti 

14、60;  中斷返回指令          對于ret和reti,它們都可以將堆棧棧頂?shù)膬蓚€字節(jié)被彈出來送入程序計數(shù)器PC中,一般用來從子程序或中斷中退出。其中reti還可以在退出中斷時,重開全局中斷使能。      有了這個基礎(chǔ),就可以建立我們的人工堆棧了。      例:  #include <avr/io.h>  void fun1

15、(void)      unsigned char i=0;    while(1)          PORTB=i+;      PORTC=0x01<<(i%8);        unsigned char Stack100; /建立一個100字節(jié)的人工堆棧  void&

16、#160;RunFunInNewStack(void (*pfun)(),unsigned char *pStack)      *pStack-=(unsigned int)pfun>>8;    /將函數(shù)的地址高位壓入堆棧,    *pStack-=(unsigned int)pfun;        /將函數(shù)的地址低位壓入堆棧, 

17、   SP=pStack;                            /將堆棧指針指向人工堆棧的棧頂    _asm_ _volatile_("RET nt");    /返回并

18、開中斷,開始運行fun1()    int main(void)       RunFunInNewStack(fun1,&Stack99);         RunFunInNewStack(),將指向函數(shù)的指針的值保存到一個unsigned  char的數(shù)組Stack中,作為人工堆棧。并且將棧頂?shù)臄?shù)值傳遞組堆棧指針SP,因此當用"ret"返回時,從SP中恢復到PC中的值,就變?yōu)榱酥赶騠un1()

19、的地址,開始運行fun1().      上面例子中在RunFunInNewStack()的最后一句嵌入了匯編代碼 "ret",實際上是可以去除的。因為在RunFunInNewStack()返回時,編譯器已經(jīng)會加上"ret"。我特意寫出來,是為了讓大家看到用"ret"作為返回后運行fun1()的過程。      第三篇:GCC中對寄存器的分配與使用        在很

20、多用于AVR的RTOS中,都會有任務(wù)調(diào)度時,插入以下的語句:            入棧:      _asm_ _volatile_("PUSH R0  nt");      _asm_ _volatile_("PUSH R1  nt");    

21、  .      _asm_ _volatile_("PUSH R31 nt");      出棧      _asm_ _volatile_("POP  R31 nt");      .      _asm_ 

22、;_volatile_("POP  R1  nt");      _asm_ _volatile_("POP  R0  nt");      通常大家都會認為,在任務(wù)調(diào)度開始時,當然要將所有的通用寄存器都保存,并且還應(yīng)該保存程序狀態(tài)寄存器SREG。然后再根據(jù)相反的次序,將新任務(wù)的寄存器的內(nèi)容恢復。       

23、;     但是,事實真的是這樣嗎?如果大家看過陳明計先生寫的small rots51,就會發(fā)現(xiàn),它所保存的通用寄存器不過是4組通用寄存器中的1組。            在Win AVR中的幫助文件 avr-libc Manual中的Related Pages中的Frequently Asked Questions,其實有一個問題是"What registers&#

24、160;are used by the C compiler?"  回答了編譯器所需要占用的寄存器。一般情況下,編譯器會先用到以下寄存器      1 Call-used registers (r18-r27, r30-r31): 調(diào)用函數(shù)時作為參數(shù)傳遞,也就是用得最多的寄存器。      2 Call-saved registers (

25、r2-r17, r28-r29): 調(diào)用函數(shù)時作為結(jié)果傳遞,當中的r28和r29可能會被作為指向堆棧上的變量的指針。            3 Fixed registers (r0, r1): 固定作用。r0用于存放臨時數(shù)據(jù),r1用于存放0。                  

26、還有另一個問題是"How to permanently bind a variable to a register?",是將變量綁定到通用寄存器的方法。而且我發(fā)現(xiàn),如果將某個寄存器定義為變量,編譯器就會不將該寄存器分配作其它用途。這對RTOS是很重要的。      在"Inline Asm"中的"C Names Used in Assembler Code&

27、quot;明確表示,如果將太多的通用寄存器定義為變量,剛在編譯的過程中,被定義的變量依然可能被編譯器占用。      大家可以比較以下兩個例子,看看編譯器產(chǎn)生的代碼:(在*.lst文件中)  第一個例子:沒有定義通用寄存器為變量  #include <avr/io.h>  unsigned char add(unsigned char b,unsigned char c,unsigned char d) 

28、      return b+c*d;    int main(void)      unsigned char a=0;    while(1)          a+;      PORTB=add(a,a,a);         &#

29、160; 在本例中,"add(a,a,a);"被編譯如下:     mov r20,r28     mov r22,r28     mov r24,r28     rcall add  第二個例子:定義通用寄存器為變量  #include <avr/io.h>  unsigned char add

30、(unsigned char b,unsigned char c,unsigned char d)       return b+c*d;    register unsigned char a asm("r20");  /將r20定義為 變量a    int main(void)     

31、0;  while(1)              a+;          PORTB=add(a,a,a);              在本例中,"add(a,a,a);"被編譯如下:     &

32、#160;  mov r22,r20      mov r24,r20      rcall add      當然,在上面兩個例子中,有部份代碼被編譯器優(yōu)化了。              通過反復測試,發(fā)現(xiàn)編譯器一般使用如下寄存器:    

33、0; 第1類寄存器,第2類寄存器的r28,r29,第3類寄存器      如在中斷函數(shù)中有調(diào)用基它函數(shù),剛會在進入中斷后,固定地將第1類寄存器和第3類寄存器入棧,在退出中斷又將它們出棧。  -未完待續(xù)-  _<armok01146983.gif> 2007-09-20,01:31:27 資料 郵件 編輯 刪除 【9樓】 cool_hawk 積分:53派別:等級:-來自:武漢第四篇:只有延時服務(wù)的協(xié)作式的內(nèi)核  Cooperative Multitasking  &

34、#160;  前后臺系統(tǒng),協(xié)作式內(nèi)核系統(tǒng),與占先式內(nèi)核系統(tǒng),有什么不同呢?     記得在21IC上看過這樣的比喻,“你(小工)在用廁所,經(jīng)理在外面排第一,老板在外面排第二。如果是前后臺,不管是誰,都必須按排隊的次序使用廁所;如果是協(xié)作式,那么可以等你用完廁所,老板就要比經(jīng)理先進入;如果是占先式,只要有更高級的人在外面等,那么廁所里無論是誰,都要第一時間讓出來,讓最高級別的人先用。”  #include <avr/io.h>  #include <avr/Interrupt.h

35、>  #include <avr/signal.h>  unsigned char Stack200;  register unsigned char OSRdyTbl          asm("r2");    /任務(wù)運行就緒表  register unsigned char OSTas

36、kRunningPrio asm("r3");    /正在運行的任務(wù)  #define OS_TASKS 3      /設(shè)定運行任務(wù)的數(shù)  struct TaskCtrBlock     /任務(wù)控制塊      unsigned int OSTaskStackTop;  /保存任務(wù)的堆

37、棧頂    unsigned int OSWaitTick;      /任務(wù)延時時鐘   TCBOS_TASKS+1;  /防止被編譯器占用  register unsigned char tempR4  asm("r4");  register unsigned char tempR5  asm("r5&

38、quot;);  register unsigned char tempR6  asm("r6");  register unsigned char tempR7  asm("r7");  register unsigned char tempR8  asm("r8");  register unsigned char 

39、;tempR9  asm("r9");  register unsigned char tempR10 asm("r10");  register unsigned char tempR11 asm("r11");  register unsigned char tempR12 asm("r12");  register uns

40、igned char tempR13 asm("r13");  register unsigned char tempR14 asm("r14");  register unsigned char tempR15 asm("r15");  register unsigned char tempR16 asm("r16");  r

41、egister unsigned char tempR17 asm("r17");  /建立任務(wù)  void OSTaskCreate(void (*Task)(void),unsigned char *Stack,unsigned char TaskID)      unsigned char i;    *Stack-=(unsigned int)Tas

42、k>>8;    /將任務(wù)的地址高位壓入堆棧    *Stack-=(unsigned int)Task;         /將任務(wù)的地址低位壓入堆棧    *Stack-=0x00;                 

43、    /R1 _zero_reg_                *Stack-=0x00;                     /R0 _tmp_reg_  &#

44、160; *Stack-=0x80;                      /SREG 在任務(wù)中,開啟全局中斷            for(i=0;i<14;i+)  /在 avr-libc 中的&

45、#160;FAQ中的 What registers are used by the C compiler?      *Stack-=i;                    /描述了寄存器的作用       

46、;   TCBTaskID.OSTaskStackTop=(unsigned int)Stack;  /將人工堆棧的棧頂,保存到堆棧的數(shù)組中      OSRdyTbl|=0x01<<TaskID;      /任務(wù)就緒表已經(jīng)準備好    /開始任務(wù)調(diào)度,從最低優(yōu)先級的任務(wù)的開始  void OSStartTask()     

47、;         OSTaskRunningPrio=OS_TASKS;    SP=TCBOS_TASKS.OSTaskStackTop+17;    _asm_ _volatile_(    "reti"       "nt"  );     

48、 /進行任務(wù)調(diào)度  void OSSched(void)   /  根據(jù)中斷時保存寄存器的次序入棧,模擬一次中斷后,入棧的情況      _asm_ _volatile_("PUSH _zero_reg_         nt");  /R1    _asm_ _volatile_("PU

49、SH _tmp_reg_          nt");  /R0    _asm_ _volatile_("IN   _tmp_reg_,_SREG_ nt");  /保存狀態(tài)寄存器SREG    _asm_ _volatile_("PUSH _tmp_reg_ 

50、60;        nt");    _asm_ _volatile_("CLR  _zero_reg_         nt");  /R0重新清零    _asm_ _volatile_("PUSH R18    

51、              nt");    _asm_ _volatile_("PUSH R19                  nt");    _asm_

52、0;_volatile_("PUSH R20                  nt");    _asm_ _volatile_("PUSH R21               

53、   nt");    _asm_ _volatile_("PUSH R22                  nt");    _asm_ _volatile_("PUSH R23     

54、0;            nt");    _asm_ _volatile_("PUSH R24                  nt");    _asm_ _volatil

55、e_("PUSH R25                  nt");    _asm_ _volatile_("PUSH R26                

56、0; nt");    _asm_ _volatile_("PUSH R27                  nt");    _asm_ _volatile_("PUSH R30       &#

57、160;          nt");        _asm_ _volatile_("PUSH R31                  nt");    _asm_

58、 _volatile_("PUSH R28                  nt");  /R28與R29用于建立在堆棧上的指針    _asm_ _volatile_("PUSH R29         &

59、#160;        nt");  /入棧完成    TCBOSTaskRunningPrio.OSTaskStackTop=SP;           /將正在運行的任務(wù)的堆棧底保存    unsigned char OSNextTaskID;    &

60、#160;                        /在現(xiàn)有堆棧上開設(shè)新的空間      for (OSNextTaskID = 0;           

61、0;                      /進行任務(wù)調(diào)度      OSNextTaskID < OS_TASKS && !(OSRdyTbl & (0x01<<OSNextTaskID);  

62、0;     OSNextTaskID+);      OSTaskRunningPrio = OSNextTaskID     cli();  /保護堆棧轉(zhuǎn)換    SP=TCBOSTaskRunningPrio.OSTaskStackTop;    sei();  /根據(jù)中斷時的出棧次序    _asm_ _vol

63、atile_("POP  R29                  nt");    _asm_ _volatile_("POP  R28              &#

64、160;   nt");    _asm_ _volatile_("POP  R31                  nt");    _asm_ _volatile_("POP  R30   &#

65、160;              nt");    _asm_ _volatile_("POP  R27                  nt");    

66、_asm_ _volatile_("POP  R26                  nt");    _asm_ _volatile_("POP  R25            

67、;      nt");        _asm_ _volatile_("POP  R24                  nt");    _asm_ _volatile_("

68、;POP  R23                  nt");    _asm_ _volatile_("POP  R22                &#

69、160; nt");    _asm_ _volatile_("POP  R21                  nt");    _asm_ _volatile_("POP  R20     &#

70、160;            nt");    _asm_ _volatile_("POP  R19                  nt");    _asm_ _

71、volatile_("POP  R18                  nt");    _asm_ _volatile_("POP  _tmp_reg_          nt"); /

72、SERG 出棧并恢復    _asm_ _volatile_("OUT  _SREG_,_tmp_reg_ nt");    _asm_ _volatile_("POP  _tmp_reg_          nt"); /R0 出棧    _asm_ _vo

73、latile_("POP  _zero_reg_         nt"); /R1 出棧    /中斷時出棧完成    -未完待續(xù)-  _<armok01146983.gif> 2007-09-20,16:47:51 資料 郵件 編輯 刪除 【10樓】 cool_hawk 積分:53派別:等級:-來自:武漢-接第三部-  void OSTimeDly(u

74、nsigned int ticks)      if(ticks)                             /當延時有效          OSRdyTb

75、l &= (0x01<<OSTaskRunningPrio);                TCBOSTaskRunningPrio.OSWaitTick=ticks;      OSSched();             &

76、#160;            /從新調(diào)度        void TCN0Init(void)    / 計時器0      TCCR0 = 0;    TCCR0 |= (1<<CS02);  / 256預分頻&

77、#160;   TIMSK |= (1<<TOIE0); / T0溢出中斷允許                      TCNT0 = 100;         / 置計數(shù)起始值  &#

78、160;       SIGNAL(SIG_OVERFLOW0)      unsigned char i;    for(i=0;i<OS_TASKS;i+)       /任務(wù)時鐘          if(TCBi.OSWaitTick)      

79、          TCBi.OSWaitTick-;        if(TCBi.OSWaitTick=0)     /當任務(wù)時鐘到時,必須是由定時器減時的才行                    OSR

80、dyTbl |= (0x01<<i);     /使任務(wù)在就緒表中置位                          TCNT0=100;    void Task0()      unsigned int

81、0;j=0;    while(1)                      PORTB=j+;      OSTimeDly(2);        void Task1()      unsigned in

82、t j=0;    while(1)          PORTC=j+;      OSTimeDly(4);        void Task2()      unsigned int j=0;    while(1)      

83、60;   PORTD=j+;          OSTimeDly(8);        void TaskScheduler()        while(1)                  

84、 OSSched();      /反復進行調(diào)度        int main(void)          TCN0Init();    OSRdyTbl=0;    OSTaskRunningPrio=0;    OSTaskCreate(Task0,&Stack49,0); 

85、;   OSTaskCreate(Task1,&Stack99,1);    OSTaskCreate(Task2,&Stack149,2);    OSTaskCreate(TaskScheduler,&Stack199,OS_TASKS);    OSStartTask();       在上面的例子中,一切變得很簡單,三個正在運行的主任務(wù),都通過延時服務(wù),主動放棄對CPU的控制權(quán)。   

86、  在時間中斷中,對各個任務(wù)的的延時進行計時,如果某個任務(wù)的延時結(jié)束,將任務(wù)重新在就緒表中置位。     最低級的系統(tǒng)任務(wù)TaskScheduler(),在三個主任務(wù)在放棄對CPU的控制權(quán)后開始不斷地進行調(diào)度。如果某個任務(wù)在就緒表中置位,通過調(diào)度,進入最高級別的任務(wù)中繼續(xù)運行。_<armok01146983.gif> 2007-09-20,16:49:20 資料 郵件 編輯 刪除 【11樓】 cool_hawk 積分:53派別:等級:-來自:武漢第五篇: 完善的協(xié)作式的內(nèi)核    &

87、#160;  現(xiàn)在為上面的協(xié)作式內(nèi)核添加一些OS中所必須的服務(wù):     1  掛起和重新運行任務(wù)     2  信號量(在必要時候,可以擴展成郵箱和信息隊列)     3  延時  #include <avr/io.h>  #include <avr/Interrupt.h>  #include <avr/

88、signal.h>  unsigned char Stack400;  register unsigned char OSRdyTbl          asm("r2");    /任務(wù)運行就緒表  register unsigned char OSTaskRunningPrio asm("r3&qu

89、ot;);    /正在運行的任務(wù)  #define OS_TASKS 3                    /設(shè)定運行任務(wù)的數(shù)量  struct TaskCtrBlock      unsigned int OSTaskStackTop;

90、60; /保存任務(wù)的堆棧頂    unsigned int OSWaitTick;      /任務(wù)延時時鐘   TCBOS_TASKS+1;  /防止被編譯器占用  register unsigned char tempR4  asm("r4");  register unsigned char tempR5 

91、60;asm("r5");  register unsigned char tempR6  asm("r6");  register unsigned char tempR7  asm("r7");  register unsigned char tempR8  asm("r8");  register unsigne

92、d char tempR9  asm("r9");  register unsigned char tempR10 asm("r10");  register unsigned char tempR11 asm("r11");  register unsigned char tempR12 asm("r12");  r

93、egister unsigned char tempR13 asm("r13");  register unsigned char tempR14 asm("r14");  register unsigned char tempR15 asm("r15");  register unsigned char tempR16 asm("r16

94、");  register unsigned char tempR17 asm("r17");  /建立任務(wù)  void OSTaskCreate(void (*Task)(void),unsigned char *Stack,unsigned char TaskID)      unsigned char i;     

95、60;                    *Stack-=(unsigned int)Task>>8;    /將任務(wù)的地址高位壓入堆棧,    *Stack-=(unsigned int)Task;        

96、0;/將任務(wù)的地址低位壓入堆棧,          *Stack-=0x00;                     /R1 _zero_reg_            

97、0;   *Stack-=0x00;                     /R0 _tmp_reg_    *Stack-=0x80;                

98、                          /SREG 在任務(wù)中,開啟全局中斷            for(i=0;i<14;i+)  /在 avr-libc 中的 

99、;FAQ中的 What registers are used by the C compiler?      *Stack-=i;                    /描述了寄存器的作用       

100、60;TCBTaskID.OSTaskStackTop=(unsigned int)Stack;    /將人工堆棧的棧頂,保存到堆棧的數(shù)組中    OSRdyTbl|=0x01<<TaskID;      /任務(wù)就緒表已經(jīng)準備好    /開始任務(wù)調(diào)度,從最低優(yōu)先級的任務(wù)的開始  void OSStartTask()       

101、60;      OSTaskRunningPrio=OS_TASKS;    SP=TCBOS_TASKS.OSTaskStackTop+17;    _asm_ _volatile_(    "reti"       "nt"  );      /進行任務(wù)調(diào)度  v

102、oid OSSched(void)   /  根據(jù)中斷時保存寄存器的次序入棧,模擬一次中斷后,入棧的情況      _asm_ _volatile_("PUSH _zero_reg_         nt");  /R1    _asm_ _volatile_("PUSH _tmp_reg

103、_          nt");  /R0      _asm_ _volatile_("IN   _tmp_reg_,_SREG_ nt");  /保存狀態(tài)寄存器SREG    _asm_ _volatile_("PUSH _tmp_reg_  &

104、#160;       nt");    _asm_ _volatile_("CLR  _zero_reg_         nt");  /R0重新清零    _asm_ _volatile_("PUSH R18    

105、0;             nt");    _asm_ _volatile_("PUSH R19                  nt");    _asm_ _v

106、olatile_("PUSH R20                  nt");    _asm_ _volatile_("PUSH R21               

107、0;  nt");    _asm_ _volatile_("PUSH R22                  nt");    _asm_ _volatile_("PUSH R23      &#

108、160;           nt");    _asm_ _volatile_("PUSH R24                  nt");    _asm_ _volatile_(&

109、quot;PUSH R25                  nt");    _asm_ _volatile_("PUSH R26                 &#

110、160;nt");    _asm_ _volatile_("PUSH R27                  nt");    _asm_ _volatile_("PUSH R30        

111、          nt");        _asm_ _volatile_("PUSH R31                  nt");    _asm_

112、0;_volatile_("PUSH R28                  nt");  /R28與R29用于建立在堆棧上的指針    _asm_ _volatile_("PUSH R29          

113、;        nt");  /入棧完成          TCBOSTaskRunningPrio.OSTaskStackTop=SP;     /將正在運行的任務(wù)的堆棧底保存    unsigned char OSNextTaskID;     

114、0;     /在現(xiàn)有堆棧上開設(shè)新的空間      for (OSNextTaskID = 0;                 /進行任務(wù)調(diào)度      OSNextTaskID < OS_TASKS &

115、& !(OSRdyTbl & (0x01<<OSNextTaskID);        OSNextTaskID+);      OSTaskRunningPrio = OSNextTaskID     cli();  /保護堆棧轉(zhuǎn)換    SP=TCBOSTaskRunningPrio.OSTaskStack

116、Top;    sei();      /根據(jù)中斷時的出棧次序        _asm_ _volatile_("POP  R29                  nt");    _as

117、m_ _volatile_("POP  R28                  nt");      _asm_ _volatile_("POP  R31          &#

118、160;       nt");    _asm_ _volatile_("POP  R30                  nt");    _asm_ _volatile_("POP  

119、;R27                  nt");    _asm_ _volatile_("POP  R26                  nt&qu

120、ot;);    _asm_ _volatile_("POP  R25                  nt");    _asm_ _volatile_("POP  R24        

121、;          nt");    _asm_ _volatile_("POP  R23                  nt");    _asm_ _volatile_("

122、;POP  R22                  nt");    _asm_ _volatile_("POP  R21                &#

123、160; nt");    _asm_ _volatile_("POP  R20                  nt");    _asm_ _volatile_("POP  R19     &#

124、160;            nt");    _asm_ _volatile_("POP  R18                  nt");    _asm_ _

125、volatile_("POP  _tmp_reg_          nt");  /SERG 出棧并恢復    _asm_ _volatile_("OUT  _SREG_,_tmp_reg_ nt");    _asm_ _volatile_("POP  _tmp_reg_   

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論