Skip to content

Misc

约 284 个字 76 行代码 3 张图片 预计阅读时间 2 分钟

Misc

12.3 补

12.24 最后一节课

alt text 之所以写:

push bp
mov bp, sp
-> bp本身是需要被保护的【保护的是上一层的bp

Important

  • 若是main调用ff毁掉了bp,问题不大
  • mainfgg改变了bp的值(mov bp, sp,没有保护和恢复),返回到f,而f很可能用到bp,例如[bp+4],这样的话f再也找不到自己的参数了。

递归(难理解)

C语言:

    int f(int n){ //第一次函数调用,n对应的是(1)位置
        if(n==1)
            return 1;
        return n+f(n-1); //第一次函数调用,n对应的是(4)位置
    }
形参由3变成了2! 用汇编进行实现:
f:
    push bp;(3)(6)(9)
    mov bp, sp
    mov ax, [bp+4] ;当前
    cmp ax, 1
    je done
    dec ax
    push ax;(4)(7)
    call f;(5)(8)
there:
    add sp, 2;(12)(15)
    add ax, [bp+4]
done: ;准备返回
    pop bp;(10)(13)(16) ;ss:1FEE - 1FF4 , 1FF4函数复活,堆栈指针回落
    ret;(11)(14)(17)

main:
    mov ax,3
    push ax;(1)
    call f;(2)
here:
    add sp, 2;(18)

执行上述代码时的堆栈布局如下:

ss:1FEE oldbp<-bp(9)
ss:1FF0 there<-(8)(10)
ss:1FF2 1<-(7)(11)
ss:1FF4 oldbp<-bp(6)12
ss:1FF6 there<-(5)(13)
ss:1FF8 2<-(4)(14)
ss:1FFA oldbp<-bp(3)(15)
ss:1FFC here <-(2)(16)
ss:1FFE 3 <-(1)(17)
ss:2000   <-(18)

Warning

由递归的原理,我们会避免在递归中用全局变量,特别是用全局变量传递参数

混合语言编程

alt text

main()
{
    int i;
    for(i=0;i<10;i++){
        asm mov ah,2
        asm mov dl, 'A'
        asm int 21h
    }

}

利用命令行编译:

$cd \tc
$tcc asmc.c
会先把程序变成汇编,再从汇编进行编译

能否在汇编中访问变量i呢?

main()
{
    int i=0;
    {
        again:
        asm mov ah,2
        asm mov dl, 'A'
        asm int 21h
        asm inc word ptr i //在汇编中使用到了变量i
        asm cmp word ptr i, 10
        asm jl again
    }
}

另一种VC内编译的形式: alt text

naked:禁止编译器在代码内随意插入代码。 若不加直接编译,可能会加入堆栈的基本框架。 在__asm前加入:

    push ebp
    mov ebp, esp
在后面加入
    pop ebp
    ret

在TC中调用汇编定义的模块

  • C语言代码:
    #include<stdio.h>
    extern void f(int a, int b, int *p); //函数f的内容在代码之外,不会报错
    main(){
        int x=10,y=20,z;
        f(x,y,&z);
        printf("z=%d\n",z);
    }
    

Comments