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