home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpm / asmutl / meyertut.ark / MEYER01.TXT < prev    next >
Encoding:
Text File  |  1987-12-04  |  13.8 KB  |  296 lines

  1.                      CP/M Assembly Language
  2.                     Part I: Assembler Basics
  3.                           by Eric Meyer
  4.  
  5.       I first discovered this about two years ago, when I needed
  6. to modify the source code for a public domain modem program for
  7. an unusual application.
  8.      Since then, I've gone on to write a number of programs in
  9. assembler, ranging from some simple public domain utilities to
  10. 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; and so on.
  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); though two bytes
  63. together can also be used as a 16-bit "word", a value from 0 to
  64. 65535 (FFFFH).
  65.      In this manner, up to 64K (64 times 1024, or 65536, bytes)
  66. of memory can be addressed. Part of this memory will be holding
  67. the CP/M operating system; part will contain the transient
  68. program that is actually running at the moment; and part will
  69. remain available as data storage space for that program.
  70.  
  71.  
  72. 2. Assembly Language
  73.      The CPU has a moderate number of "instructions", each of
  74. which performs some simple but useful task: adding two values,
  75. fetching a byte of data from memory, and so on. Each instruction
  76. is "coded" by one (or possibly several) bytes, according to an
  77. arbitrary system. For example, C9H (201) is the "return"
  78. instruction, which marks the end of a subroutine.
  79.      On the earliest microcomputers, programs were entered as a
  80. series of such numbers, often with a row of eight mechanical
  81. switches: thus the sequence "on, on, off, off, on, off, off, on"
  82. would represent 11001001B, or C9H.
  83.      This was incredibly tedious. Today, having plenty of memory
  84. available to work with, you can write assembly language like any
  85. other language, using an editor to create a text file; a special
  86. program, the assembler, will translate the statements you write
  87. (e.g., the mnemonic "RET" for return) into the appropriate
  88. machine code.
  89.      The assembler functions very much like a compiler for a
  90. higher-level language. The difference is that a language compiler
  91. will incorporate prewritten library routines to perform many
  92. common tasks, and allows you to do very complex things with just
  93. a few statements. Thus when you write something like:
  94.  
  95. 100 INPUT "DIAMETER:",D
  96. 110 PRINT "CIRCUMFERENCE IS:",3.14159*D
  97.  
  98. you are actually invoking a whole set of routines (part of your
  99. BASIC interpreter or compiler) that prints messages on the
  100. screen, gets input from the keyboard, stores and retrieves data
  101. values in memory, performs floating point arithmetic, and so on.
  102.      When you program in assembler, you have to write every
  103. single CPU instruction yourself. This can be a lot of work, since
  104. the CPU can basically do two things: move a byte from one place
  105. to another; and add, subtract, and do logical operations like
  106. "and" and "or" with byte values from 1 to 255.
  107.      Are you wondering how you would do floating point
  108. multiplication (C=3.14159*D) using an instruction set so
  109. primitive that it can only add and subtract integers from 0 to
  110. 255?  The answer is that if you are sane, you wouldn't. There are
  111. tasks well suited to assembly language, and others best done in
  112. higher level languages. (Somebody has already written the
  113. floating point code that's part of your BASIC interpreter; take
  114. advantage of it.)
  115.      In assembler, stick to fundamentally lower level tasks, such
  116. as talking to your computer hardware (like memory and I/O ports),
  117. and manipulating disk files with the CP/M BDOS calls. For these
  118. purposes there is no better "language".
  119.  
  120.  
  121. 3. The Assembler
  122.      There are several common assemblers, but they all work in
  123. similar ways. CP/M 2.2's ASM is a good example of a basic 8080
  124. assembler. MAC is a macro assembler, meaning that it lets you
  125. designate frequently-used blocks of code as "macros", and invoke
  126. them with a single name, much as you would a function call in
  127. another language -- this is just a convenience.
  128.      RMAC is a relocatable macro assembler, meaning that it can
  129. produce output in a format that can be installed to run in
  130. different parts of memory as circumstances require; the usual
  131. assembler output is code intended to run only at address 0100H,
  132. the beginning of the TPA (transient program area) under CP/M.
  133. (This is not something you are going to need to worry about at
  134. first.)
  135.      Many commercial assemblers are also available, such as
  136. Microsoft's M80. Generally these are even more powerful, and
  137. frequently they can also take advantage of the expanded
  138. instruction set of the Z80 CPU.
  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's
  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; they
  194. are merely instructions to the assembler, regarding where to put
  195. code, and the insertion of data values. You will see these used
  196. 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.      e.g., begin with "ORG 0100H", since transient CP/M programs
  204.      load 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 a
  220. table of patch information to go by, as described above, it might
  221. have provided you with an overlay file XYZEDOV.ASM which would
  222. include the following instructions:
  223.  
  224. ;XYZEDOV.ASM installation overlay
  225. YES       EQU     0FFH
  226. NO        EQU     0
  227. ORG       0130H
  228. BAKFLG:   DB      YES       ;create BAK files?
  229.                             ;  (yes or no)
  230. BUFSIZ:   DW      0800H     ;copy buffer size,
  231.                             ; in bytes
  232. END
  233.  
  234.      The semicolon ";", like REM in BASIC, indicates that the
  235. rest of the line is simply a comment, to be ignored by the
  236. assembler.
  237.      The two EQUates tell the assembler to substitute the number
  238. FFH (255) everywhere "YES" occurs in what follows, and 0 for
  239. "NO".
  240.      Not only is this convenient; it also makes the code more
  241. understandable, by making it clear that a value is logical
  242. (yes/no), rather than just an arbitrary number (like 255).
  243.      This kind of thing always helps in assembly language, which
  244. is prone to be very confusing otherwise.
  245.      The ORG statement tells the assembler that the following
  246. code or data is to be put starting at address 0130H in memory. In
  247. this case, XYZED.COM expects to find these data items at this
  248. address.
  249.      The labels "BAKFLG:" and "BUFSIZ:" are just for the purpose
  250. of identification here, though in an actual program, labels can
  251. function as names for variables or subroutines, as we'll see
  252. later.
  253.      The "DB YES" inserts one byte of data (in this case "YES",
  254. or FFH) at the current address (in this case 0130H, set by the
  255. ORG statement).
  256.      The "DW 0800H" inserts a word (two bytes) of data at the
  257. current address (now 0131H, since the previous byte went at
  258. 0130H). In fact, two-byte values are stored "backwards" or low
  259. byte first, so the assembler is actually going to put the 00H at
  260. address 0131H, and then the 08H at 0132H. So this file has
  261. instructed the assembler to set up the following sequence of
  262. three data bytes:
  263.  
  264. 9ADDRESS        DATA
  265. 0130H          FFH
  266. 0131H          00H
  267. 0132H          08H
  268.  
  269.      If you now assemble this file, with a command like
  270.  
  271. A> asm xyzedov<cr>
  272.  
  273. you will get an output file XYZEDOV.HEX which contains the HEX
  274. version of this code, a compact (though still ASCII text) format
  275. frequently used as an intermediary between source code and
  276. (unreadable) machine code. If you looked at the HEX file, you
  277. would see something like this:
  278.  
  279. :03013000FF0008F5
  280.  
  281. which can be read as "three bytes, starting at address 0130, as
  282. follows: FF, 00, 08". (The last value on the line is just a
  283. checksum byte for safety.)
  284.      You can then use a utility like MLOAD to merge this HEX file
  285. with the program XYZED.COM itself:
  286.  
  287. A> mload xyzed.com=xyzed.com,xyzedov.hex<cr>
  288.  
  289. and you will have a new copy of the XYZED program, with the
  290. values changed accordingly.
  291.  
  292.  
  293. 6. Coming Up. . .
  294.      In future installments we'll learn about the 8080 CPU and
  295. its instruction set, and explain how to use CP/M BDOS calls.
  296.