- [游客] 原来如此,以前做的时候也是一跳而过 01/10 23:37
- [游客] 赞 03/19 16:36
- [xzg6145] 我到了课程设计1,后面内容比较容易,等学完再复习下,然后写几个小游戏得瑟下,感觉以后很美好!!! 03/26 10:55
- [xiaoyao2012] 人情情人,人随情,情走人止 11/02 15:53
- [fpamc] 回看这篇文章。。 感受颇有不同。。。 我会继续往下走。。。 06/16 10:14
- [dxiaolin] 受教了 05/31 21:21
- [tomato] 支持你弄个chm出来。 05/29 16:33
- [fpamc] 收藏一下……有时间无聊了就弄chm`(*∩_∩*)′ 05/29 14:16
- [tomato] 这些命令刚动手实验了一遍,收获还是蛮大的。 05/29 13:04
- [chinatree] 在c中取段地址: 例: #include <stdio.h> f1() { re 05/27 10:00
- [游客] [url=http://www.banjia126.com/banjiachangshi/92.ht 07/26 23:46
- [jeremy] 能加你扣扣吗?我的469614823 08/07 14:36
- [e56004474] 好久不见tomato 活跃拉。。 06/18 13:39
- [fpamc] 正在研究17章…… 近期路线是…… 17章实验--复习-滚屏算法-截取中断来应用动态时间-复习- 05/29 14:19
- [xuehuihui] 请问检测点2.2的填空地(2)题第一个空到底是10001H对 还是1001H 对?谢谢 急 05/15 16:34
- [gnunix] 我的检测点3.2第二小题的sp设置的有问题吧? 05/13 09:48
- [gnunix] 谢谢番茄老师的提醒,我会改进的! 05/12 12:20
- [fpamc] 好久没见老师了。每当提交完作业,都希望老师快速的批阅。得到老师小小的夸奖。看见同学们都在努力学习,相 05/05 23:16
- [fpamc] 会的,我会的,我一定会做出来的,而且做到我内心所想的,更重要的,不会让tomato老师失望。 我想 04/21 08:42
- [sbxinran] 谢谢tomato老师给我检查作业,如果我的分析方法有错误还请您多指点指点 04/11 12:43
[2012-05-25 23:37] 【转】一个C语言题目
int a;
void f1(void)
{
a=1;
}
void f2(void)
{
a=2;
}
void f3(void)
{
a=3;
}
main()
{
...
}
转自:http://tieba.baidu.com/p/1611780801
学习C语言的哥们儿可以做一下哦!
[ chinatree 发表于 2012-05-26 18:09 ]
老师看看我这个:
#define FP_OFF(fp) ((unsigned)(fp))
#define FP_SEG(fp) ((unsigned)(unsigned long)(fp>>16))
/*这两个宏在Dos.h中定义*/
int main(void)
{
printf("f1=%#X %X\nf2=%#X %X\nf3=%#X %X",
FP_SEG(f1),FP_OFF(f1),FP_SEG(f2),FP_OFF(f2),FP_SEG(f3),FP_OFF(f3));
return 0;
}
[ chinatree 发表于 2012-05-26 18:14 ]
哦,忘记main的了,可以相同方法实现。
#define FP_OFF(fp) ((unsigned)(fp))
#define FP_SEG(fp) ((unsigned)(unsigned long)(fp>>16))
/*这两个宏在Dos.h中定义*/
int main(void)
{
printf("f1=%#X %X\nf2=%#X %X\nf3=%#X %X\nmain=%#X %X",
FP_SEG(f1),FP_OFF(f1),FP_SEG(f2),FP_OFF(f2),FP_SEG(f3),FP_OFF(f3),FP_SEG(main),FP_OFF(main));
return 0;
}
[ tomato 发表于 2012-05-26 19:35 ]
想复杂了。不用这么麻烦。
[ tomato 发表于 2012-05-26 19:37 ]
提示一下,看看《汇编语言》综合研究部分第四节中是如何打印main函数的地址的。
[ chinatree 发表于 2012-05-26 22:43 ]
那打印的只是偏移地址,段地址不能直接得到。
上面那个宏错了。应该是:
#define FP_SEG(fp) ((unsigned)((unsigned long)(fp)>>16))
[ tomato 发表于 2012-05-26 22:59 ]
不是不能直接得到,可以直接得到。
打印偏移地址用这个:
printf("%x",f1);
打印段地址用这个:
printf("%lx",f1);
试一下是不是这样。
可以简单解决的问题,尽量不要搞得很复杂。
[ chinatree 发表于 2012-05-27 00:26 ]
虽然复杂些,但是通用啊。支持取变量的段地址哩。
[ chinatree 发表于 2012-05-27 10:00 ]
在c中取段地址:
例:
#include <stdio.h>
f1()
{
return ;
}
int main()
{
printf("%lx",f1);
return 0;
}
例子很简单,用长整型16进制打印出f1的地址,反汇编后大致如下:
push bp; int main(){
mov bp,sp
mov ax,cs
push ax
mov ax,xxxx
push ax; f1地址压栈
mov ax,xxxx;"%lx"压栈
call printf
add sp,6;平衡栈,c调用约定
mov sp,bp
mov ax,0
ret; return 0;}
可以看到,在压栈时,把段地址也压栈了.再来个例子
int main()
{
int i;
printf("%lx",&i);/*注意这里有错误*/
return 0;
}
反汇编后大致是这样的:
push bp
mov bp,sp
lea ax,[bp-2]
push ax ;&i
push xxxx; "%lx"
call printf
pop cx
pop cx;编译器优化,add sp,4需要3字节
mov sp,bp
mov ax,0
ret
可以看到,这次并不会把段地址压栈,也就是说printf("%lx",&i);会读越界,所显示的并不是i的段地址了.
再来一个:
fun()
{
return ;
}
int main()
{
fun();
return 0;
}
反汇编后大致是这样的:
retf ;fun(){return;}
push bp; int main(){
mov bp,sp
push cs
call near ptr fun; fun();
mov sp,bp
xpr ax,ax ;return 0;
ret ;}
结论如下:
对于函数名(本身也是个地址)参与时,会先把函数的段地址压栈.而对于普通指针而言,只是简单的把偏移地址压栈.另外有一种极端的情况,如: unsigned char *p=(unsigned char *)0xa0000000;这时p占两个字,当它参与时,如:printf("%lx",p);会把它的两个字都压栈,有兴趣的话可以试试.