【正文】
evices, is implemented as a peripheral device, and is not part of the ALU (see Chapter 6). Working Registers The 39。430 gives the developer twelve 16bit working registers, R4 through R15. (R0 through R3 are used for other functions, as described later.) They are used for register mode operations (see Addressing Modes, Chapter 8), which are much more efficient than operations which require memory access. Some guidelines for their use: Use these registers as much as possible. Any variable which is accessed often should reside in one of these locations, for the sake of efficiency. Generally speaking, you may select any of these registers for any purpose, either data or address. However, some development tools will reserve R4 and R5 for debug information. Different pilers will use these registers in different fashions, as well. Understand your tools. Be consistent about use of the working registers. Clearly document their use. I have code, written about 8 months ago, that performs extensive operations on R8, R9, and R15. Unfortunately, I don39。t know today what the values in R8, R9 and R15 represent. This was code I wrote to quickly validate an algorithm, rather than production code, so I didn39。t document it sufficiently. Now, it is relative gibberish. Don39。t let this happen to you. No matter how obvious or trivial register use seems, document it anyway. Constant Generators R2 and R3 function as constant generators, so that register mode ma y be used instead of immediate mode for some mon constants. (R2 is a dual use register. It serves as the Status Register, as well.) Generated constants include some mon singlebit values (0001h, 0002h, 0004h, and 0008h), zero (0000h), and an all 1s field (0FFFFh). Generation is based on the W(S) value in the instruction word, and is described by the table below. W(S) value in R2 value in R3 00 ———— 0000h 01 (0) (absolute mode) 0001h 10 0004h 0002h 11 0008h 0FFFFh Program Counter The Program Counter is located in R0. Since individual memory location addresses are 8bit, but all instructions are 16 bit, the PC is constrained to even numbers (. the LSB of the PC is always zero). Generally speaking, it is best to avoid direct manipulation of the PC. One exception to this rule of thumb is the implementation of a switch, where the code jumps to a spot, dependent on a given value. (., if value=0, jump to location0, if value=1, jump to location1, etc.) This process is shown in Example . Example Switch Statement via Manual PC Control Mov value,R15 。put the switch value into R15 Cmp R15,8 。range checking Jge outofrange 。if R157,do not use PC switch Cmp 0,R15 。more range checking Jn outofrange 。 Rla R15 。multiply R15 by two,since PC is always even Rla R15 。double R15again,since symbolic jmp is 2 words long Add R15,PC 。PC goes to proper jump Jmp value0 Jmp value1 Jmp value2 Jmp value3 Jmp value4 Jmp value5 Jmp value6 Jmp value7 Outofrange Jmp RangeError This is a relatively mon approach, and most C pilers will implement switch statements with something similar. When implementing this manually (., in assembly language), the programmer needs to keep several things in mind: Always do proper range checking. In the example, we checked for conditions outside both ends of the valid range. If this is not performed correctly, the code can jump to an unintended location. Pay close attention to the addressing modes of the jump statements. The second doubling of R15, prior to the add statement, is added because the jump statement requires two words when symbolic mode addressing is used. Be careful that none of your interrupt handlers have the potential to affect your value register (R15 in the example). If the interrupt handler needs to use one of these registers, the handler needs to store the value to RAM first. The most mon procedure is to push the register to the stack at the beginning of the ISR, and to pop the register at the end of the ISR. (See Example .) Example Push/Pop Combination in ISR Timer_A_Hi_Interrupt Push R12 。We will use R12 Mov P1IN,R12 。use R12 as we please Rla R12 Rla R12 Mov R12amp。BAR 。Done with R12 Pop R12 。Restore previous value to R12 Reti 。return from interrupt ORG 0FFF0h DW Timer_A_Hi_Interrupt Status Register The Status Register is implemented in R2, and is prised of various system flags. The flags are all directly accessible by code, and all but three of them are changed automatically by the processor itself. The 7 most significant bits are undefined. The bits of the SR are: ? The Carry Flag (C) Location: SR(0) (the LSB) Function: Identifies when an operation results in a carry. Can be set or cleared by software, or automatically. 1=Carry occurred 0=No carry occurred ? The Zero Flag (Z) Location: SR(1) Function: Identifies when an operation results in a zero. Can be set or cleared by software, or automatically. 1=Zero result occurred 0=Nonzero result occurred ? The Negative Flag (N) Location: SR(2) Function: Identifies when an operation results in a negative. Can be set or cleared by software, or automatically. This flag reflects the value of the MSB of the operation result (Bit 7 for byte operations, and bit 15 for word operations). 1=Negative result occurred 0=Positive result occurred ? The Global Interrupt Enable (GIE) Location: SR(3) Function: Enables or disables all maskable interrupts. Can be set or cl