[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

[January , 13, 2008] 因为工作关系,现在又重新开始学习C语言,随手写一点笔记 Watcom C (1)

因为工作关系,现在又重新开始学习C语言,随手写一点笔记 Watcom C (1)

    		Watcom C 第一日

    之所以选择Watcom C,主要是因为有对于保护模式的支持,否则的话,

虽然自己编写4G的访问也不是什么困难的问题,但是调用DOS 或者 BIOS的

中断会出现不知所谓的问题。另外一个考虑就是:这是工作需要,普通人

看C远比看Pascal的代码轻松一些。

   之前还试验过 DGGPP 给我的感觉仿佛是一支拆成零件的强大武器,如果

说是自动步枪,摸索一下还有装配好的可能,但它确实有如坦克,我在Windows

下面摸索了好久仍然不得要领----据说这是标准的“黑客风格”?

    Watcom C 之前是商业软件,后来改为开源,资料方面还是挺全的~

网站是 http://www.openwatcom.org/index.php/Main_Page 。

我下载了最新的版本 open-watcom-c-win32-1.7.exe 。没有直接安装,

而是解压到watcomc目录下。

Open Watcom C/C++ Version 1.7 - README 中有提到如何进行配置,

我的目标就是编写直接在dos下使用的可执行文件。

DOS BAT file:
----------------------------------------------------------
@ECHO OFF
SET WATCOM=C:\WATCOM
SET PATH=%WATCOM%\BINW;%PATH%
SET EDPATH=%WATCOM%\EDDAT
SET INCLUDE=%WATCOM%\H
REM SET LIB=
REM SET WWINHELP=D:\BINW

     修改成为我自己的配置文件,命名为 comp.bat

SET WATCOM=g:\WATCOMc
set include=%watcom%\h
path %watcom%\binw
\watcomc\binw\wcl386 /l=dos4g %1

     编译时使用  comp 程序名 即可生成exe。

     下面就是我的第一个程序 hello.c

#include <stdio.h>
int main()
{
int x;
printf( "Hello world\n" );
return( x );
}
//后面要记得留一个空行

     后面最好加上一个空行,要不然会提示

“HELLO.C(7): Warning! W138: No newline at end of file”。

     comp hello.c 

     即可完成编译,生成 hello.exe 

     至此万里长征走完了第一步。

				2008-1-8

[January , 7, 2008] 鸟问题

 

			鸟问题

    这里的“鸟”,并非自然界中飞翔的那种动物,也非某种器官。这里

的意思和《水浒传》中常提到的“鸟人”中的“鸟”是差不多的。更具体说

“鸟问题”就是电视中经常看到的,运动会中记者们问夺冠运动员的那种

问题,比如“你现在拿了金牌,心情怎么样?”“除了激动还有什么想法”

“刚才我们看到你的冲刺,请问你当时为什么跑这么快?”

    经常有人问我类似问题。比如,知道我在台资企业,很多人就会好奇,

问问你们和台湾人怎么相处,随着次数的增多,我也总结出了回答方法。

如果是外人,正经的回答是“我们从来不会讨论政治问题的”,劲爆的回答是

“我们经常恐吓他们,在厕所上写着‘宁可台湾不长草,也要拿下台湾岛’,

然后看着他们表情凝重的进入厕所,表情更凝重的出来... ...”似乎人们

更喜欢这样的回答,因为答案足够刺激而不必在乎是否荒诞不经;如果是

新进来的同事一脸虔诚的问这个问题,我会告诉他我们时时刻刻盼望着早打

大打,一旦开战,这个企业马上就会军管----你知道军管是什么意思么,

就是类似于找个什么工宣队进驻企业,或者跟土改差不多吧,也说不定会封

你个厂长协助管理呢~ 说到这里我会用力拍拍提问者,他们一般都会露出憧憬

的目光,眼神会越过我的肩膀仿佛看到了他自己接替公司人资那个更年期的

妇女主持一个月一次的月会... ...

    还有的鸟问题是,“你毕业怎么来到这里了”,通常前面还会有很多赞美

性的条件,比如:“哇,你是电子科技大学毕业的”“哇,你长得这么帅”或者

“哇,你家是东北的”......对于前半句一般我都是颔首许可的样子,后面的

那个问题只好一次又一次的重复我进入公司的原因。当时,毕业考了半年研究生

未遂,成了待业青年王某,为了减少社会不安定因素,只好找工作。大学的上铺

兄弟,当时也在这家公司,就把我介绍进来了。可以想象一下那是三月份,

三月的东北依旧是天寒地冻,依旧是可以当街卖糖葫芦的季节。东北的一个待业

青年给公司投了一份简历,然后石沉大海了。三月的最后一天兄弟还在劝我,

不能一棵树上吊死啊,多投几个公司吧。四月一日,我正在和母亲买裤子,突然

接到了电话,这家公司的人资给我打电话告诉我,希望我参加4日的面试,当时

我想问问她,是不是和我开玩笑。于是乎,第二天就买了一张南下的车票出发了。

到了这边借宿在初中同学家,然后就来面试了。面试的具体内容记不得多少了,

没有让我做英语题,也没有数学题,上机做了心理测试还无法显示结果,唯一的

专业问题就是 loop 指令默认的寄存器是哪个,两个月前我正好翻译了emu8088

这个软件的帮助文件,回答这个问题还是小菜一碟。后来想想心理测试没有结果的

原因可能是记忆了不好吧,题目都是“你经常大怒吗?A.经常 B.从不 C.偶尔

D.有时”两页之后还会出现“你经常不大怒吗?A.经常 B.从不 C.偶尔 D.有时”,

可能是前面选了偶尔后面再选有时,电脑就会认为你在说谎吧。面试结束,对方

(硬件牛人)和我握手告诉我,如果面试通过星期四上午我们会给你打电话,如果

你没有接到电话,那么非常抱歉......面试后,我就去了上海,拜访好多年没有谋面

的老师,并在他家住下了。周四上午连短信都没有更不用说电话了。给我大学的兄弟

发MAIL让他帮忙问问,回信都是一砣乱码,再发他用英语回复“you are not employed”

失望之极,回来从同学家搬走,住进一家小旅馆。不知何去何从间,周五下午接到

人资电话,还是一个mm,说希望我周六去xx体检,周一入职,我还想问问“你不是

和我开玩笑吧”... ...然后就工作到了现在。

						Z.t
						2008-1-7