home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / JSAGE / ZSUS / PROGPACK / MEYERTUT.LBR / MEYER01.TZT / MEYER01.TXT
Text File  |  2000-06-30  |  14KB  |  299 lines

  1.              CP/M Assembly Language
  2.             Part I: Assembler Basics
  3.               by Eric Meyer
  4.  
  5.       I first discovered CP/M assembly language about two years
  6. ago, when I needed to modify the source code for a public domain
  7. modem program for an unusual application.
  8.      Since then, I've gone on to write a number of programs in
  9. assembly language, ranging from some simple public domain utili-
  10. ties to the memory resident utility PRESTO!.
  11.      For many such applications, assembler is the language of
  12. choice:  it's very compact and fast.  It's the most efficient way
  13. to do simple tasks that deal with moving around bytes of data,
  14. such as copying and modifying files and it allows the most
  15. sophisticated interfacing with the CP/M operating system, which
  16. is itself written in assembler.
  17.      Another nice thing is that you already have all the tools
  18. that you need to learn and use assembly language:  nothing more to
  19. buy, unless your needs grow to be very sophisticated.
  20.      CP/M 2.2 includes the ASM assembler - CP/M 3.0 comes with MAC
  21. and RMAC.  All you lack is instructions.  Let me quickly mention
  22. two good books on the subject:    CP/M Assembly Language
  23. Programming, and The Soul of CP/M.  Both, while not complete
  24. language references, put a lot of emphasis on programming in the
  25. CP/M environment, which will have you doing truly useful things
  26. (like manipulating disk files) in short order.
  27.      Both are far more comprehensive than I can attempt to be
  28. here.  I will just just present an introduction, and explain some
  29. basic concepts for those who would like to become literate in
  30. assembler.
  31.      Numbers play an important role in all that follows.
  32. Basically, everything in the computer is (or is represented as)
  33. numbers -- such as the instructions that make up a program, or
  34. the operating system itself, characters of text and other data
  35. that you may be manipulating, addresses in memory where various
  36. data or subroutines can be found, etc.
  37.      Only the context determines whether a particular value is to
  38. be interpreted as a number, an ASCII character, part of an
  39. address, or a machine instruction.
  40.      This can be very powerful, but it's also potentially very
  41. confusing.  (Pascal aficionados may need a strong drink before
  42. proceeding.)
  43.      All numbers in what follows are decimal, unless followed by
  44. a "H" (for Hexadecimal, base 16) or "B" (for Binary, base 2).
  45. Hexadecimal is commonly used in assembly language programming, as
  46. it's the most natural representation for the numbers from 1 to
  47. 255 (or 65535) that your computer manipulates on the most
  48. fundamental level.
  49.      If you're unfamiliar with these base systems, you may want
  50. to find or make a conversion chart for reference.
  51.  
  52.  
  53. 1. The CPU
  54.      The CPU (central processing unit) is the integrated circuit
  55. at the heart of your computer.    It fetches your instructions,
  56. executes them, and keeps track in the meantime (via "interrupts")
  57. of all the other tasks your computer needs to have done.
  58.      Most CP/M computers today use the Z80 CPU, though some still
  59. use the 8080 (or 8085), which are very similar but don't have
  60. quite as many instructions.
  61.      These "8-bit" CPUs deal primarily with "bytes", numeric
  62. values from 0 to 255 (11111111B, or FFH).  Two bytes together can
  63. also be used as a 16-bit "word", a value from 0 to 65535 (FFFFH).
  64.      In this manner, up to 64K (64 times 1024, or 65536, bytes)
  65. of memory can be addressed.  Part of this memory will be holding
  66. the CP/M operating system, part will contain the transient
  67. program that is actually running at the moment and part will
  68. remain available as data storage space for that program.
  69.  
  70.  
  71. 2. Assembly Language
  72.      The CPU has a moderate number of "instructions", each of
  73. which performs some simple but useful task: adding two values,
  74. fetching a byte of data from memory, and so on.  Each instruction
  75. is "coded" by one (or possibly several) bytes, according to an
  76. arbitrary system.  For example, C9H (201) is the "return"
  77. instruction, which marks the end of a subroutine.
  78.      On the earliest microcomputers, programs were entered as a
  79. series of such numbers, often with a row of eight mechanical
  80. switches:  thus the sequence "on, on, off, off, on, off, off, on"
  81. would represent 11001001B, or C9H.
  82.      This was incredibly tedious.  Today, having plenty of memory
  83. available to work with, you can write assembly language like any
  84. other language, using an editor to create a text file.    A special
  85. program, the assembler, will translate the statements you write
  86. (e.g., the mnemonic "RET" for return) into the appropriate
  87. machine code.
  88.      The assembler functions very much like a compiler for a
  89. higher-level language.    The difference is that a language compiler
  90. will incorporate prewritten library routines to perform many
  91. common tasks, and allows you to do very complex things with just
  92. a few statements. Thus when you write something like:
  93.  
  94.     100 INPUT "DIAMETER:",D
  95.     110 PRINT "CIRCUMFERENCE IS:",3.14159*D
  96.  
  97. you are actually invoking a whole set of routines (part of your
  98. BASIC interpreter or compiler) that prints messages on the
  99. screen, gets input from the keyboard, stores and retrieves data
  100. values in memory, performs floating point arithmetic, and so on.
  101.      When you program in assembler, you have to write every
  102. single CPU instruction yourself.  This can be a lot of work, since
  103. the CPU can basically do two things:  move a byte from one place
  104. to another and add, subtract, and do logical operations like
  105. "and" and "or" with byte values from 1 to 255.
  106.      Are you wondering how you would do floating point
  107. multiplication (C=3.14159*D) using an instruction set so
  108. primitive that it can only add and subtract integers from 0 to
  109. 255?  The answer is that if you are sane, you wouldn't.  There are
  110. tasks well suited to assembly language, and others best done in
  111. higher level languages.  (Somebody has already written the
  112. floating point code that's part of your BASIC interpreter, take
  113. advantage of it.)
  114.      In assembler, stick to fundamentally lower level tasks, such
  115. as talking to your computer hardware (like memory and I/O ports),
  116. and manipulating disk files with the CP/M BDOS calls. For these
  117. purposes there is no better "language".
  118.  
  119.  
  120. 3. The Assembler
  121.      There are several common assemblers, but they all work in
  122. similar ways. CP/M 2.2's ASM is a good example of a basic 8080
  123. assembler.  MAC is a macro assembler, meaning that it lets you
  124. designate frequently-used blocks of code as "macros" and invoke
  125. them with a single name, much as you would a function call in
  126. another language -- this is just a convenience.
  127.      RMAC is a relocatable macro assembler, meaning that it can
  128. produce output in a format that can be installed to run in
  129. different parts of memory as circumstances require.  The usual
  130. assembler output is code intended to run only at address 0100H,
  131. the beginning of the TPA (transient program area) under CP/M.
  132. (This is not something you are going to need to worry about at
  133. first.)
  134.      Many commercial assemblers are also available, such as
  135. Microsoft's M80.  Generally these are even more powerful, and
  136. frequently they can also take advantage of the expanded
  137. instruction set of the Z80 CPU.  The latest version of this
  138. program was written in 1981.
  139.      My personal favorites are SLR Systems' SLRMAC (8080) and
  140. Z80ASM, both of which are incredibly fast relocatable assemblers,
  141. and can also generate COM files directly.  But unless you get as
  142. heavily involved in assembly language as I have recently, it
  143. won't much matter which you use.  The common procedure is:
  144.  
  145.   1)  Write the source code with your favorite text editor.
  146.   2)  Run the assembler, typically producing a HEX output file.
  147.   3)  Generate an executable (COM) file from the HEX file.
  148.  
  149.      The first step will require learning the assembler
  150. instruction set.  The second is usually as easy as typing A>ASM
  151. PROG<cr>.  See your computer documentation for (probably minimal)
  152. instructions on assembler usage.  The third is done using the
  153. HEXCOM utility under CP/M 3.0, or LOAD and SAVE under CP/M 2.2
  154. (though a fine public domain utility called MLOAD is much easier
  155. than this combination).
  156.  
  157.  
  158. 4. Practical Tasks
  159.      Before we get into real assembler programming, it is
  160. worthwhile to note that frequently, what you need to do is not
  161. actually to write a program from scratch, but simply to get an
  162. existing program running the way you want.  Good public domain
  163. utilities, for example, often allow a number of features to be
  164. changed, to allow proper operation on different computers, or
  165. just to conform to different tastes.
  166.      At the simplest level, the program's DOC file may just give
  167. a list of patching addresses.  For example, the instructions for
  168. the (imaginary) XYZED text editor might include this information:
  169.  
  170.   ADDRESS VALUE
  171.   0130H   create BAKup files? (00=no, FF=yes)
  172.   0131H   copy buffer size in bytes (0...3000H)
  173.  
  174.      This indicates, for example, that you can get XYZED to
  175. create backup files or not, as you like, by changing a particular
  176. byte in the COM file.  The easiest way to do this is to edit
  177. XYZED.COM with a utility like EDFILE, PATCH, or DU.  Find the
  178. value at address 0130H and change it, if necessary, to what you
  179. wanted.  That's all you have to do.  XYZED must be designed to
  180. check the value it has at 0130H and adjust its behavior
  181. accordingly.
  182.      Sometimes the installation process can be more complex.
  183. Modem programs, for example, typically have to have very
  184. different basic routines to talk to the I/O hardware of different
  185. computers.  Here there will often be a whole "overlay".  An
  186. assembler source file containing an actual listing of portions of
  187. the program.
  188.      You will have to edit this file, then assemble it and merge
  189. it with the rest of the COM file.  This can require knowledge of
  190. some basic assembly language, but sometimes it can also be as
  191. simple as changing data values.
  192.      Let's begin by considering a handful of simple assembler
  193. directives.  These are not actually CPU instructions at all.
  194. They are merely instructions to the assembler, regarding where to
  195. put code, and the insertion of data values. You will see these
  196. used frequently in overlay files.
  197.  
  198.  
  199. 5. Assembler Directives
  200.  
  201. ORG (origin):  tells the assembler the address in memory at which
  202.      the following code, or data, should be put.  Most programs,
  203.      begin with "ORG 0100H", since transient CP/M programs load
  204.      in at address 0100H, the beginning of the TPA.
  205.  
  206. END:  marks the end of an assembler source file.
  207.  
  208. EQU (equate):  assigns a numerical value to a label. This isn't a
  209.      "variable", as its value cannot change, and it generates no
  210.      output code.  It's merely a convenience.
  211.  
  212. DB, DW (define byte, define word):  like the "DATA" statement in
  213.      BASIC, instructs the assembler simply to insert the
  214.      following numerical values at the current address in memory.
  215.      Presumably the program is going to refer to them as data at
  216.      some point.
  217.  
  218.  
  219.      Consider the XYZED program again.    Instead of merely giving
  220. a table of patch information to go by, as described above, it
  221. might have provided you with an overlay file XYZEDOV.ASM which
  222. would include the following instructions:
  223.  
  224.   ; XYZEDOV.ASM installation overlay
  225.  
  226. YES    EQU    0FFH
  227. NO    EQU    0
  228.  
  229.     ORG    0130H
  230.  
  231. BAKFLG: DB    YES    ; Create .BAK files?
  232.             ;   (Yes or No)
  233. BUFSIZ: DW    0800H    ; Copy buffer size,
  234.             ;   in bytes
  235.     END
  236.  
  237.      The semicolon ";", like REM in BASIC, indicates that the
  238. rest of the line is simply a comment, to be ignored by the
  239. assembler.
  240.      The two EQUates tell the assembler to substitute the number
  241. FFH (255) everywhere "YES" occurs in what follows and 0 for
  242. "NO".
  243.      Not only is this convenient.  It also makes the code more
  244. understandable, by making it clear that a value is logical
  245. (Yes/No), rather than just an arbitrary number (like 255).
  246.      This kind of thing always helps in assembly language, which
  247. is prone to be very confusing otherwise.
  248.      The 'ORG' statement tells the assembler that the following
  249. code or data is to be put starting at address 0130H in memory.
  250. In this case, XYZED.COM expects to find these data items at this
  251. address.
  252.      The labels "BAKFLG:" and "BUFSIZ:" are just for the purpose
  253. of identification here.  In an actual program, labels can
  254. function as names for variables or subroutines, as we'll see
  255. later.
  256.      The "DB YES" inserts one byte of data (in this case "YES",
  257. or FFH) at the current address (in this case 0130H, set by the
  258. ORG statement).
  259.      The "DW 0800H" inserts a word (two bytes) of data at the
  260. current address (now 0131H, since the previous byte went at
  261. 0130H).  In fact, two-byte values are stored "backwards" or low
  262. byte first, so the assembler is actually going to put the 00H at
  263. address 0131H, and then the 08H at 0132H.  This file has
  264. instructed the assembler to set up the following sequence of
  265. three data bytes:
  266.  
  267.   9ADDRESS  DATA
  268.   0130H     FFH
  269.   0131H     00H
  270.   0132H     08H
  271.  
  272.      If you now assemble this file, with a command like
  273.  
  274. A>ASM XYZEDOV<ret>
  275.  
  276. you will get an output file XYZEDOV.HEX which contains the HEX
  277. version of this code, a compact (though still ASCII text) format
  278. frequently used as an intermediary between source code and
  279. (unreadable) machine code.  If you looked at the HEX file, you
  280. would see something like this:
  281.  
  282.   :03013000FF0008F5
  283.  
  284. which can be read as "three bytes, starting at address 0130, as
  285. follows: FF, 00, 08".  (The last value on the line is just a
  286. checksum byte for safety.)
  287.      You can then use a utility like MLOAD to merge this HEX file
  288. with the program XYZED.COM itself:
  289.  
  290. A>MLOAD XYZED.COM=XYZED.COM,XYZEDOV.HEX<ret>
  291.  
  292. and you will have a new copy of the XYZED program, with the
  293. values changed accordingly.
  294.  
  295.  
  296. 6. Coming Up. . .
  297.      In future installments we'll learn about the 8080 CPU and
  298. its instruction set, and explain how to use CP/M BDOS calls.
  299.