汇编网首页登录博客注册
aten的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
学习动态
友情链接

[2009-04-22 00:11] 研究实验5 函数如何接收不定数量的参数

void showchar(char a,int b);
main()
{
 showchar('a',2);
}
void showchar(char a,int b)
{
 *(char far *)(0xb8000000+160*10+80)=a;
 *(char far *)(0xb8000000+160*10+81)=b;
}
 
  用tc.exe对a.c进行编译,连接,生成a.exe.用debug加载a.exe,对函数的汇编代码进行分析。解答这两

个问题:main函数是如何给showchar传递参数的?showchar是如何接收参数的?
  下面是反汇编后的代码:
140E:01FA 55            PUSH    BP
140E:01FB 8BEC          MOV     BP,SP
140E:01FD B80200        MOV     AX,0002
140E:0200 50            PUSH    AX
140E:0201 B061          MOV     AL,61
140E:0203 50            PUSH    AX
140E:0204 E80400        CALL    020B
140E:0207 59            POP     CX
140E:0208 59            POP     CX
140E:0209 5D            POP     BP
140E:020A C3            RET

140E:020B 55            PUSH    BP
140E:020C 8BEC          MOV     BP,SP
140E:020E 8A4604        MOV     AL,[BP+04]
140E:0211 BB00B8        MOV     BX,B800
140E:0214 8EC3          MOV     ES,BX
140E:0216 BB9006        MOV     BX,0690
140E:0219 26            ES:
140E:021A 8807          MOV     [BX],AL
140E:021C 8A4606        MOV     AL,[BP+06]
140E:021F BB00B8        MOV     BX,B800
140E:0222 8EC3          MOV     ES,BX
140E:0224 BB9106        MOV     BX,0691
140E:0227 26            ES:
140E:0228 8807          MOV     [BX],AL
140E:022A 5D            POP     BP
140E:022B C3            RET
通过跟踪,发现main函数将要给showchar传递的参数入栈,showchar再从栈中取出main函数压入栈的值!

(2)写一个程序b.c
void showchar(int,int,...);
main()
{
 showchar(8,2,'a','b','c','d','e','f','g','h');
}
void showchar(int n,in color,...)
{
 int a;
 for(a=0;a!=n;a++)
 {
   *(char far *)(0xb8000000+160*10+80+a+a)=*(int *)(_BP+8+a+a);
   *(char far *)(0xb8000000+160*10+81+a+a)=color;
 }
}
分析程序b.c,深入理解相关知识。
思考:showchar函数是如何知道要显示多少个字符的?printf函数是如何知道有多少个参数的?
反汇编代码如下:
140E:01FA 55            PUSH    BP
140E:01FB 8BEC          MOV     BP,SP
140E:01FD B86800        MOV     AX,0068
140E:0200 50            PUSH    AX
140E:0201 B86700        MOV     AX,0067
140E:0204 50            PUSH    AX
140E:0205 B86600        MOV     AX,0066
140E:0208 50            PUSH    AX
140E:0209 B86500        MOV     AX,0065
140E:020C 50            PUSH    AX
140E:020D B86400        MOV     AX,0064
140E:0210 50            PUSH    AX
140E:0211 B86300        MOV     AX,0063
140E:0214 50            PUSH    AX
140E:0215 B86200        MOV     AX,0062
140E:0218 50            PUSH    AX
140E:0219 B86100        MOV     AX,0061
140E:021C 50            PUSH    AX
140E:021D B80200        MOV     AX,0002
140E:0220 50            PUSH    AX
140E:0221 B80800        MOV     AX,0008
140E:0224 50            PUSH    AX
140E:0225 E80500        CALL    022D
140E:0228 83C414        ADD     SP,+14
140E:022B 5D            POP     BP
140E:022C C3            RET

140E:022D 55            PUSH    BP
140E:022E 8BEC          MOV     BP,SP
140E:0230 56            PUSH    SI
140E:0231 33F6          XOR     SI,SI
140E:0233 EB49          JMP     027E
140E:0235 8BDD          MOV     BX,BP
140E:0237 03DE          ADD     BX,SI
140E:0239 03DE          ADD     BX,SI
140E:023B 83C308        ADD     BX,+08
140E:023E 8A07          MOV     AL,[BX]
140E:0240 50            PUSH    AX
140E:0241 8BC6          MOV     AX,SI
140E:0243 99            CWD
140E:0244 52            PUSH    DX
140E:0245 50            PUSH    AX
140E:0246 8BC6          MOV     AX,SI
140E:0248 99            CWD
140E:0249 5B            POP     BX
140E:024A 59            POP     CX
140E:024B 03D8          ADD     BX,AX
140E:024D 13CA          ADC     CX,DX
140E:024F 81C39006      ADD     BX,0690
140E:0253 81D100B8      ADC     CX,B800
140E:0257 8EC1          MOV     ES,CX
140E:0259 58            POP     AX
140E:025A 26            ES:
140E:025B 8807          MOV     [BX],AL
140E:025D 8A4606        MOV     AL,[BP+06]
140E:0260 50            PUSH    AX
140E:0261 8BC6          MOV     AX,SI
140E:0263 99            CWD
140E:0264 52            PUSH    DX
140E:0265 50            PUSH    AX
140E:0266 8BC6          MOV     AX,SI
140E:0268 99            CWD
140E:0269 5B            POP     BX
140E:026A 59            POP     CX
140E:026B 03D8          ADD     BX,AX
140E:026D 13CA          ADC     CX,DX
140E:026F 81C39106      ADD     BX,0691
140E:0273 81D100B8      ADC     CX,B800
140E:0277 8EC1          MOV     ES,CX
140E:0279 58            POP     AX
140E:027A 26            ES:
140E:027B 8807          MOV     [BX],AL
140E:027D 46            INC     SI
140E:027E 3B7604        CMP     SI,[BP+04]
140E:0281 75B2          JNZ     0235
140E:0283 5E            POP     SI
140E:0284 5D            POP     BP
140E:0285 C3            RET

showchar函数知道要显示多少个字符是因为main函数给showchar函数传的值8,通过8控制要显示多少字符。printf函数是如何知道多少个函数的呢?我想应该是通过%的个数!但想到%S又有些糊涂了!
于是写了下面程序,生成exe文件用debug跟踪。
main()
{
 char a='a',b='b';
 printf("%c%c",a,b);
}
在里面找到了这句
140E:0D96 3C25          CMP     AL,25    (25为%的ASCII码)
所以猜想是通过%来确定参数个数!

(3)因为才刚学C,对一些语法,程序结构还不清楚,就先到这吧,然后再完成这题!以后补上!
评论次数(2)  |  浏览次数(1319)  |  类型(汇编作业) |  收藏此文  | 

[  mess   发表于  2009-04-23 13:01  ]

不错,用debug分析printf:)

[  younggay   发表于  2009-04-24 11:12  ]

分析理解的很不错了。
%s的时候应该是将参数作为地址处理,就像printf第一个参数的字符串一样,压栈的是地址。

 
 请输入验证码  (提示:点击验证码输入框,以获取验证码