. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->综合研究
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  newprintf(%c,%d); 思路  [待解决] 回复[ 0次 ]   点击[ 328次 ]  
cutebe
[帖 主]   [ 发表时间:2013-06-27 23:07 ]   [引用]   [回复]   [ top ] 
荣誉值:4
信誉值:0
注册日期:2010-01-27 19:28
newprintf(%c,%d); 思路
P326
“(3) 实现一个简单的 printf 函数,只需要支持‘%c、%d’即可。”

newprintf("ASCII %c: %d, Number: %d.",_AL,_AL,_AX);

首先讲讲遇到的困难吧。
1、怎么支持不定数量的参数?

2、字符串怎么声明定义?
3、字符串怎么显示?
4、函数是怎么接收字符串的?

5、怎么判断不定数量参数具体应用时到底有几个,或是当前接收的是第几个?


之后就是解决困难,即按你的想法编程并调试了。
有一个前提想法是:
既然“综合研究”有整节整节的内容来强调不使用变量编程,而是使用寄存器与内存来编程。
我们就应该遵行这个条件来完成这个研究,以使这个 newprintf(); 函数更加“汇编”一点。

其实仔细想想,上面提到的问题基本上和最后一个“思考”要分析解决的问题是一样的。
(最后一个思考:showchar 函数是如何知道要显示多少个字符的?printf 函数是如何知道有多少个参数的?)
而“思考”中第一问很容易,分析一下就应知是第1个参数。如示例程序中第1个参数是8,这里就显示 a ~ h 这8个字符;再看看,如果 8 改成 7,就算后面的参数完全不变,也只显示 a ~ g 共7个字符,而 h 则不显示了。在 8 变 7 的前提下,再将最后一个参数 'h' 也去掉,是不是也显示7个字符呢?调试分析一下就知道了。
从以上的思考分析中是不是得到一些有关不定参数的启示!但是这离解决“困难1”还有一点点距离。因为如果思维定势在这个数量参数“8”上,既不利于深入理解不定参数,也会使你与“思考”中第2问的答案间的迷雾更浓。
因此我们抛弃这个“8”,回到不定参数上来。有了这样的想法,问题也变得简单。

困难1:
在抛弃了“8”后,分析一下showchar()函数声明部分“void showchar(int,int,...);”
很明显main()函数中“8,2”对应声明中前两个“int,int”,对应函数中“int n,int color”。
声明与函数中都用“...”对应 main() 函数中什么呢?当然是“'a','b','c','d','e','f','g','h'”这8个字符参数啰。再加上上面分析与调试试验,既然'h'可以去掉,当然其他的也字符参数也可以去掉,那不就说明这是“不定参数”了吗!不定参数使用“...”,声明与函数中都一样。困难1得到了解决。


困难2,3,4都与字符串有关。三个困难一起来袭也会让你头大,还是一个一个解开的好。
还是先分析最后一个示例程序 b.c。想想函数 showchar() 是如何显示“abcdefgh”字符串的呢。很容易想得到是一个字符一个字符地显示,函数如何接收这些字符呢,通过DEBUG分析 a.c 知道是main() 函数将参数压入栈中,函数使用参数时,定位到参数在栈中的地址,取出来使用。一个参数对应一个地址,长度是2个字节;也即参数最大2个字节。
再看一下printf("abcd"); 这个参数是"abcd" 显然与“'a','b','c','d'”这样的4个参数不同,"abcd"是一个参数。一个参数最大2个字节,而"abcd" 有4个字节,存不下。

写一个 p.c
main()
{
  printf("abcd");
}
编译连接后DEBUG调试发现main() 函数只将一个参数入栈了(因为只有一个字符串参数),那这个入栈的参数是什么呢?思考调试后再往下看。

原来是一个内存地址,这个地址在段DS中。

困难4:
困难3:
到这里困难3,困难4都解决了。将字符串所在的首地址压入栈中,供函数接收,这样就解决了困难4。函数取出地址,一个一个字符地显示就变成了字符串,这样困难3 也得到了解决。对于困难3 还有一个小困难,字符串是怎么结束的?汇编语言有以 0 作结尾标识,也有以字符 $ 作标识的,分析调试 p.c 自己总结,如不确定还可以将 "abcd" 换成其他文字如,"hello world!" 来确定自己的判断。

困难2:
字符串怎么声明定义?
分析了老半天,要显示的字符串还没有声明定义呢,程序也没法写阿!其实不然,我们可以先写汇编代码,以前有写过显示字符串的子程序。这里有一点不同,之前汇编中字符串的地址是通过寄存器(即类似DS:SI)传给子程序的,而这里字符串的地址是存在栈中传递给子程序的,可以根据这个条件写一个汇编程序。如果不懂怎么用,还可以参考“附注4”。

回到困难2,字符串怎么声明的?
前面提到对应字符串的参数其实是她的地址。那么声明时就要声明一个内存地址,类型是字符型。
研究试验3 中有“‘(char *)’里面的‘*’指明了这个数值表示一个内存空间的地址”,这里“指明”和“声明”意思一样。仔细分析原文中这句所在的整段话,会有收获。
困难2 也基本上得到了解决。一个小困难是函数声明是不用指明变量名,而具体的函数却是要有变量名的,前面有提到不用变量来编程C,那我们不会用寄存器或内存地址阿!是不是真的这样呢?自己编程分析吧。

只剩最后一个“困难”了,当然是最困最难的,也是最关键的。这个困难不解决,等于程序一半没写完。虽然我们的函数是不定参数个数的,但具体在函数调用时却是确定数量的,调用时到底有几个呢?或是可以用什么变通的方法解决这个调用问题,不然少调用一个参数程序就变成半截或是无法实现全部功能了。
我们再写一个使用 printf() 函数的 pa.c
main()
{
  printf("char %c's ASCII code is: %d\n",'T','T');
}

DEBUG调试前先想想,程序运行后怎么不显示 %c 和 %d 呢?字符串放到内存中时难道就已经不是 %c  %d 了?

DEBUG分析这个程序,分析她在什么情况下把后面的参数'T'加到字符串中替换掉 %c %d 的,发现了什么?

(有一个简单的小困难,提一下,就是怎么在屏幕上显示字符?因为书上已经显式的给出,因此不分析了!)
到这里所有的困难都解决了,何不上手一一编写调试,体验一下快乐。

****************************************************
程序写完当然也有一些缺憾,无法在光标位置显示。因为这个在汇编中都要用到INT中断来确定光标属性,在C中??我不会C,当然不知道C是如何确定光标的。

另一个是没有分析换行,即 \n 的用法。方法可能类似 %c %d,先查看一下“\n”在内存中是怎么显示的,再进行处理。可不简单呢!我没有分析所以也不会!
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved