自制操作系统08-内存中的栈堆地址

java里有个知识是"局部变量在栈里,全局变量在堆里",这个栈啊堆的,谁也不知道在那里,无法描述。只有书上画了两个图还比较形象,现在学了汇编,就可以从最底层来解释这些东西了。

1.局部变量与全局变量的地址

先看一段c语言程序:
int a1,a2,a3;
main(){
    int b1,b2,b3;
    a1=0xa1;a2=0xa2;a3=0xa3;
    b1=0xb1;b2=0xb2;b3=0xb3;
}

我们用tc编译,连接生成main.exe。然后debug main.exe,然后u bb1:1fa查看这段c语言对应的汇编语句:


BP是(Base Pointer基址寄存器),在这里对这个名称体现得相当贴切。一进入main函数,就先保存(push)好当前的BP值,让SP(Stack Pointer栈寄存器)的值覆盖BP值,因为我们要利用SP来存一些变量了。编译器发现我们声明了3个int变量(int b1,b2,b3;),于是把栈位置(指针)向上移6字节。
SUB SP,+06
表示要用6个字节,来保存我们这三个变量的值。
再下面是三句赋值语句:
MOV     WORD PTR [01A6],00A1

这里的[01A6],是DS:1A6.这三个位置用来保存全局变量,可能对应了java里的堆内存,这块内存只有没有引用了才会被回收。我们在前面说过DS:100以后才是程序地址。我们看一下这段地址(刚进入main函数的状态):


嗯,大多数是空着的,除1A6前面一点的地址被用了。

2.返回值的地址

好了,我们再调用一个函数,看看这个返回值是放到那里去了,我估计是DS:100后的。C代码改成这样:

int a1,a2,a3;
int f(void);
main(){
    int b1,b2,b3;
    a1=0xa1;a2=0xa2;a3=0xa3;
    b1=0xb1;b2=0xb2;b3=0xb3;
    b1=f();
}

int f(void){
    return a1*a2;
}

然后我们还是用
u bb1:1ba
开始看,转到下一页就是这个了:



在跳到f函数后,可以看到把相乘的结果放入AX寄存器了,结束函数后又放进了DS:[1AC]。哈,果然是这段地址。

3.参数的地址

我们再看一下,参数是存那里的。c代码改成这样:

void showchar(char a);
main(){
    showchar('a');
}

void showchar(char a){
    *(char far *)(0xb8000000+160*10+80)=a;
    *(char far *)(0xb8000000+160*10+81)=2;
}

debug可以查到如下汇编代码:


也就是说参数值也是放在栈空间的。




文/中中 浏览次数:0次   2020-04-19 18:05:24

相关阅读


评论: