久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1036|回復: 2
打印 上一主題 下一主題
收起左側

Keil匯編進階指南(4) - 與C共舞

[復制鏈接]
跳轉到指定樓層
樓主
與C共舞

我們在之前的內容學習了段的聲明以及相關變量內存的聲明,現在我們要開始最重要的一節課——匯編和C的混合編程
首先是在C中調用匯編
我們在匯編的學習中知道了匯編代碼的跳轉和調用都是依賴所謂的標記來進行,我們還是拿LCD1602的驅動舉例

  1. <div class="blockcode"><blockquote>LCDWRCOM:
  2.                 CLR LCD_RS;寫命令
  3.                 SJMP GOON
  4.         LCDWRDAT:
  5.                 SETB LCD_RS;寫數據,這個沒有jmp,應該更快一些
  6.         GOON:
  7.                 SETB LCD_EN;兩段代碼合一,這種技巧很常見,甚至編譯器都這么優化
  8.                 MOV LCD_BUS,R7;注意,根據文檔,單個char會直接傳入R7,多看文檔
  9.                 MOV R6,#10H;等待LCD
  10.                 DJNZ R6,$
  11.                 CLR LCD_EN
  12.                 CLR LCD_RS
  13.                 RET
復制代碼


  1. LCDINIT:
  2.                 CLR LCD_RW
  3.                 CLR LCD_EN
  4.                 MOV R7,#38H
  5.                 CALL LCDWRCOM
  6.                 MOV R7,#0CH
  7.                 CALL LCDWRCOM
  8.                 MOV R7,#06H
  9.                 CALL LCDWRCOM
  10.                 MOV R7,#01H
  11.                 CALL LCDWRCOM;啟動序列,別處抄的
  12.                
  13.                 MOV R7,#0FH
  14.         LCDFINWAIT:
  15.                 MOV R6,#0FFH
  16.                 DJNZ R6,$
  17.                 DJNZ R7,LCDFINWAIT;LCD需要一段時間準備
  18.                
  19.                 RET
復制代碼




我們可以知道,上面有三個程序,一個是LCDWRCOM,一個是LCDWRDAT,以及LCDINIT,這三個都是程序的入口,我們要做的就是把入口聲明告知C編譯器,有這么個東西
我們以LCDINIT為例
首先,LCDINIT是一個沒有輸入輸出的函數,所以一般來說它在C語言里的聲明是這樣的
  1. void lcdinit();
復制代碼
其次,我們在C文件中調用的是別的文件中的函數,我們需要extern來表明,這個函數是從外部薅過來的(函數入口在別的文件)
最終,我們寫在頭文件里的聲明函數是這樣的
  1. extern void lcdinit();
復制代碼

還記得我說過傳到匯編編譯器的名字不分大小寫嗎?這里就體現出來了,你只要名字對上就可以,它能找到認出來
光這樣還不行,匯編語言的入口實際上是不符合C編譯器的命名規則的,所以我們需要在匯編里做些操作,讓匯編編譯器知道,這個入口是可以被外界使用的,這里就要用到PUBLIC,具體用法是這樣的
PUBLIC 標記名



所以最終的代碼是這樣的
  1. PUBLIC LCDINIT

  2. LCDINIT:
  3. CLR LCD_RW
  4. CLR LCD_EN
  5. MOV R7,#38H
  6. CALL LCDWRCOM
  7. MOV R7,#0CH
  8. CALL LCDWRCOM
  9. MOV R7,#06H
  10. CALL LCDWRCOM
  11. MOV R7,#01H
  12. CALL LCDWRCOM;啟動序列,別處抄的

  13. MOV R7,#0FH
  14. LCDFINWAIT:
  15. MOV R6,#0FFH
  16. DJNZ R6,$
  17. DJNZ R7,LCDFINWAIT;LCD需要一段時間準備

  18. RET
復制代碼

C語言中

  1. extern void lcdinit();
復制代碼

這樣,我們就完成了C語言調用匯編
但是對于有傳入形參的函數,情況稍微復雜一些,C51傳遞參數有些不同,它是寄存器傳參,參數放置在從R7開始的寄存器,然后才輪得到內存(可以關掉這個選項,但是內存能省則。,如果是一個char,那就R7,兩個那就R7和R6,三個那就765,一個int就是R7和R6,以此類推,至于內存傳參,你可以看看手冊,一般來講,超過四五個形參的我建議直接傳指針進去
其次,匯編語言中的標記的前面必須帶有一個下劃線,比如ABC要變為_ABC
這里回收上一節埋下的伏筆,實際上內存段的標記也可以public


  1. ?DT?LCDMEM SEGMENT DATA
  2.                 PUBLIC LCDMEM
  3.                 RSEG ?DT?LCDMEM
  4.         LCDMEM:
  5.                 DS 32
復制代碼
C語言中是這樣的
  1. extern unsigned char LCDMEM[32];
復制代碼


好了,C調用匯編已經學會了,我們現在要倒反天罡,讓匯編也揩一下C語言的油
這一次,我們直接扒keil一開始給的StartUp.A51里面的例子
從116行開始
  1. ?C_C51STARTUP   SEGMENT   CODE
  2. ?STACK          SEGMENT   IDATA

  3.                 RSEG    ?STACK
  4.                 DS      1

  5.                 EXTRN CODE (?C_START)
  6.                 PUBLIC  ?C_STARTUP

  7.                 CSEG    AT      0
  8. ?C_STARTUP:     LJMP    STARTUP1

  9.                 RSEG    ?C_C51STARTUP
復制代碼

好了,那個?C_START就是我們的目標,它就是我們調用C語言的方法(也是STARTUP以后跳轉主函數的入口)
EXTRN CODE (函數名)
實際上還能用EXTERN,兩者的區別就是EXTERN只能把PUBLIC過的標記薅過來用(順便一提,變量也可以薅過來用,只需要把CODE改成DATA)
我們這次不寫函數給匯編調用,我們在StartUp.A51上搞事情,眾所周知,StartUp.A51先于主函數運行,所以它一定會跳轉到主函數,我們使個壞把主函數改成mian(我不太確定是不是有副作用,就僅僅整活用吧)
所以我們需要改成
  1. EXTRN CODE (mian)
復制代碼

好了,還有最后一步,我們可以在StartUp.A51的尾部看見這個
  1.                 LJMP    ?C_START

  2.                 END
復制代碼

把它也改了,然后……
  1. StartUp.A51
  2. ……
  3. EXTRN CODE (mian)
  4. ……
  5. LJMP mian
  6. END

  7. main.c

  8. void mian(){
  9. ……
  10. }
復制代碼
順便一說,提示找不到?C_START也可以用這招

最后,匯編里面調用函數用CALL,這個應該不用多說


評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:1138341 發表于 2024-12-2 18:52 | 只看該作者
好資料,51黑有你更精彩!!!
回復

使用道具 舉報

板凳
ID:624769 發表于 2024-12-3 23:33 | 只看該作者
你不要想當然啊……, 傳參 3個 char 是 R7,R5,R3, 不是 R7R6R5, 算了,給你個表吧……


最多能通過通用寄存器 傳3個參,再多就要用?DT? 聲明了。
而這3個參有明確規定,比如 long 只能在 第一,第二位置傳,傳了long, 就只能再傳 指針了。等等一系列的規定。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人免费观看视频 | 99热播精品 | 欧美一级黄视频 | 天天干天天草 | www免费视频 | 欧美精品一区二区三区在线 | 性生生活大片免费看视频 | 国产精品一区二区福利视频 | 日韩欧美国产精品一区 | 成人特区 | 免费在线观看一区二区 | 精品一区国产 | 一区二区三区精品在线 | www.色综合| 日韩视频一区二区 | 日韩av一二三区 | 在线观看视频91 | 在线视频中文字幕 | 性一交一乱一伦视频免费观看 | 欧美精品综合 | 成人亚洲精品久久久久软件 | 宅女噜噜66国产精品观看免费 | 久久久毛片| 99在线精品视频 | 国产日韩一区二区三免费高清 | 国产 日韩 欧美 在线 | 久久精品久久久 | 99pao成人国产永久免费视频 | 综合色久 | 亚洲一区二区三区在线免费观看 | av网站在线播放 | 在线成人免费视频 | 每日在线更新av | 亚洲九色 | 日韩中文一区 | 日本精品视频一区二区三区四区 | 成人高清在线 | 黄网站免费在线看 | 国产成人a亚洲精品 | 国产偷录叫床高潮录音 | 在线a视频 |