[March , 20, 2008] 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

发表评论

电子邮件地址不会被公开。 必填项已用*标注