五三记 中关村的水啊深又深 又是“五一”,这是我在北京度过的第一个劳动节,三天假期。 本打算去“家*乐*福”看看热闹,正好有事情,没去成。等到有空了,在网上 搜索“家*乐*福”惊奇的发现无论是baidu还是google都表示“这个东西不存在”。汗。 缩短关键字绕过去,找到某人的blog,似乎什么都没发生。想必也是真的没有发生 什么吧,大家还是相应了xxx的号召,度过了一个平和安详的劳动节。 3号,被隔壁装修的电钻吵醒。起来准备上街。天色昏暗,一眼望去,竟然有黄昏 的错觉,天,非常严肃的阴沉着。带伞,外套。逛街去了~ 先去银行,开通可以支付的网上银行,交水煤气费会省事许多,到了北大北门只见 上面挂着横幅“庆祝北大建校110周年”。有很多人在照相,白天照出夜景效果。我拿出 手机拍了张,回来一看:果真是夜晚的效果,除了灯泡耀出的光点,其余部分一片漆黑。 回来baidu一下,“北京大学创建于1898年”,历史真的蛮长的,同西南交大有得一拼。 清华建校于1928年,原来以为他们是一起建立的。现在知道北大是清华他爹那辈的了。 天色越发阴沉,仿佛晚上七八点。路上的车都打开了前灯,楼中也都开了灯。 走着走着,我头顶一闪,心中一紧,不由得快“走”了起来。虽然江湖传闻,雷公雷母 只打坏人,但是,没准有打歪的时候。一阵小跑,穿过马路,翻越护栏,冲进了工商 银行。刚进门,伴随着巨大的雷声,外面的雨下起来了。 这家银行位于中关村图书大厦附近,周末人很少,莫非是因为附近没有住宅区? 门口牌子上提示,您可能需要等待20分钟,但是排号大约只有2分钟就到了。我要开户, 实践证明,银行之间关于网上银行的规定差别还是挺大的。比如,招商银行,只容许 开设一个网上银行账号,其余的无论你是在什么地方办的账号只能挂在这个账号 下面。我去开户的时候,对方突然问我以前是不是开设过账号?我想了一下,敢情 1999年在学校的时候开过,里面还有50元,卡还在我手中,密码已经忘记了很多年。 工商银行,你可以开多个。比如,我在昆山开过一个网上银行,现在北京又可以开一个。 刚开始服务小姐不知道,本打算将昆山账号帮我注销掉。后来才发现可以同时开设2个的。 之后我又去中关村图书大厦转了一圈,书非常多,办个会员卡就可以打8折,和网上 购书差别不大,最主要是网上购书配送总是瓶颈。转了2个多小时。相中了几本书,用手机 拍下封皮,等以后有时间有精力再来买。我现在最大的问题是没有时间和精力来看书。 床上一本《联想风云》,已经翻看了个把星期,竟然还没有看完,惭愧之极。 中午吃的麦当劳,注意到他的门都是从里面向外推的,后来又光顾了一下肯德基 (不是吃东西)发现它的门也是这样的。不知道其他的麦肯店是不是也是这样的呢? 吃麦当劳,点了一份套餐,装可乐的是非常夸张的带吸管的塑料杯。端的时候,服务员 特地提醒,请用双手,容易翻... ...等我坐下了,边上来了几个学生就给我表演了一下 单手拿托盘,他们的杯子哗的一下翻了~ 水淹七军。 顶风冒雨,打算去买个小灵通,公司晚上经常开电话会议,只有固定电话或者小灵通 接入才是免费的,而我的住地没有固定电话,一般是在楼下的IC卡机器上拨打。拨打免费, 但是,深更半夜,一个精壮的男人,胯下红色的自行车,占着电话机一言不发,一听就是 1个小时,难免招来怀疑的目光。 海龙,鼎好门口聚集着很多拉客的人,他们用“秃鹫”的眼神打量着每一个过往者。 口中念到,数码相机看一下,笔记本电脑看一下。有时候还会拉你,让人很不舒服。据说 他们给拉上一位客人到某个摊位,就会有几十元的提成。转了半天,智能手机很多,黑莓 手机很多,小灵通没有。 转出去,准备到对面的科贸看看。过了马路,对面有一家华信通电讯,店面挺大,看起 来很正规。进去问了一下价格,感觉不贵,就在那里买了部ZTE V190,花了399,又买了张 充值卡。回来上网一查,这部小灵通报价在100-150,被人宰了。更不幸的是,我发现 将小灵通的SIM卡,放在公司的小灵通上竟然也可以用。早知道买个号码就可以了。 总结:中关村水很深,到哪里买东西最好现在网上查询好。然后,进去只买你查好的那个 东西,其余不计。唉,这次是花钱买个教训吧。
[April , 23, 2008] 三无产品:管理小故事
三无产品:管理小故事
三无产品:管理小故事 最近又看余世维先生的管理讲座,发现他基本上不用那种管理小故事来说明问题了。许多年前, 他的管理讲座中有很多小故事,比如日本人参观北洋水师的定远号,伸手一摸发现炮管里面灰很大, 必定平常疏于打扫,于是断定舰队没有战斗力;还有镇远在船尾晾衣服… … 上班4年,每月的早会都会有一个台干来“分享管理小故事”。我们的喇叭通常只认女人,尖锐的 声音很容易从中播出,而男人的声音听起来多像狗叫。偶然有几个能让人听得清楚的男人讲述的管理 小故事必定是“从频谱功率上来说,高音部分功率谱密度较大”。因此,几年下来还记得的小故事不多, 有一个是卖鞋的去非洲市场调查,悲观的人报告那边的人没有穿鞋的习惯,所以我们没有市场;乐观的 人调查结果是,那边市场很大,大家都光脚… …讲这个故事的时候,我一直在疑心话锋一转会讲应该 先给当地的医生卖钉子,再买治疗脚伤的药品和工具,最后卖鞋子—-这样的做法称为营销(一次我去 测试组转悠,有一个dd在复习准备考试,其中的一道填空题是“营销的目的是创造需求”)。还有一个 有点印象的故事是动物园的斑马经常跑出来,于是管理部门不断加高围栏,结果斑马还是能跑出来。后来 斑马和邻居长颈鹿聊天说“如果他们继续忘记锁门,围栏再高我也会跑出来”。 我已经过了喜欢这样的小故事的年龄了。并且这样的小故事多是“三无产品”,同江湖传闻中那些 “吃人的树”和“神秘的金字塔”等等很类似。好比现在告诉我说某人,小时候特别笨,长大了学习也不好, 后来坚持读书,读到了博士,引申出来不断坚持,不断进取再笨的人也可能成功。我一定摇头不相信, 现实中,这样的事情发生的唯一理由是他有很多好爷爷或者爸爸。 以前还有个经典的管理小故事:说某家牙膏厂,面向员工征集提高销量的办法,许诺重金奖励, 在各种方案中最终采纳的是非常简单的方案“加大牙膏口1mm”… …当时我觉得这个是非常好的主意, 直到有一天我突然发现这个方法不能保证降低成本甚至会很愚蠢。是这样的,我在床上喝矿泉水,一瓶是 农夫山泉,另一瓶是娃哈哈的。我试验将农夫山泉的瓶盖拧在娃哈哈上,竟然严丝合缝,反之亦然。为什么 这样是这样的?原因很简单:标准化工业生产。制造饮料的公司,如果连瓶子瓶盖都要自己生产,那他 肯定是国企。“正常思维”的企业都会找其他公司直接买,自己把关质量就可以了。从外面买能降低很多成本。 而生产瓶盖的公司则会采用同样的模具为不同家生产,这样,不同牌子的矿泉水瓶盖相同不足为奇了。再回 到上面的小故事,你就会发现这个故事的荒谬之处了。修改口径之后,装牙膏的容器要重新设计,盖子也要 重新设计。这些是很大的花费。 若干年前,还有个经典小故事:说一个拾荒者与众不同,善于思考,别人只是捡易拉罐,而他花了600块 到金属研究所测试了易拉罐中各种金属的含量,发现其中有很多有价值的金属,于是自己开始提炼这些金属。 这个故事告诉我们要多观察,多思考,多动脑。后来,我在《知音》杂志上看到了一篇类似的文章,颇感惊讶。 开头都非常相似,那个人提炼金属,很快发家致富,老婆都娶了5个。最后的结局是进监狱了,不是因为重婚, 而是因为他偷电。融化金属需要大量的电,他在输电线上做手脚… …我宁愿相信这个故事是真是的,很多 东西我们不去做,原因很可能是成本太高。这样说说似乎有吃不着葡萄就说葡萄是酸的意味…… 房屋都是有使用寿命的,哪怕你修建之时用料再扎实也是这样的。国外有很多旧房屋改造加固的项目, 有人看好这样的项目,希望引入国内。但是经过一番考察发现这是不可能的,原因是:成本太高。国外,这样的 项目费用通常接近重新建造。而国内,这样高的成本来维护旧房子,人们根本不接受。或者一拆了之,再建 新房。 总而言之,事物是诸多因素交织在一起的,单独的强调某个方面是不科学的,甚至与真实的决定因素大相径庭。 我想也正是因为这样的小故事过于捕风捉影,正龙打虎,余世维先生在他的讲座中也不愿意使用了吧? Zoologist 2008-4-23
[April , 16, 2008] 离职指南
离职指南
离职指南 许许多多年以前,偶然父亲听说单位(大型国有企业)有两个“人事干部”。一个负责 “进口”,就是负责考核招聘干部;另一个负责“出口”,基本上工作就是送葬等等善后工作。 据说前者脾气非常好,态度也非常好,后者与之截然相反。后来我接触到心理学,尝试着 使用心理学的观点进行分析,有很多种解释。不过现在想起来,这个和心理学什么关系都 没有,完全是利益的问题:你招聘的时候谁知道进来的人是领导的七大姑还是八大姨? 谁知道招进来的干部是否会成为他的上司?而负责出口的则完全没有顾虑,他“送出去”的 干部永远不会再见的。 通常与XX课打交道非常痛苦,因为他们总是认为很多事情都是常识,比如:政府公文 “都”必须用黑色水笔填写(黑色圆珠笔不行,蓝黑色钢笔不行)。当我说我不知道的时候, 人资一个mm用惊异的表情看着我,仿佛她刚知道自己吃下了什么似的。其实,我要问问她 身为一个在主板制造为主的公司呆了n多年,你可知道当今最流行的 LGA775接口的CPU有 多少脚,她肯定回答不正确----没接触过,谁TMD知道啊! 闲话不提,下午三点之后,到人资取离职单。主意必须是三点之后,这样的刻意安排让我 很不理解。也许是上峰考虑经过一天紧张激烈的工作,应该让手下放松一下,找机会发泄 一下吧。早于这个时间去,通常他们会用瞪着绿豆的眼神看着你,说三点后过来。如果此刻 心情不好,必定补充道“你们有看到过通知么”?仔细回想起来,还真没少收过各种龟“腚”。 不过时日一长,总是不清楚哪里是头哪里是尾的。 记得带一支笔,他们那边没有多余的。会让你填三份单子。还要找到最近一次的合同交 上去。如果没有的话,说说好话,借他们的复印一下。这里我非常怀疑他们把我当成日本鬼子, 我问是否可以借来复印的时候,某人居然一口咬“腚”说他们没有,都上交了... ... 多问几个 人就好了,总会有人说漏嘴的。另外,还要交上去一份什么户籍证明,档案在人力资源有限 公司的,需要去青阳路的劳动局打印出来,收费是2元。尽量多打电话问问先,这方面,昆山的 政府部门还是非常不错的。需要注意,公司在这里还有个“腚”,打印完证明之后,必须去派出所 盖章。劳动局的工作人员说,其他公司都没有这个手续的。 然后,把三份单子,合同,户籍证明,交上。换来一张移交手续办理单。去成仓,零仓找人 签字。正常情况下不会有什么问题。法务也不会有什么问题。之后跑电子公文,将能转出去的都 转出去。财产将会是非常麻烦的事情。东西很多的话你就有种被当作土豪被“打”的感觉。你还会 发现名下会平白“多”出很多东西。最常见的就是“不小心”,工作机里面的东西在外面又列出 一次。遇到这种情况,最好及时解释清楚,能早解决就尽量早解决,也给后继者方面的,大家 都是同事,枪口对外。我们这时候也要理解YY课的行为,他们不琢磨多点事情怎么体现价值, 怎么表现很忙碌的样子,此之谓“有困难要上,没有困难创造困难也要上”,是也。 上面的东西签下来,大约要2天时间。之后可以去找会计签字。他要检查你的财产是否已经 清理干净。他们使用ERP的网站查询,ERP会比电子公文再慢上3-4天(YY课自己承认的)。也就 是说,你的电子公文中可能什么东西都没有了,但是ERP上还有一大坨。解决方法是将跑完的电子 公文打印出来,给会计看一下。保存好这个电子公文,说不定后面还要给总务课show出来。 顺便提一句:除非你有特别的信心----比如老大渴望你马上滚蛋,或者你爬的职位足够高, 否则,报废物品上缴的时候,千万要记得,找那个“没收”你物品的人签名留作纪念。我在去年报废 几样物品,上缴时说非常敬仰,好不容易瞻仰到容貌,请他签了字(先见之明,事实上当时我说 的是“哥们我信不着你”)。果真,即至离职的时候惊奇的发现报废单跑了4个月居然没有跑完。 而没签的人,恰好是XX课“最有常识的人”。找她的时候,她竟然和我要看报废的东西。不过好 在我拿出那张签字的单子,她最后没有抵赖。前车之鉴引以为戒,害人之心不可有。 余下还有总务课要签字,退工衣之前必须先退水卡才可以。退这些东西的时候要记得 带上那个离职单,否则去了也没有用。需要注意,他们不会主动给你免穿工衣卡,除非你还有 工衣,否则警卫会找你的麻烦。ps:他们就没有给我,也许这个又是我不知道的常识:( 还有取消资讯权限,要通过电子公文申请取消,这样做多少有点自废武功的意思。 最后,找老大再签字。交给人资,他们会给你一个小纸片,上面注明日期。在那个日期的 12之前必须离开公司,隐约仿佛宾馆客栈。不知道如果商量一下过几天再走是否可行? 还有一项非常非常重要的事情就是离职单。公司规定是你离职之日之后的15天。如果你是 4日走的,那么19日左右才能拿到这个单子。并且这个单子对于你入职来说非常重要。 很多大公司必须凭借这个单子才能报道。因此在开始最好计算清楚。通常可以和对方公司 商量着来的。多出来的时间你可以用来熟悉环境,或者像我一样,用这些时间认真钻研2个 单机游戏。 最后的抒情:当我摘下胸口的钥匙交上去之后(不好意思,幼稚了,我一直把寝室 钥匙挂在了胸前),再戴上工牌,就隐隐的觉得胸口少了点什么。木然回首(工程师做久 了人都这样),我已经在公司呆了四年。从面带青涩,慌张应付客户的毕业生,成为 即使对待FAE也是连唬带蒙的工程师。四年间我改变了很多。床铺,我已经睡了3年(第一年 睡上铺),已经符合人体工程学(床板某处裂了,碎了)。 天是阴沉沉的,大雄在我身后用力的挥着手,亲爱的朋友们,我们不知何时才能够再次 相见;不知何时我才能对你们再说一次“I am back!” Zoologist 2008年4月5日
[April , 12, 2008] 汇编语言作业的作弊方法 本文程序和工具
汇编语言作业的作弊方法 本文程序和工具
ah 汇编语言作业的作弊方式 帮着朋友写汇编语言作业(好像从小到大我经常帮别人写作业),前后花了一个星期,没写出来。感觉很糟糕, 出题老师疯了,居然要求学生用汇编语言写学生成绩管理系统。要求“能够实现菜单显示、菜单选择、编辑(录入、 插入、修改、删除等)、查找、显示、求总成绩、按总成绩排序(高→低)并显示、装入数据文件、数据文件存盘、 退出、为数据动态分配存储空间等功能”。这样的要求仿佛是给学生火柴棍和502胶水,要求制作能装人的船---- 理论上完全能实现,实际上可行性不高。 既然没写出来,自然要琢磨“歪门邪道”。方法就是用C语言直接写出功能。编译之后有2条路可以选择: 1.反编译为汇编语言;2.插入在汇编语言中。 花了大约4个小时编写了简单的C语言程序,用TC3正常编译,生成 xy.exe 再使用 exe2bin 生成 xy.com文件。 不清楚什么地方的问题,最开始使用TCC -mt -lt xy.c 可以直接编译为 xy.com 文件。选择生成 com文件的原因是 它没有段切换的问题,使用非常方便,也足够小。 xy.com的大小是18,576byte,一般来说汇编程序的源程序大小是它生成的机器代码的7-8倍。反过来估计, 如果手写汇编,完成这些功能就需要大约 140000byte 的源程序... ...这就是我说出题老师疯了的原因...... 使用IDA 5反编译,结果太难看懂了,估计老师一眼就能看出来“代码不是人写的”。顺便提一句:IDA5的功能 好强大,反编译后直接能够生成程序的流程图(接近);使用IDA4 反编译了一下,结果也过于复杂,整理起来非常 困难。 看起来想直接反出来汇编程序这条路走不通。 第二条路,用汇编程序包括这个文件,这个是名副其实的“作弊”,不过看起来更专业。我想如果有汇编语言老师 能看到我的这个文章,并且发现有同学用我这个方法,不妨放他们一马吧,你的题目太难了能理解/想到这个方法的人 就是对汇编认识很深刻的了。 具体方法,用工具 bin2inc 将 xy.com 转化为 x.inc,然后将程序写成这个样子: .model tiny ;为了表示你是一个认真的同学,这里可以插入宏 .data ;为了表示你是一个专业的同学,这里可以插入数据定义 .code ;为了表示你不想让老师一眼看出问题的同学,这里可以插入过程 .startup include x.inc ;为了表示你写了很多,这里可以插入代码 .exit end 实际上,程序的关键只有 include x.inc 这句话。 交作业的时候,需要交上上面的程序和x.inc 。 最后的话,我将东西做完,交给朋友。朋友没同意,觉得 x.inc 太难解释清楚。后来不得不再花了十几个小时给他 写纯汇编语言的作业。未来如果有一个以生成汇编语言代码为目标的简单C编译器,中国学生的汇编语言作业将不会是 什么难题。 Zoologist 2008-4-12
[March , 26, 2008] Watcom C 的笔记14 Watcom C (14)
Watcom C 的笔记14 Watcom C (14)
[March , 25, 2008] Watcom C 的笔记13 Watcom C (13)
Watcom C 的笔记13 Watcom C (13)
生成 .COM 文件的 BUG? 如下程序: #include <stdint.h> main () { uint32_t wsize=64*1024,length=0x12345678; return length/wsize; } 编译命令: SET WATCOM=\watcomc set include=%watcom%\h path %watcom%\binw wcc bbb.c /ms wlink system com file bbb.obj 运行期会出现除零错误 “Divide overflow”。 查看代码发现它使用下面的代码处理这个乘法 seg000:030F mov ax, 5678h seg000:0312 mov dx, 1234h seg000:0315 xor bx, bx seg000:0317 xor cx, cx seg000:0319 call sub_104DB seg000:031C pop dx seg000:031D pop cx seg000:031E pop bx seg000:031F retn seg000:031F sub_10306 endp 子程sub_104DB是使用bx作为除数的除法过程。计算这个除法的 过程很有意思,是分开,先计算 1234h / bx ,再计算 (余数+5678h)/ bx 的。也许这样处理应该是防止结果过大溢出的吧。 如果让代码生成 DOS4GW的 EXE文件就不会有这样的问题。 暂时的猜测是 Watcom C 生成 COM 是默认在16位代码方式下的。它在处理 32位的数据上是有问题的,应该避免这样的情况。 Zoologist 2008-3-25
[March , 24, 2008] Watcom C 的笔记12 Watcom C (12)
Watcom C 的笔记12 Watcom C (12)
函数指针的简单试验 函数指针是:指向一个函数的指针。 #include <stdio.h> void (*ptr)(); void func1() { printf( "This is function 1 \n" ); } void func2() { printf( "This is function 2 \n" ); } int main() { ptr=func2; (*ptr)(); ptr=func1; (*ptr)(); return( 0 ); } Zoologist 2008-3-20 参考: 【1】:来自 http://www.yourblog.org/Data/20041/2519.html 作者:在黑暗中举起探索的火炬 指针函数和函数指针有什么区别 1,这两个概念都是简称,指针函数是指带指针的函数,即本质是一个函数。我们知道函数都又返回类型(如果不返回值,则为无值型),只不过指针函数返回类型是某一类型的指针。其定义格式如下所示: 返回类型标识符 *返回名称(形式参数表) { 函数体 } 返回类型可以是任何基本类型和复合类型。返回指针的函数的用途十分广泛。事实上,每一个函数,即使它不带有返回某种类型的指针,它本身都有一个入口地址,该地址相当于一个指针。比如函数返回一个整型值,实际上也相当于返回一个指针变量的值,不过这时的变量是函数本身而已,而整个函数相当于一个“变量”。例如下面一个返回指针函数的例子: #include float *find(); main() { static float score[][4]={{60,70,80,90},{56,89,34,45},{34,23,56,45}}; float *p; int i,m; printf("Enter the number to be found:"); scanf("%d",&m); printf("the score of NO.%d are:\n",m); p=find(score,m); for(i=0;i<4;i++) printf("%5.2f\t",*(p+i)); } float *find(float(*pionter)[4],int n)/*定义指针函数*/ { float *pt; pt=*(pionter+n); return(pt); } 学生学号从0号算起,函数find()被定义为指针函数,起形参pointer是指针指向包含4个元素的一维数组的指针变量。pointer+1指向 score的第一行。*(pointer+1)指向第一行的第0个元素。pt是一个指针变量,它指向浮点型变量。main()函数中调用find()函数,将score数组的首地址传给pointer. 2,“函数指针”是指向函数的指针变量,因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上一致的。函数指针有两个用途:调用函数和做函数的参数。函数指针的说明方法为: 数据类型标志符 (*指针变量名)(参数);注:函数括号中的参数可有可无,视情况而定。 下面的程序说明了函数指针调用函数的方法: #include int max(int x,int y){ return(x>y?x:y); } void main() { int (*ptr)(); int a,b,c; ptr=max; scanf("%d,%d",&a,&b); c=(*ptr)(a,b); printf("a=%d,b=%d,max=%d",a,b,c); } ptr是指向函数的指针变量,所以可把函数max()赋给ptr作为ptr的值,即把max()的入口地址赋给ptr,以后就可以用ptr来调用该函数,实际上ptr和max都指向同一个入口地址,不同就是ptr是一个指针变量,不像函数名称那样是死的,它可以指向任何函数,就看你像怎么做了。在程序中把哪个函数的地址赋给它,它就指向哪个函数。而后用指针变量调用它,因此可以先后指向不同的函数,不过注意,指向函数的指针变量没有++和--运算,用时要小心。 junglesong 转载www.chinagpa.com
[March , 20, 2008] Watcom C 的笔记11 Watcom C (11)
Watcom C 的笔记11 Watcom C (11)
结构体对齐 我是不主张使用汇编语言学习算法的,最主要的原因是汇编语言并不适合 构造复杂的数据结构。当然,在内存特别紧张的情况下,必须使用汇编语言做算法, 将会是非常痛苦的事情。我曾经研究过一段压缩代码,从上面的部分特征来看, 似乎是先用C语言实现算法,再尝试逐步转化为汇编语言的。额外的话题:BIOS 中的代码大部分是压缩后再存放的。AMI的压缩比大约高出Award 20-30%(个人 估计:) 下面是我写程序中使用的结构体,编写中需要确定结构体中每个成员是否处在内存 中正确的位置,诸如freg0要在 50h 偏移处...... struct spistruct{ uint32_t bfpr; //00-03 BIOS Flash Primary Region uint16_t hsfsts;//04-05 Hardware Squuencing Flash Status uint16_t hsfctl;//06-07 Hardware Sequencing Flash Control uint32_t faddr; //08-0B Flash Address uint32_t rsrvd1;//0C-0F Reserved uint8_t fdata[0x40];//10-13 Flash Data 0 //14-4F Flash Data N uint32_t fracc; //50-57 Flash Region Access Permissions uint32_t freg0; //54-57 Flash Region0 uint32_t freg1; //58-5B Flash Region1 uint32_t freg2; //5C-5F Flash Region2 uint32_t freg3; //60-63 Flash Region3 uint32_t freg4; //64-67 Flash Region4 uint8_t rsrvd2[12];//68-73 Reserved uint32_t fpr0; //74-77 Flash Protected Range 0 uint32_t fpr1; //78-7B Flash Protected Range 1 uint32_t fpr2; //7C-7F Flash Protected Range 2 uint32_t fpr3; //80-83 Flash Protected Range 3 uint32_t fpr4; //84-87 Flash Protected Range 4 uint32_t rsrvd3[2];//88-8F Reserved uint8_t ssfsts;//90 Software Squency Flash Status uint16_t ssfctl1;//91-92 uint8_t ssfctl2;//93 //91-93 Software Squency Flash Control uint16_t preop; //94-95 Prefix Opcode Configuration uint16_t optype;//96-97 Opcode Type Configuration uint8_t opmenu[8];//98-9F Opcode Menu Configuration uint32_t bbar; //A0-A3 BIOS Base Address Configuration uint32_t rsrvd4[3];//A4-AF Reserved uint32_t fdoc; //B0-B3 Flash Descriptor Observerability Control uint32_t fdod; //B4-B7 Flash Descriptor Observerability Data uint32_t rsrvd5[2];//B8-BF Reserved4 uint32_t afc; //C0-C3 Additional Flash Control Register uint32_t lvscc; //C4-C7 Host Lower Vendor Specific Component Capabilities Register uint32_t uvscc; //C8-CB Host Upper Vendor Specific Component Capabilities Register uint32_t rsrvd6;//CC-CF Reserved uint32_t fpb; //D0-D3 } ; 最初,我采用的是笨办法:给成员赋值,然后查看是否出现在应该的内存位置。 后来发现了一个很好用的宏,它是标准库的扩充,可以直接使用: #define offsetof(type,memb) ((size_t) & ((type *) 0)->memb 参考[2] 使用的例子: printf("[%lx] [%x]\n",spi->opmenu[0],offsetof(struct spistruct,opmenu) ); 随后调试中又发现 ssfctl1 成员总是不能处在正确的位置上。经过研究发现, 结构体中有一个"对齐"的问题。因为内存如果对齐的话,会节省访问时间。我们希望 成员处于91h的位置,而由于对齐,编译器会将其放在92h处对齐。 Watcom C 中上述问题可以用下面的方法解决: #pragma pack(1) //指定按照 1 byte 对齐 struct spistruct{ uint32_t bfpr; //00-03 BIOS Flash Primary Region uint16_t hsfsts;//0 ... ... ... ... ... ... ... ... ... ... ... ... 参考: [1] 败中求胜——Qdieyou个人工作室 http://blog.csdn.net/Qdieyou/archive/2007/04/26/1585715.aspx [2]《C语言参考手册》 P325 Zoologist 2008-3-20
[March , 17, 2008] DOS下的C语言编辑器 我之前之前一直使用Boxer,感觉很糟糕。这个编辑器似乎是专门为Watcom C 设计的,不过最好不要配置在IDE中编译,我试验发现编译经常会死机。也许以后有时间我会考虑写一个类似Turbo C的编辑器吧。
DOS下的C语言编辑器 我之前之前一直使用Boxer,感觉很糟糕。这个编辑器似乎是专门为Watcom C 设计的,不过最好不要配置在IDE中编译,我试验发现编译经常会死机。也许以后有时间我会考虑写一个类似Turbo C的编辑器吧。
[March , 15, 2008] Watcom C 的笔记10 Watcom C (10)
Watcom C 的笔记10 Watcom C (10)
局部变量在内存的位置 在编写一个com文件的时候,遇到奇怪的问题:编译正常,运行后显示 “Stack Overflow!”。程序片段如下: #include <stdio.h> int main(int argc,char *argv[]) { int i,n; FILE *f; long int sum=0; char buffer[2048]=; //1K 就在这里指定一个做buffer的变量 if (argc!=2) {printf("usage: checksum file 试验表明,如果在1024之上就会出现这个错误。在编译过程中,还发现 这个地方的大小不会影响生成com文件的大小。查阅资料【参考1】,上面说 局部变量存放在堆栈中... ...因此如果太大了自然会出现堆栈溢出的问题。 设置为全局变量就可以了,这样并不会影响生成文件的大小,看起来仍然是 在运行过程中动态分配的。分配在代码和堆栈之间的空间。具体如何确定,还不 清楚。 编译批处理文件 mkchk.bat wcc checksum /ms wlink system com file checksum 源程序: #include <stdlib.h> #include <stdio.h> char buffer[0xC000]; //48K int main(int argc,char *argv[]) { int i,n; FILE *f; unsigned long int sum=0; if (argc!=2) {printf("usage: checksum filename\n"); exit(1);}; //argv[0] is executable file name f=fopen(argv[1],"r+b"); if (f==NULL) {printf("File open error!");} n=fread(buffer,sizeof(char),sizeof(buffer),f); while (n!=0) { for (i=0;i<n;i++) { sum=sum+buffer[i]; } n=fread(buffer,sizeof(char),sizeof(buffer),f); } printf("Checksum in BYTE: %12hX\n",sum & 0xFF); printf("Checksum in WORD: %12X\n", sum & 0xFFFF); printf("Checksum in DWORD: %12lX\n",sum); return 0; } 运行结果: G:\watcomc>checksum dos4gw.exe Checksum in BYTE: 40 Checksum in WORD: 3E40 Checksum in DWORD: F0153E40 参考: 1.http://topic.csdn.net/t/20040316/12/2848204.html 2008-3-15 Zoologist