/*这个还只是个简化版,只能实现简单功能,让大家从感性上认识下C的标准库函数是如何实现的仅此而已*/
#include<windows.h>
void __cdecl zll_printf(int color,int row,int col,const char *str,...);
main()
{
zll_printf(4,10,40,"%c",'z');
}
void __cdecl zll_printf(int color,int row,int col,const char *str,...)
{
int parameter_num=6;/*堆栈参数定位,初值设为6是因为4+2(ip,bp)*/
char temp_ch=0;/*从控制字符临时取值用*/
int temp_ch_i;//转存所用
int temp=0;/*控制整够循环*/
int display_col=0;/*控制显示的列参数*/
int temp_int;/*从整数临时取值用*/
int m=10;/*用于整数分离*/
while(str[temp]!='\0')
{
if(str[temp]=='%')
{
temp++;
switch(str[temp])
{
case 'c': {
__asm
{
mov eax,parameter_num
add eax,parameter_num
add eax,eax
mov ebx,ebp
add ebx,ea
mov eax,ss:[ebx]
mov temp_ch_i,eax
}
temp_ch=(char)temp_ch_i;
//temp_ch=*(char *)(_BP+parameter_num*2);//parameter_num*4
*(char far *)(0xb8000000+160*row+2*(col+display_col))=temp_ch;//这边由于是在保护模式下,物理地址是不能直接访问的,SO,在vc6.0下是无法运行的,要在DOS下才可以
*(char far *)(0xb8000000+160*row+2*(col+display_col)+1)=color;
display_col++;
break;
}
case 'd': {
__asm{
mov eax,parameter_num
add eax,parameter_num
add eax,eax
mov ebx,ebp
add ebx,eax
mov eax,ss:[ebx]
mov temp_ch_i,eax
}
temp_ch=(char)temp_ch_i;
// temp_int=*(int *)(_BP+parameter_num*2);
while(temp_int/m)
{
m*=10;
}
m/=10;
while(m!=1)/*m==1,说明temp_int已经为个位数*/
{
temp_ch=temp_int/m+48;
*(char far *)(0xb8000000+160*row+2*(col+display_col))=temp_ch;
*(char far *)(0xb8000000+160*row+2*(col+display_col)+1)=color;
temp_int%=m;
m/=10;
display_col++;
}
temp_ch=temp_int+48;
*(char far *)(0xb8000000+160*row+2*(col+display_col))=temp_ch;
*(char far *)(0xb8000000+160*row+2*(col+display_col)+1)=color;
display_col++;
break;
}
}
parameter_num++;/*获取下一个参数堆栈位置*/
}
else
{
temp_ch=str[temp];
*(char far *)(0xb8000000+160*row+2*(col+display_col))=temp_ch;
*(char far *)(0xb8000000+160*row+2*(col+display_col)+1)=color;
display_col++;
}
temp++; /*获取控制字符串的下一个字符*/
}
}