原文在: http://sun.lynx.blog.163.com/blog/static/120905237200952702454214/

6月20日,随团参加了成都中国青年旅行社组织的稻城亚丁7日游,这是做了一个月的功课研究决定的,因为有两本书都推荐这条线路,一本书是《中国自助游 2009》,一本书是《恋恋四川》,写这两本书的作者,真不知你们居心何在?再加上四川省旅游局大力的宣传和推广,最终选择了这条线路。
然而,此行却成了我的梦魇之旅,原本想象的是一趟梦幻之旅,7天之后,是满怀希望而去,满怀失望而归,7天,坐了7天的车,每天平均坐车10个小时,沿途看到的不是美丽的风光,而是村民,牧民对环境的破坏,自家的河流里随处可见随手扔下的垃圾。
第一天,成都-泸定-丹巴,沿途无风景可看,只是看了看二郎山隧道,泸定桥。早上6点出发,晚上7点,到达丹巴,坐了13个小时的车,拍了张二郎山隧道和泸定桥的照片。雅安的飞仙关堵车,泸定-丹巴的路况不好。
第二天,丹巴-八美-新都桥,丹巴-八美沿途路况还可以,八美-新都桥的路况极差,土路,沿途可谓尘土飞扬,早上7点出发,晚上8点到达,据说新都桥被某 位摄影大师评为”摄影家的天堂”,这位摄影大师的摄影技术如何,不敢恭维,但是这位大师的嘴上功夫一定了得,真能忽悠,佩服,佩服。对了,新都桥的治安较 差,晚上没事,游客不要瞎溜达。
第三天,新都桥-理塘-稻城,翻越五座大山,可笑的是某人拿着高度表,随时看着海拔高度,是旅游,还是羡慕高度来的。沿途风景没什么可看的,看看山,看看 垃圾。沿途车发生了故障,勉强从新都桥开到理塘,在理塘修车,车修好了,没油,幸亏同行的一位游客,因为去年汶川地震,私人慰问过抗震救灾武警官兵,找到 当地的驻军,借了点油,车才可以继续前往稻城(可这位游客最后也差点成为司机殴打的对象)。再次,不由得感谢和敬佩我们的人民子弟兵,遇到困难时,永远是 我们最可爱的人在帮助我们,感谢帮助过我们的理塘驻军官兵们。这也是此行最大的收获,感动了一把。这一天,早上7点出发,第二天的凌晨2点到达稻城,坐车 做的让你这辈子都不想再做了,这哪里是旅游观光,光没观赏,真正成了一把驴子。
第四天,稻城-亚丁,可能因为昨天的车马劳累,大家起的也都比较晚,司机也不紧不慢的晃悠,直到下午4点才到亚丁村。沿途开了四个小时的车,今天还算轻 松。到了亚丁,就赶紧骑马去冲古寺,花费了40元的骑马费,上去后,看到一座破旧不看的寺院,周围牛粪,马粪到处可见,然后,步行到卓玛拉错,下起了雨, 只看到一潭洼水,这就是传说中的卓玛拉错湖吧,后面有点雪山的影子。徒步了四公里,花费了四十元,看到的就是这些,失望,悲怆。下山后,已经快八点了。
第五天,继续亚丁之旅,重新花40元骑马到冲古寺,然后50元电瓶车,最后300元骑马到所谓的牛奶海,原来就是一个方圆不到1公里的一个小湖泊,后面有 点雪山的背景,这也许是这七天唯一看到的一点点风光,为了这点点风景,我们花费了6天的车马颠簸,翻山越岭,我们的运气还算不错,还看到了雪山,有的人因 为赶上雨,什么也没有看到,就结束了7天的旅程。值得一提的是在亚丁的花销,从亚丁到冲古寺骑马1.5公里(去40元,回城30元),冲古寺到洛绒牛场 4.1公里乘电瓶车(去50元,回来50元),牛场到牛奶海往返300元,不骑马上去,很困难,我很佩服石家庄的三位驴友,全程徒步。核算起来,总共花销 了470元看了昙花一现的雪山风景,真不明白,为什么会有人推荐这条线路。
第六天,稻城-新都桥,开始返程,坐了一天的车,早上7点出发,晚上7点到达新都桥,再次看了所谓的“摄影天堂”,再次骂了那位冠以“摄影天堂”的大师。
第七天,新都桥-康定-成都,新都桥到康定总共76公里,车开了6个小时,在尘土飞扬之中,品位了“康定情歌”,在飞沙走石之中,感受了“康定情歌”,漫 天飞舞的尘土,仿佛置身在双旗镇刀客,泥泞的道路想起了红军爬雪山,过草地,真的是感受了一把红军。76公里的道路,建国60周年了,改革30年了,这条 路还依旧如此,主管这条路的政府职能部门,你们不该反思吗?四川省大力推广旅游事业,难道就是这样的路在迎接远方的客人吗?不敢恭维。
这7天中,驾驶川V 06559的司机周宾,服务极差,不但和导游发生冲突,而且把这种矛盾转嫁到游客身上,因为分为标准团和豪华团,两个团分住不同的宾馆,标准团到游客连续 三天徒步背着自己沉重的行李从一个宾馆走到另一个宾馆,其中一天赶上外面下着小雨,泥泞的道路溅起过往车辆的泥水,其中在亚丁,几位50多岁的人背着自己 的行李爬坡走到另一个宾馆,司机不管接送。6月25日,导游订的是6:30在蓝月谷宾馆集合,标准团的游客要把行李放到车里,司机到点没有起床,车门无法 打开,游客一直等着司机。一位女游客当司机出来时,质问司机为什么不守时,结果司机不但不开车门,反而谩骂该游客,争执本来就是过去就过去的事。没想到的 是6月26日,回到成都一下车,该司机竟然提前纠集了4个人预先在停车点等着这位女乘客夫妇,准备殴打这夫妇二人,在众人的劝说下,总算安全把这夫妇二人 送走。我看了此事,只能表示愤慨,四川省大力推动旅游事业,竟然还会发生这样的事件,你还会来四川旅游吗?今天,在网上查询四川旅游投诉电话打了几个不是 无人接听,就是空号,下面的号码打不通:
成都市旅游投诉电话:96927
成都市旅游局  028-87706026

原来所谓的投诉也形同虚设,请你们不要再什么熊猫卡了,别在忽悠我们这些游客了,我,下次绝不来四川旅游。稻城-亚丁线路,中国旅游的垃圾线路。
附图,川V 06559

泥泞的康定情歌之路

路这样几时能修好?

所谓的亚丁风光,不过如此,不看也罢

九寨黄龙不过如此,不看也罢
珍珠滩瀑布大金铃小金铃熊猫海碧水蓝天

徘徊?探秘?只是看看一个叫天府之国的地方。

creating a ssh tunnel using plink

if you are working in a censored/filtered network, or just feel insecure surfing pron at work, plink is a nice tool for you.
using plink you can create your own personal proxy. all you need is a ssh account somewhere on the net.

1. download plink(it is from the creators of putty)
2. write a batch file or just in a terminal:

plink -v -D 127.0.0.1:3388 -l sshlogin -pw sshpassword sshserver -P 22

(change sshlogin/sshpassword/sshserver to your needs.)
3. to use this tunnel in firefox, open it, go to preferences / connections / socks-host – enter 127.0.0.1 and port 3388
4. you are now surfing over a ssh connection.

now firefox still uses the default dns server, which means, sites could still be censored, or someone could log your dns request. to change this (for firefox): enter as url: “about:config” , find “network.proxy.socks_remote_dns”, change value to “true”.

push ebp
mov ebp,esp
mov esi,dword ptr ss:[ebp+8]

push 1次,esp 的值会减4

在高级语言中函数调用是很普通的了,但对于其汇编级别的掌握还是不太容易,文章中会涉及寄存器以及数据指令的相关汇编知识.在谈正文前先大概介绍下,
产生汇编代码的阶段: 一个程序首先,C预处理器会扩展源代码,插入所有用#INCLUDE命令指定的文件,并扩展所有的宏.其次,编译器产生两个源文件的汇编代码,名字分别为 P1.S和P2.S.接下来,汇编器会将汇编代码转化成二进制目标代码文件P1.O和P2.O.最后,连接器将两个目标文件与现实标准函数库的代码合并, 并最后产生可执行的文件.
C预处理器—-à编译器—-à汇编器—-à连接器
反汇编语言(Equivalent assembly language): 由于目标代码给阅读造成了障碍,而反汇编的格式与目标代码非常接近,因此对于汇编调试来说,看懂反汇编是很有价值的.
数据传送指令&寄存器:比如mov,lea等以及寄存器的使用规则;建议参考汇编语言书籍.注意不同的汇编器对于指令的定义有所不同,在VC中mov ebp esp 表示将寄存器esp值赋给寄存器ebp,以下代码均如此.
栈帧结构:IA32 程序用栈来支持过程调用.栈用来传递参数,存储返回信息,保存寄存器一供以后恢复等,为单个过程分配的栈叫做栈帧.注意,对于每个过程系统都将为其单独分 配一个独立的栈帧,而寄存器的使用是共享的.其最顶端是以两个指针定界的,寄存器%ebp作为帧指针,而%esp作为栈指针
远调用与近调用:子程序的调用指令分为近(near)调用和远(far)调用,这里我们记住一个结论,远调用的返回地址占8个字节,近调用的返回地址占4个字节.
注:这里涉及很多汇编知识,请大家多多参看
大家对以上知识有了了解后就可以开始下面的内容了,以下C代码展示了2个函数的调用:
———————————————————————–
int swap_add(int *xp,int *yp)
{
int x=*xp;
int y=*yp;
return x+y;
}
int caller()
{
int arg1=534;
int ary2=1057;
int sum=swap+add(&arg1,&arg2);
return 0
}
main()
{
caller();
}
———————————————————————–
上面caller()调用了函数swap_add(),并且通过地址传递参数.下面我们来看看系统是怎么传递参数、调用函数、寄存器使用以及是如何进栈出栈的.下面是VC6.0下的反汇编代码对应上面的源码.
———————————————————————–
10:   int caller()  //为便于理解,我将汇编代码的顺序按照函数调用的次序来展示的,真实应该按照前面的标号来
11:   {
00401070   push        ebp                                     //将ebp入栈,大多数信息的访问都是相对于帧指针的,而esp是永远、

始终指向栈顶的,不要期望通过控制它的相对位置来访问其他位置

00401071   mov         ebp,esp                              //将栈顶值赋给ebp,这时的ebp就指向栈顶了,当然esp仍然指向栈顶

这里仅仅是对ebp赋值而已

00401073   sub         esp,4Ch                              //将esp减去48h,这时内存中将藤出一定空间用来为以后存放局部变

量,后头将会看到是如何存放的
00401076   push        ebx                                      //ebx,esi,edi是作为”被调用者保存”寄存器,也就是说在被调函数要访
00401077   push        esi                                      //问某个寄存器时,我们样避免被调者修改覆盖了主调用函数稍后会
00401078   push        edi                                      //使用的寄存器,我们必须在被调者覆盖前将其保存到起来,调用结束                                                                                     后再恢复原来的值.当然这里所谓的”保存/恢复”就是压栈和弹栈
00401079   lea         edi,[ebp-4Ch]
0040107C   mov         ecx,13h
00401081   mov         eax,0CCCCCCCCh
00401086   rep stos    dword ptr [edi]
12:       int arg1 = 534;
00401088   mov         dword ptr [ebp-4],216h    //将216h(534)值放入相对于ebp-4的位置
13:       int arg2 = 1057;
0040108F   mov         dword ptr [ebp-8],421h    //将421h(1057)值放入相对于ebp-8的位置
14:       int sum = swap_add( &arg1,  &arg2);
00401096   lea         eax,[ebp-8]                           //计算arg1的地址放入eax,并压栈
00401099   push        eax
0040109A   lea         ecx,[ebp-4]                           //计算arg2的地址放入ecx,并压栈
0040109D   push        ecx
0040109E   call        @ILT+5(_swap_add) (0040100a)     //调用swap_add函数,同时将call指令下面的地址作为返
回地址压入栈中,注意这两个动作是在一个call指令内同
时完成的 (到此系统开始调用swap_add函数)
004010A3   add         esp,8
004010A6   mov         dword ptr [ebp-0Ch],eax
15:
16:        return 0;

004010A9   xor         eax,eax
17:
18:   }

004010AB   pop         edi
004010AC   pop         esi
004010AD   pop         ebx
004010AE   add         esp,4Ch
004010B1   cmp         ebp,esp
004010B3   call        __chkesp (00401110)
004010B8   mov         esp,ebp
004010BA   pop         ebp
004010BB   ret
—————————————————————————
1:    #include <stdio.h>
2:    int swap_add(int *xp, int *yp)
3:    {

00401030   push        ebp                                                  //ebp继续压栈,接到call()函数的返回地址压入 的
00401031   mov         ebp,esp
00401033   sub         esp,48h
00401036   push        ebx
00401037   push        esi
00401038   push        edi
00401039   lea         edi,[ebp-48h]
0040103C   mov         ecx,12h
00401041   mov         eax,0CCCCCCCCh
00401046   rep stos    dword ptr [edi]                               //以上注释与call()原理相同,但请注意ebp寄存器值(相对位
置)的改变
4:        int x = *xp;
00401048   mov         eax,dword ptr [ebp+8]                     //这里的x=*xp显然是个赋值语句,如果只从C代码来看很容
易知道*xp指向的值是arg1(534),那么程序是怎么知道的
呢?这段汇编叫告诉了我们答案,子程序通过自己栈帧中的
ebp+8 的偏移量来访问了存放在主调函数call()栈帧中
arg1,arg2 的地址从而进一步访问到他们的具体值.那么,为
什么是加8的偏移量呢?在预备知识中有个叫远调用的东西,
因为返回地址占据了8个字节,推理,如果是近调用这里就应
该是加4个字节了.这个就是很常用的”寄存器传递参数”,到
此,参数如何传递,寄存器如何使用就应该比较清楚了.图解1
0040104B   mov         ecx,dword ptr [eax]
0040104D   mov         dword ptr [ebp-4],ecx                      //将得到的具体值放如自己的栈帧中,相对位置在ebp-4,为
局部变量
5:        int y = *yp;
00401050   mov         edx,dword ptr [ebp+0Ch]               //相当于EBP+12
00401053   mov         eax,dword ptr [edx]
00401055   mov         dword ptr [ebp-8],eax                      //同理
6:
7:        return x + y;
00401058   mov         eax,dword ptr [ebp-4]
0040105B   add         eax,dword ptr [ebp-8]                      //将最后的返回结果放入eax中
8:    }
0040105E   pop         edi
0040105F   pop         esi
00401060   pop         ebx
00401061   mov         esp,ebp
00401063   pop         ebp
00401064   ret                                                                      //从过程调用中返回
————————————————————————————–
内存是这样的…..
↓                       ↓
内存地址                  堆栈
┆                  ┆
├──────┤
│       ebp    │
├─┄┄┄┄─┤
│216h (arg1)│
├─┄┄┄┄─┤
│216h (arg1)│
├─┄┄┄┄─┤
┆ 4ch的空间  ┆
┆                ┆                   兰色为call()的栈帧结构
│                │
│                │
├─┄┄┄┄─┤
│ ebx/esi/edi│
├──────┤
│    &arg2    │
├──────┤
│    &arg1    │
——–|
├──────┤              |
│   返回地址  │             | (ebp+8访问call()栈帧中的&arg1)图解1
├──────┤              |                       |
│      ebp     │_________|                       |
├─┄┄┄┄─┤                                       |
│         x     │←————————–|
├─┄┄┄┄─┤
│         y     │
├─┄┄┄┄─┤
┆ 48h的空间  ┆
┆                ┆               黑色swap_add的栈帧结构
│                │
│                │
├─┄┄┄┄─┤
│ ebx/esi/edi│
├──────┤
┆        .     ┆
│        .     │
│        .     │
├─┄┄┄┄─┤ (如果swap_add还要调用其他函数,那么结构就类似了)
到此,整个过程就介绍完了,我们可以看到,对于每个函数过程,系统 都为其分配了单独的栈,也就是所谓的栈帧,仔细观察代码可以进一步发现,每个过程的汇编代码有几部分都是大致一样的,这就提示我们系统对每个过程分配方式 都是统一的,也就是说先给你分配好了,至于怎么用再看具体情况,其实我们可以把代码看成三部分:(建立部分)作用是初始化栈帧;(主体部分)执行过程的实 际计算,(结尾部分)恢复栈的状态和过程返回.至于怎么返回,内存如何释放,堆栈如何平衡等问题就是以上过程的反推.
结语:我个人认为适当的掌握些硬件汇编知识对于我们学生来说很有帮助,这也是受我们学校一位老师的启发,以我为鉴,我想作为一个计算机学生可以适当的做些 项目,但不要沉迷于某些项目的反复开发当中,这对自己知识结构的搭建没有太大好处,平时应该”做做学学,学学做做”,最后还是应该回到书本当中,同时在不 同的实践中深刻体会知识,检验自己,这样才会有提高.说实话写博客真很耗时啊,不过在这个过程中也算自己巩固下知识.

Next Page »