1 Atari Assembler Course --------------------------------- 6.1 -Shift and Rotate Instructions In many programming situations, we need to work with a memory location a bit at a time. The Shift and Rotate instructions let us manipulate a byte of data by moving its bits either left or right. These operations are useful in multiplication and division (shifting left multiplies by two and shifting right divides by two!) and where ever "bit-mapped" data is used (player/missiles,etc.). The carry flag has special functions during shift and rotate. After the operation, the furthest bit in the direction of movement will move into the carry flag. Here, the branch-on-carry instructions will allow decision making based on that bit. The difference between a shift and a rotate appears when we look at the bit coming in. For the shift instructions, a zero always fills the bit furthest from the move direction and, in a rotate, the carry flag moves in. This makes the carry flag act as a "ninth" bit. ,-----. | LSR | -- Logical Shift Right One Bit '-----' 0->m->c ,-----. | ASL | -- Arithmetic Shift Left One Bit '-----' c<-m<-0 ,-----. | ROR | -- Rotate Right One Bit '-----' c->m->c ,-----. | ROL | -- Rotate Left One Bit '-----' c<-m<-c These instruction can operate directly on memory or just the accumulator. Also, they can use indexed addressing with the X register but cannot be used for indirect addressing. BEGIN LDY #4 ;shift four times. LOOP1 ASL A ;"multiply" by two. DEY BNE LOOP1 ;This takes the contents of the accumulator and multiplies by 16 (2 to the forth power). 6.2 Interrupt Programming One of the greatest advantages of Assembly programming is its ability to handle many functions continuously without giving each one constant attention. Other functions can "interrupt" the main program and execute immediately when a certain action occurs or when a timed interval has elapsed. Because an interrupting routine temporarily controls the computer, it should not inadvertantly effect the main program. In most types of interrupts, the Atari Operating System (O/S) handles this problem to a certain degree. All interrupts are first sent through a O/S routine which determines what type of interrupt it is. Then, the routine that handles that type of interrupt takes control of the computer through its "vector". A vector is simply a pair of memory location that contain the low- and high-byte address where the routine begins. The block of memory which holds these vectors is called the "Interrupt vector table" and begins at $200. The 6502 microprocessor accepts two types of interrupts: Non-maskable Interrupts and Interrupt Requests. 6.3 Non-Maskable Interrupts The Non-maskable interrupts are controlled by the "ANTIC" video microprocessor in the Atari computer. The types of NMI's are Display List Interrupt, Vertical Blank Interrupt and System Reset Interrupt. The System reset NMI is used solely by the O/S to initialize the system at power-up and system-reset. The display list interrupt (DLI) is normally ignored by the O/S unless you change its vector to your own routine. This interrupt may be timed with one or more mode lines of the TV display in order to change colors and other display variables. But, this code must be kept short to keep it from overlapping another NMI such as the vertical blank interrupt. Also, it must save and restore any 6502 registers used by its instructions. The end of a DLI must be a "return from interrupt" instruction, "RTI", which will give control back to the main program. The vertical blank interrupt (VBI) occurs at the end of each TV display frame (every 60th of a second). The O/S uses this time to update system variables, some hardware registers, and system software timers. The "immediate" VBI vector points to this O/S routine, but the programmer may "steal" this vector for their own purposes. The "deffered" VBI is unused by the O/S and will execute following the immediate VBI if there is no critical I/O in process. The O/S vertical blank routine updates five count-down timers and a real-time-clock. Timers 1 and 2 have their own vector and will cause a JSR when they reach zero. Timers 3, 4 and 5 will only set a flag which must be checked later by your own routine. The VBI vectors and timer values are carefully set by the routine SETVBV at $E45C in the O/S. To set a timer value, first store the address of your routine (timers 1 and 2) or reset its flag (timers 3,4 and 5). Then, load the accumulator with the timer number (1-5), the Y-register with the low-byte, and the X-register with the high-byte of the timer value. Likewise, the VBI vectors must be set by loading the accumulator with a 6 for the Immediate VBI or a 7 for the Deffered VBI, and the Y- and X-registers with the low- and high-byte of your routine's address. For all types, a JSR to SETVBV will carefully set the timer or vector. 6.4 Interrupt Requests (IRQ's) The IRQ's are "maskable" interrupts which originate from the "POKEY" input/output processor. All IRQ's are sent through the vector VIMIRQ to the O/S before they are sent through their individual vectors. This routine determines which type of IRQ has occured and jumps to the appropriate routine though its vector. The main types of interrupt request, according to priority, are: serial I/O, Pokey timers, Keyboard, and parallel ports. The three serial I/O IRQ vectors are used by the O/S during all input and output operations on the serial bus; these would by used only for advanced device I/O purposes. The Pokey timers are actually the sound-channel (1, 2 and 4) count-down timers and are unused by the O/S. These timers may be used to cont2A] events which must take place more often than the vertical blank interrupt (60th sec.). A keyboard interrupt occurs when any key is pressed and is handled by the O/S though the keyboard IRQ vector. The [BREAK] key has its own IRQ vector. These vectors are useful for disabling certain keyboard inputs (such as control characters and the [BREAK] key) or defining single keys to execute complete instructions. The two parallel I/O interrupts originate from the PIA circuit (joystick ports) and are located on the serial connector. They are not used by the O/S but may be useful for interfacing external. Any of the IRQ maskable interrupts can be seperately enabled/disabled by changing the appropriate bit of the IRQEN (IRQ enable) hardware register and its shadow POKMSK. All IRQ's are enabled/disabled as a group by the 6502 instructions CLI (clear interrupt) and SEI (set interrupt), respectively. A detailed discussion of all types of interrupts appears in the ATARI Operating System Manual. Also read De Re Atari pages 8-12 thru 8-21.