首页 > 解决方案 > 调整堆栈指针以推动函数的争论

问题描述

通常当我为 8051 芯片编写程序集时。在调用函数之前,我使用寄存器 R0-R7 进行争论。

mov r6, #6
mov r7, #2
lcall setpos

我有兴趣通过使用堆栈来做到这一点(忽略这可能效率较低的事实)。在互联网上搜索,我在此链接中找到了一个遮阳篷

我在答案中遗漏了一些东西。在答案中,他执行以下操作

push #0
push #5
call function
pop  r7 ; return value -> r7
...
function:
   pop r7
   pop r6 ; store return address
   pop b ; 5 -> b
   pop a ; 0 -> a
   add a, b
   push a  ; store result in a and push it
   push r6
   push r7
   ret

我认为每个寄存器都是可修改的,包括堆栈指针,所以可以这样做

push #4
push #8
call function
pop r7 ; result -> r7
...
function:
    dec SP ; leave return address untouched
    dec SP
    pop r4 ; 8 -> A
    pop r5 ; 4 -> B
    add A, B
    inc SP
    push A; push result
    ret

反而?我做得对吗?

标签: assemblystack8051

解决方案


你的想法还不错,因为它不需要寄存器来缓冲返回地址,使用更少的时钟周期,并且使用更少的代码空间。

只有一个问题需要注意:因为返回地址在堆栈中保持其位置,所以参数的所有空间都在使用中。在呼叫站点,您必须POP <any>DEC SP与呼叫前推送的金额相同。

所以你的例子应该是:

push #4
push #8
call function
pop r7 ; result -> r7
dec sp

被调用的函数在返回之前不能改变 SP:

function:
    dec SP ; leave return address untouched
    dec SP
    pop r4 ; 8 -> A
    pop r5 ; 4 -> B
    add A, B
    inc SP
    push A; push result
    inc SP
    inc SP
    ret

附加说明: PUSH并且POP只取内部 RAM(00H 到 7FH)和特殊功能寄存器(80H 到 0FFH)的地址作为参数。立即数没有变体。即使你PUSH R2在当前寄存器组中写入R2的绝对地址也是使用的。


推荐阅读