某公司笔试题
#include “stdio.h”
void print()
{
*
}
void main()
{
}
在*号处加一段代码,使程序打印出”hello,world”.
庄sir的解法:
//hello.c by MentalDease
#include “stdio.h”
void print()
{
#pragma comment(linker, “/entry:print”)
#pragma comment(linker, “/SECTION:.text,REW” )
int mainCRTStartup();
void main();
__asm
{
MOV EAX, OFFSET main
MOV BYTE PTR[EAX], 0xB8 //MOV EAX, 0x
MOV DWORD PTR[EAX+1], OFFSET SHOWSTRING
MOV WORD PTR[EAX+5], 0xE0FF // JMP EAX
}
mainCRTStartup();
SHOWSTRING:
printf (“i am MentalDease\n”);
getchar();
}
void main()
{
}
很多运行库函数是其他代码执行的基础。这意味着,必须在执行用户代码(程序开发者编写的代码)之前初始化运行库。我们知道程序是从入口函数开始执行的,所以要在入口函数开始或者之前调用运行库的初始化函数。
事实上,编译器会为每个模块自动插入一个入口函数,这个函数进行好各种初始化工作之后再调用用户的入口函数,在用户的入口函数返回之后再运行自己的清理函数。这个编译器插入的入口函数即称为CRT(C Run Time)入口函数:
CRTmainStartUp()
{
CRT Init();
Call main();
CRT CleanUp();
}
默认情况下,链接器会将CRT入口函数注册为模块的入口。不过连接器支持通过/entry:function 选项指定其他函数作为入口。
#pragma comment(linker, “/entry:print”)
把程序的入口点设为print函数
MainCRTStartup是C运行期库的初始化函数。CRT堆必须在用户代码调用之前被初始化好,即在入口函数之前调用运行库的初始化函数。我们在设定函数入口为print函数之后,必须显示调用mainCRTStartup。
main CRT入口:mainCRTStartup
WinMain CRT入口:WinMainCRTStartup
DLL模块的CRT入口函数是 _DllMainCRTStartup
CRT 源码 crt0.c 中包含了CRT入口函数的代码,CRT入口函数的初始化工作主要有以下几项:
__security_init_cookie 初始化安全Cookie
_heap_init 创建和初始化CRT堆
_mtinit 初始化多线程支持
_ioinit 初始化低级IO
_cinit 初始化C和C++数据
… …