研究试验4
不使用 main 函数
编写程序 f.c
f()
{
*(char far *)(0xb8000000 + 160 * 10 + 2 * 40) = 'a';
*(char far *)(0xb8000000 + 160 * 10 + 2 * 40 + 1) = 2;
}
1. 将程序保存在 minc
目录下 编译链接
- 在连接过程中会出现问题
- 提示出的缺少
_main
- 可能与
C0S
有关
2. 用学习汇编是的 link.exe
对 tc.exe
生成的 f.obj
进行连接 生成 f.exe
- 由图中可见总共由 303 个字节
- 函数
f
实现了其功能 在屏幕中打印出 a- 但是函数不能正常结束 Dosbox 会卡死后然后退出
- debug 后可见
f
函数的偏移地址为0
3. 写一个 m.c
在 编译 连接
main()
{
*(char far *)(0xb8000000 + 160 * 10 + 2 * 40) = 'a';
*(char far *)(0xb8000000 + 160 * 10 + 2 * 40 + 1) = 2;
}
- 由图可见代码总长为 4280 个字节
- 由图可见
m.exe
可以正常返回 因为在执行玩m.exe
后还可以在命令行输入新的命令 m.exe
的汇编代码中main 的偏移地址为 01fa 而f.exe
中 f 的偏移地址为 0000- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SWBas6Bz-1592729246469)(0608-%E7%A0%94%E7%A9%B6%E8%AF%95%E9%AA%8C4-%E5%AE%A3%E8%AE%B2%E4%BC%9A%E7%A0%94%E7%A9%B6%E6%8A%A5%E5%91%8A-%E5%B0%B9%E5%BF%A0%E6%81%A9.assets/image-20200608171625247.png)]
4. debug 对 m.exe 进行跟踪
- 跳转到main函数开始地址
- 执行到 ret 后 跳转到 了
076a:011d
- 由图可以看到 在
07fa:011a
中调用main
- 在执行完
划红线的ret 然后一直按p 会找到程序的返回指令为
int 21
5. 思考问题
- main函数的调用指令和程序返回指令应该是c0s中对应的代码中调用的
- 没有main 函数,提示错误信息中由 “c0s” 的相关信息,因该是 tc.exe 把 在搭建环境时所需要的 文件 和 用户的
obj
生成.exe
而不单单是 一个c0s.obj
- 调用 main 函数的指令 因该来自于
c0s.obj
- 用
link.exe
连接c0s.obj
- debug 后的
c0s.exe
- 可以看见基本结构和由用户生成的包含main 函数的基本结构相似
6. 用link.exe
对 c0s.obj
连接生成 c0s.exe
c0s.exe | m.exe |
---|---|
由上图可知代码开头部分两者的开始部分都相同
7. 对比 m.exe
和 c0s.exe
中调用main函数的call指令的偏移地址的后10条指令
c0s.exe | m.exe |
---|---|
由上图可知前10行有3行调用的不同 第一个为调用main函数然后返回到 c0s.obj
中的 076a:011d,其余的call应该也是完成相关任务后返回 c0s.oj
8. 改写 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
-
用
masm
生成c0s.obj
-
在
tc
中 打开f.c
编译 连接 后可以正常生成f.exe
9 debug f.exe
可以看到程序正确的调用了 f()
疑问:
为什么汇编代码中仅仅调用了 s 然后 s 什么都没用,连接完后就把f函数自动填充过去到 s 处
10 编写新的f.c
#define Buffer ((char *)*(int far *)0x02000000)
f()
{
Buffer = 0;
Buffer[10] = 0;
while (Buffer[10] != 8)
{
Buffer[Buffer[10]] = 'a' + Buffer[10];
Buffer[10]++;
}
}
debug 后的 f.exe
可以看到编译连结完debug后的代码逻辑和汇编代码逻辑基本一致
感悟
C0S.OBJ的功能就是进行相关初始化,申请资源、设置DS、SS等寄存器,并且在MAIN函数结束后进行相关资源的释放、环境恢复等工作,随后调用DOS的21H程序返回。
- [外链图片转存中…(img-rWtudEKQ-1592729246649)]
可以看到编译连结完debug后的代码逻辑和汇编代码逻辑基本一致
感悟
C0S.OBJ的功能就是进行相关初始化,申请资源、设置DS、SS等寄存器,并且在MAIN函数结束后进行相关资源的释放、环境恢复等工作,随后调用DOS的21H程序返回。