娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

歷史上的今天

今天是:2024年09月08日(星期日)

2018年09月08日 | STM8匯編代碼分析

發布者:錢老李 來源: eefocus關鍵字:STM8  匯編代碼 手機看文章 掃描二維碼
隨時隨地手機看文章

使用STVD建立完匯編工程項目之后(具本建立方法可以看我的另一篇博文http://blog.csdn.net/u010093140/article/details/49983397),可以看到這個目錄結構(以STM8S105C6芯片為例) 
這里寫圖片描述 
其中.asm文件是匯編代碼的源文件,.inc文件是包含文件,類似于C語言當在的.c文件和.h文件。接下來讓我們來分析一下這三個文件。(分析匯編代碼最好也要對STM8單片機的啟動流程有所了解,可以看我的另一篇博文http://blog.csdn.net/u010093140/article/details/49982879) 
首先是看mapping.inc文件:

    ;------------------------------------------------------

    ; SEGMENT MAPPING FILE AUTOMATICALLY GENERATED BY STVD

    ; SHOULD NOT BE MANUALLY MODIFIED.

    ; CHANGES WILL BE LOST WHEN FILE IS REGENERATED.

    ;------------------------------------------------------

    #define RAM0 1

    #define ram0_segment_start 0

    #define ram0_segment_end FF

    #define RAM1 1

    #define ram1_segment_start 100

    #define ram1_segment_end 5FF

    #define stack_segment_start 600

    #define stack_segment_end 7FF


這一段代碼應該不難看懂,就是定義了一些常量。需要注意的是,分號”;”是匯編代碼中用于寫注釋的符號。所以分號后面跟的是注釋。 

接下來就是看一下mapping.asm文件


stm8/

    ;------------------------------------------------------

    ; SEGMENT MAPPING FILE AUTOMATICALLY GENERATED BY STVD

    ; SHOULD NOT BE MANUALLY MODIFIED.

    ; CHANGES WILL BE LOST WHEN FILE IS REGENERATED.

    ;------------------------------------------------------

    #include "mapping.inc"


    BYTES           ; The following addresses are 8 bits long

    segment byte at ram0_segment_start-ram0_segment_end 'ram0'


    WORDS           ; The following addresses are 16 bits long

    segment byte at ram1_segment_start-ram1_segment_end 'ram1'


    WORDS           ; The following addresses are 16 bits long

    segment byte at stack_segment_start-stack_segment_end 'stack'


    WORDS           ; The following addresses are 16 bits long

    segment byte at 4000-43FF 'eeprom'


    WORDS           ; The following addresses are 16 bits long

    segment byte at 8080-FFFF 'rom'


    WORDS           ; The following addresses are 16 bits long

    segment byte at 8000-807F 'vectit'


        END


上面的代碼第一行以stm8/開頭,很多人不知道為什么要這樣子。其實是因為我們所用的匯編連接器Assembler Linker不僅支持STM8匯編代碼而且還支持ST公司的另一款芯片ST7的匯編代碼,如果你用的是ST7芯片的話,就要以st7/開頭了。結論就是使用stm8/開頭是為了表明代碼的目標芯片是stm8芯片。 

分號后面的注釋不算入代碼里面,剩下來的代碼就定義了芯片上的內存段,比如說segment byte at ram0_segment_start-ram0_segment_end ‘ram0’的意思就是,從ram0_segment_start到ram0_segment_end的這一段內存起個名字叫做“ram0”,segment byte at ram1_segment_start-ram1_segment_end ‘ram1’的意思就是,從ram1_segment_start到ram1_segment_end的這一段內存起個名字叫做“ram1”,其它的也是一樣的道理。那么,你也會注意到,每一句這樣的代碼之前都有一句”Bytes”或者”Words”,這是什么意思呢?按代碼注釋里的意思就是,Bytes代表內存段里內存的地址是8位的,而Words代表內存段里內存的地址是16位的。通過查Assembler Linker PDF,發現Bytes和Words用于指定跟在它下面的的標號的默認長度,什么意思?可以看以下的例子:


   Bytes

label1 

;下面這條語句是編譯通過的。因為A是8位的,label1也是8位的。

   LD A,#label1  

   Words

 label2

 ;下面這條語句是編譯不通過的。因為A是8位的,而label2是16位的,通過賦值給A。

   LD A,#label2  

   Words

 label3.b

 ;而下面這條語句是可以編譯通過的,因為我顯式地指定了label3為byte的長度(.b),是8位的。


我們再看回到mapping.asm那個文件,mapping文件里所有的指令都是偽指令,并不產生實際的可執行代碼,那么使用了bytes,words是什么作用呢?從上面bytes和words的作用來看,我個人認為它們在mapping.asm里不起作用,只起到說明的作用,相當于注釋。當然如有錯誤,歡迎大家指出^_^。所以mapping的作用就是給芯片的存儲空間劃分區域并命名。我們后面我們寫的代碼可以通過這個名字,指定存到該名字所代表的存儲區域下。比如說ram0區,ram1區,rom區等。 

接下來再來看main.asm,這個代碼有一些長了,先貼出來吧。


stm8/


    #include "mapping.inc"


    segment 'rom'

main.l

    ; initialize SP

    ldw X,#stack_end

    ldw SP,X


    #ifdef RAM0 

    ; clear RAM0

ram0_start.b EQU $ram0_segment_start

ram0_end.b EQU $ram0_segment_end

    ldw X,#ram0_start

clear_ram0.l

    clr (X)

    incw X

    cpw X,#ram0_end 

    jrule clear_ram0

    #endif


    #ifdef RAM1

    ; clear RAM1

ram1_start.w EQU $ram1_segment_start

ram1_end.w EQU $ram1_segment_end   

    ldw X,#ram1_start

clear_ram1.l

    clr (X)

    incw X

    cpw X,#ram1_end 

    jrule clear_ram1

    #endif


    ; clear stack

stack_start.w EQU $stack_segment_start

stack_end.w EQU $stack_segment_end

    ldw X,#stack_start

clear_stack.l

    clr (X)

    incw X

    cpw X,#stack_end    

    jrule clear_stack


infinite_loop.l

    jra infinite_loop


    interrupt NonHandledInterrupt

NonHandledInterrupt.l

    iret


    segment 'vectit'

    dc.l {$82000000+main}                                  ; reset

    dc.l {$82000000+NonHandledInterrupt}   ; trap

    dc.l {$82000000+NonHandledInterrupt}   ; irq0

    dc.l {$82000000+NonHandledInterrupt}   ; irq1

    dc.l {$82000000+NonHandledInterrupt}   ; irq2

    dc.l {$82000000+NonHandledInterrupt}   ; irq3

    dc.l {$82000000+NonHandledInterrupt}   ; irq4

    dc.l {$82000000+NonHandledInterrupt}   ; irq5

    dc.l {$82000000+NonHandledInterrupt}   ; irq6

    dc.l {$82000000+NonHandledInterrupt}   ; irq7

    dc.l {$82000000+NonHandledInterrupt}   ; irq8

    dc.l {$82000000+NonHandledInterrupt}   ; irq9

    dc.l {$82000000+NonHandledInterrupt}   ; irq10

    dc.l {$82000000+NonHandledInterrupt}   ; irq11

    dc.l {$82000000+NonHandledInterrupt}   ; irq12

    dc.l {$82000000+NonHandledInterrupt}   ; irq13

    dc.l {$82000000+NonHandledInterrupt}   ; irq14

    dc.l {$82000000+NonHandledInterrupt}   ; irq15

    dc.l {$82000000+NonHandledInterrupt}   ; irq16

    dc.l {$82000000+NonHandledInterrupt}   ; irq17

    dc.l {$82000000+NonHandledInterrupt}   ; irq18

    dc.l {$82000000+NonHandledInterrupt}   ; irq19

    dc.l {$82000000+NonHandledInterrupt}   ; irq20

    dc.l {$82000000+NonHandledInterrupt}   ; irq21

    dc.l {$82000000+NonHandledInterrupt}   ; irq22

    dc.l {$82000000+NonHandledInterrupt}   ; irq23

    dc.l {$82000000+NonHandledInterrupt}   ; irq24

    dc.l {$82000000+NonHandledInterrupt}   ; irq25

    dc.l {$82000000+NonHandledInterrupt}   ; irq26

    dc.l {$82000000+NonHandledInterrupt}   ; irq27

    dc.l {$82000000+NonHandledInterrupt}   ; irq28

    dc.l {$82000000+NonHandledInterrupt}   ; irq29


    end

上面的代碼看得明白嗎?哈哈。首先先給一個內存圖,有用到內存的地方可以回來看這個圖比較直觀。 
這里寫圖片描述

下面采用一行一行注釋的方式給大家講解(發表完之后發現注釋跑到屏幕外面了,把代碼欄下面的橫條向右拉就可以看到了。)。

;就如之前所說的,stm8指明以下的代碼是用于stm8芯片的,而不是st7芯片。

stm8/

;以下代碼是把mapping.inc文件包含進來的意思,這樣就可以直接用mapping.inc里面定義的常量了。

    #include "mapping.inc"

;以下代碼是指明往后的代碼都是放在rom存儲區域的意思,就如mapping.asm里所表明的,rom的地址范圍是8080-FFFF。

    segment 'rom'

;main.l是一個標號,寫在最左邊的一行,標號不產生實際的指令。標號的作用時給一個地址進行命名,然后其它指令就可以使用這個名字來使用這個地址了。比如說下面的main.l的地址就跟下面的ldw X,#stack_end所在的地址相等的。而.l的意思是該地址是3個字節24位的。

main.l

    ; initialize SP

    ;下面這一句的意思是把stack_end的值加載到X寄存器,#是立即數的意思。ldw的w是word的意思,表明是16位是加載指令。也有8位的加載指令,為ld.

    ldw X,#stack_end

    ;下面這一句的意思是把寄存器X的值賦給SP寄存器的意思,SP是棧指針,上下兩句的作用是讓SP指向棧頂。(STM8的棧結構是自頂向下的,棧頂的值就是stack_end,棧中地址值最大的那個數)。

    ldw SP,X

    ;偽指令,如果定義了RAM0就編譯其后的代碼,顯然這個判斷是為真的,因為在mapping.inc中已經定義了RAM0和RAM1.

    #ifdef RAM0 

    ; clear RAM0

;偽指令,定義標號ram0_start.b的值為ram0_segment_start的值,$是16進制數的意思,ram0_end.b同理。這種直接賦值的方式跟前面的main.l標號有所不同,下面這種是賦絕對地址,而main.l是賦相對地址。

ram0_start.b EQU $ram0_segment_start

ram0_end.b EQU $ram0_segment_end

    ;加載ram0_start的值到X

    ldw X,#ram0_start

;定義標號clear_ram0.l

clear_ram0.l

        ;clr是清除的意思,()是間接尋址的意思,clr(X)就是以X的值為地址,清除該地址上的值的意思。

    clr (X)

    ;X加1,incw有個w是因為X是16位的。

    incw X

    ;cpw是compare的意思,比較X和ram0_end的值,w的意思跟上面講的意思一樣。

    cpw X,#ram0_end 

    ;jrule(jump relative unsigned less than)這個意思明白了吧?就是如果小于就跳轉到clear_ram0標號地址的意思。

    jrule clear_ram0

    ;跟前面的#ifdef RAM0相對應。

    #endif

    ;這個面RAM1的操作跟以上對RAM0的操作一樣。整一段代碼的作用就是清零存儲區的作用。

    #ifdef RAM1

    ; clear RAM1

ram1_start.w EQU $ram1_segment_start

ram1_end.w EQU $ram1_segment_end   

    ldw X,#ram1_start

clear_ram1.l

    clr (X)

    incw X

    cpw X,#ram1_end 

    jrule clear_ram1

    #endif

    ;下面初始化棧區的操作也是跟前面對RAM0的操作一樣的。

    ; clear stack

stack_start.w EQU $stack_segment_start

stack_end.w EQU $stack_segment_end

    ldw X,#stack_start

clear_stack.l

    clr (X)

    incw X

    cpw X,#stack_end    

    jrule clear_stack

;下面定義了infinite_loop.l標號。

infinite_loop.l

    ;jra是相對跳轉的意思,跳轉到上面那個標號。所以這是一個無限循環,代碼到這里就是不斷地執行jra infinite_loop這條語句,相當于C語言中的while(1);

    jra infinite_loop

    ;interrupt是偽指令,把NoHandleInterrupt說明成是用于中斷的標號。

    interrupt NonHandledInterrupt

;定義NonHandledInterrupt.l標號

NonHandledInterrupt.l

    ;iret是中斷返回的意思。而ret是函數返回的意思。

    iret

;segment 'vectic'指令其下面的代碼是放在vectit存儲區的,即8000-807F所在的區域。

    segment 'vectit'

    ;dc.l的意思是申請一段四個字節的空間,后面加的數字就是賦予這個空間的值。什么?前面的l的用法都是3個字節的,這里dc.l里的l就成4個字節了?沒錯,就是這樣子的,有點亂,這也是有點費解的地方,我也不明白為啥不改另一個說法。{}的用法是在編譯時運算里面的語句,而不是在代碼里演算。比如說{1+1}會在編譯后變成2.

    ;下面的所有dc.l其實就是定義了一個中斷向量表,分別對應于不同的中斷,比如第一個就是復位中斷,芯片復位后會在這里找到main標號,然后程序跳轉到main里去。當然如果你對main不爽,也可以改成其它的,比如說example.但是這個改了之后,最前面的main.l標號也要相應的改成example.l.就相當于這個程序里面“沒有”main函數了。是不是很神奇呢?呃。下面有注釋了trap,irq0,irq2等這些,其實就是對應了不同的中斷,比如說I2C的中斷就對應了其中的irq19,所以當你寫好I2C的中斷服務程序后,需要把它的標號填寫到irq19那一句中,可以參考dc.l{$82000000+main}這句,如果你把I2C中斷服務程序的標號定義I2C_Interrupt.l則irq19中那一句要改成dc.l{$82000000+I2C_Interrupt}.最后一個問題,中斷后單片機會跳到中斷標號里去執行這點沒問題了,那下面$82000000中的82是什么意思呢?(現在想找之前看到的資料已經找不到了。。。。不過我還記得那個意思)82是STM8指令集中的一個操作碼(匯編指令是由操作碼和操作數組成的),我想用在中斷這里的意思就是表面這個地址標號是中斷服務程序地址標號的意思吧,芯片可以識別82這個操作碼,從而區別對待。

    dc.l{$82000000+main}                                   ; reset

    dc.l {$82000000+NonHandledInterrupt}   ; trap

    dc.l {$82000000+NonHandledInterrupt}   ; irq0

    dc.l {$82000000+NonHandledInterrupt}   ; irq1

    dc.l {$82000000+NonHandledInterrupt}   ; irq2

    dc.l {$82000000+NonHandledInterrupt}   ; irq3

    dc.l {$82000000+NonHandledInterrupt}   ; irq4

    dc.l {$82000000+NonHandledInterrupt}   ; irq5

    dc.l {$82000000+NonHandledInterrupt}   ; irq6

    dc.l {$82000000+NonHandledInterrupt}   ; irq7

    dc.l {$82000000+NonHandledInterrupt}   ; irq8

    dc.l {$82000000+NonHandledInterrupt}   ; irq9

    dc.l {$82000000+NonHandledInterrupt}   ; irq10

    dc.l {$82000000+NonHandledInterrupt}   ; irq11

    dc.l {$82000000+NonHandledInterrupt}   ; irq12

    dc.l {$82000000+NonHandledInterrupt}   ; irq13

    dc.l {$82000000+NonHandledInterrupt}   ; irq14

    dc.l {$82000000+NonHandledInterrupt}   ; irq15

    dc.l {$82000000+NonHandledInterrupt}   ; irq16

    dc.l {$82000000+NonHandledInterrupt}   ; irq17

    dc.l {$82000000+NonHandledInterrupt}   ; irq18

    dc.l {$82000000+NonHandledInterrupt}   ; irq19

    dc.l {$82000000+NonHandledInterrupt}   ; irq20

    dc.l {$82000000+NonHandledInterrupt}   ; irq21

    dc.l {$82000000+NonHandledInterrupt}   ; irq22

    dc.l {$82000000+NonHandledInterrupt}   ; irq23

    dc.l {$82000000+NonHandledInterrupt}   ; irq24

    dc.l {$82000000+NonHandledInterrupt}   ; irq25

    dc.l {$82000000+NonHandledInterrupt}   ; irq26

    dc.l {$82000000+NonHandledInterrupt}   ; irq27

    dc.l {$82000000+NonHandledInterrupt}   ; irq28

    dc.l {$82000000+NonHandledInterrupt}   ; irq29


    end


好了,本文就講完了,其實想盡量講得明白一些,但發現涉及到的方面太多了,展開來講的話,篇幅會很大,也會顯得很啰嗦了。比如說匯編指令我就沒有介紹過,匯編連接器所支持的偽指令有哪些我也沒有講到,想講,但可能花的篇幅比本文還長。。后續有時間,覺得有必要再進行補充吧。最近也比較忙。當然最重要的一點是,沒人看。沒人看。沒人看啊。



關鍵字:STM8  匯編代碼 引用地址:STM8匯編代碼分析

上一篇:學習STM8 關于數據類型的定義心得
下一篇:stm8單片機內部存儲EEPROM字節讀寫實例解析

推薦閱讀

百度Apollo?近一個月來消息頻頻。?9月5日,比亞迪全球開發者大會上,張亞勤與王傳福再次同臺“跨界”對話,并宣布了百度與比亞迪的一系列新的合作進展:在地圖方面,百度地圖汽車版將覆蓋比亞迪全系車型;在自動駕駛方面,百度將為比亞迪L3級別智能駕駛提供完整解決方案,雙方計劃在3年內實現自動駕駛車輛量產。同時,第一批開放版的秦Pro已被百度預定作...
(文章來源:中科羅伯特機器人學院) 根據國際機器人聯合會的數據,雖然2018年全球工業機器人銷量再創新高,達到了38.4萬臺,但增速緩慢,從前幾年的兩位數增長降到了個位數。去年我國工業機器人消費總量為13.5萬臺,雖然還是全球最大的消費市場,但比2017年下降了3.75%。 工信部副部長辛國斌分析,雖然原因是多方面的,包括國際貿易環境惡化、全球經...
我是稀里糊涂的走上了嵌入式開發的道路,回想起來,多虧了身邊的幾位朋友,是在與他們的閑侃中慢慢的走上了這條道路:從最早的電路設計,PCB打板,電路調試,模擬仿真,單片機開發到后來的ARM開發,回想起來,心里也是誠惶誠恐,如履薄冰。我開始做電子是用的AVR單片機,從I/O、按鍵…到內存、外設玩了一通。工作之后,才開始玩ARM。在項目中逐漸對ARM開發有...
實驗目的:通過STM32CubeMX進行簡單配置生成HAL庫實現內部晶振RTC。一、STM32CubeMX配置如下:1.時鐘樹配置:因為板子沒有外部RTC晶振,所以只能使用內部32KHz晶振,時鐘樹配置如下:2.RTC配置:(1)關于Asynchronous Predivider value 和 Synchronous Predivider value填寫多少,請看下面:因為內部晶振是32KHz,所以毫無疑問應該選擇LSI=32KHz即...

史海拾趣

小廣播
設計資源 培訓 開發板 精華推薦

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 仙游县| 内丘县| 甘洛县| 上犹县| 罗甸县| 从化市| 肇东市| 南江县| 鄂托克旗| 德保县| 阿拉善盟| 湖南省| 都安| 廊坊市| 丁青县| 建瓯市| 榆林市| 涟水县| 措勤县| 通渭县| 云龙县| 孝义市| 永济市| 唐山市| 文水县| 张家口市| 宜春市| 沂南县| 三明市| 石柱| 武山县| 博湖县| 宜都市| 诏安县| 沈阳市| 广河县| 本溪市| 惠安县| 阿坝县| 含山县| 神池县|