• 博客访问： 40143
• 博文数量： 14
• 博客积分： 1472
• 博客等级： 上尉
• 技术积分： 160
• 用 户 组： 普通用户
• 注册时间： 2009-02-09 09:34

2013年（6）

2011年（1）

2010年（6）

2009年（1）

2010-01-15 16:57:45

2009-09-03

fireskyli

vidalid
firefox
foxyproxy

### Low Level Operators and Bit Fields

We have seen how pointers give us control over low level memory operations.

Many programs (e.g. systems type applications) must actually operate at a low level where individual bytes must be operated on.

NOTE: The combination of pointers and bit-level operators makes C useful for many low level applications and can almost replace assembly code. (Only about 10 % of UNIX is assembly code the rest is C!!.)

The bitwise operators of C a summarised in the following table:

 & AND OR XOR One's Compliment << Left shift >> Right Shift

DO NOT confuse & with &&: & is bitwise AND, && logical AND. Similarly for and .

is a unary operator -- it only operates on one argument to right of the operator.

The shift operators perform appropriate shift by operator on the right to the operator on the left. The right operator must be positive. The vacated bits are filled with zero (i.e. There is NO wrap around).

For example: x << 2 shifts the bits in x by 2 places to the left.

So:

if x = 00000010 (binary) or 2 (decimal)

then:

or 0 (decimal)

Also: if x = 00000010 (binary) or 2 (decimal)

or 8 (decimal)

Therefore a shift left is equivalent to a multiplication by 2.

Similarly a shift right is equal to division by 2

NOTE: Shifting is much faster than actual multiplication (*) or division (/) by 2. So if you want fast multiplications or division by 2 use shifts.

To illustrate many points of bitwise operators let us write a function, Bitcount, that counts bits set to 1 in an 8 bit number (unsigned char) passed as an argument to the function.

 int bitcount(unsigned char x)    		 { int count;   				 for (count=0; x != 0; x>>=1); 						 if ( x & 01) 								 count++; 				 return count; 		 }

This function illustrates many C program points:

• for loop not used for simple counting operation
• x x = x >> 1
• for loop will repeatedly shift right x until x becomes 0
• use expression evaluation of x & 01 to control if
• x & 01 masks of 1st bit of x if this is 1 then count++

Bit Fields allow the packing of data in a structure. This is especially useful when memory or data storage is at a premium. Typical examples:

• Packing several objects into a machine word. e.g. 1 bit flags can be compacted -- Symbol tables in compilers.
• Reading external file formats -- non-standard file formats could be read in. E.g. 9 bit integers.

C lets us do this in a structure definition by putting :bit length after the variable. i.e.

 struct packed_struct { 		 unsigned int f1:1; 		 unsigned int f2:1; 		 unsigned int f3:1; 		 unsigned int f4:1; 		 unsigned int type:4; 		 unsigned int funny_int:9; } pack;

Here the packed_struct contains 6 members: Four 1 bit flags f1..f3, a 4 bit type and a 9 bit funny_int.

C automatically packs the above bit fields as compactly as possible, provided that the maximum length of the field is less than or equal to the integer word length of the computer. If this is not the case then some compilers may allow memory overlap for the fields whilst other would store the next field in the next word (see comments on bit fiels portability below).

Access members as usual via:

pack.type = 7;

NOTE:

• Only n lower bits will be assigned to an n bit number. So type cannot take values larger than 15 (4 bits long).
• Bit fields are always converted to integer type for computation.
• You are allowed to mix normal'' types with bit fields.
• The unsigned definition is important - ensures that no bits are used as a flag.

Frequently device controllers (e.g. disk drives) and the operating system need to communicate at a low level. Device controllers contain several registers which may be packed together in one integer (Figure ).

Fig.  Example Disk Controller Register We could define this register easily with bit fields:

struct DISK_REGISTER  {      unsigned ready:1;      unsigned error_occured:1;      unsigned disk_spinning:1;      unsigned write_protect:1;      unsigned head_loaded:1;      unsigned error_code:8;      unsigned track:9;      unsigned sector:5;      unsigned command:5; };

To access values stored at a particular memory address, DISK_REGISTER_MEMORY we can assign a pointer of the above structure to access the memory via:

struct DISK_REGISTER *disk_reg = (struct DISK_REGISTER *) DISK_REGISTER_MEMORY;

The disk driver code to access this is now relatively straightforward:

/* Define sector and track to start read */  disk_reg->sector = new_sector; disk_reg->track = new_track; disk_reg->command = READ;  /* wait until operation done, ready will be true */  while ( ! disk_reg->ready ) ;  /* check for errors */  if (disk_reg->error_occured)   { /* interrogate disk_reg->error_code for error type */     switch (disk_reg->error_code)     ......   }

Bit fields are a convenient way to express many difficult operations. However, bit fields do suffer from a lack of portability between platforms:

• integers may be signed or unsigned
• Many compilers limit the maximum number of bits in the bit field to the size of an integer which may be either 16-bit or 32-bit varieties.
• Some bit field members are stored left to right others are stored right to left in memory.
• If bit fields too large, next bit field may be stored consecutively in memory (overlapping the boundary between memory locations) or in the next word of memory.

If portability of code is a premium you can use bit shifting and masking to achieve the same results but not as easy to express or read. For example:

unsigned int  *disk_reg = (unsigned int *) DISK_REGISTER_MEMORY;  /* see if disk error occured */  disk_error_occured = (disk_reg & 0x40000000) >> 31;

Exercise 12507

Write a function that prints out an 8-bit (unsigned char) number in binary format.

Exercise 12514

Write a function setbits(x,p,n,y) that returns x with the n bits that begin at position p set to the rightmost n bits of an unsigned char variable y (leaving other bits unchanged).

E.g. if x = 10101010 (170 decimal) and y = 10100111 (167 decimal) and n = 3 and p = 6 say then you need to strip off 3 bits of y (111) and put them in x at position 10xxx010 to get answer 10111010.

Your answer should print out the result in binary form (see Exercise  although input can be in decimal form.

Your output should be like this:

   x = 10101010 (binary)    y = 10100111 (binary)    setbits n = 3, p = 6 gives x = 10111010 (binary)

Exercise 12515

Write a function that inverts the bits of an unsigned char x and stores answer in y.

Your answer should print out the result in binary form (see Exercise  although input can be in decimal form.

Your output should be like this:

   x = 10101010 (binary)    x inverted = 01010101 (binary)

Exercise 12516

Write a function that rotates (NOT shifts) to the right by n bit positions the bits of an unsigned char x.ie no bits are lost in this process.

Your answer should print out the result in binary form (see Exercise  although input can be in decimal form.

Your output should be like this:

   x = 10100111 (binary)    x rotated by 3 = 11110100 (binary)

Note: All the functions developed should be as concise as possible

Dave Marshall
1/5/1999

2009-09-03

fireskyli

2009-09-03

fireskyli

### 如何成为一名黑客

To follow the path:（沿着这样一条道路：）
look to the master,（寻找大师，）
follow the master,（跟随大师，）
walk with the master,（与大师通行，）
see through the master,（洞察大师，）
become the master.（成为大师。）

（同样你必须对你自己的学习能力建立信心——相信尽管当你对某问题近乎一无所知，但只要你一点一点地试验、学习，最终会掌握并解决它。）

(你不必认为一定要把你 所有的发明创造公布出去，但这样做的黑客是赢得大家极度尊敬的人。卖些钱来养家糊口，租房买计算机甚至发大财和黑客价值观也是相容的，只要你别忘记你还是个黑客。)

(对此有一个明显的例外。黑客有时也做一些在他人看来是重复性或枯燥的工作以进行"脑力休息"，或是为了获得某种技能，或是获得一些除此以外无法获得的特别经验。但这是自愿的——有脑子的人不应该被迫做无聊的活儿。）

(这并非向所有权威挑战。儿童需要监护，罪犯要被看管起来。 如果服从命令得到某种东西比起用其他方式得到它更节约时间，黑客可以同意接受某种形式的权威。但这是一个有限度的，有意的交易；那种权威想要的个人服从不是你应该同意给予的。)

Java也是好的入门语言。它比Python难得多，但是生成的代码速度也快得多。它同时也是一种优秀的计算机语言，不止是用来入门。

C非常有效率，节约你的机器资源。不幸的是，C的高效是通过你手动做很多底层的管理（如内存）来达到的。底层代码都是复杂极易出现bug的，会使你花极多的时间调试。如今的机器速度如此之快，这通常是得不偿失——比较明智的做法是使用一种运行较慢、较低效率，但大幅节省你的时间的语言。因此，选择Python。

LISP值得学习的理由不同——最终掌握了它时你会得到丰富的启迪和经验。这些经验会使你在以后的日子里成为一个更好的程序员，即使你实际上很少使用LISP本身。

（注：如果你是一个新手，我不推荐自己独立安装Linux或者BSD。安装Linux的话，寻求本地Linux用户组的帮助；或联系 。 LISC维护着一些 ，在那里你可以获得帮助。）

Linus Torvalds，一个芬兰人，用英语注释他的代码（很明显这对他来说不是凑巧）。他流利的英语成为他能够管理全球范围的Linux开发人员社区的重要因素。这是一个值得学习的例子。

（过去我们称之为"free software （自由软件）"，但这却使很多不知 free 的精确含义的人感到困惑。现在我们很多人，根据搜索引擎网页内容分析至少有2：1的比率，使用" "software（开放源代码软件）这个词）。

• 学会流畅地用母语写作。尽管程序员不能写好文章的错误看法相当普遍，但是有令人惊讶数目的黑客（包括所有我知道的最棒的）都是不错的作家。

• 阅读科幻小说。参加科幻小说讨论会。（一个碰到黑客和未来会成为黑客的人的好方法）

• 学禅，并且/或者练功习武。（精神修炼看来是惊人相似。）

• 练就能分析音乐的听觉，学会鉴赏特别的音乐。学会玩某种乐器，或唱歌。

• 提高对双关语、文字游戏的鉴赏能力。

• 不要使用愚蠢的，哗众取宠的ID或昵称。

• 不要卷入Usenet（或其他地方的论坛）的骂战。

• 不要自称为"cyberpunk（网络叛客）"，也不要浪费时间和那些人打交道。

• 不要让你寄出的Email或张贴的帖子充满错误的拼写和乱七八糟的语法。

Peter Seebach 维护着一个非常好的 ，专给那些不懂如何与黑客打交道的经理看的。如果Peter的站点不能访问，下面这个 应该有一份拷贝。

Rick Moen写了一份很好的关于 的文档。

Visual Basic特别糟糕。它是Microsoft的私有语言这个事实就足够让它脸面全无，不像其他的Basic，它是一种设计糟糕的语言会教给你坏的编程习惯。

C 确实重要，但它要比 Python 或 Perl 难多了。不要尝试先学 C。

Windows用户不要满足于 Visual Basic。它会教给你坏习惯，而且它不可以移植，只能在Windows下运行。避免它。

2009-09-03

fireskyli

0