TC2.0编译器,编译连接如下代码
用Debug加载,-u命令查看汇编代码,发现根本找不到main函数所在代码段,故用print语句将main函数所在代码段的偏移地址输出方便查找。
可以看到,在程序开头多出两行代码push bp;mov bp,sp这是因为汇编程序将main函数作为子程序处理,须将栈顶指针保存,以便返回。
程序访问内存空间需要知道两点:
地址
类型
C语言的指针型数据即可完成这两个功能,例如
*(char *)0x2000='a'
表示向偏移地址为2000的内存空间存入一个字符'a',可以用段地址和偏移地址的形式表示
*(char far *)0x20000000='a'
注意*(char far *)0x20001000='a'汇编翻译为
mov bx,2000
mov es,bx
mov bx,1000
mov byte ptr [bx],61
原来,C语言中全局变量是放在ds:[01A6]开始的内存中,代码段中的多有函数都可以访问,而局部变量是存放在栈中的。
C语言使用AX寄存器传递返回值为int型数据的值
编译报错,无法找到c0s.obj文件,使用汇编的连接器LINK.EXE进行连接生成exe文件,并用debug查看
可以看到,程序从偏移地址0开始,下面再写一个使用main函数的正常程序,并编译连接生成exe
程序从01fa开始,我们猜测,偏移地址0到01fa之间的代码就是c0s.obj调用main函数的相关代码,从偏移地址0处开始使用u命令查看,发现在011A处调用main函数,在0156处返回
所以,我们清楚了exe文件的生成过程:
1.编译器加载c0s.obj文件,进行相关的初始化工作
2.c0s.obj调用main函数,开始用户程序
3.用户程序运行结束从main函数返回到c0s.obj的程序中继续运行
4.c0s.obj进行资源释放,环境恢复等工作
5.c0s.obj的程序调用DOS的int 21h例程的4ch号中断功能,程序返回
现在,我们自己重新写一个c0s.asm文件并生成c0s.obj取代tc原有的c0s.obj文件
1 assume cs:codesg 2 3 data segment 4 db 128 dup (0) 5 data ends 6 7 codesg segment 8 9 start: 10 mov ax,data 11 mov ds,ax 12 mov ss,ax 13 mov sp,128 14 15 call s 16 17 18 mov ax,4c00h 19 int 21h 20 s: 21 22 23 codesg ends 24 end start
连接原先的f函数文件生成f.exe,使用debug查看,f函数作为一个子程序成功运行了
学的越多,发现不会的越多,学海无涯!