int val = 0x12345678;
byte_pointer valp = (byte_pointer) &val;
show_bytes(valp, 1); /* A. */
show_bytes(valp, 2); /* B. */
show_bytes(valp, 3); /* C. */ (查看原文)
You are poised for an exciting journey. If you dedicate yourself to learning the concepts in this book, then you will be on your way to becoming a rare "power programmer," enlightened by an understanding of the underlying computer system and its impact on your application programs. (查看原文)
We begin our study of systems by tracing the lifetime of the hello program, from the time it is created by a programmer, until it runs on a system, prints its message, and terminates. (查看原文)
The source program is a sequence of bits, each with a value of 0 or 1, organized in 8-bit chunks called. Each byte represents some text character in the program.
Most modern systems represent text characters using the ASCII standard that represents each character with a unique byte-sized integer value. For example, Figure 1.2 shows the ASCII representation of the hello.c program. (查看原文)
The hello.c program is stored in a file as a sequence of bytes. Each byte has an integer value that corresponds to some character.
The representation of hello.c illustrates a fundamental idea: All information in a system-including disk files, programs stored in memory, user data stored in memory, and data transferred across a network-is represented as a bunch of bits. The only thing that distinguishes different data objects is the context in which we view them. For example, in different context, the same sequence of bytes might represent an integer, floating-point number, character string, or machine instruction. (查看原文)
In order to run hello.c on the system, the individual C statements must be translated by other programs into a sequence of low-level machine-language instructions. These instructions are then packaged in a form called an executable object program and stored as a binary disk file. Object programs are also referred to as executable object files.
On a Unix system, the translation from source file to object file is performed by a compiler driver:
unix> gcc - o hello hello.c (查看原文)
The preprocessor (cpp) modifies the original C program according to directives that begins with the # character. For example, the #include <stdio.h> command in line 1 of hello.c tells the preprocessor to read the contents of the system header file stdio.h and insert it directly into the program text. The result in another C program, typically with the .i suffix. (查看原文)
The compiler (ccl) translates the text file hello.i into the text file hello.s, which contains an assembly-language program. Each statement in an assembly-language program exactly describes one low-level machine-language instruction in a standard text form. (查看原文)
Studying the assembly-code representation of a program is one of the most
effective means for gaining an understanding of the compiler and how the generated
code will run. A good strategy is to start by looking carefully at the code
for the inner loops, identifying performance-reducing attributes such as excessive
memory references and poor use of registers. Starting with the assembly code, we
can also predict what operations will be performed in parallel and how well they
will use the processor resources. As we will see, we can often determine the time
(or at least a lower bound on the time) required to execute a loop by identifying
critical paths, chains of data dependencies that form during repeated executions
of a loop. We can then go back and modify the source code to try to steer th... (查看原文)
Most major compilers, including gcc, are continually being updated and improved, especially in terms of their optimization abilities. One useful strategy is to do only as much rewriting of a program as is required to get it to the point where the compiler can then generate efficient code. By this means, we avoid compromising the readability, modularity, and portability of the code as much as if we had to work with a compiler of only minimal capabilities. Again, it helps to iteratively modify the code and analyze its performance both through measurements and by examining the generated assembly code.
To novice programmers, it might seem strange to keep modifying the source code in an attempt to coax the compiler into generating efficient code, but this is indeed how many high-performance ... (查看原文)
1. The first step in optimizing a program is to eliminate unnecessary work, making
the code perform its intended task as efficiently as possible. This includes
eliminating unnecessary function calls, conditional tests, and memory references.
These optimizations do not depend on any specific properties of the target machine.
2. Modern computers use sophisticated techniques to process a machine-level program, executing many instructions in parallel and possibly in a different order than they appear in the program. Programmers must understand how these processors work to be able to tune their programs for maximum speed. We present a high-level model of such a machine based on recent designs of Intel and AMD processors.We also devise a graphical data-flow notation to visualize the execution... (查看原文)
1. You are going to learn practical skills such as how to avoid strange numerical
errors caused by the way that computers represent numbers.
2. You will learn how to optimize your C code by using clever tricks that exploit the designs of modern processors and memory systems.
3. You will learn how the compiler implements procedure calls and how to use this knowledge to avoid the security holes from buffer overflow vulnerabilities that plague network and Internet software.
4. You will learn how to recognize and avoid the nasty errors during linking that confound the average programmer.
5. You will learn how to write your own Unix shell, your own dynamic storage allocation package, and even your own Web server.
6. You will learn the promises and pitfalls of concurrency, a topic of i... (查看原文)
People get surprisingly emotional about which byte ordering is the proper one. In fact, the terms “little endian” and “big endian” come from the book Gulliver’s Travels by Jonathan Swift, where two warring factions could not agree as to how a soft-boiled egg should be opened—by the little end or by the big. Just like the egg issue, there is no technological reason to choose one byte ordering convention over the other, and hence the arguments degenerate into bickering about socio-political issues. As long as one of the conventions is selected and adhered to consistently, the choice is arbitrary. (查看原文)