這篇是給慣用組合語言的人做為比較的,並且看看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還是要看一下組合語言在幹什麼,常常和想的不同。
沒有留言:
張貼留言