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