设为首页 加入收藏

TOP

关于C语言不定参数的研究(一)
2017-01-02 08:15:10 】 浏览:333
Tags:关于 语言 不定 参数 研究

编写程序如下:



编译连接并用debug加载,观察main函数的内容:



Showchar函数的内容:




观察发现,main函数要传递两个参数‘a’和2,在汇编代码中是先将2赋给ax,再将ax入栈,然后将a赋给ax,ax入栈。在showchar函数中,程序将sp赋给bp,再从bp+4处取出形参a赋给al,再将al中的值赋给b800690h,然后再从bp+6处取出形参b赋给al,再将al中的值赋给b800691h。可见main函数给showchar传递参数是把要传递的值赋给ax,再将ax入栈,且如果有多个要传递的值,是由后往前将参数入栈。Showchar函数接收参数是将sp赋给bp,然后由bp+4找到栈中存储的参数a,由bp+6找到栈中存储的的参数b,为什么是bp+4bp+6呢?因为程序在将两个参数入栈后,call指令将showchar的地址入栈占2个字节,在showchar中将bp入栈又占2个字节,所以要由bp+4找到第一个参数的地址。那么我对此提出三个问题:


(1)main函数将char型数据和int型数据入栈是占2个字节,那么如果是float型或者longint型、double型、longdouble型等超过2字节的变量类型怎么办?


(2)Showchar函数将栈中取出的参数赋给al,为什么2int型也只赋给一个字节的al?如果是更大的参数怎么办?


(3)我们注意到这一个指令



是把al赋给es[bx],是不是所有非ds的段寄存器都要像这样写?


对于第一个问题,我们把程序中的charint改成floatdouble看看:



编译连接,用debug查看,main函数为:



Showchar函数为:




发现main函数的入栈值为:400800000000000040066666.


再看showchar函数的内容,查资料发现int35h的作用是读取中断向量,但是不知道它的具体功能,incsilesax[06fb]int39的作用是什么呢?


这里我对于c语言的一些语句在汇编里的实现还是有的不理解,但是这不是我们研究的重点,既然暂时弄不懂,就先跳过这个问题。


再看第三个问题,发现所有es作段地址的指令都是如上格式,ds作段寄存器的指令都把ds省略了。



再来看下一个程序:



编译连接,用debug加载查看,main函数为:




Showchar函数为:





观察C语言的showchar函数可以发现:第一个参数n是要显示的参数数量,第二个参数color是要显示的参数颜色,之后的就是要显示的参数。Showchar函数通过参数n来知道要显示多少个字符。然后通过循环来调用寄存器从栈中提取参数。


但是printf函数的参数是要直接输出的,没有一个参数是告诉它下面有多少个参数。但是printf里面是要输入%c或者%d,那么函数是通过统计%c%d的数量来判断要输出多少参数的吗?我们写一个printf函数来看看:



编译连接并用debug加载有:



这里是将参数12入栈,再入栈194,然后执行printf函数,那么194有什么作用呢?查阅资料知,程序将%c%d等符号放在偏移地址0194处,结尾加0,通过统计该地址处的%个数来确定要输出的字符数量。所以peintf函数和showchar函数的区别就是showchar函数参数个数已给出而printf函数是要根据%c%d个数来确定参数个数而已。那么我们要实现简单的printf函数,可以在showchar函数的基础上来改动。


下面是网上找的代码:


void printf(char *,...);


int pow(int, int);



main()


{


/*printf("I think this is interesting :%c and %c and %c",0x61,0x62,0x63);*/



printf("No.%d,%d,%d,this is me %c ing yuan",45,123,8958,'Q');


}



void printf(char *des, ...)


{


/*first sure the length of string des*/


int len=0;


int i=0;


int showp=0; /*define the point of showing chars*/


int parap=0; /*define of parameter position in stack*/


int intValueLength=1;


int signalNum=0;


/*calculate length of stirng des */


while(des[i]!='/0')


{


len++;


i++;


}


i=0;



while(des[i]!='/0')


{


if(des[i]=='%')


{


/*check type of value user want to show.*/


if(des[i+1]=='d')


{


/*here show integer value*/


int showIntValue=*(int *)(_BP+6+parap+parap); /*here, we show understand that define one char point value, we just push the point value into stack, but not the string value*/


int reva lue=showIntValue;


/* *(int far *)(0xb8000000+160*10+80+showp+showp)=showIntValue;


*(int far *)(0xb8000000+160*10+81+showp+showp)=2;*/


i+=2;


parap++;


intValueLength=1;


/*here we calculate the length of integer value we want to show ,and then we can sure the next value show position*/


while(reva lue/10!=0)


{


intValueLength++;


reva lue/=10;


}


/*first calculate the length of unmber and show every sigal positon number of Integer */


signalNum = showIntValue/pow(10,--intValueLength);


*(char far *)(0xb8000000+160*10+80+showp+showp)=signalNum+48; /*show the highest signal number*/


*(char far *)(0xb8000000+160*10+81+showp+showp)=2;


showp++;


while(intValueLength!=0)


{


showIntValue=showIntValue-signalNum*pow(10,intValueLength);


signalNum= showIntValue/pow(10,--intValueLength);


*(char far *)(0xb8000000+160*10+80+showp+showp)=signalNum+48; /*show the highest signal number*/


*(char far *)(0xb8000000+160*10+81+

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇为什么C程序里一定要写main函数 下一篇关于tcc、tlink的编译链接机制的..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目