汇编函数调用的现场保护 - ikarishinjieva/unixV6-code-analyze-chs GitHub Wiki

综述

举例

  • 首先我们写了个小程序作为实例
  • 实例由两个文件组成,c.c 和 d.s,代码如下
//c.c
main()
{
test(100,999,888);
}
//d.s
.globl test
_test:
mov $3,r0
rts pc
  • 我们在pdp11虚拟机上编译了上面的代码,并进行反汇编,将得到的汇编代码精简,加以分析
  • 主程序
...
jsr pc,30
调用地址30
...
  • 地址30
jsr r5,102
调用地址102,实为变形的csv程序
mov $1570,(sp)
mov $1747,-(sp)
mov $144,-(sp)
  • 向堆栈存入三个函数参数:888,999,100
  • 注意第一个元素是置入栈顶,而压栈了后两个元素
jsr pc,*$62
调用地址62,实为我们写的汇编程序
cmp (sp)+,(sp)+
  • 从堆栈弹出两个元素
  • 实为恢复 函数参数压栈前 的堆栈栈顶,注意只需弹出两个元素
  • 当变化参数个数时,此处也随之变化,总能恢复堆栈栈顶
jmp 120
转入地址120,实为cret程序
  • 地址102,对照csv
mov r5,r0
mov sp,r5
mov r4,-(sp)
mov r3,-(sp)
mov r2,-(sp)
tst -(sp)
  • 这里与csv程序不同,这里直接将栈顶指针上移一位
  • 主要作用是 现场还原 时能直接调用 地址120的cret
jmp (r0)
  • 这里与csv程序不同,这里直接转入(r0)地址,并不将PC压栈
  • 地址62,是我们写的汇编程序
进入我们写的汇编函数时,堆栈状况如下:

mov $3,r0
rts pc
  • 地址120,与cret一样
mov r5,r1
mov -(r1),r4
mov -(r1),r3
mov -(r1),r2
mov r5,sp
mov (sp)+,r5
rts pc

总结

函数调用的现场保护的主要差别为:

进入我们写的汇编函数时,堆栈状况如下:

  • 此堆栈情况与一般的函数调用的现场保护不同,是由于受到如下因素的影响而不同
    • 受到了函数传递方式不同的影响
    • 受到了102地址的程序与csv不同的影响
⚠️ **GitHub.com Fallback** ⚠️