汉诺塔的非递归解法
分类: Other
[February , 22, 2008] Watcom C 的笔记7 Watcom C (7)
Watcom C 的笔记7 Watcom C (7)
判断是否在 Windows 下 之前使用int 2Fh,ax=1600h 的方法已经失效;现在提出检测CR0 的Bit0 (V86 enabled位)。在Windows的DOS box是 v86 mode。 #include <stdio.h> #include <i86.h> extern short isV86( void ); #pragma aux isV86 = \ "smsw ax ", \ "test ax, 1 ", \ "jz V86 ", \ "xor ax, ax ", \ "V86: ", \ "mov ax, 1 " \ value [ ax ]; void main() { if (isV86() ==0) {printf("The program is running in pure DOS\n");} else {printf("The program is running in Windows!\n");} } 实验表明,DOS下,上面的程序不好用,仍然会判断为在Windows下,因为DOS4GW 实现的也是要使得程序进入保护模式。 Function 0400H This function returns the version of DPMI services supported. Note that this is not necessarily the version of any operating system that supports DPMI. It should be used by programs to determine what calls are legal in the current environment. Pass the following information: AX = 0400H The information returned is: AH = Major version AL = Minor version BX = Flags Bit 0 = 1 if running under an 80386 DPMI implementation. Bit 1 = 1 if processor is returned to real mode for reflected interrupts (as opposed to Virtual 8086 mode). Bit 2 = 1 if virtual memory is supported. Bit 3 is reserved and undefined. All other bits are zero and reserved for later use. CL = Processor type 02 = 80286 03 = 80386 04 = 80486 05 = Pentium DH = Current value of virtual master PIC base interrupt DL = Current value of virtual slave PIC base interrupt Carry flag clear (call cannot fail) 返回值中的 BX Bit1 =1 表明返回到Real Mode下;Bit1 =0 表明返回的是V86模式下。 #include <stdio.h> #include <i86.h> void main() { union REGS r; r.w.ax=0x400; int386(0x31,&r,&r); if ((r.w.bx & 2)==0) {printf("The program is in Windows!\n");} else {{printf("The program is in DOS!\n");}} } 实验表明很好用~ Z.t 2008-1-20
[February , 18, 2008] Watcom C 的笔记6 Watcom C (6)
Watcom C 的笔记6 Watcom C (6)
命令行参数的获得 标准C语言定义如下: int main(int argc,char *argv[])。 第一个字符串 argv[0] 是包含全路径的程序名。 #include <stdio.h> int main(int argc,char *argv[]) { int i; printf("You have input %d arguments. Argv[0]=[%s]\n",argc-1,argv[0]); //argv[0] is file name for (i=1;i<argc;i++) { printf("argument %d:[%s]\n",i,argv[i]); } return 0; } G:\>getarg /L p oo.bak DOS/4GW Protected Mode Run-time Version 1.97 Copyright (c) Rational Systems, Inc. 1990-1994 You have input 3 arguments. Argv[0]=[G:\GETARG.EXE] argument 1:[/L] argument 2:[p] argument 3:[oo.bak] 修改一下,枚举文件和目录的例子: #include <stdio.h> #include <dos.h> int main(int argc,char *argv[]) { struct find_t fileinfo; unsigned rc; /* Display name and size of "*.c" files */ rc=_dos_findfirst("*.*",_A_NORMAL+_A_RDONLY+_A_HIDDEN+_A_SYSTEM+_A_SUBDIR,&fileinfo); while ( rc == 0) { //take care of this: the priority of "==" is higher than "&" if ((fileinfo.attrib & _A_SUBDIR)==0) {printf("%14s %10ld\n",fileinfo.name,fileinfo.size);} //File else {printf("%14s <DIR>\n",fileinfo.name);} //Directory rc= _dos_findnext(&fileinfo); } return 0; } 运行结果: RDTSC.C 429 PCI <DIR> PRACTICE <DIR> GETCHAR.EXE 33236 COMP.BAT 107 GETCHAR.OBJ 483 PTEST.C 667 HELLO.C 86 NOTE <DIR> PTEST.OBJ 551 PTEST.EXE 33256 GETARG.C 257 EMUFILE.C 596 MAIN.EXE 33372 MAIN.OBJ 504 R.TXT 1543 GETARG.OBJ 526 HELLO.OBJ 409 EMUFILE.EXE 33384 EMUFILE.OBJ 574 HELLO.EXE 33216 MEMTEST.OBJ 464 HELLO.ERR 54 Z.t 2008-1-19
[January , 26, 2008] Watcom C 的笔记5 Watcom C (5)
Watcom C 的笔记5 Watcom C (5)
DOS/4GW PCI 配置空间的读取 参考 http://www.openwatcom.org/index.php/PCI_Device_access_under_32-Bit_PM_DOS 很奇怪的是原文是编译不过的,需要将 Example 中的 #include "pci.h" 改为 #include "pci.c" 才能编译通过。 第一个程序:getpci.c 使用二维数组保存结果,在后面输出: #include <stdio.h> #include "pci.c" int main() { char pcicon[0x10][0x10]; uint8_t bus, dev, func; short int i,j; printf("Please input BUS DEV FUN"); scanf("%hx %hx %hx",&bus,&dev,&func); for (i=0;i<0x10;i++) for (j=0;j<0x10;j++) { pcicon[j][i]=PciReadConfigByte(bus,dev,func,(char) (j+i*16)); } for (i=0;i<0x10;i++) { printf("\n"); for (j=0;j<0x10;j++) { printf("%02x ",pcicon[j][i]); } } return( 0 ); } 第二个程序:getpci1.c 动态分配内存,使用指针保存分配的内存首地址。 #include <stdio.h> #include <stdlib.h> #include "pci.c" int main() { char *pcicon; //指针 uint8_t bus, dev, func; short int i,j; printf("Please input BUS DEV FUN"); scanf("%hx %hx %hx",&bus,&dev,&func); pcicon=malloc(0x100); if (pcicon==NULL) {printf("Error");} for (i=0;i<0x10;i++) for (j=0;j<0x10;j++) { *(pcicon+i*16+j)=PciReadConfigByte(bus,dev,func,(short int) (j+i*16)); } for (i=0;i<0x10;i++) { printf("\n"); for (j=0;j<0x10;j++) { printf("%02X ",*(pcicon+i*16+j)); } } free(pcicon); return( 0 ); } 第二个程序:getpci2.c 动态分配内存,使用数组指针。 #include <stdio.h> #include <stdlib.h> #include "pci.c" int main() { char (*pcicon)[0x10][0x10]; //数组指针(指向数组的指针) uint8_t bus, dev, func; short int i,j; printf("Please input BUS DEV FUN"); scanf("%hx %hx %hx",&bus,&dev,&func); pcicon=malloc(0x200); if (pcicon==NULL) {printf("Error");} for (i=0;i<0x10;i++) for (j=0;j<0x10;j++) { (*pcicon)[i][j]=PciReadConfigByte(bus,dev,func,(short int) (j+i*16)); } for (i=0;i<0x10;i++) { printf("\n"); for (j=0;j<0x10;j++) { printf("%02X ",(*pcicon)[i][j]); } } free(pcicon); return( 0 ); } 编译后的程序都是无法在XP下面运行的(运行结果不确定),只能在DOS下运行。 另外,参考的访问PCI配置空间的方法是调用PCI BIOS中断。 Z.t 2008-1-17
[January , 24, 2008]办证记
办证记 我的一个兄弟跳槽去了北京,婆家要求新媳妇交一个什么户籍证明,以便验明正身, 也为了安定团结,毕竟北京是“伟大祖国的首都,俺们国家的政治文化中心”,有一群 “带着三块表的”,还有“八个要脸的和八个不要脸的”。无奈,兄弟的户口还在这边, 距离北京一千多公里,于是乎,打印一份户籍证明光荣而艰巨的任务就交给了我。 他把身份证快递给我,我特意翻了一下信封,里面只有身份证。打电话过去, “除了身份没有其他的了么?”兄弟信誓旦旦的说“绝对没有!”我说“XX,邮回去的邮费 呢?”兄弟说“哦,没有!”我又说“XX,和你开玩笑呢!”他说“我知道,所以要配合一下 传统!哈哈”。 某年某月的某一个下午,我特地请了半天假,来到了派出所。一进门我发现人居然 很少,心里很高兴,印象中派出所应该是类似于农贸市场的地方,不想竟然如此冷清。 看起来气氛竟然有点怪异,四位民警阿姨面色凝重或者站或者坐,在高大的柜台后面仿佛 银行的员工在清账一般,又仿佛庙中的四大天王。 到柜台前,等了一会,其中的一个抬起眼睛瞟了我一眼,“干什么的?”我差点想 说“我交待,我全交待。”定神说道“打印户籍证明的”。说罢交上去了身份证。那兄弟 的身份证还是第一代的。大娘又瞟了一眼,扔出来道“第一代,不能开!”我忙问, “为什么不能开啊?”答曰“第一代,电脑里面没资料。”我再问,“那怎么办”? 大娘已经很不耐烦了,“去苏州,查原件”。没办法,我只好立马给身处北京的兄弟 打电话,告诉他不能办,因为什么什么,所以什么什么。打完了,我又问了一下,感觉 大娘已经很生气了,随时都可能高喊“关门放狗!”没办法,受人之托啊~ 这时,站着的 女警官说话了,你去劳动局查一下资料吧,具体位置在什么什么... ...谢过,怀揣着 微弱的希望又去劳动局了。 昆山的劳动服务是不错的,比方说,医院一进门通常有告示“工伤鉴定请上5楼”。 到了劳动局,我明白了,敢情农贸市场搬到这里了,人这个多啊。服务的是5个小姑娘, 看起来态度都非常好,想必是临时工?柜台特别低,她们坐着,办事的人几乎都趴在了 柜台上。电话响了,兄弟打过来的,开头说“老王,我刚在网上查了一下《身份证法》 ...”,说道这里,我马上打断他,开始骂道“你XXX的又不是party员,信那个XXX干XX!” 马上兄弟无语了,屋子里面的人纷纷对我投来复杂的目光... ...挂了。我心中骂道, 你就是国家主席,法律也保护不了你啊,唉上学上多了,XXX。 后面还是很顺利的,排队,交钱,打出来,邮寄回去了... ... 后来,听一个朋友说她去办暂住证的时候感觉派出所态度很好,也许是因为她说的 方言?我是纯正的东北普通话,地域歧视,毕竟他们是昆山cop,不是people cop。 2008-1-11
[January , 23, 2008] Watcom C 的笔记4 Watcom C (4)
Watcom C 的笔记4 Watcom C (4)
运行时间的计算 使用RDTSC指令取出两次之间CPU运行的周期数,可以用来 计算程序的效率。 #include <stdio.h> #include <ctype.h> unsigned __int64 rdtsc(void); #pragma aux rdtsc =\ 0x0F 0x31 \ value [edx eax] \ parm nomemory \ modify exact [edx eax] \ nomemory; int main() { int i; unsigned __int64 start = rdtsc (),avege; printf("Start at: %Ld\n",start); for (i=0;i<1000000;i++) { } avege = rdtsc () -start; printf("end at: %Ld\n",avege); return( 0 ); } 用这个东西来进行一下多位数组的访问效率测试。对于多位数组, 采用的是行优先。比如: a[2][3] 存储起来就是 a[0][0] a[0][1]... ... 在访问时,使用 a[x][y] 和 a[x][y+1] 这样的形式会有优势。 #include <stdio.h> #include <ctype.h> unsigned __int64 rdtsc(void); #pragma aux rdtsc =\ 0x0F 0x31 \ value [edx eax] \ parm nomemory \ modify exact [edx eax] \ nomemory; int main() { int i,j,k; int a[1000][1000]; unsigned __int64 start; start= rdtsc(); for (i=0;i<1000;i++) { for (j=0;j<1000;j++) { k=a[i][j]; } } printf("First method cost %Ld\n",rdtsc() - start); start= rdtsc(); for (i=0;i<1000;i++) { for (j=0;j<1000;j++) { k=a[i][j]; } } printf("Second method cost %Ld\n",rdtsc() - start); return( 0 ); } 本机运行测试结果: DOS/4GW Protected Mode Run-time Version 1.97 Copyright (c) Rational Systems, Inc. 1990-1994 First method cost 2433405 Second method cost 1702575 参考资料: http://developer.novell.com/wiki/index.php/How_to_use_RDTSC_with_Watcom_C_C-plus-plus_and_CodeWarrior_PDK 1月12日
[January , 21, 2008] 暗合
暗合 暗合,俗称“英雄所见略同”。 《三国演义》里面就有很多“暗合”的故事。首推赤壁大战之前, 诸葛亮和周瑜在一起讨论破曹计策,双方都想到火攻,于是都在手心写 上一个“火”字----江湖传说诸葛亮手心什么都没有写,只是在双方 掌心相对的时候,直接从周瑜的手心印出来的。此为暗合也。后面还有, 曹操写了一部兵书,《孟德新书》,杨修拿给张松看了,没成想,张松 过目不忘。张松有意和曹操说,这本书是“盗版”吧?我以前看过, 是战国一位不知姓名的人写的,然后就一字不差的背了出来。曹操大惊, 心想“莫非我与古人暗合”?遂命人烧了这本书... ... 另外,野史记载当年王勃在阎都督的宴会上一挥而就写《滕王阁序》, 阎都督的女婿不服气,说这个我在什么地方看过,然后背诵了一遍。王勃 哈哈大笑,说你那个最多是古人与我“暗合”,我这后面还有一首诗, 说罢,又添了一首: 滕王高阁临江渚,佩玉鸣鸾罢歌舞。 画栋朝飞南浦云,珠帘暮卷西山雨。 闲云潭影日悠悠,物换星移几度秋。 阁中帝子今何在?槛外长江空自流! 前几天,我偶然在网上看了一本《毛泽东自传》,是太祖口述,斯诺 记载的。太祖描述童年生活,说自己家是“父党母党”。我看后大惊, 怎么和我奶奶家一样了?暗合啊!父亲在给我讲他过去经历的时候,常常 这么说,那时候我还并不了解,今日竟在此处“暗合”。翻看后面, 太祖说他最喜欢的一本书是《盛世危言》,记得一个叔叔也曾经这样和 我说过,原来是在此“暗合”啊! 等我有孩子的时候,在他还不认字的时候,一定要给他讲许许多多“我” 小时的故事,比如我父亲给我买了一把斧头,正好我家后面有一棵樱桃树; 或者我上劳动课认真做出一个丑陋的小板凳;还有我学母鸡孵鸡蛋等等。 当他长大的时候一定会惊讶与他父亲与伟人的种种暗合吧? 2008-1-10
[January , 19, 2008] Watcom C 的笔记3 Watcom C (3)
Watcom C 的笔记3 Watcom C (3)
Watcom C 显示指定内存位置的值 终于完成了显示指定内存位置的程序,在XP下显示1MB以内的没有问题,最高 可能到16MB吧,应该和cmd.exe的设置有关系,但是不确定。WC没有DOS下面的IDE 环境,用起来没有TC顺手。 下面是程序代码,这个程序在TC3下无法正常工作,估计是因为TC使用的还是 segment:offset的内存形式而不是线性的。 #include <stdio.h> #include <ctype.h> int main() { unsigned long int address; unsigned char *data; unsigned int i,j; printf("Please Input the address:"); scanf("%lx",&address); //取得地址,按照16进制输入,无论前面是否有0x都认为是 //十六进制 for (i=0;i<0x10 ;i++ ) { printf("%08lxh ",address); //输出8位长的十六进制 for (j=0;j<0x10;j++) { data=(unsigned char*)(address+j); printf( "%02X ",*data); //输出2位大写的十六进制字符串 } for (j=0;j<0x10;j++) { data=(unsigned char*)(address+j); if (isprint(*data)) //如果是可以显示的字符,则输出 {printf( "%c",*data);} else {printf(".");} } printf("\n"); address+=0x10; } return( 0 ); } //后面要记得留一个空行 前面不添加 #include <ctype.h> 在编译过程中会出现一个warning GETCHAR.C(23): Warning! W131: No prototype found for function 'isprint' 不过对编译结果没有影响~ 错误代码 W131 可以在 cguide.pdf 上查到。 界面不是很漂亮,有空再研究一下Turbo Vision好了~ 2008-1-9
[January , 16, 2008] Watcom C 的笔记2 Watcom C (2)
Watcom C 的笔记2 Watcom C (2)
WatcomC + DOS4GW 非常郁闷,在网上查了好久如何使用 Watcom C 访问 4G 内存,无果。 自己也在试验,从资料上看 Watcom C 自带的 Dos4GW 版本是 1.97,只能 访问 32MB内存 (http://www.tenberry.com/dos4g/watcom/4gwtable.html) 我编写了一个程序来验证如何访问,一直没有成功。 最终发现是我的程序写错了,试验是否有32MB限制,结果是“没有!”; 再试验是否有64MB限制,结果还是是“没有!”(试验的方法是用其他dos工具 向这个内存位置写值,如果能够读取出来,就是没有限制,如果有限制,则应该是 一个回转到 0MB的地方)最后试验直接读取4G的位置,那里有BIOS信息。哭死, 居然读出来了,就是说我前面的工作都是白费的,这个编程工具在DOS下根本就没 有内存方面的限制! memtest.c #include <stdio.h> int main() { unsigned long int address=4*1024*1024*1024-256; unsigned char *data; unsigned int i; for (i=0;i<0x100 ;i++ ) { data=(unsigned char*)(address); printf( "%c",*data); if ((i+1) % 16 ==0) {printf("\n");} address+=1; } return( 0 ); } //后面要记得留一个空行 使用 comp memtest.c 编译运行,运行结果会出现 0AAA000 等字样。 下面是使用工具dump 4G的结果,可以看出就是这个样子的: 0D 00 00 00 00 00 00 00 00 00 00 00 00 24 42 54 53 ............$BTS 0E 30 41 41 41 41 30 30 30 20 07 12 04 08 07 08 00 0AAAA000 ....... 0F EA AA FF 00 F0 31 32 2F 30 34 2F 30 37 00 FC 00 .....12/04/07... 在 XP 下面编译运行了一次,结果是崩溃的,想必如此。 DPMI (DOS Protected Mode Interface) 是保护模式的DOS扩展器和实模式的DOS 之间的接口。 总结:如果一个问题在网上没有人问,那么它肯定不是一个问题。 2008-1-8
[January , 14, 2008] 逃课记
逃课 近来看了一条新闻,一个著名教授和一个女学生发生龌龊(这样写似乎太暧昧了), 缘起这个授上课无人捧场,感觉学生“很不给面子”,恰好一个女生当堂离开,授不允, 二人吵,女不盛怒,蹄之... ... 我大学的时候不是好学生,不过逃课不算多。一来神经衰弱到点就醒,二来没有吃 喝嫖赌的恶习,不去上课也无聊。 印象中逃课的原因,多半是因为课程实太没有意思了。记得一次上C语言,刚开场人满 为患,上了一节就走了一半。老师是个男的,很害羞,犹如刚过门的小媳妇,而台下都是 她的公公婆婆。老师从一开始就拿起课本,从头开始念,真的是“照本宣科”。课堂过半, 也许是发现自己念的太快了,照这个速度,3天就能“上完”吧,于是停顿,结果一抬头, 好家伙,半屋子人没有了... ... 然后,这个老师就很生气的样子... ...后面的情形记不 清楚了。大约记得他后来想了很多办法挽留“观众”。比如,不定期的点名。点名是抽点, 我们在下面多有“相互照应”。再后来,人气是在太低了,还惊动了辅导员,让她象羊倌 一样,看着我们到课堂,大门关上才离开... ... 对我来说,即使是大学,仍然是填鸭式的教学,死记硬背仍然是主体。更关键的是根本 缺少对于自由精神的培养。所谓的学习,更多的是“让你接受这个观点”或者记住某个 结论,虽然每个老师都宣扬“我教授的是方法”,但是真正讲述为什么的却不多。我认为, 大学过程中,最重要的是自学能力的培养,以及独立思考的精神。不过后者似乎过于危险, 有了精神免不了会有不和谐的想法。安全第一,安全第一,据说骡子们都是脾气温顺的。 Z.t 2008-1-14