鴻蒙內核源碼分析(匯編匯總篇) | 匯編可愛如鄰家女孩

匯編其實很可愛

  • 絕大部分IT從業人員終生不用觸碰到的匯編,它聽著像上古時代遙遠的呼喚,總覺得遠卻又能聽到聲,匯編再往下就真的是01110011了,匯編指令基本是一一對應了機器指令.
  • 所謂內核是對硬件的驅動,對驅動之后資源的良序管理,這里說的資源是CPU(單核/多核),內存,磁盤,i/o設備.層層封裝,步步遮蔽,到了應用層,不知有漢,無論魏晉才好.好是好,但有句話,其實哪有什么歲月靜好,只是有人替你負重前行.難道就不想知道別人是怎么負重前行的?
  • 越高級的語言是越接近人思維模式的,越低級的語言就是越貼近邏輯與非門的高低電平的起伏.匯編是貼著硬件飛行的,要研究內核就繞不過匯編,覺得神秘是來源于不了解,恐懼是來自于沒接近.
  • 其實深入分析內核源碼之后就會發現,匯編其實很可愛,很容易,比c/c++/java容易太多了,真的是很傻很單純.

鴻蒙內核源碼分析系列篇至少已經有五篇涉及到了匯編,請自行翻看,但還是遠遠不夠,要寫十五篇,徹底摸透,現在才剛剛開始,本篇先整理鴻蒙內核所有匯編文件和大概說明文件的作用,后續一塊一塊來剝,不把這些匯編剝個精光不罷休.

匯編目錄

鴻蒙所有匯編文件如下:
直接點擊可以查看注解源碼,有些站點會把鏈接去除,沒辦法,可直接去各大站點搜"鴻蒙內核源碼分析",找到源碼注解.

hw_user_get.S

將用戶空間數據src 拷貝到內核空間 dst

// errno_t _arm_get_user(void *dst, const void *src, size_t dstTypeLen, size_t srcTypeLen)
FUNCTION(_arm_get_user)
    stmdb   sp!, {r0, r1, r2, r3, lr} @四個參數入棧,保存LR
    cmp     r2, #0  @r2 和 0比較
    beq     .Lget_user_return @相等 跳到Lget_user_return 直接返回
    cmp     r2, r3  @r2 和 r3比較
    bne     .Lget_user_err  @不等,說明函數要返回錯誤
    cmp     r2, #1  @r2 和 1比較
    bhi     .Lget_user_half @if(dstTypeLen>1) 跳轉到Lget_user_half
.Lget_user_byte:         @按字節拷貝數據
0:  ldrbt   r3, [r1], #0 @r3=*r1
1:  strb    r3, [r0], #0 @*r0=r3
    b       .Lget_user_return 
.Lget_user_half:
    cmp     r2, #2  @r2 和 2比較
    bhi     .Lget_user_word  @if(dstTypeLen>2) Lget_user_word
2:  ldrht   r3, [r1], #0    @完成最后一個字節的拷貝
3:  strh    r3, [r0], #0    @完成最后一個字節的拷貝
    b       .Lget_user_return
.Lget_user_word:
    cmp     r2, #4 @r2 和 4比較
    bhi     .Lget_user_err @if(dstTypeLen>4) 跳轉到Lget_user_err
4:  ldrt   r3, [r1], #0
5:  str    r3, [r0], #0
.Lget_user_return:  @返回錨點
    ldmia   sp!, {r0, r1, r2, r3, lr}   @保存的內容出棧,恢復各寄存器值
    mov     r0, 0   @r0保存返回值為0
    bx      lr  @跳回調用函數繼續執行,_arm_get_user到此結束!
.Lget_user_err:
    ldmia   sp!, {r0, r1, r2, r3, lr}   @保存的內容出棧,恢復各寄存器值
    mov     r0, #-14    @r0保存返回值為-14    
    bx      lr  @跳回調用函數繼續執行,_arm_get_user到此結束!

.pushsection __exc_table, "a"
    .long   0b,  .Lget_user_err
    .long   1b,  .Lget_user_err
    .long   2b,  .Lget_user_err
    .long   3b,  .Lget_user_err
    .long   4b,  .Lget_user_err
    .long   5b,  .Lget_user_err
.popsection

解讀

  • 用戶空間和內核空間的數據為什么需要拷貝?
    這是個經典問題,看了網上的一些回答,沒毛病:

    內核不能信任任何用戶空間的指針。必須對用戶空間的指針指向的數據進行驗證。如果只做驗證不做拷貝的話,那么在隨后的運行中要隨時受到其它進/線程可能修改用戶空間數據的威脅。所以必須做拷貝。

    在內存系列篇中已經反復的說過,每個用戶進程都有自己獨立的用戶空間,但這個用戶空間是通過MMU映射出來的,是表面上繁花似錦,背后都共用著真正的物理內存,所以在高頻率的任務切換過程中,原有的用戶空間地址內容很容易被覆蓋掉.舉個例子說明下:

    • 用戶A有個美女西施放在萬聰酒店21號房說要獻給內核大佬,如果內核不直接把美女接回家,而僅僅是做個記錄,寫著西施在萬聰酒店21號房,內核大佬立馬跑去過,還不會錯能拿對人,但如果被其他事給耽擱了呢?
    • 耽擱的這回功夫,調度算法把萬聰酒店21號房給了用戶B使用,當然用戶B使用之前,酒店管理人員會把西施置換個地方(以至于用戶A再回到酒店時,原來的東西該怎樣還咋樣還原). 等21號房空出來了,B肯定不知道原來的房間是A在用,而且里面曾經還過有個美女西施,更不可能曉得A把西施獻給內核大佬這回事了.因為B的業務需要,很可能往21號房整了個東施進來.
    • 此時如果內核大佬事忙完了,想起用戶A獻美女的事了,是時候了.因為只記錄了地址,直接去萬聰酒店21號房抓人,可這會抓出來那是咱東施小姐呀.這可不把事給搞砸啦.
    • 所以需要跨空間拷貝,直接把美女接回家找個地方關起來先.

reset_vector_mp.S 和 reset_vector_up.S

鴻蒙開機代碼根據 CPU多核還是單核分成了兩個獨立文件處理.
mp就是多處理器(multiprocessing)的意思:
多CPU核的操作系統3種處理模式(SMP+AMP+BMP) 鴻蒙實現的是 SMP 的方式

  • 非對稱多處理(Asymmetric multiprocessing,AMP)每個CPU內核
    運行一個獨立的操作系統或同一操作系統的獨立實例(instantiation)。

  • 對稱多處理(Symmetric multiprocessing,SMP)一個操作系統的實例
    可以同時管理所有CPU內核,且應用并不綁定某一個內核。

  • 混合多處理(Bound multiprocessing,BMP)一個操作系統的實例可以
    同時管理所有CPU內核,但每個應用被鎖定于某個指定的核心。

up(unit processing )的意思,單個CPU,雖然沒mp的復雜,但文件也很大 500行匯編,一小節講不完,需要單獨的一篇專講 reset_vector

這里只列出up情況下的開機代碼

reset_vector: @鴻蒙單核cpu 開機代碼
    /* do some early cpu setup: i/d cache disable, mmu disabled */
    mrc     p15, 0, r0, c1, c0, 0
    bic     r0, #(1<<12)
    bic     r0, #(1<<2 | 1<<0)
    mcr     p15, 0, r0, c1, c0, 0

    /* r11: delta of physical address and virtual address */
    adr     r11, pa_va_offset
    ldr     r0, [r11]
    sub     r11, r11, r0

    /* if we need to relocate to proper location or not */
    adr     r4, __exception_handlers            /* r4: base of load address */
    ldr     r5, =SYS_MEM_BASE                   /* r5: base of physical address */
    subs    r12, r4, r5                         /* r12: delta of load address and physical address */
    beq     reloc_img_to_bottom_done            /* if we load image at the bottom of physical address */

    /* we need to relocate image at the bottom of physical address */
    ldr     r7, =__exception_handlers           /* r7: base of linked address (or vm address) */
    ldr     r6, =__bss_start                    /* r6: end of linked address (or vm address) */
    sub     r6, r7                              /* r6: delta of linked address (or vm address) */
    add     r6, r4                              /* r6: end of load address */

los_dispatch.S 和 los_hw_exc.S

異常模式處理入口和統一分發現實,之前也有提到過,很復雜,1000多行,后續單獨細說實現過程.

jmp.S

兩個簡單的函數longjmp setjmp 的實現,加注解部分請前往【鴻蒙內核源碼注解分析】 查看

FUNCTION(longjmp)
        ldmfd   r0,{r4-r12}
        add     r0,#(4 * 9)
        ldr     r13,[r0]
        add     r0,#4
        ldr     r14,[r0]
        cmp     r1,#0
        moveq   r1,#1
        mov     r0,r1
        mov     pc,lr

FUNCTION(setjmp)
        stmea   r0,{r4-r12}
        add     r0,#(4 * 9)
        str     r13,[r0]
        add     r0,#4
        str     r14,[r0]
        mov     r0,#0
        mov     pc,lr

los_hw_runstop.S

    .global  OsSRSaveRegister
    .global  OsSRRestoreRegister

兩個函數的匯編現實,有點復雜,后續單獨說明.

cache.S

這是緩存部分的兩個函數實現,此處沒有加注解,試著看明白這兩個函數的實現.加注解部分請前往
鴻蒙內核源碼注解分析 查看

.macro  DCACHE_LINE_SIZE, reg, tmp
    mrc     p15, 0, \tmp, c0, c0, 1
    lsr     \tmp, \tmp, #16
    and     \tmp, \tmp, #0xf
    mov     \reg, #4
    mov     \reg, \reg, lsl \tmp
.endm

FUNCTION(arm_inv_cache_range)
    push    {r2, r3}
    DCACHE_LINE_SIZE r2, r3
    sub    r3, r2, #1
    tst    r0, r3
    bic    r0, r0, r3

    mcrne  p15, 0, r0, c7, c14, 1

    tst    r1, r3
    bic    r1, r1, r3
    mcrne  p15, 0, r1, c7, c14, 1
1:
    mcr    p15, 0,  r0, c7, c6, 1
    add    r0,  r0, r2
    cmp    r0,  r1
    blo    1b
    dsb
    pop    {r2, r3}
    mov    pc, lr

FUNCTION(arm_clean_cache_range)
    push   {r2, r3}
    DCACHE_LINE_SIZE r2, r3
    sub    r3, r2, #1
    bic    r0, r0, r3

1:
    mcr    p15, 0,  r0, c7, c10, 1
    add    r0,  r0, r2
    cmp    r0,  r1
    blo    1b
    dsb
    pop    {r2, r3}
    mov    pc, lr

寫在最后

  • 如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
  • 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
  • 關注小編,同時可以期待后續文章ing??,不定期分享原創知識。
  • 想要獲取更多完整鴻蒙最新學習知識點,請移步前往小編:https://gitee.com/MNxiaona/733GH/blob/master/jianshu
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容