Normal quotes
This commit is contained in:
parent
5e10794a24
commit
18011c595a
352 changed files with 6040 additions and 6040 deletions
52
04-01.md
52
04-01.md
|
|
@ -21,19 +21,19 @@ of PC programmers to pedal-to-the-metal optimization.
|
|||
This chapter focuses almost entirely on the first popular x86-family
|
||||
processor, the 8088. Some of the specific features and results that I
|
||||
cite in this chapter are no longer applicable to modern x86-family
|
||||
processors such as the 486 and Pentium, as I’ll point out later on when
|
||||
processors such as the 486 and Pentium, as I'll point out later on when
|
||||
we discuss those processors. Nonetheless, the overall theme of this
|
||||
chapter—that understanding dimly-seen and poorly-documented code
|
||||
gremlins called cycle-eaters that lurk in your system is essential to
|
||||
performance programming—is every bit as valid today. Also, later
|
||||
chapters often refer back to the basic cycle-eaters described in this
|
||||
chapter, so this chapter is the foundation for the discussions of
|
||||
x86-family optimization to come. What’s more, the Zen timer remains an
|
||||
x86-family optimization to come. What's more, the Zen timer remains an
|
||||
excellent tool with which to flush out and examine cycle-eaters, as
|
||||
we’ll see in later chapters, and this chapter is as good an illustration
|
||||
of how to use the Zen timer as you’re likely to find.
|
||||
we'll see in later chapters, and this chapter is as good an illustration
|
||||
of how to use the Zen timer as you're likely to find.
|
||||
|
||||
So, don’t take either the absolute or the relative execution times
|
||||
So, don't take either the absolute or the relative execution times
|
||||
presented in this chapter as gospel for newer processors, and read on to
|
||||
later chapters to see how the cycle-eaters and optimization rules have
|
||||
changed over time, but do take the time to at least skim through this
|
||||
|
|
@ -46,8 +46,8 @@ Programming has many levels, ranging from the familiar (high-level
|
|||
languages, DOS calls, and the like) down to the esoteric things that lie
|
||||
on the shadowy edge of hardware-land. I call these *cycle-eaters*
|
||||
because, like the monsters in a bad 50s horror movie, they lurk in those
|
||||
shadows, taking their share of your program’s performance without regard
|
||||
to the forces of goodness or the U.S. Army. In this chapter, we’re going
|
||||
shadows, taking their share of your program's performance without regard
|
||||
to the forces of goodness or the U.S. Army. In this chapter, we're going
|
||||
to jump right in at the lowest level by examining the cycle-eaters that
|
||||
live beneath the programming interface; that is, beneath your
|
||||
application, DOS, and BIOS—in fact, beneath the instruction set itself.
|
||||
|
|
@ -55,15 +55,15 @@ application, DOS, and BIOS—in fact, beneath the instruction set itself.
|
|||
Why start at the lowest level? Simply because cycle-eaters affect the
|
||||
performance of all assembler code, and yet are almost unknown to most
|
||||
programmers. A full understanding of code optimization requires an
|
||||
understanding of cycle-eaters and their implications. That’s no simple
|
||||
understanding of cycle-eaters and their implications. That's no simple
|
||||
task, and in fact it is in precisely that area that most books and
|
||||
articles about assembly programming fall short.
|
||||
|
||||
Nearly all literature on assembly programming discusses only the
|
||||
programming interface: the instruction set, the registers, the flags,
|
||||
and the BIOS and DOS calls. Those topics cover the functionality of
|
||||
assembly programs most thoroughly—but it’s performance above all else
|
||||
that we’re after. No one ever tells you about the raw stuff of
|
||||
assembly programs most thoroughly—but it's performance above all else
|
||||
that we're after. No one ever tells you about the raw stuff of
|
||||
performance, which lies *beneath* the programming interface, in the
|
||||
dimly-seen realm—populated by instruction prefetching, dynamic RAM
|
||||
refresh, and wait states—where software meets hardware. This area is the
|
||||
|
|
@ -78,56 +78,56 @@ Which brings us to cycle-eaters.
|
|||
|
||||
Cycle-eaters are gremlins that live on the bus or in peripherals (and
|
||||
sometimes within the CPU itself), slowing the performance of PC code so
|
||||
that it doesn’t execute at full speed. Most cycle-eaters (and all of
|
||||
those haunting the older Intel processors) live outside the CPU’s
|
||||
that it doesn't execute at full speed. Most cycle-eaters (and all of
|
||||
those haunting the older Intel processors) live outside the CPU's
|
||||
Execution Unit, where they can *only* affect the CPU when the CPU
|
||||
performs a bus access (a memory or I/O read or write). Once your code
|
||||
and data are already inside the CPU, those cycle-eaters can no longer be
|
||||
a problem. Only on the 486 and Pentium CPUs will you find cycle-eaters
|
||||
inside the chip, as we’ll see in later chapters.
|
||||
inside the chip, as we'll see in later chapters.
|
||||
|
||||
The nature and severity of the cycle-eaters vary enormously from
|
||||
processor to processor, and (especially) from memory architecture to
|
||||
memory architecture. In order to understand them all, we need first to
|
||||
understand the simplest among them, those that haunted the original
|
||||
8088-based IBM PC. Later on in this book, I’ll be better able to explain
|
||||
8088-based IBM PC. Later on in this book, I'll be better able to explain
|
||||
the newer generation of cycle-eaters in terms of those ancestral
|
||||
cycle-eaters—but we have to get the groundwork down first.
|
||||
|
||||
#### The 8088’s Ancestral Cycle-Eaters {#Heading5}
|
||||
#### The 8088's Ancestral Cycle-Eaters {#Heading5}
|
||||
|
||||
Internally, the 8088 is a 16-bit processor, capable of running at full
|
||||
speed at all times—unless external data is required. External data must
|
||||
traverse the 8088’s external data bus and the PC’s data bus one byte at
|
||||
traverse the 8088's external data bus and the PC's data bus one byte at
|
||||
a time to and from peripherals, with cycle-eaters lurking along every
|
||||
step of the way. What’s more, external data includes not only memory
|
||||
step of the way. What's more, external data includes not only memory
|
||||
operands *but also instruction bytes,* so even instructions with no
|
||||
memory operands can suffer from cycle-eaters. Since some of the 8088’s
|
||||
fastest instructions are register-only instructions, that’s important
|
||||
memory operands can suffer from cycle-eaters. Since some of the 8088's
|
||||
fastest instructions are register-only instructions, that's important
|
||||
indeed.
|
||||
|
||||
The major cycle-eaters are:
|
||||
|
||||
- The 8088’s 8-bit external data bus.
|
||||
- The 8088's 8-bit external data bus.
|
||||
- The prefetch queue.
|
||||
- Dynamic RAM refresh.
|
||||
- Wait states, notably display memory wait states and, in the AT and
|
||||
80386 computers, system memory wait states.
|
||||
|
||||
The locations of these cycle-eaters in the primordial 8088-based PC are
|
||||
shown in Figure 4.1. We’ll cover each of the cycle-eaters in turn in
|
||||
this chapter. The material won’t be easy since cycle-eaters are among
|
||||
shown in Figure 4.1. We'll cover each of the cycle-eaters in turn in
|
||||
this chapter. The material won't be easy since cycle-eaters are among
|
||||
the most subtle aspects of assembly programming. By the same token,
|
||||
however, this will be one of the most important and rewarding chapters
|
||||
in this book. Don’t worry if you don’t catch everything in this chapter,
|
||||
in this book. Don't worry if you don't catch everything in this chapter,
|
||||
but do read it all even if the going gets a bit tough. Cycle-eaters play
|
||||
a key role in later chapters, so some familiarity with them is highly
|
||||
desirable.
|
||||
|
||||
### The 8-Bit Bus Cycle-Eater {#Heading6}
|
||||
|
||||
*Look! Down on the motherboard! It’s a 16-bit processor! It’s an 8-bit
|
||||
processor! It’s...*
|
||||
*Look! Down on the motherboard! It's a 16-bit processor! It's an 8-bit
|
||||
processor! It's...*
|
||||
|
||||
...an 8088!
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ processor.
|
|||
|
||||
The 8088 is internally a full 16-bit processor, equivalent to an 8086.
|
||||
(In fact, the 8086 is identical to the 8088, except that it has a full
|
||||
16-bit bus. The 8088 is basically the poor man’s 8086, because it allows
|
||||
16-bit bus. The 8088 is basically the poor man's 8086, because it allows
|
||||
a cheaper—albeit slower—system to be built, thanks to the half-sized
|
||||
bus.) In terms of the instruction set, the 8088 is clearly a 16-bit
|
||||
processor, capable of performing any given 16-bit operation—addition,
|
||||
|
|
|
|||
Loading…
Reference in a new issue