Keil c函数参数传递的讨论
引起我注意Keil c函数参数传递的是在一个偶然的机会,我在写一个函数的时候:如下
write_byte(uLONG addr, uCHAR dat)
{
…
}
我原本以为addr会通过R4—R7来传递,而dat则通过R3传递的,在调试的时候却发现dat是通过固定地址储存区传递的。因此引发了我想知道它到底是怎样传递参数的。
因为大家都知道,keil c的参数传递规则
参数 CHAR, int, LONG, generic
数目 1-byte pointer 2-byte pointer float pointer
1 R7 R6 & R7 R4-R7 R1-R3
2 R5 R4 & R5
3 R3 R2 & R3
我原本以为三个int参数都通过寄存器能传递,一个uLONG和一个uCHAR应该也可以吧,真是有点不明白。如果写为如下
write_byte(uLONG addr, uCHAR * dat)
{
…
}
即一个uLONG参数和一个指针参数则都能通过寄存器传递。
导致上面第二个uCHAR参数不通过寄存器传递的原因大概是因为第二个uCHAR型参数一定要通过R5来传递吧,而第一个uLONG型参数正好用了R5,所以dat就只能通过固定地址的存储区来传递了。
为此我就想测试一下如果不通过寄存器来传递参数或通过模拟栈来传递参数时参数的传递情况会是怎样的。
第一个例子如下,通过寄存器传递参数,代码共101字节。
void delay(uLONG dlyh, uint dlyl)
{
while(dlyh--);
while(dlyl--);
}
void main(void)
{
delay(0x100, 0x50);
while(1);
}
汇编代码如下,
RSEG ?PR?_delay?TEST_PARA
_delay:
USING 0
; SOURCE LINE # 6
MOV dlyh?040+03H,R7 ;把从寄存器R4—R7传来的第一个参数
MOV dlyh?040+02H,R6 ;存入固定地址。
MOV dlyh?040+01H,R5 ;(有时真觉得这动作啥冒)
MOV dlyh?040,R4
; {
; SOURCE LINE # 7
?C0001:
; while(dlyh--);
; SOURCE LINE # 8
MOV R0,#LOW (dlyh?040)
MOV A,#0FFH
LCALL ?C?LLDIIDATA8
MOV A,R4
ORL A,R5
ORL A,R6
ORL A,R7
JNZ ?C0001
?C0003:
; while(dlyl--);
; SOURCE LINE # 9
MOV A,dlyl?041+01H
DEC dlyl?041+01H
MOV R6,dlyl?041
JNZ ?C0009
DEC dlyl?041
?C0009:
ORL A,R6
JNZ ?C0003
; }
; SOURCE LINE # 10
?C0005:
RET
; END OF _delay
;
; void main(void)
RSEG ?PR?main?TEST_PARA
main:
USING 0
; SOURCE LINE # 12
; {
; SOURCE LINE # 13
; delay(0x100, 0x50);
; SOURCE LINE # 14
MOV ?_delay?BYTE+04H,#00H ;传递第二个参数
MOV ?_delay?BYTE+05H,#050H
MOV R7,#00H ;传递第一个参数
MOV R6,#01H
MOV R5,#00H
MOV R4,#00H