久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
Keil匯編進階指南(4) - 與C共舞
[打印本頁]
作者:
Astrix
時間:
2024-11-30 00:11
標題:
Keil匯編進階指南(4) - 與C共舞
與C共舞
我們在之前的內容學習了段的聲明以及相關變量內存的聲明,現在我們要開始最重要的一節課——匯編和C的混合編程
首先是在C中調用匯編
我們在匯編的學習中知道了匯編代碼的跳轉和調用都是依賴所謂的標記來進行,我們還是拿LCD1602的驅動舉例
<div class="blockcode"><blockquote>LCDWRCOM:
CLR LCD_RS;寫命令
SJMP GOON
LCDWRDAT:
SETB LCD_RS;寫數據,這個沒有jmp,應該更快一些
GOON:
SETB LCD_EN;兩段代碼合一,這種技巧很常見,甚至編譯器都這么優化
MOV LCD_BUS,R7;注意,根據文檔,單個char會直接傳入R7,多看文檔
MOV R6,#10H;等待LCD
DJNZ R6,$
CLR LCD_EN
CLR LCD_RS
RET
復制代碼
LCDINIT:
CLR LCD_RW
CLR LCD_EN
MOV R7,#38H
CALL LCDWRCOM
MOV R7,#0CH
CALL LCDWRCOM
MOV R7,#06H
CALL LCDWRCOM
MOV R7,#01H
CALL LCDWRCOM;啟動序列,別處抄的
MOV R7,#0FH
LCDFINWAIT:
MOV R6,#0FFH
DJNZ R6,$
DJNZ R7,LCDFINWAIT;LCD需要一段時間準備
RET
復制代碼
我們可以知道,上面有三個程序,一個是LCDWRCOM,一個是LCDWRDAT,以及LCDINIT,這三個都是程序的入口,我們要做的就是把入口聲明告知C編譯器,有這么個東西
我們以LCDINIT為例
首先,LCDINIT是一個沒有輸入輸出的函數,所以一般來說它在C語言里的聲明是這樣的
void lcdinit();
復制代碼
其次,我們在C文件中調用的是別的文件中的函數,我們需要extern來表明,這個函數是從外部薅過來的(函數入口在別的文件)
最終,我們寫在頭文件里的聲明函數是這樣的
extern void lcdinit();
復制代碼
還記得我說過傳到匯編編譯器的名字不分大小寫嗎?這里就體現出來了,你只要名字對上就可以,它能找到認出來
光這樣還不行,匯編語言的入口實際上是不符合C編譯器的命名規則的,所以我們需要在匯編里做些操作,讓匯編編譯器知道,這個入口是可以被外界使用的,這里就要用到PUBLIC,具體用法是這樣的
PUBLIC 標記名
所以最終的代碼是這樣的
PUBLIC LCDINIT
LCDINIT:
CLR LCD_RW
CLR LCD_EN
MOV R7,#38H
CALL LCDWRCOM
MOV R7,#0CH
CALL LCDWRCOM
MOV R7,#06H
CALL LCDWRCOM
MOV R7,#01H
CALL LCDWRCOM;啟動序列,別處抄的
MOV R7,#0FH
LCDFINWAIT:
MOV R6,#0FFH
DJNZ R6,$
DJNZ R7,LCDFINWAIT;LCD需要一段時間準備
RET
復制代碼
C語言中
extern void lcdinit();
復制代碼
這樣,我們就完成了C語言調用匯編
但是對于有傳入形參的函數,情況稍微復雜一些,C51傳遞參數有些不同,它是寄存器傳參,參數放置在從R7開始的寄存器,然后才輪得到內存(可以關掉這個選項,但是內存能省則省),如果是一個char,那就R7,兩個那就R7和R6,三個那就765,一個int就是R7和R6,以此類推,至于內存傳參,你可以看看手冊,一般來講,超過四五個形參的我建議直接傳指針進去
其次,匯編語言中的標記的前面必須帶有一個下劃線,比如ABC要變為_ABC
這里回收上一節埋下的伏筆,實際上內存段的標記也可以public
?DT?LCDMEM SEGMENT DATA
PUBLIC LCDMEM
RSEG ?DT?LCDMEM
LCDMEM:
DS 32
復制代碼
C語言中是這樣的
extern unsigned char LCDMEM[32];
復制代碼
好了,C調用匯編已經學會了,我們現在要倒反天罡,讓匯編也揩一下C語言的油
這一次,我們直接扒keil一開始給的StartUp.A51里面的例子
從116行開始
?C_C51STARTUP SEGMENT CODE
?STACK SEGMENT IDATA
RSEG ?STACK
DS 1
EXTRN CODE (?C_START)
PUBLIC ?C_STARTUP
CSEG AT 0
?C_STARTUP: LJMP STARTUP1
RSEG ?C_C51STARTUP
復制代碼
好了,那個?C_START就是我們的目標,它就是我們調用C語言的方法(也是STARTUP以后跳轉主函數的入口)
EXTRN CODE (函數名)
實際上還能用EXTERN,兩者的區別就是EXTERN只能把PUBLIC過的標記薅過來用(順便一提,變量也可以薅過來用,只需要把CODE改成DATA)
我們這次不寫函數給匯編調用,我們在StartUp.A51上搞事情,眾所周知,StartUp.A51先于主函數運行,所以它一定會跳轉到主函數,我們使個壞把主函數改成mian(我不太確定是不是有副作用,就僅僅整活用吧)
所以我們需要改成
EXTRN CODE (mian)
復制代碼
好了,還有最后一步,我們可以在StartUp.A51的尾部看見這個
LJMP ?C_START
END
復制代碼
把它也改了,然后……
StartUp.A51
……
EXTRN CODE (mian)
……
LJMP mian
END
main.c
void mian(){
……
}
復制代碼
順便一說,提示找不到
?C_START也可以用這招
最后,匯編里面調用函數用CALL,這個應該不用多說
作者:
快樂的大橙子
時間:
2024-12-2 18:52
好資料,51黑有你更精彩!!!
作者:
188610329
時間:
2024-12-3 23:33
你不要想當然啊……, 傳參 3個 char 是 R7,R5,R3, 不是 R7R6R5, 算了,給你個表吧……
傳參.png
(5.94 KB, 下載次數: 0)
下載附件
2024-12-3 23:30 上傳
最多能通過通用寄存器 傳3個參,再多就要用?DT? 聲明了。
而這3個參有明確規定,比如 long 只能在 第一,第二位置傳,傳了long, 就只能再傳 指針了。等等一系列的規定。
歡迎光臨 (http://m.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
国产做a爱片久久毛片
|
日本三级黄视频
|
日韩在线视频一区二区三区
|
亚欧午夜
|
三级国产三级在线
|
夜色www国产精品资源站
|
黄色免费三级
|
aⅴ色国产 欧美
|
成人精品一区二区三区中文字幕
|
日韩中文在线观看
|
中文字幕免费视频
|
久久久久久一区
|
午夜精品久久久久久久
|
九九热这里只有精品在线观看
|
毛片.com
|
一区二区小视频
|
亚洲另类春色偷拍在线观看
|
精品久久一区
|
精品视频一区二区三区在线观看
|
丁香婷婷综合激情五月色
|
中文字幕av在线播放
|
99国产精品99久久久久久
|
亚洲精品一区二区三区蜜桃久
|
午夜午夜精品一区二区三区文
|
国产精品久久久久久久久久久新郎
|
一区二区三区高清
|
激情黄色在线观看
|
日韩一区二区在线看
|
亚洲成人高清
|
久久综合久色欧美综合狠狠
|
久久久精品国产
|
日本一二三区在线观看
|
日本精品在线播放
|
日操操
|
国产精品亚洲综合
|
精品日韩
|
亚洲成人中文字幕
|
www日本在线播放
|
在线黄
|
欧美日韩亚
|
婷婷福利视频导航
|