2010年2月18日 星期四

8051簡單多工6:核心編譯之組語

這篇是給慣用組合語言的人做為比較的,並且看看8051是如何去做函式指標呼叫。

我使用SDCC的組譯程式來看,因為Keil c的比較複雜。以下為main()中程式轉成組合語言段落:

C語言部分:前面數字為行號,可以在組合語言中找到對應段落。TASK_NUM設為4
77:void main(void)
78:{
79:    PCA0MD &= ~0x40;                    // Disable Watchdog timer
80:    Init_Device();
81:    while (1)
82:    {
83:        register void (*Current_Func)(void);
84:        EA = 0;
85:        Current_Func = TaskFunc[FuncID]; // may break with interrupt
86:        EA = 1;
87:        Current_Func();
88:        FuncID = (++FuncID) % TASK_NUM;
89:    }
90:}

ASM組合語言結果:
;------------------------------------------------------------
;Allocation info for local variables in function 'main'
;------------------------------------------------------------
;Current_Func              Allocated to registers r2 r3
;    main.c 77
;    -----------------------------------------
;     function main
;    -----------------------------------------
_main:
;    main.c 79
    anl    _PCA0MD,#0xBF
;    main.c 80
    lcall    _Init_Device
;    main.c 81
00102$:
;    main.c 84
    clr    _EA
;    main.c 85
    mov    r0,#_FuncID
    mov    a,@r0
    add    a,acc
; Peephole 105   removed redundant mov
    mov  r2,a
    add    a,#_TaskFunc
    mov    r0,a
    mov    ar2,@r0
    inc    r0
    mov    ar3,@r0
    dec    r0
;    main.c 86
    setb    _EA
;    main.c 87
    mov    a,#00107$
    push    acc
    mov    a,#(00107$ >> 8)
    push    acc
    push    ar2
    push    ar3
    ret
00107$:
;    main.c 88
    mov    r0,#_FuncID
    mov    a,#0x01
    add    a,@r0
    mov    r2,a
    mov    r0,#_FuncID
    mov    b,#0x04
    mov    a,r2
    div    ab
    mov    @r0,b
; Peephole 132   changed ljmp to sjmp
    sjmp 00102$
00104$:
    ret

可以看到Current_Func是使用r2及r3暫存器。
取函式指標執行是第87行的動作,使用四個push及一個ret來做,這不是一般人可以理解的吧。Keil C呼叫更多東西。
唯一可以確定的是push ar2及puah ar3中的ar2及ar3就是暫存器r2及r3。

從這裏可以看到除餘(%)真的是拿去除,所以上一篇才會提到加速及展開的問題。不過Keil C就聰明多了,會用and 3去做。
要玩MCU還是要看一下組合語言在幹什麼,常常和想的不同。



沒有留言:

張貼留言