home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-10-23 | 85.1 KB | 2,308 lines |
- Atari ST Machine Specific Programming In Assembly
-
- Chapter 2: The Editors/Assembler/Debugger
-
-
- My recommendations concerning an assembly language
- programming environment for the Atari ST are based on the
- results of a comparative analysis which are so
- overwhelmingly lopsided that I can present conclusions
- without evidence of those results. I have used three
- MC68000 assemblers on the Atari ST; and I have concluded
- that AssemPro is the only one worth discussing. AssemPro,
- written by Peter Schulz in 1986 and produced by Data Becker,
- is distributed by Abacus. Comparing this superior assembly
- programming package to the others would serve no purpose.
- Abacus products can be purchased from Atari ST dealers, but
- if you can't find what you want, there is an order form in
- the back of the Internals book. The Abacus phone number is
- (616)698-0330.
-
- Establishing a Programming Environment
-
- Your programming environment will be composed of
- computer hardware and software, furniture and ambiance. If
- you are accustomed to lengthy sessions with a computer, you
- probably know that provisions for anatomical comfort during
- those sessions are prerequisites for success. Proper
- lighting, comfortable furniture and an appropriate level of
- seclusion create an ambiance that is conducive to
- productivity. A productive ambient environment can be
- comprised of nothing more than a $45.00 computer desk, a
- $16.00 swivel monitor stand, a $29.00 typing chair, a $9.99
- lamp and the quietest corner of a room.
- Within the computer system environment, appropriate
- computer hardware and software amenities will contribute to
- the proliferation of algorithmic ideas and programming
- statements. A hard disk drive and/or a second floppy drive
- will permit faster file transfers; as will software designed
- to format floppy disks in a more efficient manner than does
- the ST operating system. A hardware or software print
- buffer permits one to continue programming while output is
- being routed to the printer. Additional ram allows the use
- of a ram disk and other software amenities, such as a more
- sophisticated file selector. A programmer's calculator, a
- hardware or software model, is an asset also.
- I use the Compute! recoverable ram disk (Recoverable
- RAM Disk, Schweitzer, K., Compute!'s Atari ST Disk &
- Magazine, June, 1987). My RAMDISK.INF file contains the
- information shown in figure 2.1. This file is stored on the
- C partition of the hard disk. I usually boot up with
- RAMDISK.PRG in the AUTO folder, which is also on the C
- partition. A program called AUTOBOOT.PRG, written by Gordon
- Moore, available from ST Informer (909 NW Starlite Place,
- Grants Pass OR 97526) on disk PDM 887 (stored in
- BOOTMAKR.ARC on that disk), makes this possible. The
- RAMDISK.PRG creates the 400K ram disk and automatically
- loads the indicated files therein. The magazine article
- explains the usage of the ram disk. If you understand the
- article, then you should realize, by looking at the
- information file, that I store the AssemPro and TEMPUS
- files, as well as any source programs on which I may be
- working, in a folder named ASSEMPRO on hard disk partition
- D.
-
- Figure 2.1. RAMDISK.INF file.
-
- * Configuration file for COMPUTE!'s June 1987
- * recoverable RAM disk.
- *
- SIZE=400K
- DISK=H
- LOAD=D:\ASSEMPRO\ASSEMPRO.INF
- LOAD=D:\ASSEMPRO\ASSEMPRO.PRG
- LOAD=D:\ASSEMPRO\ASSEMPRO.RSC
- LOAD=D:\ASSEMPRO\ASSEMPRO.TAB
- LOAD=D:\ASSEMPRO\TEMPUS.PRG
- LOAD=D:\ASSEMPRO\TEMPUS.INS
- LOAD=D:\ASSEMPRO\PRESERVE.TTP
- LOAD=D:\ASSEMPRO\*.S
-
-
- You may choose to use a smaller ram disk. With no
- source file in the ram disk, the memory occupied by the
- AssemPro and TEMPUS files is 222,279 bytes. You must have
- enough additional memory in the ram disk to accommodate your
- source file and its backup, if you choose to have TEMPUS or
- AssemPro back it up. In addition, there must be room enough
- to accommodate assembled files. Whenever I work with very
- large source programs, I don't use the ram disk at all; I
- just execute TEMPUS and AssemPro from the hard disk. But,
- let me warn you about that. There have been times when
- AssemPro did not replace a file on disk with an updated
- version; instead it stored the updated file with the same
- name as that of the original file. See figure 2.2A. I
- don't know whether or not this is caused by a system fault.
-
- Figure 2.2A. Updated and original files with identical
- names.
-
-
-
-
-
-
-
- No specific sequence of events has precipitated the
- incident described. In trying to pin down the cause of the
- problem, I have found that the severity of the problem
- depends on the presence of certain load and stay resident
- (LSR) programs. Furthermore, the problem seems to worsen
- with directory depth, and, although files with PRG and S
- extensions are affected, those files with TOS and TTP
- extensions are most often duplicated. I had never
- experienced this problem with any other ST application until
- I began to use Supra Drive utilities to format my Atari
- SH204 hard disk with 11 partitions. Then I began to
- experience the same problem with the Tempus editor. See
- figure 2.2B.
-
- Figure 2.2B. Same problem shown in figure 2.2A, but these
- files were saved from the Tempus editor.
-
-
-
-
-
-
-
- For a time, whenever this mishap occurred, if the
- duplicated files were machine code, I simply discarded the
- files and reassembled. If a source file was involved, I
- examined the files on disk and discarded those that were
- erroneous. Of course, the best protection against such
- mishaps is backups on floppies. I back up my files on two
- separate floppies. Eventually I found a better way to avoid
- the problem. If the AssemPro editor Back-up copy option,
- under the File menu is selected, each time you attempt to
- save a file that is already present on disk, a dialog box,
- similar to that shown in figure 2.2C appears. You can
- choose to rename either of the files and avoid the
- duplication problem. I suggest that you change the
- extension of eldest source files to .DUP because that is the
- backup file extension used by the editor TEMPUS. I suggest
- that you alter the extension of eldest object files to BAK
- or DIS (for discard).
-
- Figure 2.2C. AssemPro dialog box which appears when a file
- to be saved already exists on disk, if the Back-up copy
- editor option is selected. To avoid the file
- duplication problem, backspace over the TOS in the
- extension of the old file and type BAK. Then press the
- Return key, or click on the OK button.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- To avoid the file duplication problem with TEMPUS, you
- can choose the Save with backup option. When you choose
- that option, TEMPUS automatically alters the extension of
- the eldest file to DUP before it writes the new file to
- disk. Figure 2.2D shows the appearance of the backup disk
- file icon when that option is used. Pages 29 and 30 of the
- TEMPUS manual discusses all of the Save options, as well as
- their effects, from which you can choose.
-
- Figure 2.2D. Avoiding the file duplication problem with the
- TEMPUS Save with backup option. The back up file has a DUP
- extension.
-
-
-
-
-
-
-
- I use the Atari SH204 hard disk drive, the star NX-10
- dot matrix printer and the Supra Corporation MicroStuffer
- print buffer. I have been very pleased with the performance
- of all three items; but I have discovered that my star NX-10
- prints at 68 characters per second in draft pica mode, not
- at the specified 120 characters per second; and I have
- learned that the quick response of a hard disk drive
- degenerates rapidly when there are only four partitions;
- that's why I now use Supra's hard disk utilities to format
- my disk with eleven partitions.
- I also consistently use the Hewlett-Packard HP-16C
- programmer's calculator. Occasionally I use the
- programmer's calculator that is available from the TEMPUS
- menu. This type of calculator is required for the many
- hexadecimal computations and number system conversions
- involved in assembly language programming.
- Finally, I have virtually every book and magazine ever
- written in English (or translated thereto) about the ST. I
- have found that access to convenient tools and references
- tends to keep frustration at a minimum level. Furthermore,
- even though I make statements about the inadequacies of some
- portions of the references and the software I use, let me
- make this clear: I could not have achieved any level of
- success with the Atari ST without them. I truly owe all
- that I know to the people that took the time to learn and to
- communicate their knowledge via the many books, magazine
- articles and public domain disks. Most of all, I owe to
- Peter Schulz, the author of AssemPro, my gratitude for the
- many productive hours I have spent with the ST. I know that
- I cannot match the efforts of so many, but I'm going to do
- what I can to perpetuate interest in this fine machine.
-
- The Editors
-
- I usually write my source programs with the TEMPUS
- editor, then transfer the source to AssemPro for assembly,
- reediting and final assembly. When the amount of reediting
- to be done is extensive, I go back to TEMPUS. The number of
- trips back and forth between TEMPUS and AssemPro depends on
- the complexity of the program. The TEMPUS editor is so much
- faster than the AssemPro editor that any inconvenience
- because of the switching between them is overlooked.
- You will discover the many differences between the two
- editors as you use them. I only want to point out the less
- obvious. The AssemPro editor begins counting text on a line
- in column 1; TEMPUS begins counting in column 0. This is
- the kind of, seemingly, non-critical information that one
- can omit during the daily grind of writing. In my work, I
- have often found just such an item of information to be the
- crucial key to solving a problem. When I begin to discuss
- the basepage command line and the manner in which it is
- accessed by AssemPro, you will see just how critical an
- offset of one character position can be.
- The major difficulty I had experienced in switching
- between the two editors is line deletion. TEMPUS uses
- function key F8; AssemPro uses Alternate - Delete.
- Therefore, I redefined the AssemPro F8 key, according to the
- instructions in section 1.6.1.3 on page 17 of the manual.
- The command to be used in redefining the F8 key to a Delete
- key is listed in the table in section 1.8.6 on page 32. The
- command of interest is LZ. Figure 2.3 illustrates the
- appearance of the the Function key redefinition dialog box
- for this operation, just before you press the OK button.
-
- Figure 2.3. Redefining the AssemPro F8 function key. This
- is a compressed representation of the dialog box.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The TEMPUS Editor
-
- This is an editor! TEMPUS was written by M. Schuelein
- in 1987. The only caution I should give concerning the
- TEMPUS editor is this: when I received the editor, the
- single quote key was not functioning, therefore, I had to
- return the disk for corrections. The distributor, Eidersoft
- USA Inc (P.O. Box 288, Burgettstown, PA 15021), explained
- that the inconvenience was due to the difference between
- European and American keyboards. I accept that. If you
- purchase TEMPUS and find that the single quote key does not
- function, you can send the original back to Eidersoft and
- work with your backup disk, using double quotes, until the
- corrected disk returns. Or you can try the TMPUSFIX.ARC
- file that has been posted to GEnie's ST User's Library as of
- December 12, 1988.
- TEMPUS requires a setup that involves the execution of
- the program PRESERVE.TTP. You can calculate the value that
- must be entered into the parameter line, also known as (aka)
- the command line, in various ways. But since it is kind of
- hokey to have to do this, I just usually use 307200. Then,
- if I don't have enough room in TEMPUS for the source on
- which I am working, I execute PRESERVE.TTP again and enter a
- smaller number on the command line (the value must be some
- multiple of 1024). The amount of memory assigned to TEMPUS
- is the total amount of memory available minus the value
- entered on the command line.
- The only other complaints that I have concerning the
- TEMPUS editor involves its custom file selector. In the
- first place, it displays only 7 disk buttons, enough for
- floppies A and B and hard disk partitions C through G; it
- should display enough for all possible hard disk partitions.
- In the second place, TEMPUS does not allow one a choice
- between one's standard file selector and its custom
- selector; therefore, I cannot use the Universal Item
- Selector; and furthermore, TEMPUS clashes with the operation
- of the Universal Item Selector when it is being used as a
- desk accessory. These TEMPUS flaws are serious. I hope
- that someone will fix them soon, or I shall be forced to do
- it myself.
-
- The AssemPro Editor
-
- The first thing I want to mention is the error on pages
- 7, 52, 119 and 130 of my AssemPro manual, and, unless
- someone has corrected the documentation, it will be in your
- manual also. On those pages, reference to a menu called
- Help is made. This item actually appears as Table on the
- menu line. If necessary, make corrections to your
- documentation, then execute ASSEMPRO.PRG. With the
- assembler window activated, (See pages 5 and 6 of the
- AssemPro manual. The assembler window is activated by
- moving the mouse arrow to the assembler window and clicking
- the left mouse button; the editor window is activated by
- moving the arrow to the editor window and clicking.), move
- the mouse arrow to the Assembler menu. Now, activate the
- following options, and only the following options, by
- clicking on them (some may already be activated):
-
- * Optimize backward Bcc's
- * Flag undef. variables
- * PC-relative
- * Original line
-
- When you are done, there should be four check-marks,
- one for each of the options selected. Refer to figure 2.4A.
- All of the options are discussed in the AssemPro manual, and
- I will be discussing each as its usage becomes appropriate.
- The PC-relative and Relocatable assembly modes will be
- discussed and compared in the next chapter, along with the
- pc-relative addressing mode. For now, if any other items
- are checked, deactivate them. Next, click on the Search
- menu and deactivate the Replace selection if it is checked.
-
- Figure 2.4A. Setting Assembler and Search Options
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Next, activate the Editor window and the Editor menu.
- Click on the Function keys option; when the dialog box
- appears, click on the F8 key button. On the first line
- under the label Program :, type LZ; on the line under the
- label Explanation : type the following, or something
- similar: Delete Line. Then click on the OK box. Refer to
- figure 2.3.
- Now, activate the File menu and click on the Back-up
- copy option. See figure 2.4B. Activate the File menu
- option again and click on the Save defaults option. All of
- the options you have selected will be saved in the
- ASSEMPRO.INF file. If you are working from a RAM disk,
- leave AssemPro with the Quit option under the File menu and
- copy the ASSEMPRO.INF file to the disk or partition on which
- ASSEMPRO.PRG resides. Thereafter, whenever you execute the
- ASSEMPRO.PRG, your options will be read in from the INF file
- and set automatically.
-
- Figure 2.4B. Setting the File option.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- As you receive the AssemPro package, each of the
- function keys will most likely be assigned a default
- program. Redefining the F8 key to function as a Delete Line
- key will hasten your adaptation to the switches from TEMPUS
- to AssemPro and back. You can explore other key
- reassignments to suit your taste. In my version of
- AssemPro, the function keys had been assigned the following
- default functions:
-
- F1 = BA = Mark blockstart
- F2 = BE = Mark blockend
- F3 = BV = Move block
- F4 = BK = Copy block
- F5 = BL = Delete block
- F6 = BD = Unmark block
-
- Functions defined with unprintable characters were
- assigned to the F7, F8, F9 and F10 function keys. You can
- view those assignments by selecting the Function keys menu
- option and by clicking the appropriate function key button
- in the dialog box. The program assigned to function key F10
- is of special interest, only because it brings up the idea
- of converting files prepared by resource construction sets
- for use in assembly language programs. I will return to
- this subject in an appropriate, later chapter, however, I
- want to point out here that the *.I file discussed on page
- 34 of the AssemPro manual would be a *.H file for some
- construction sets. Furthermore, since the layout of such
- files varies with the particular construction set used, the
- default program assigned to F10 is not compatible with all
- resource construction sets.
-
- The Editor's Search Function
-
- AssemPro has two Search functions; one for the editor;
- one for the debugger. The editor's Search function,
- discussed on page 18 of the manual, is particularly
- inconvenient. Using this function requires two, sometimes
- three, trips to the Search menu. First you must select the
- For what ? option and define the search criteria in the
- dialog box (see figure 2.5). Then you must deactivate the
- Replace selection if it is activated (Don't forget to do
- this if you are only searching, not replacing.) Finally,
- you must click on the appropriate Search direction option
- (see figure 2.4A). Of course, the Replace function is
- equally inconvenient.
- The Search/Replace function has one more annoying
- attribute. When executing multiple replaces (enabled with
- the all button), even though it has successfully completed
- any number of them, it will end the event with the Not
- found!, Sorry alert box, therefore, you must manually search
- the file to determine whether or not the Replace operation
- was successful.
-
- Figure 2.5. The Editor's Search/Replace Dialog Box; a
- slightly compressed representation.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The First Program
-
- Before we begin to look at the debugger, we should
- discuss and prepare a program. I have stated that the
- minimum amount of code necessary is a primary requirement of
- any example program that I choose to discuss. In order to
- fulfill my desire to begin with the rudimentary, it seems
- reasonable to attempt to construct the first program from a
- single statement. Consider the one statement which must
- appear in every assembly language source program, the
- instruction end. However necessary it may be to every
- program, end is not an instruction for the MC68000
- processor; it is an instruction for the assembler. This
- instruction produces no executable code. End belongs to a
- group of such instructions called assembler directives,
- pseudo-ops, or by any other name that differentiates them
- from processor instructions.
- Furthermore, because every program executed on the ST
- must prohibit execution beyond its boundaries, the task of
- declaring which instruction or function constitutes the most
- rudimentary possible is preempted by necessity. The single
- executable algorithm that represents a minimum ST program is
- the GEMDOS function number $0, which is one of many system
- functions designed to transfer processor control.
- Identified by various names such as p_term_old, term or
- terminate, this function causes processor control to be
- transferred to the program that invoked the program which is
- executing p_term_old. Normally, the final goal of every
- user program should be the return of control to the
- operating system, but there times when control is returned
- to another user program instead.
- Referring back to the name of GEMDOS function $0, at
- times the names given to ST operating system functions may
- seem strange. Actually, I am being facetious; the
- names will seem to be totally undescriptive of the function
- being performed most of the time. I use the names that are
- commonly seen in the references so that I can match them up,
- but I always try to add my own descriptive label. You will
- find that I tend to use labels such as the following:
-
- this_label_attempts_to_completely_describe_the_algorithm_below:.
-
- In addition to serving as the example for a short
- tutorial on the AssemPro debugger, the first program will
- help me to simultaneously illustrate several concepts
- involving the relative execution speed and memory
- requirements of similar processor instructions. At the
- conclusion of the discussion, the first program, the
- concepts and a program that justifies their relevance will
- be convincingly juxtapositioned (unless I screw it up in the
- telling).
-
- Program 1. A minimum ST program.
-
- ; Program Name: PRG_1AP.S
- ; Version: 1.001
-
- ; Assembly Instructions:
-
- ; 1. Assemble in AssemPro PC-relative mode and save the assembled
- ; program with a PRG extension, then save it with a TOS extension.
-
- ; 2. Click on the PC-relative option under the Assembler menu to activate
- ; the Absolute assembly mode. The Absolute mode is active when there
- ; is no check mark in front of the PC-relative option and no check mark
- ; in front of the Relocatable option. Change the name of the source
- ; file to PRG_1AA. Do this by clicking on the File option under the
- ; File menu and, in the dialog box that appears, backspace over the
- ; letter P and type an A. Do not save the new source file, but
- ; assemble it and save the assembled program with a PRG extension,
- ; then save it with a TOS extension.
-
- ; 3. Click on the Relocatable option under the Assembler menu.
- ; Change the name of the source file to PRG_1AR. Do not save the
- ; source file, but assemble in the Relocatable mode and save with
- ; PRG and TOS extensions.
-
- ; Program Function:
-
- ; This program invokes a single GEMDOS function. That function performs
- ; three services. It relinquishes processor control, prohibits execution
- ; beyond the program's upper boundary and removes the program from ram.
-
- ; Program Purpose:
-
- ; To introduce the smallest possible ST program. Every ST program must
- ; accomplish at least two functions. It must relinquish processor control,
- ; and it must prevent execution beyond its boundaries. Processor control
- ; must be relinquished at some time during the life of each program, if for
- ; no other reason, then because all programs must eventually finish the
- ; task for which they were invoked. Without some sort of demarcating code
- ; within an executing program, the processor will continue to try to execute
- ; whatever is in memory, until a fatal error eventually occurs.
-
- ; GEMDOS function $0, also known as (aka) p_term_old, term or terminate,
- ; may be invoked to perform these two functions. But, in addition, this
- ; function also removes the program from memory.
-
- ; When GEMDOS $0 is invoked, processor control is returned to the
- ; agent that initiated the execution of the program that is now invoking
- ; GEMDOS $0. That agent may be the Desktop or some other program.
-
- ; An additional purpose of this exercise is to compare the sizes of
- ; the code files produced by the three assembly modes. Furthermore, if
- ; you are able to carefully observe the length of time it takes to execute
- ; each type of program, where the mode of assembly indicates "type", you
- ; will see that the time required to execute the Relocatable types is longer
- ; than the time required to execute the other types.
-
- terminate: ; My descriptive label.
- move.w #0, -(sp) ; Function = p_term_old = GEMDOS $0.
- trap #1 ; GEMDOS call.
- end ; Assembler pseudo-op.
-
-
- Upon invocation, p_term_old performs three functions.
- It prohibits execution beyond the boundaries of the program;
- it removes this program from ram; and it returns processor
- control back to the program that invoked this one, which in
- this case is the system program Desktop. Without some sort
- of termination code within an executing program, the
- processor would continue to execute instructions until a
- fatal error occurred. I use the phrase termination code to
- refer to code which sets an execution boundary, I do not use
- it to connote execution termination. I make this
- distinction because both phenomena coincidentally occur when
- the p_term_old function is used, however, these phenomena
- are not mutually inclusive.
- You should type program 1 into the AssemPro editor,
- with or without the comments, and assemble it at this time.
- Before you type the file into the the editor, name it by
- clicking on the File : option under the File menu, then by
- entering PRG_1AP on the parameter line of the dialog box
- which subsequently appears. If you have not yet read the
- portion of the manual that describes assembling, the
- following few sentences should contain enough information to
- insure success. Assemble PRG_1AP by activating the
- assembler window, then the Assembler menu, and finally, by
- clicking on the Assembling selection. Now, save the source
- file by clicking on the Save option under the File menu, and
- by clicking on the S button in the dialog box after it
- appears. Next, save the object file by clicking on the TOS
- button, after you activate the dialog box a second time.
- Unfortunately, however routine it may be to save both
- files, the saves must be done individually. Finally, save
- the object file again, but, this time, click on the PRG
- button, after you activate the dialog box a third time. For
- each save that you perform, the filename extension button
- that you choose tells AssemPro to affix that extension to
- the basic filename before writing the file to disk. Figure
- 2.6 is a picture of the Save dialog box with the name of the
- program typed therein.
-
- Figure 2.6. The dialog box used to save files.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Click on the File : option under the File menu and change
- the file name to PRG_1AA. There is no reason to save this
- source file. Click on the PC-relative option under the
- Assembler menu to active the Absolute assembly mode; the
- Absolute mode is active when there is neither a check in
- front of the PC-relative option, nor in front of the
- Relocatable option. Assemble this new source and save the
- object code with TOS and PRG extensions. Finally, change
- the file name to PRG_1AR and click on the Relocatable option
- under the Assembler menu to activate the Relocatable
- assembly mode. Do not save the source file, but assemble
- and save the object code with TOS and PRG extensions.
- Comparisons between the size of each of the six assembled
- programs and their execution speeds will be accomplished
- shortly.
- Although it may not be obvious, there are algorithmic
- choices to be made for even so elementary a program as
- PRG_1AP. Only two requirements are necessary for successful
- execution of the function. The number of the function, $0,
- must be pushed onto the stack, and a trap #1 call must be
- invoked. No choices are available as far as the trap
- instruction is concerned (at this elementary stage). It
- must appear as shown. However, there is more than one way
- to push the $0 onto the stack. Table 2.1 lists three
- algorithms that accomplish the task. The number of clock
- periods and memory requirements for each are indicated. For
- this table, the clock periods were calculated from
- information in appropriate charts provided in the Motorola
- M68000 Programmer's Reference Manual, fifth edition.
-
- Table 2.1. Three ways to store 0 on the stack. Comparison
- of the execution speed and memory requirements of three ways
- to push zero onto the stack. Although -(sp) is used as the
- destination operand in the table, the data applies to any
- -(An).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Instruction execution time is measured in clock
- periods; memory requirement is measured in bytes. The
- method used to calculate the execution times as they are
- shown in table 2.1 is discussed in a later chapter. In
- addition, I shall present programs that accomplish the task,
- in the sense that relative execution speeds are calculated,
- with much less bother and with precision that is tied to the
- ST's operating system and internal hardware.
- The data in the table illustrate the classic speed
- versus memory requirement tradeoff so often discussed in
- computer literature. To wit: if we are willing to sacrifice
- 2 more bytes of memory, we can take advantage of the faster
- execution speed exhibited by either of the second or the
- third algorithm. Of course, in PRG_1AP there is only a
- single incident of the algorithm involved, therefore, one
- might think that it doesn't matter which of the three
- algorithms is used. I insist that the choice should be made
- deliberately. If a conscious effort is being made to
- sacrifice speed for conservation of memory, then the first
- algorithm should be chosen, otherwise one of the others
- should be used, because I prefer that the default
- consideration always be speed. Let me illustrate how much
- just one casual choice costs in overall machine performance.
- The ST has an 8mhz clock. Each clock period is 1.25 X
- 10-7 seconds. The 14 clock period instruction takes 14 X
- 1.25 X 10-7 = 1.75 X 10-6 seconds = 1.75 microseconds.
- Neglecting any extraneous delays, in one second, the ST can
- execute 1,000,000 / 1.75 = 571,428 instructions of this
- type. An instruction that requires 12 clock periods takes
- 1.5 microseconds. Neglecting extraneous delays again, in
- one second, the ST can execute 666,666 instructions of this
- type. By choosing the instruction that requires 14 clock
- periods, we lose an execution capability of 666,666 -
- 571,428 = 95,238 instructions per second.
- When you start doing things such as moving zeroes into
- 32000 bytes of memory to clear a video screen or two every
- so often in a program, such loses begin to pile up and
- performance becomes unsatisfactory. The insidious thing
- about choosing unconsciously is that it becomes a habit. By
- habitually using slower, albeit more familiar, instructions
- we risk using them as the worst choice for an algorithm in
- which we are trying to emphasize speed.
-
- Executing Program 1 From the Desktop
-
- Exit AssemPro by clicking on the Quit option under the
- File menu. Then execute PRG_1AA.PRG from the desktop. The
- operating system will briefy display a gray screen (assuming
- a monochrome monitor) with the program name at the top and a
- busy bee cursor. Now, execute PRG_1AA.TOS. The operating
- system will briefly display a blank white screen with a
- black, blinking cursor in the upper left hand corner of the
- screen. The difference in screens occurs because programs
- with a PRG extension are expected to use windows, while
- those with a TOS extension are expected to be keyboard
- driven.
- The quickest way to understand the difference is to
- change the extension of a program that uses windows, such as
- a word processor, from PRG to TOS and execute it. There
- will be no mouse activity, so you will not be able to make
- any selections. The only way out will be to reset the
- computer with the reset switch. On the other hand, if you
- alter the suffix of a TOS program to PRG and execute, the
- mouse pointer will be present, but the cursor will be
- absent. And, of course, the screen will not be clear.
- The PRG_1AA programs were assembled using AssemPro's
- Absolute mode. Execute PRG_1AP.PRG and PRG_1AP.TOS from the
- desktop also. These programs were assembled using
- AssemPro's PC-relative mode. The behavior of these programs
- will be identical to that of the programs which were
- assembled using the Absolute mode.
- Now execute PRG_1AR.PRG and PRG_1AR.TOS. The same
- types of screens will appear, but they will remain longer
- than they did when the PRG_1AA and PRG_1AP programs were
- executed. The time differential, as well as the reason it
- exists, will be explored in the next chapter. For now, I
- just want you to observe that the difference is noticeable.
- To observe another difference in the way the operating
- system processes these programs, click on PRG_1AA.PRG, then
- click on the Show Info option under the File menu. Note the
- file size in bytes. Do this for each of the other five
- files. You will see that the Absolute and PC-relative files
- consume 34 bytes of disk space, while the Relocatable files
- consume 42 bytes. To my knowledge, the only reference that
- explains the 8-bytes difference (two longwords) is the
- AssemPro manual, on page 80. These 8 bytes contain
- information for the relocator. However, in the next chapter
- we will see that this 8-byte differential is just the
- minimum size difference incurred by a program assembled in
- the Relocatable mode.
-
- An Executable File's Disk Image
-
- Each executable ST file has a distinctive header which
- identifies it as such. An executable file's header (and the
- entire file) can be examined using a utility such as The
- Disk Doctor, copyright 1985, 1986 by Daniel Matejka, or File
- Viewer, by Richard Smereka, COMPUTE!'s Atari ST, August
- 1987. A disk image for the file with the PRG extension from
- each of the three assembled sets is shown in file 2.1. The
- file header extends from word $0 of the file through word
- $1B. Of particular interest during this discussion is the
- word at location $1A. If this word is $0000, then the file
- has been assembled in AssemPro's Relocatable mode, otherwise
- the file has been assembled in one of the other two modes.
- When a program is loaded into ram, the ST's relocator will
- adjust addresses as necessary, if this word is $0000, as
- explained on page 79 of the AssemPro manual. It is this
- extra step which is partly responsible for the increase in
- execution time that is experienced when a Relocatable
- program is executed. If the overall execution time is
- divided into two parts, one of which is a loading time
- component, then the relocation step clearly adds to this
- component.
-
- File 2.1. A hex dump of programs PRG_1AA.PRG, PRG_1AP.PRG
- and PRG_1AR.PRG. The disk images of the three executable
- files are shown.
-
- PRG_1AY.DMP
-
- Hex dump of programs PRG_1AA.PRG, PRG_1AP.PRG and PRG_1AR.PRG.
-
- The first word of each of the three files is a branch instruction.
- The branch is to the location that is the sum of the 8-bit displacement,
- 1A, plus 2: that is, to location 1C. In each file that location is marked
- as "start of text segment".
-
- The word immediately preceding the "start of text segment" marks the
- program as relocatable if the word is $0000. In files that are assembled in
- AssemPro's Absolute and PC-relative modes, this word will be $FFFF.
-
- The longword beginning at location $02 is the size of the text segment;
- for each of the three programs the size of the text segment is 6 bytes. The
- longword beginning at location $06 is the size of the data segment, which is
- zero for the three programs. The longword beginning at location $0A is the
- size of the BSS segment, which is zero for the three programs.
-
- Note that the size of the relocatable program, PRG_1AR.PRG, is 42 bytes,
- eight bytes longer than the size of the other two programs.
-
-
- ADDRESSES CONTENTS OF FILE PRG_1AA.PRG
- FROM TO
- 00000 00000F 601A 0000 0006 0000 0000 0000 0000 0000
- 00010 00001F 0000 0000 0000 0000 0000 FFFF 3F3C 0000
- 00020 000021 4E41 ^start of text
- segment
-
- CONTENTS OF FILE PRG_1AP.PRG
-
- 00000 00000F 601A 0000 0006 0000 0000 0000 0000 0000
- 00010 00001F 0000 0000 0000 0000 0000 FFFF 3F3C 0000
- 00020 000021 4E41 ^start of text
- segment
-
- CONTENTS OF FILE PRG_1AR.PRG
-
- 00000 00000F 601A 0000 0006 0000 0000 0000 0000 0000
- 00010 00001F 0000 0000 0000 0000 0000 0000 3F3C 0000
- 00020 000029 4E41 0000 0000 0000 0000 ^start of text
- segment
-
- The AssemPro Debugger
-
- To prepare for this discussion, load PRG_1AP.S in the
- editor by clicking on the Load option under the File menu,
- then by clicking on the S button when the dialog box
- appears. The file selector will appear after you click the
- S button. After the source is loaded into the editor,
- assemble it using either the PC-relative mode or the
- Relocatable mode.
- Now, activate the debugger by clicking on the Debugger
- option under the Debugger menu. When the debugger screen
- appears, if the program was assembled with the Relocatable
- option checked, click on the relocate button. You will be
- able to see the two statements of the program in the output
- field of the debugger window. The output field is
- displaying memory in normal disassembled mnemonic format.
- See figure 2.7. In this format, memory addresses are
- followed by their content in both hexadecimal digits and,
- where possible, the assembly language translation of those
- digits. In this figure, and in all future figures and
- discussions, the memory addresses that you will see in your
- debugger window will most likely never match those of mine,
- except when we are both viewing locations assigned to the
- system. That is so because the addresses we see depend on
- the desk accessories and other load and stay resident
- programs we have previously loaded into ram.
-
- Figure 2.7. Normal disassembled mnemonic format.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Note the appearance of the program statements, then
- click on the symbolic button. The output field now displays
- the TERMINATE: label also. Refer to figure 2.8. This
- display, called the symbolic disassembled mnemonic format,
- eliminates the hexadecimal representation of instructions
- after the addresses.
-
- Figure 2.8. Symbolic disassembled mnemonic format.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Displaying the source text labels in the debugger
- output field is one of AssemPro's most prominent features.
- You enable this option by doing two things, if the program
- is assembled in PC-relative mode, three things if it is
- assembled in Relocatable mode. First you must load the
- source code into the editor and assemble it (of course, if
- you create the source code as new text, loading it is not
- necessary). If the program is assembled in the Relocatable
- mode, you must click on the relocate button in the debugger
- window. Then you must click on the symbolic button in the
- debugger window.
- The dark line that you see in the output field is the
- program counter cursor; therefore, it indicates the next
- instruction to be executed, if execution is to take place.
- The address that you see in the output field for the first
- instruction of the program will depend on the exact
- configuration of your machine. In any case, the address
- that you see for the second instruction will be the address
- of the first instruction plus four. The memory occupied by
- the first instruction is the address of the second
- instruction minus the address of the first instruction, that
- is, four bytes. You should be able to deduce the memory
- occupied by the second instruction; it is two bytes.
- Click on the disassembled button; the state of the
- symbolic button is of no consequence. The output field will
- display memory in the hexadecimal/ASCII dump format. See
- figure 2.9. In this format, you can view the content of
- memory in hexadecimal digits, and, if any sequence of those
- digits forms a valid ASCII string, you will be able to
- observe that string. The most significant feature available
- via this format (aside from viewing data in ASCII) is the
- ability to directly alter the content of memory. Refer to
- page 85 of the AssemPro manual. This feature will be
- explored, in detail, in a later chapter.
-
- Figure 2.9. Hexadecimal/ASCII Dump Format. In this mode,
- the symbolic button has no effect of the display.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Click on the disassembled button to return to a
- mnemonic formatted output field, then click on the Execute
- program button; it is located just above the => erase button
- (called => delete in the AssemPro manual), which is located
- just above the relocate button. Clicking the Execute
- program button will not execute the program. In the dialog
- box that appears, click on the OK button. Refer to figure
- 2.10. You will be presented with the file selector box;
- choose PRG_1AP.PRG or PRG_1AR.PRG, one of the assembled
- files previously saved.
-
- A Special Note: To remove a program from memory,
- after it has been loaded with the Execute program
- button, click on the => erase button while pressing
- the Control key on the keyboard.
-
-
- Figure 2.10. The Execute program dialog box; a slightly
- compressed representation.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- AssemPro will load in the object code for the program
- and you will be able to see the program's two instructions
- in the output field again. Activate the symbolic button, if
- it has been deactivated; in this mode, the label TERMINATE:
- can't be seen in the output field. When you load a program
- into memory using the Execute program button, AssemPro knows
- nothing about labels in the source code. It is only when a
- program has just been assembled that such information is
- available to the debugger.
- There are two memory configuration differences existing
- between this object code and that which you had been
- viewing; this object code has a basepage (See pages 145 and
- 146 of the Internals book.), the other did not. Any program
- that is in debugger memory because it has just been
- assembled does not have a basepage. The significance of the
- distinction is this: if the basepage is not present, then
- you will not be able to execute instructions which depend on
- information stored in the basepage.
- In addition, this program has claimed all of available
- memory for its own use. You can verify this by clicking on
- the box in the upper left corner of the debugger screen to
- get back to the Assemble/Edit screens. There you will see
- that there are only 50 bytes of available memory. The rest
- of it is being consumed by PRG_1AP. These important
- distinctions will be explored later, when I discuss the
- function which returns excess memory back to the operating
- system.
-
- Executing the Program
-
- As you can see, there are many other debugger options
- present. We will cover them all in time. For now, you can
- simply execute the program by clicking on the Run program
- option. After the program has executed, address $000000
- appears in the output field as the next instruction to be
- executed. See figure 2.11. Another alteration of interest
- has also taken place. Observe the ten status register bits
- that are shown as buttons under the label Statusregister,
- just to the left of the second output field instruction
- line.
-
- Figure 2.11. Output field and status register after
- executing program 1.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- There you will see that three of the status register
- bits have been set (the S bit and two bits of the interrupt
- mask), apparent because of their dark color (reverse video).
- The new state of these bits will not interfere with the
- repeated execution of this program, however, their state
- could be a matter of importance, of which we are unaware, to
- AssemPro. Furthermore, such a change in the status register
- bits could have drastic effects on a program that utilized
- the state of those bits. Therefore, it is a good idea to
- put things back in order whenever we can, so reset those
- bits by clicking on them. The reset condition of a bit is
- indicated by a white color in the bit button.
- In addition to the changes in the microprocessor status
- register caused by a program's execution, there are
- alterations in data register and address register contents.
- Figure 2.12 illustrates typical alterations. You can look
- at the register field of your debugger screen to view
- similar changes.
-
- Figure 2.12. Changes in register content after program
- execution.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Now look to the top right corner of the debugger
- screen. There you see the label Program start :, followed
- by a hexadecimal number. That number is the starting memory
- address of the your program. At the moment, the PC (program
- counter) cursor is located at memory location $000000. If
- you were to click on the Run program button now, you would
- be greeted by a warning box, telling you that a Bus error
- has occurred at address 000000. When this type of error
- occurs, it is sometimes possible to get back to the debugger
- by clicking on the Debugger button in the warning box.
- Sometimes you will simply get another warning box, or the
- system may freeze. The only way to be sure that everything
- is as it should be after a Bus error is to reset the machine
- by pressing the reset button, holding it for at least 10
- seconds.
- To execute the program again, you must, as step one of
- two steps, get the first executable instruction of your
- program back in the debugger output field (This is not
- always the first instruction of the program.). To do this,
- you rapidly double click on the from address button in the
- lower right hand corner of the debugger screen. If you
- don't click rapidly enough, the output field will not be
- altered; instead, an editable line will open at the Change
- register field, located at the very bottom of the debugger
- window.
- In this particular case, you would see *=$___________.
- When the $ is present, you can enter a hexadecimal address.
- The address you would enter now, if the editable line has
- indeed appeared, is that which is labeled Program start at
- the top of the screen. Never leave a space between the $
- and the first digit of the address. Conclude the dialog by
- pressing the Return key on the keyboard.
- When the correct address appears in the output field,
- perform step two, which is placing the PC cursor at the
- appropriate instruction. Do this by moving the mouse
- pointer to the instruction line, then hold down the Control
- key on the keyboard, while clicking the left mouse button.
- Now you may execute the program again, by clicking on the
- Run program button.
- Referring to the from address button and the Change
- register editable parameter line again, if the program in
- debugger memory is there because it was recently assembled,
- and if it has been relocated as described previously
- (required only if the program was assembled in the
- relocatable mode), then you can go to any labeled line by
- backspacing over the $ on the parameter line, and by typing
- the label on the line. When done correctly, the line will
- read *=label________. The $ is permitted and necessary only
- if it is followed by a hexadecimal number.
- As an example of the proper use of this function, if
- you have just assembled program 1 and are now in the
- debugger mode; and, if you have just executed the program,
- you can get back to the program's start address by clicking
- once on the from address button, then by backspacing over
- the $ on the change register parameter line, and, finally,
- by typing the name of the label terminate on the line. When
- you press the return key, the first line of program 1 will
- appear as the first line in the output field.
-
- Loading Programs With Other Extensions
-
- The Execute program function, by default, looks for
- programs with the PRG extension. To load a program that has
- any other extension, you must edit the path specification in
- the file selector when it appears. Loading programs with a
- TOS extension incurs no special considerations; but AssemPro
- does not handle TTP programs correctly.
- Recall the Execute program dialog box shown in figure
- 2.10. The Command line evident in that figure invites TTP
- parameters that are to be stored at the program's basepage
- address plus $80. Although AssemPro accepts the data typed
- on the command line, it does not store the data in an ST
- specific format. Figure 2.13 illustrates the manner in
- which the operating system stores TTP command line data.
- The program start address for the program which
- produced the results shown in the figure was $25956. The
- basepage address was $25956 - $100 = $25856. The command
- line address was $25856 + $80 = $258D6, as shown in figure
- 2.13. There you see that the first byte of the command
- line, $0D, is the number of characters typed on the TTP
- program's input parameter line (command line). Following
- that you see the ASCII codes for the 11 characters,
- PRG_1AP.TOS, which were typed as input. Then you see the
- code for a carriage return, 0D, which is placed at the end
- of the command line input, whether the mouse or the Return
- key was used to terminate the dialog.
-
- Figure 2.13. Command line data stored by the ST operating
- system.
-
-
-
-
-
-
-
-
- In figure 2.14 you can see why the manner in which
- AssemPro stores the input parameters creates two major
- problems. AssemPro does not store the input parameter
- character count; therefore, any program that processes the
- command line in a loop which uses that count is doomed.
- And, to compound the problem, AssemPro stores the first
- character at basepage address plus $80 instead of at
- basepage address plus $81; therefore, any program which
- processes the command line by looking for the first
- character at basepage plus $81 is also doomed. Although not
- as critical, AssemPro does not store a carriage return at
- the end of the command line string.
-
- Figure 2.14. Command line data stored by AssemPro.
-
-
-
-
-
-
-
-
- My solution to the problem is this: when the Execute
- program dialog box appears, type a leading space on the
- command line, then follow with the input parameters. This
- will place the first character of the input at basepage
- address plus $81, where it belongs. Remember, the stored
- command line parameters (as they are placed in the basepage
- by the operating system) are a mixture composed of a one-
- byte binary number and ASCII characters, so you can't just
- type in a number in place of that leading space. After the
- TTP program has been loaded by AssemPro, manually replace
- the leading space with the ASCII character count. To do
- that, click on the from address bar at the bottom of the
- debugger screen; and, on the parameter line which appears,
- type the address of the command line, which is basepage
- address + $80 or program start address - $80. When you
- press the Return key, the command line address will appear
- as the first line in the output field window.
- Click on the disassembled bar located just above the
- from address bar at the bottom of the screen. When the
- hexadecimal characters appear in the output field, the first
- two digits will be the ASCII code for the leading space that
- you typed on the command line. Using the mouse, move the
- cursor to the first digit, which is 2, and type the number
- of characters in the command line. The number you type must
- be in hexadecimal and you must include a leading 0 if the
- number you type is less than hexadecimal $10.
- Referring to that dialog box again, the load option
- should always be selected (reverse video). The parameter
- line labeled Environment: refers to something called an
- environment string. Just so you'll know what it is, I'll
- tell you. It is used to pass an ordinary string as a
- parameter to be stored at offset $2C from the start of the
- program's basepage. The program can access the string at
- that location. I will show you how this can be done in a
- later program. The address of a block of environmental
- strings can be passed, on the stack, to a spawned process,
- using the GEMDOS $4B (p_exec) function.
-
- A Program With User Interaction
-
- Let's add something to PRG_1AP that will prevent the
- program from returning control to the operating system until
- we permit it to do so. For now, I am relying on the GEMDOS
- (trap #1) functions, even though these are the farthest from
- the hardware, because they are the least complex. As a
- matter of fact, none of the operating system functions
- should be considered taboo simply because they are not the
- fastest. The important thing is to choose deliberately,
- with a knowledge of which is which and what does what, to
- whom, when.
- All of the GEMDOS functions, as well as the BIOS and
- XBIOS functions are discussed in the Abacus Internals book;
- and, in general, the functions are adequately described;
- therefore, I shall not have much to say about most of them.
- However, there are some errors present in some descriptions.
- Charles F. Johnson has written an article, Errors in Abacus,
- ST-LOG, June, 1988, describing some of the more critical
- errors in the Internals book, as they exist in revision two.
- Some of these errors were corrected in revision three. I
- suggest that you obtain a copy of the article mentioned
- above to use as a reference for functions that I won't have
- a reason to use.
-
- Program 2. Halting program execution.
-
- ; Program Name: PRG_1BP.S
-
- ; Assembly Instructions:
-
- ; Assemble in AssemPro PC-relative mode and save the assembled program
- ; with a PRG extension, then save it with a TOS extension.
-
- ; Program Function:
-
- ; This program waits until a key is pressed on the keyboard. When
- ; that event occurs, it returns control to the operating system.
-
- ; NOTE: This program cannot be executed repeatedly in the debugger unless
- ; the S bit of the status register is reset after each execution.
- ; If the S bit is not reset as stated, the system will freeze, and
- ; must be reset with the computer's reset switch.
-
- wait_for_keypress:
- move.w #8, -(sp) ; Function = c_necin = GEMDOS $8.
- trap #1 ; GEMDOS call.
- addq.l #2, sp ; Reposition stack pointer at top of stack.
-
- terminate: ; My descriptive label.
- move.w #0, -(sp) ; Function = p_term_old = GEMDOS $0.
- trap #1 ; GEMDOS call.
-
- end ; Assembler pseudo-op.
-
-
- After you have installed PRG_1BP in the editor,
- assemble it, save the source with an S suffix, save the
- object code with both a PRG and a TOS suffix, then activate
- the debugger. On the debugger screen, click the symbolic
- button. You should see the wait_for_keypress label as the
- first instruction in the debugger output field; it should be
- shown in reverse video, indicating that the PC counter
- contains the address of this instruction.
- Observe the condition of the status register bits; they
- are all reset. Also, notice that the content of all
- registers shown in the register field is zero (except for
- register A7). These are the initial conditions of the
- registers at the start of the program run. As we shall soon
- discover, these initial conditions are forced by AssemPro,
- and they are not identical to those imposed by the operating
- system when a program is loaded from the desktop. You
- should notice that the content of A7 matches neither that of
- the SSP nor that of the USP. This should seem unreasonable,
- and it is. The AssemPro manual provides an explanation, of
- sorts, on p.90. This discrepancy will not interfere with
- our work.
- Click on the Run program button to execute the program.
- There will be no change in the AssemPro screen, however, the
- mouse pointer will disappear; an indication that the program
- is running. In fact, the program will be waiting for an
- event to occur; that being the press of a keyboard key.
- Press the Return key. As you have come to expect, address
- 000000 is now the topmost line in the debugger output field,
- and the program counter now contains that address. Look at
- the status register and notice the same alterations that you
- observed after executing program 1. Also, look at the
- register output field and notice that the content of many
- registers have been changed. Our initial conditions have
- been altered by AssemPro and the operating system.
- By the way, the L that precedes each register label
- indicates that you are viewing long word data. Get in the
- habit of noticing that prefix. It can be set to B, W or L,
- and what you see as a register's content varies greatly
- depending on that prefix. Furthermore, the lines at which
- register contents are displayed may be altered to display
- the contents of memory locations or their addresses.
- Without resetting anything, get the program start
- address back in the output window, move the program counter
- cursor to that line (Move the mouse pointer to the line,
- hold down the Control key and press the left mouse button.),
- then execute the program again. Things seem to be as they
- were during the first execution. But they are not. Press
- the Return key and notice the lack of response. The system
- is frozen because the alteration of the S bit is of
- consequence to the proper execution of this program.
- Furthermore, it is safe to assume that all initial
- conditions must be reset between repeated executions of any
- program in the debugger. You must manually reset the
- computer.
- Load in the source code for program 2 again, assemble
- it and go to the debugger. Click the symbolic button, as is
- usual, then execute the program. This time, reset all
- initial conditions before the second execution. Click on
- the dark status register bits to set them to zero. For each
- register (except A7) shown in the register window, with a
- nonzero content do the following:
-
- 1. Click on the Change register bar at the bottom of
- the debugger screen.
-
- 2. On the parameter line which appears, type the
- register label, an equal sign and a zero.
-
- example: d0=0 or D0=0
-
- There must be no spaces between the characters.
-
- 3. Press the Return key.
-
- Execute the program and press the Return key. The
- execution should be normal. Reset all initial conditions
- again, then click on the Save screen button. With the
- content of PC as it should be, execute the program. Now,
- you see that a blank white screen appears. The program is
- still waiting for a keypress, but AssemPro has presented a
- screen for program usage. Terminate the execution by
- pressing the Return key.
- Once again, reset all initial conditions, but leave the
- Save screen feature checked. Features such as this and
- symbolic are not included in the term initial conditions.
- Set a breakpoint at the TERMINATE label. To do this, move
- the mouse pointer to the Breakpoint button. Press the left
- mouse button and, while holding it pressed, move the pointer
- to the instruction line containing the label, before
- releasing the mouse button. You should see the word
- BREAKPOINT appear on the line just to the right of the
- label. Refer to figure 2.15. Run the program and press the
- Return key. Execution will stop at the breakpoint, apparent
- by the instruction line being highlighted by the program
- counter cursor. Notice that the S bit has not yet been set
- and notice that only the D0 and A0 registers have been
- altered (ignoring A7, as we should). Refer to the
- compressed register field, also shown in figure 2.15.
-
- Figure 2.15A. Installing a breakpoint to halt execution.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Figure 2.15B. Content of Registers at the breakpoint.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- These are the only two registers we expect to be
- altered, according to the Internals book p.106. We must be
- cognizant of this type of information so that we may know in
- which registers data is safe during operating system
- function calls. Remember, we have learned (via the
- references and an experiment) that all registers but D0 and
- A0 are safe during GEMDOS (trap #1) calls; this example
- provides no information concerning register alteration
- during other calls.
- Of course, we have not seen conclusive proof that all
- GEMDOS calls behave identically, and we will be looking out
- for deviations from the norm. The aforementioned page also
- informs us that any values returned by the function call
- will be in D0. Looking at the register field, you should
- see the ASCII code for a carriage return, the hexadecimal
- character D, in the lower word of that register. For this
- example, we are not interested in the content of register
- A0, nor are we interested in the upper word of D0. But we
- do need to remember that the character received from the
- keyboard is returned in the lower byte of the lower word of
- D0, because there will be times when we want to process that
- input.
- Remove the breakpoint. To do this, move the mouse
- pointer to the line containing the breakpoint, press the
- left mouse button, and, while holding the button down, move
- the pointer to the Breakpoint button, then release the mouse
- button. Click on the Run program button to conclude the
- execution.
- Exit AssemPro without saving the object code. Back at
- the desktop, execute PRG_1BP.PRG. You will see the PRG type
- screen, as you did when you executed program 1; but, this
- time, the program will be waiting for the keyboard event.
- You will notice that you can move the busy bee cursor to any
- position on the screen without affecting anything.
- Terminate the program by pressing any key.
- Now, execute PRG_1BP.TOS. You will see the clear
- screen with the blinking cursor in the upper left hand
- corner of the screen. Terminate the program at any time, by
- pressing any key. Note this please: there are times when
- you will exit from the debugger after doing many strange
- things as far as the computer is concerned. Occasionally,
- after you are back at the desktop, you will execute some
- program that you know is bug-free (If there is such a
- thing.), yet the program will bomb. This happens. You just
- have to reset the machine and try again, that's all.
-
- Writing to an AssemPro Screen
-
- When a program is to write text or graphics to a screen
- without destroying the debugger screen, the debugger option
- Save screen must be selected before the program is loaded
- into the debugger; or before a just assembled Relocatable
- program is relocated; or just after the function which
- returns excess memory to the operating system has been
- executed. Unfortunately, even though the option is
- selected, the very first line of output usually overwrites a
- critical portion of the debugger screen. The location of
- overwrite is random unless the program being executed
- actually positions the cursor at some selected position on
- the screen. The problem is introduced by program 3.
- I am going to assume that, unless I say otherwise, you
- will know that, as each program is introduced, you must get
- it into the editor, assemble it and save everything in the
- manner described for the programs previously introduced,
- unless the new program instructs you to do something
- different. Further, I will assume that you will go to the
- debugger screen and select Save screen, relocate (if the
- program was assembled in Relocatable mode) and symbolic. In
- addition, I trust you to reset initial conditions between
- repeated executions.
- You should realize that you will receive the warning
- message about saving object code every time you load a
- source file and assemble, then attempt to quit AssemPro
- without saving the assembled file. Having previously saved
- the object code, you will be able to simply click on the NO
- button.
-
- Program 3. A program that contaminates the debugger screen.
-
- ; Program Name: PRG_1CP.S
- ; Version: 1.002
-
- ; Assembly Instructions:
-
- ; Assemble in AssemPro PC-relative mode and save the assembled program
- ; with PRG and TOS extensions.
-
- ; Program Function:
-
- ; Prints a string to the video screen. If the program is executed
- ; within the AssemPro debugger, the string should overwrite the debugger
- ; screen, even if the AssemPro "Save Screen" option has been selected. To
- ; verify this phenomenon, power the computer down, then back up. Execute
- ; ASSEMPRO.PRG, then load or type this program into the editor. Assemble,
- ; then activate the debugger. Select "Save Screen" and "symbolic". Finally,
- ; select "Run Program". The debugger screen will be overwritten in an
- ; unpredictable area.
-
- ; Watch the debugger screen carefully, during execution, so that you
- ; will be able to see the writeover occur.
-
- ; Depending on the location of the overwritten area, AssemPro may
- ; redraw a portion of its screen after the event.
-
- ; The overwrite is likely to occur only once, the first time a program
- ; which writes to the screen is executed within the debugger.
-
- ; After the string has been written, the program waits until a key
- ; is pressed on the keyboard. When that event occurs, it returns control
- ; to the debugger.
-
- ; Note - We have not defined a program stack. We are using the default
- ; system stack located at $4DB8, according to Internals page 276.
-
- print_string:
- pea string ; Push address of the string onto stack.
- move.w #9, -(sp) ; Function = c_conws = GEMDOS $9.
- trap #1 ; GEMDOS call
- addq.l #6, sp ; Reset stack pointer to top of stack.
-
- wait_for_keypress:
- move.w #8, -(sp) ; Function = c_necin = GEMDOS $8.
- trap #1 ; GEMDOS call.
- addq.l #2, sp ; Reposition stack pointer at top of stack.
-
- terminate: ; My descriptive label.
- move.w #0, -(sp) ; Function = p_term_old = GEMDOS $0.
- trap #1 ; GEMDOS call.
-
- string: dc.b 'This string will overwrite the AssemPro debugger screen.'
- dc.b $D,$A,0 ; The string is continued on this line. Here, we
- ; declare a carriage return and linefeed, then
- ; terminate the entire string with a NULL = 0.
-
- end ; Assembler pseudo-op.
-
-
- When you execute this program in the debugger, the
- program screen will appear, but the line which was printed
- will not be on that screen. Terminate execution and go back
- to the AssemPro screen by pressing the Esc key on the
- keyboard. As the debugger screen appears you will see, just
- before the output fields of the debugger screen are redrawn,
- that the line has overwritten the debugger screen. Any
- portion of the line that had overwritten the output fields
- of the debugger screen will be cleared by the redraw. On my
- screen the line was written at a location that caused a
- portion of the Single step button to be overwritten. See
- figure 2.16. Execute the program a second time; the
- sentence will be written on the program screen. Use the Esc
- key to terminate execution and get back to the debugger
- screen; it will be as it was previously.
-
- Figure 2.16. Text improperly written on the debugger
- screen.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Now deselect the Save screen option and execute the
- program again. Probably, nothing will be written on the
- debugger screen this time. Press any key to terminate
- execution. Select Save screen and execute again. You
- should see the clear program screen, and when you press Esc
- to terminate and go back to the debugger screen, you will
- probably see that the program's sentence has overwritten the
- debugger screen in a different location. By the way, the
- Esc key is the key which permits flipping between the
- program's screen and the debugger screen.
- Go to the desktop and execute PRG_1CP.PRG several
- times. Then execute PRG_1CP.TOS several times. You should
- notice that each time the program with the TOS suffix is
- executed, the operating system prints the sentence on the
- first line of the screen. This is because the cursor is
- initialized to the upper left corner of screen when a
- program has a TOS suffix. When a program with a PRG suffix
- is executed, the sentence is printed with the cursor
- positioned wherever the previous program execution happened
- to leave it. Occasionally, you may not even see the results
- of GEMDOS function $9 when the program has a PRG suffix,
- unless the program initializes the cursor position.
- If you execute the TOS program, then immediately
- execute the PRG program, the PRG program's output will
- appear on the first line of the screen. Do that a few times
- so that you understand what I mean. Now you see that
- execution of a program can be influenced by a previous
- program execution. To drive this point deeper, execute the
- PRG program several times. Notice that, with each
- execution, the sentence is printed one line lower on the
- screen. Via these experiments, I want you to understand
- that the way in which the operating system processes
- programs varies according to the suffix attached to the
- program name. As a programmer, you must know when you can
- relinquish control to the system and when you must provide
- control of even the most basic of functions within your
- program.
- The next program sends a newline (carriage return +
- line feed) to the screen as an initialization character. I
- believe that this eliminates the debugger screen overwrite
- problem because the character forces AssemPro to switch
- logical screen bases. Refer to page 168 of the Internals
- book: XBIOS function 3. You should assemble this program
- and execute it from the debugger to confirm that it
- functions as I have specified.
-
- Program 4. Eliminating debugger screen overwrite.
-
- ; Program Name: PRG_1DP.S
- ; Version: 1.002
-
- ; Assembly Instructions:
-
- ; Assemble in PC-relative mode and save with PRG and TOS extensions.
-
- ; Program Function:
-
- ; Prints a newline (combination of a carriage return and a linefeed)
- ; to the video screen before it prints a string. This added feature
- ; prevents the string from overwriting the AssemPro debugger screen, if
- ; the Save Screen debugger option is chosen before the assembled program
- ; is relocated with the Relocate option or before it is loaded with the
- ; Execute Program option.
-
- ; After the string has been written, the program waits until a key is
- ; pressed on the keyboard. When that event occurs, it returns control to
- ; AssemPro.
-
- ; Note - We have not defined a program stack. We are using the default
- ; system stack located at $4DB8, according to Internals p. 276.
-
- print_newline: ; Prints a carriage return and linefeed.
- pea newline ; Push address of string onto stack.
- move.w #9, -(sp) ; Function = c_conws = GEMDOS $9.
- trap #1
- addq.l #6, sp
-
- print_string:
- pea string ; Push address of the string onto stack.
- move.w #9, -(sp) ; Function = c_conws = GEMDOS $9.
- trap #1
- addq.l #6, sp
-
- wait_for_keypress:
- move.w #8, -(sp) ; Function = c_necin = GEMDOS $8.
- trap #1
- addq.l #2, sp
-
- terminate:
- move.w #0, -(sp) ; Function = p_term_old = GEMDOS $0.
- trap #1
-
- data
- newline: dc.b $D,$A,0 ; All strings must be NULL terminated because the
- ; function we are used to print them requires it.
- string: dc.b 'This string will not overwrite the AssemPro debugger screen.'
- dc.b $D,$A,0 ; The string is continued on this line. Here, we
- ; declare a carriage return, linefeed and terminate
- ; the entire string with a NULL = 0.
- end
-
-
- Declaring Data Within the Text Area of a Program
-
- Notice that the all of the data of program 4 has been
- declared in a more conventional location within the program.
- There is no reason to declare the data at the end of the
- program, other than that programmers find it convenient to
- do so. There are times, however, when it is more convenient
- to declare data within a program's text area. Program 5
- illustrates a method of doing that.
-
- Program 5. Declaring data within a text area.
-
- ; Program Name: PRG_1EP.S
- ; Version: 1.002
-
- ; Assembly Instructions:
-
- ; Assemble in AssemPro PC-relative mode and save the assembled program
- ; program with PRG and TOS extensions.
-
- ; Program Function:
-
- ; Illustrates a method of program organization which places declarations
- ; at the beginning of a program.
-
- ; Note - We have not defined a program stack. We are using the default
- ; system stack located at $4DB8, according to Internals p. 276.
-
- bra.s print_string ; Jump over the declarations below.
-
- string: dc.b 'This string will not overwrite the AssemPro debugger screen.'
- dc.b $D,$A,0 ; The string is continued on this line. Here, we
- ; declare a carriage return and linefeed, then
- ; terminate the entire string with a NULL = 0.
- newline: dc.b $D,$A,0 ; All strings must be NULL terminated because the
- ; function we are used to print them requires it.
-
- align ; This is the assembler pseudo-op that forces the next
- ; instruction to start at a word boundary. It is necessary
- ; because we have declared byte data above and we don't care to
- ; count the bytes to confirm that there is an even number of
- ; byte-size data.
-
- text ; This is an assembler pseudo-op. dc.b is a pseudo-op also. We
- ; can define the string above the source code if we put this
- ; pseudo-op between the declaration and the text of the source.
- ; Of course, since the processor will attempt to execute the
- ; first thing it sees, whether it be an instruction or data, we
- ; must jump over the data. You don't jump when the data is
- ; actually an instruction you want to execute, such as when an
- ; a-line (illegal) instruction is declared as data.
-
- print_string:
- pea newline ; Prints a carriage return and linefeed.
- move.w #9, -(sp) ; Function = c_conws = GEMDOS $9.
- trap #1
- addq.l #6, sp
-
- pea string ; Push address of the string onto stack.
- move.w #9, -(sp) ; Function = c_conws = GEMDOS $9.
- trap #1 ; GEMDOS call
- addq.l #6, sp ; Reset stack pointer to top of stack.
-
- wait_for_keypress:
- move.w #8, -(sp) ; Function = c_necin = GEMDOS $8.
- trap #1 ; GEMDOS call.
- addq.l #2, sp ; Reposition stack pointer at top of stack.
-
- terminate: ; My descriptive label.
- move.w #0, -(sp) ; Function = p_term_old = GEMDOS $0.
- trap #1 ; GEMDOS call.
-
- end ; Assembler pseudo-op.
-
-
- Don't execute the program yet, but when you do, the
- first thing you will notice is that, although it does output
- correctly to the program's screen, the sentence is not
- likely to appear on the top line of the screen. This is
- true because AssemPro does not initialize the cursor on that
- screen; at least, not for this program. After you look at
- the output on the program's screen, you can go back to the
- debugger by pressing the Esc key.
- For now, notice that the first instruction of the
- program is a branch to the label print_string. Under that
- instruction you see the label string followed by the
- instruction
-
- ADDQ.W #2,$6973(A0)
-
- which is certainly not one of the instructions we included
- in our program. We declared a string at that point in the
- program. Figure 2.17 depicts the situation.
-
- Figure 2.17. PRG_1EP in symbolic disassembled format.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- It so happens that our declared data is just that which
- would be the binary representation of that instruction. You
- should convince yourself that this is true by going to the
- editor and typing in that instruction just before the branch
- instruction. Then assemble, and return to the debugger.
- After relocating, click the symbolic button so that it is
- unchecked. Now you can see that the normal disassembled
- format of both the first and third lines in the output field
- are identical. Refer to figure 2.18.
-
- Figure 2.18. PRG_1EP with added statement in normal
- disassembled format.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Now click the disassembled button so that you can view
- the content of memory in hexadecimal and ASCII. You can see
- that the same sequence of hexadecimal digits (54586973) and
- ASCII characters are formed by both the instruction ADDQ.W
- #2,$6973(A0) and the string THIS. See figure 2.19. We are
- tipped that something is not legitimate about the sequence
- of "instructions" directly following the branch instruction
- by the line DC.W $2073 which is definitely not a legitimate
- instruction. You will learn to be suspicious of any
- instruction whose hexadecimal representation forms a neat
- ASCII string.
-
- Figure 2.19. PRG_1EP with added statement in
- hexadecimal/ASCII dump format.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Some Other Debugger Functions
-
- After eliminating the addq.w statement that you added
- to the program for the demonstration, assemble and go back
- to the debugger. Click on the appropriate buttons to get
- back to the symbolic format. Notice that the label to which
- the branch is to be taken is not visible in the output
- field. You will be able to see it if you click on the
- window's right hand scroll bar. After doing that, double
- click on the from address button to go back to program
- start. Now, go over to the from address button with the
- mouse pointer and click once. When the parameter line
- appears in place of the Change register bar, backspace over
- the $ and type PRINT_STRING, then press the Return key.
- The line containing the PRINT_STRING label will replace
- the line containing the branch instruction as the first line
- in the output field. Use this method to branch to labels in
- your programs; do not use the Search function. The AssemPro
- manual indicates, on page 95, under the Search heading, that
- you can use labels with this function, however, if you
- attempt to do this, you will sit waiting while an exhaustive
- search through all of memory is conducted, then you will be
- greeted with a Not found, sorry message.
- Use the Search function to search (forward) for a
- declared string or a numerical quantity. The string for
- which you are searching must be typed on the parameter line,
- within single or double quotes, as indicated in the AssemPro
- manual, however, do not type the word Byte: before the
- string as is indicated in the manual. Instead, as shown in
- figure 2.20, you must click on the .B button which appears
- in the Search function's dialog box.
-
- Figure 2.20. The debugger Search function's dialog box; a
- slightly compressed representation.
-
-
-
-
-
-
-
-
-
-
-
- When searching for a numerical quantity, you must use
- the appropriate base indicator ($ for hexadecimal, % for
- binary, or nothing for decimal), and select the appropriate
- button (.B, .W or .L), depending on the size of the data you
- are looking for. You do not type anything else in front of
- your search criteria. The manual does not properly describe
- the use of the Search function.
-
- The Register Field
-
- Below the debugger register field there is a button
- labeled Show register. If you click on this button, the
- register field disappears. I can't imagine why anyone would
- want to do that, but the manual tells us that displaying the
- register field is optional. Figure 2.21 is a representation
- of the register field. The dotted lines shown in the figure
- are not actually visible on the AssemPro screen. I have
- included them so that you can understand the manner in which
- the content of the field is divided. It is the area between
- a set of those dotted lines on which you must double click
- to activate the dialog box discussed on page 89 of the
- manual.
-
- Figure 2.21. The debugger register field. If you double
- click on an area between a set of dotted lines, a dialog box
- will appear.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The dialog box permits you to specify an effective
- address to be flagged. Usually, you will want to view the
- content or address of a variable or a pointer. In that
- case, you would press the Esc key to clear the parameter
- line, then you would type in a label or some other effective
- address such as (A0), 6(A1) or $72FB0. You must also select
- a button to indicate whether the content or the address of
- the effective address is to be shown in the register field.
- Finally, you must chose .B, .W, or .L to indicate the length
- of the data that will be shown. However, the manual does
- not properly describe the manner in which a label must be
- typed on the parameter line. Figure 2.22 shows a label
- correctly specified on the parameter line.
-
- Figure 2.22. Flagging a string for the register field.
-
-
-
-
-
-
-
-
-
-
-
-
-
- In the discussion to follow, I will be using figures
- that indicate specific addresses and the content of those
- addresses. These are the values which appeared on my
- debugger screen while I was preparing the example. When you
- run through the example on your computer, the values will
- probably be different because they depend on each system's
- particular configuration.
- With PRG_1EP in the debugger, figure 2.23 shows the
- register field after four sessions with the dialog box. All
- we care to see is the content of memory at the location
- labeled STRING. The address at which the label STRING is
- located is $72FBO. But when STRING is typed on the
- parameter line, with the button options Content and .L
- selected, the long word $2B540000 is shown in the field as
- the content of that location. There are two reasons why we
- know this information is not correct: we did not store that
- information after the STRING label, and we can see the true
- data in the disassembled field. The register field is
- showing the content of memory location $2FB0. It is showing
- that because it has incorrectly recorded the memory location
- of STRING.
-
- Figure 2.23. Appearance of the register field when the
- parameter line of the dialog box has been prepared according
- to the instructions in the AssemPro manual.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Fortunately, I have discovered a solution to this
- problem. When you are specifying a label on the parameter
- line, type .L after the label name. Both the label and the
- extension may be in lower case or upper case. For example,
- STRING.L and string.l are equivalent. Figure 2.24
- illustrates the effectiveness of this solution.
-
- Figure 2.24. The appearance of the register field when the
- label has been followed by the suffix .L. Note that a ^
- replaces the = when an address is being shown.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- In this figure you are able to see the .L suffix in the
- register field. Note that it will only be visible when the
- label name is short enough so that truncation is not
- required. Figure 2.25 shows what happens when a label
- composed of more than seven characters is flagged.
-
- Figure 2.25. Register field showing the truncation
- of a flagged label.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Conclusion
-
- I have suggested an assembly language programming
- environment for the Atari ST with a great deal of
- confidence. I was able to do that because the AssemPro and
- TEMPUS packages are, respectively, the most powerful
- assembler and programming editor available for the ST,
- beyond question. Furthermore, both of the packages are
- reasonably priced.
- However, although I recommend the packages without
- hesitation, I have had to point out certain undesirable
- effects noticed during their use, and I have suggested
- methods of dealing with those faults. I assign no
- responsibility for the faults because the environment in
- which AssemPro and TEMPUS are forced to operate is not
- without flaws itself. I have simply reported my
- observations and the solutions that I have found to be
- satisfactory.
-
-