8051 堆栈操作指令(2条)
PUSH direct ;SP <- SP+1, (SP) <- (direct)
POP direct ;(SP) -> (direct), SP <- SP-1
第一条指令称为压栈指令,用于把 direct 为地址的操作数传送到堆栈中去。这条指令执行时分为两步:第一步是先使 SP 的地址加 1,使之指向新的存储单元;第二步是把 direct 中的操作数压入由 SP 指向的存储单元中。第二条指令称为弹栈指令,其功能是把 SP 所指向的存储单元中的内容弹到 direct 单元中。
注意:8051 的硬件堆栈的生长方向是由下往上!
8051 子程序调用和返回指令
短调用指令:ACALL addr11 ;PC <- PC+2
;SP <- SP+1, (SP) <- PC7 - PC0
;SP <- SP+1, (SP) <- PC15 - PC8
;PC10 - PC0 <- addr11
长调用指令:LCALL addr16 ;PC <- PC+3
;SP <- SP+1, (SP) <- PC7 - PC0
;SP <- SP+1, (SP) <- PC15 - PC8
;PC <- addr16
无论是短调用指令还是长调用指令,都有一个压栈的过程,这是调用该指令后硬件自动完成的。
返回指令:
RET ;PC15 - PC8 <- (SP), SP <- SP-1
;PC7 - PC0 <- (SP), SP <- SP-1
RETI ;PC15 - PC8 <- (SP), SP <- SP-1
;PC7 - PC0 <- (SP), SP <- SP-1
这两条指令的功能完全相同,都是把堆栈中的断点地址恢复到程序计数器 PC 中,从而使单片机回到断点地址处执行程序。RET 称为子程序返回指令,只能用在子程序末尾。RETI 称为中断返回指令,只能用在中断服务程序末尾。机器执行 RETI 指令后除返回程序断点地址处执行外,还将清除相应中断优先级状态位,以允许单片机响应低优先级中断请求。
KEIL C 编译器在子函数调用过程中,参数的传递默认是采用寄存器,当寄存器无法满足要求时,额外的参数由存储器传递,而并不通过堆栈 SP。这也是为什么 KEIL C 中的函数默认情况下是不可重入的。
扩展:ARM程序参数传递规则
如果参数小于 4 个,使用寄存器 R0-R3 来传递;如果参数的个数超过 4 个,就必须用堆栈来传递。
——忠于梦想 勇于实践 linux_xpj@opencores.org
阅读(3797) | 评论(0) | 转发(0) |