自制操作系统09-不用main函数编程

不用main函数编程

不管c语言还是java,main函数都是程序员必须键入的入口,始终如此,没有例外。在学完汇编后,是时候揭露它神秘的面纱了。

1.环境

干这事之前还是要先准备好环境
1.windows xp
2.trubo C 2.0

trubo c只需要几个文件,不需安装,如下图:

为什么是这几个文件?试出来的,最开始中只有一个tc.exe,编译、连接需要啥加啥。
准备源文件:
main(){
    //printf("%x",main);
    *(char far *)(0xb8000000+160*10+80)='a';
    *(char far *)(0xb8000000+160*10+81)=2;
}

用tc编译,连接,运行,可以看到屏幕中间有个绿色的a,这是正常的代码。

2.破除main函数的魔咒

用tc尝试把main改名

现在把函数名改为f,如下:

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

用tc编译,然后cmd进入命令行(dos).你会发现用tc连接会报错的。
那么用link命令(上一文的汇编环境)连接生成main.exe。查看main.exe的文件大小,是541字节,文件够小,方便研究.执行一下这个文件,发现并不正常,屏幕上各种色块,如下图:


我们用bz打开这个exe文件,可以看到,虽然有541字节,但大部分都是空的,除了开始与后面的几个字节。

然后我再用debug main.exe命令运行这个程序,用r查看内存情况。
可发现代码段为bb1,偏移地址为0,如下图:

那么用d bb1:0看看,程序将要运行的是什么数据。如下图:

有没有发现与可执行文件相同的字节数。55 8B ...5D C3

可能执行exe文件时,一开始就把有效字节用来执行了。所以才有那样的效果。debug看一下,如下图:


在显示完后显示命令后,后面还有地址,也就是在执行一些乱七八糟的东西。我把f改成main,也是同样的效果。回想起汇编的套路总是执行完正常的程序后后面加两行:
mov ax,4c00h
int 21h

进入c语言的函数(包含main),需要一个引导汇编程序:

于是我按王爽老师的代码,写一个如下的引导程序,c0s.asm:

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

生成obj之前先把原来的c0s.obj备份下。然后用masm生成c0s.obj文件,然后再连接两个文件。注意是这样:
link c0s.obj f.obj
c0s.obj与f.obj的位置不能换,经实验生成的exe是严格按照这个顺序来生成可执行文件的,换了就无法正常运行。
因为与c0s.obj同级的tc.exe使用的连接工具也是c0s.obj,我们换了之后,tc也能正常连接。当然这个c0s.obj是"阉割"后的c0s.obj,在f函数中使用个printf函数都不行,因为没有连接相应函数。


其实也就是这么简单,用我们自己的汇编程序引导一下,就破除了main函数的魔咒。

3.讨论分析
我们恢复c0s.obj,用tc编译(f函数代码),再连接,会报如下图的错:

就是c0s.obj在引用main呢。那就把f改成main,就正常了。然后看一下它的结尾与我们写的int 21h是一样的。


我们用正常的tc生成的main.exe与link生成的main.exe做对比,为方便对比,把link的main.exe改成main_link.exe。对比这两文件,首先可以看出大小不一样,一个是541字节,一个是4294字节。

其实还有一个方法,用link命令连接时把相关的文件都连接进去。生成的文件就能正常执行了。如下图:

这次生成的文件大小是2326字节,这个文件也能正常的执行。




文/中中 浏览次数:0次   2020-04-19 21:17:22

相关阅读


评论: