一,研究过程:
在main函数中添加语句,使下面的程序可以打印出所有函数的段地址和偏移地址;具体例程如下:
Int a;
Void f1(void)
{
A=1;
}
Void f2(void)
{
A=2;
}
Void f3(void)
{
A=3;
}
Main()
{
int addr=(int)f1;
int (*P)()=f1;
printf("f1(P) address is:\t%x\n",P);
printf("f1(addr) address is:\t%x\n",addr);
printf("f1 address is:\t\t%x\n",f1);
printf("f2 address is:\t\t%x\n",f2);
printf("f3 address is:\t\t%x\n",f3);
printf("the code segment is:\t%x\n",_CS);
printf("the main segment is:\t%x\n",main);
printf("main:\t%lx\n",(long)main);
printf("f1:\t%lx\n",(long)f1);
printf("f2:\t%lx\n",(long)f2);
printf("f3:\t%lx\n",(long)f3);
}
运行结果:
Debug 2.exe文件查看起反汇编代码如下:
-u 1fa
0B70:01FA C706E6040100 MOV WORD PTR [04E6],0001
0B70:0200 C3 RET 此处验证f1偏移地址为1fa
0B70:0201 C706E6040200 MOV WORD PTR [04E6],0002
0B70:0207 C3 RET 此处验证f2其偏移地址为201
0B70:0208 C706E6040300 MOV WORD PTR [04E6],0003
0B70:020E C3 RET 此处验证f3其偏移地址为208而上述的三个段地址与打印的结果不符;在这里有点小疑问!!!
0B70:020F 56 PUSH SI 此处为main函数的偏移地址
0B70:0210 57 PUSH DI
0B70:0211 BEFA01 MOV SI,01FA
0B70:0214 BFFA01 MOV DI,01FA
0B70:0217 57 PUSH DI 此处用栈传送待打印的P(f1)的偏移地址
0B70:0218 B89401 MOV AX,0194
0B70:021B 50 PUSH AX
0B70:021C E83F09 CALL 0B5E 调用printf函数打印
0B70:021F 59 POP CX
0B70:0220 59 POP CX 以上两句恢复栈平衡
0B70:0221 56 PUSH SI 此处用栈传送待打印的addr(f1)的偏移地址
0B70:0222 B8AA01 MOV AX,01AA
0B70:0225 50 PUSH AX
0B70:0226 E83509 CALL 0B5E 调用printf函数打印
0B70:0229 59 POP CX
0B70:022A 59 POP CX 以上两句恢复栈平衡
0B70:022B B8FA01 MOV AX,01FA
0B70:022E 50 PUSH AX 此处用栈传送f1的偏移地址
0B70:022F B8C301 MOV AX,01C3
0B70:0232 50 PUSH AX
0B70:0233 E82809 CALL 0B5E 调用printf函数打印
0B70:0236 59 POP CX
0B70:0237 59 POP CX 以上两句恢复栈平衡
0B70:0238 B80102 MOV AX,0201
0B70:023B 50 PUSH AX 此处用栈传送f2的偏移地址
0B70:023C B8D701 MOV AX,01D7
0B70:023F 50 PUSH AX
0B70:0240 E81B09 CALL 0B5E 调用printf函数打印
0B70:0243 59 POP CX
0B70:0244 59 POP CX 以上两句恢复栈平衡
0B70:0245 B80802 MOV AX,0208
0B70:0248 50 PUSH AX 此处用栈传送f3的偏移地址
0B70:0249 B8EB01 MOV AX,01EB
0B70:024C 50 PUSH AX
0B70:024D E80E09 CALL 0B5E 调用printf函数打印
0B70:0250 59 POP CX
0B70:0251 59 POP CX 以上两句恢复栈平衡
0B70:0252 8CC8 MOV AX,CS
0B70:0254 50 PUSH AX 此处用栈传送待打印的_CS的偏移地址
0B70:0255 B8FF01 MOV AX,01FF
0B70:0258 50 PUSH AX
0B70:0259 E80209 CALL 0B5E 调用printf函数打印
0B70:025C 59 POP CX
0B70:025D 59 POP CX 以上两句恢复栈平衡
0B70:025E B80F02 MOV AX,020F
0B70:0261 50 PUSH AX 此处用栈传送待打印的main的偏移地址
0B70:0262 B81802 MOV AX,0218
0B70:0265 50 PUSH AX
0B70:0266 E8F508 CALL 0B5E 调用printf函数打印
0B70:0269 59 POP CX
0B70:026A 59 POP CX 以上两句恢复栈平衡
0B70:026B 0E PUSH CS 因用的是long型打印故首先入栈cs,紧接着下面入栈main的偏移地址
0B70:026C B80F02 MOV AX,020F
0B70:026F 50 PUSH AX
0B70:0270 B83102 MOV AX,0231
0B70:0273 50 PUSH AX
0B70:0274 E8E708 CALL 0B5E 调用printf函数打印
0B70:0277 83C406 ADD SP,+06 恢复栈平衡
0B70:027A 0E PUSH CS 因用的是long型打印故首先入栈cs,紧接着下面入栈f1的偏移地址
0B70:027B B8FA01 MOV AX,01FA
0B70:027E 50 PUSH AX
0B70:027F B83C02 MOV AX,023C
0B70:0282 50 PUSH AX
0B70:0283 E8D808 CALL 0B5E 调用printf函数打印
0B70:0286 83C406 ADD SP,+06 恢复栈平衡
0B70:0289 0E PUSH CS 因用的是long型打印故首先入栈cs,紧接着下面入栈f2的偏移地址
0B70:028A B80102 MOV AX,0201
0B70:028D 50 PUSH AX
0B70:028E B84502 MOV AX,0245
0B70:0291 50 PUSH AX
0B70:0292 E8C908 CALL 0B5E 调用printf函数打印
0B70:0295 83C406 ADD SP,+06 恢复栈平衡
0B70:0298 0E PUSH CS 因用的是long型打印故首先入栈cs,紧接着下面入栈f3的偏移地址
0B70:0299 B80802 MOV AX,0208
0B70:029C 50 PUSH AX
0B70:029D B84E02 MOV AX,024E
0B70:02A0 50 PUSH AX
0B70:02A1 E8BA08 CALL 0B5E 调用printf函数打印
0B70:02A4 83C406 ADD SP,+06 恢复栈平衡
0B70:02A7 5F POP DI
0B70:02A8 5E POP SI 恢复进main时栈平衡
0B70:02A9 C3 RET main返回
二,遇到的问题:
在研究的过程当中,打印的段地址与debug中查看到的不一致,在这里有一点疑惑;
三,解决掉的问题:
通过本次的研究知道了如何去打印函数的段地址和偏移地址,在探究时也用了几个不同的方法去打印他们的值,其结果是一样的。
四,研究体会:
通过本次的研究,更加深一步的去了解了子函数和main函数的偏移和段地址的查找方法,因为此代码加载到内存时,其默认的段地址为cs段,故我们在此打印_CS就为这些函数的段地址,此程序有一疑问,偏移地址打印的和debug查看内存cs值是一样的,就是打印的段地址和加载到内存中的段地址数据不同!其原因为何?此问题有待于深一步的研究!!!