tc2.0环境下的C语言研究-关于main函数编程
2011-09-23 11:08
323 查看
用一个简单的程序来研究如何用tc.exe来对这个程序进行编译、连接,生成正确的可以运行的程序。
f()
{
*(char far *)(0xb8000000+160*12+80)='a';
*(char far *)(0xb8000000+160*12+81)=2;
}
将此函数保存在最简开发环境下,会发现:编译无错误,连接时提示错误并显示与C0S.obj有关
用masm开发环境下的link.exe进行连接,生成.exe文件,并debug程序,-r命令查看,可见CX值为0x001d(此表示程序占用1d个字节),且f的偏移地址为0;
将f换成main,用tc.exe重新编译连接,生成m.exe,并debug程序,同理用-r命令查看,可见CX值为0x0eb8(此表示程序占用eb8个字节),且main的偏移地址为1fa;
熟练使用debug的操作命令,从头开始跟踪,查看从什么时候开始调用了1fa偏移地址的main函数(注意用-p和-g命令),
耐心一点,很快就会发现的。
可以发现:没有main函数时,出现的错误信息里有和“c0s”相关的信息;而前面在搭建开发环境时,没有c0s.obj文件tc.exe就无法对程序进行连接。
由此可以知道
对main函数调用的指令和程序返回的指令是从c0s.obj来的;tc.exe把c0s.obj和用户程序的.obj文件一起进行连接生成.exe文件;
利用masm中的link.exe可以使c0s.obj生成c0s.exe,对比m.exe并从头查看,可以发现到了一定代码,m.exe直接调用main函数,而c0s.exe调用了一个紧接着的地址。
总结c0s.obj的工作过程:
①c0s.obj里的程序先运行,进行相关的初始化,比如,申请资源、设置DS、SS等寄存器;
②c0s.obj里的程序调用main函数,从此用户程序开始运行;
③用户程序从main函数返回到c0s.obj的程序中;
④c0s.obj的程序接着运行,进行相关的资源释放,环境恢复等工作;
⑤c0s.obj的程序调用DOS的int 21h例程的4ch号功能,程序返回。
C程序必须从main函数开始,是C语言的规定,这个规定不是在编译时保证的,因为tc.exe对f.c的编译是通过的,也不是连接的时候保证的,因为用link.exe可以使文件生成f.exe.
如下机制保证了程序必须从main函数开始。
C语言系统提供了用户写的应用程序正确运行所必需的初始化的程序返回等相关程序,这些程序放在相关的.obj文件(比如,c0s.obj)中
需要将这些文件和用户的.obj文件一起进行连接,才能生成可正确运行的.exe文件。
连接在用户.obj文件前面的由C语言开发系统提供的.obj文件里的程序要对main函数进行调用。
基于这种机制,只要修改c0s.obj,让它调用其他函数,编程时就可以不写main函数了。
我们用汇编语言编写一个程序c0s.asm,然后把它编译成为c0s.obj,替代最简目录下的c0s.obj.
程序如下
assume cs:code
data segment
db 128 dup(0)
data ends
code segment
start:
mov ax,data
mov ds,ax
mov ss,ax
mov sp,128
call s
mov ax,4c00h
int 21h
s:
code ends
end start
重新对f.c进行编译连接,此时编译连接能通过,并且f.exe可以正确运行。但是请注意,如果此时用新的c0s.obj进行编译连接,而编写的.c文件中既有main函数又有
其他的函数,c0s只是默认连接第一个函数的。
知道了调用main函数的原理,也就明白了32程序的函数入口winmain的原理...
f()
{
*(char far *)(0xb8000000+160*12+80)='a';
*(char far *)(0xb8000000+160*12+81)=2;
}
将此函数保存在最简开发环境下,会发现:编译无错误,连接时提示错误并显示与C0S.obj有关
用masm开发环境下的link.exe进行连接,生成.exe文件,并debug程序,-r命令查看,可见CX值为0x001d(此表示程序占用1d个字节),且f的偏移地址为0;
将f换成main,用tc.exe重新编译连接,生成m.exe,并debug程序,同理用-r命令查看,可见CX值为0x0eb8(此表示程序占用eb8个字节),且main的偏移地址为1fa;
熟练使用debug的操作命令,从头开始跟踪,查看从什么时候开始调用了1fa偏移地址的main函数(注意用-p和-g命令),
耐心一点,很快就会发现的。
可以发现:没有main函数时,出现的错误信息里有和“c0s”相关的信息;而前面在搭建开发环境时,没有c0s.obj文件tc.exe就无法对程序进行连接。
由此可以知道
对main函数调用的指令和程序返回的指令是从c0s.obj来的;tc.exe把c0s.obj和用户程序的.obj文件一起进行连接生成.exe文件;
利用masm中的link.exe可以使c0s.obj生成c0s.exe,对比m.exe并从头查看,可以发现到了一定代码,m.exe直接调用main函数,而c0s.exe调用了一个紧接着的地址。
总结c0s.obj的工作过程:
①c0s.obj里的程序先运行,进行相关的初始化,比如,申请资源、设置DS、SS等寄存器;
②c0s.obj里的程序调用main函数,从此用户程序开始运行;
③用户程序从main函数返回到c0s.obj的程序中;
④c0s.obj的程序接着运行,进行相关的资源释放,环境恢复等工作;
⑤c0s.obj的程序调用DOS的int 21h例程的4ch号功能,程序返回。
C程序必须从main函数开始,是C语言的规定,这个规定不是在编译时保证的,因为tc.exe对f.c的编译是通过的,也不是连接的时候保证的,因为用link.exe可以使文件生成f.exe.
如下机制保证了程序必须从main函数开始。
C语言系统提供了用户写的应用程序正确运行所必需的初始化的程序返回等相关程序,这些程序放在相关的.obj文件(比如,c0s.obj)中
需要将这些文件和用户的.obj文件一起进行连接,才能生成可正确运行的.exe文件。
连接在用户.obj文件前面的由C语言开发系统提供的.obj文件里的程序要对main函数进行调用。
基于这种机制,只要修改c0s.obj,让它调用其他函数,编程时就可以不写main函数了。
我们用汇编语言编写一个程序c0s.asm,然后把它编译成为c0s.obj,替代最简目录下的c0s.obj.
程序如下
assume cs:code
data segment
db 128 dup(0)
data ends
code segment
start:
mov ax,data
mov ds,ax
mov ss,ax
mov sp,128
call s
mov ax,4c00h
int 21h
s:
code ends
end start
重新对f.c进行编译连接,此时编译连接能通过,并且f.exe可以正确运行。但是请注意,如果此时用新的c0s.obj进行编译连接,而编写的.c文件中既有main函数又有
其他的函数,c0s只是默认连接第一个函数的。
知道了调用main函数的原理,也就明白了32程序的函数入口winmain的原理...
相关文章推荐
- tc2.0环境下的C语言研究-关于链接
- tc2.0环境下的C语言研究-需要耐心的指针研究
- tc2.0环境下的C语言研究-变量与参数返回值
- tc2.0环境下的C语言研究-简单使用寄存器并打印函数的偏移地址
- tc2.0环境下的C语言研究-函数如何接收不定数量参数
- 我想把关于软件环境研究博客搬到这里来
- 因近日安装java设置环境变量无果,转载以前发的帖子-----关于C语言
- c语言中关于可变参数的研究
- 关于MiniFedora12分析-Linux GCC编译环境搭建及Glibc研究
- 关于X86_64Linux环境下suffix or operands invalid for ‘mov’问题的研究
- 关于如何在c语言环境中求一个未知数的各个数字之和
- 关于C语言中a=a++与a=++a的研究
- <C语言>关于函数返回值是指针,取不到值的问题研究
- 复杂环境下关于人员 快速统计、识别及定位的研究
- 关于linux环境下c语言内核开发中头文件分类
- 复杂环境下关于人员 快速统计、识别及定位的研究
- 关于在.net2003和2008开发环境下,FileUpload的使用会有不同结果的未完成研究。
- 关于C语言可变参数函数的一些研究和总结
- 研究实验一 搭建一个精简的C语言开发环境
- 关于ORACLE 在windos 环境下出现ORA-12546的问题研究