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 / MEYER03.TZT / MEYER03.TXT
Text File  |  2000-06-30  |  7KB  |  200 lines

  1.              CP/M Assembly Language
  2.              Part III: Calling BDOS
  3.               by Eric Meyer
  4.  
  5.      Last time we learned about the structure of the 8080 CPU,
  6. and wrote a simple little program to move around bytes (or words)
  7. of data with it. We found, however, that we couldn't tell we had
  8. done anything. Now we need to learn how to communicate with the
  9. terminal, print messages, and get keyboard input.
  10.  
  11.  
  12. 1. The CALL and JMP instructions
  13.      It's good practice to divide assembler code into separate
  14. modules. As you probably can imagine, once you have a few dozen
  15. (or hundred) lines of code, things start looking disorganized.
  16.      Then, of course, you need to be able to run each module of
  17. code in the proper sequence. By nature, the 8080 CPU just goes
  18. along executing one instruction after another, as it finds them.
  19. But there is a pair of instructions that cause it to go and
  20. execute code at some other location instead. The JMP (jump)
  21. instruction is like GOTO (a branch) in many languages; it simply
  22. goes and begins executing code someplace else.
  23.      The CALL instruction, like GOSUB (a subroutine call), does
  24. the same thing, but remembers where you were before, and will
  25. return there when it finds a RET instruction.
  26.      Both JMP and CALL take an address (16-bit data value) for an
  27. argument. This is almost always a label marking the beginning of
  28. the code you want to execute. For example:
  29.  
  30.     INSRT1
  31.     INSTR2
  32.     JMP    LABEL
  33.     INSTR3
  34. LABEL:    INSTR4
  35.     INSTR5
  36.  
  37. actually will execute instructions 1, 2, 4, 5, skipping instr3.
  38. Similarly,
  39.  
  40.     INSTR1
  41.     CALL    LABEL
  42.     INSRT2
  43.     RET
  44. LABEL:    INSTR3
  45.     INSTR4
  46.     RET
  47.  
  48. will execute the instructions in the order 1, 3, 4, 2.
  49.      As an exercise, you might want to go back to the byte mover
  50. program of the last installment, and rewrite the instructions
  51. that move a byte from source to destination as a subroutine,
  52. which you could then CALL any number of times in sequence.
  53.  
  54.  
  55. 2. BDOS Calls
  56.      In Part I, I said that assembler differed from higher-level
  57. languages in that there were no prepared subroutines for you to
  58. call, you had to write every byte of code yourself.
  59.      Actually, this isn't strictly true.
  60.      CP/M has a number of routines in the BDOS (basic disk
  61. operating system) which are designed to be called as subroutines,
  62. and allow you to do useful things like send characters to and
  63. from the terminal, read and write disk files, etc.
  64.      This is the only way to do these tasks without knowing a lot
  65. of specific detail about (or duplicating a lot of the code in)
  66. the BIOS (basic input/output system) that allows CP/M to run on
  67. your particular computer.
  68.      In brief, the operating system has already been told how to
  69. do these things -- all you have to do is ask it to do them.
  70.      There are several dozen "BDOS calls". At address 0005H in
  71. memory, there is always a JMP instruction which leads into the
  72. operating system.
  73.      Thus you make a BDOS call by setting up certain initial
  74. values, and then CALLing address 0005H. First you need to decide
  75. which BDOS function you want. Each has a code number, which has
  76. to be loaded into the C register. Then, if necessary, you put
  77. some additional information into the D-E registers. Then you CALL
  78. 0005H. The whole thing winds up looking like:
  79.  
  80.     MVI    C,xx    ; Put the BDOS function number here
  81.     LXI    D,xxxx    ;   (may need some more data here)
  82.     CALL    0005H    ; Ask the BDOS to do it
  83.  
  84.      Our immediate need is to communicate with a program. Here
  85. are three BDOS calls to do the job.
  86.      Function 2 sends a character to the screen. You have to put
  87. the desired ASCII code into the E register (the D register isn't
  88. used here):
  89.  
  90.     MVI    C,2    ; Console output function
  91.     MVI    E,xx    ; Put the character you want here
  92.     CALL    0005H    ; Ask BDOS to do it
  93.  
  94.      This could get tedious for a whole string. We could write a
  95. subroutine to use this call repeatedly, but for now let's be
  96. lazy.
  97.      Function 9 sends a whole string of characters to the screen.
  98. You have to use the $ character to mark the end of the string,
  99. and to put the address where the string starts into the D-E pair.
  100. The following complete program, which you can assemble and run,
  101. prints out "Hello world!":
  102.  
  103.     ORG    0100H
  104. ;
  105.     MVI    C,9     ; Print string function
  106.     LXI    D,STRING ; Address of the string to print
  107.     CALL    0005H     ; Ask BDOS to do it
  108.     RET
  109. ;
  110. STRING: DB    'Hello world!$'
  111.     END
  112.  
  113.      Function 1 gets a character from the keyboard. It doesn't
  114. require any other information; you simply:
  115.  
  116.     MVI    C,1    ; Console input function
  117.     CALL    0005H    ; Ask BDOS to do it
  118.  
  119. and the BDOS will wait for a key to be pressed. The ASCII code of
  120. the key will be returned to your program in the A register. The
  121. following program will ask you a question and accept your
  122. response:
  123.  
  124.     ORG    0100H
  125.     MVI    C,9     ; Print string
  126.     LXI    D,QUESTN ;  (this one)
  127.     CALL    0005H
  128.     MVI    C,1     ; get key
  129.     CALL    0005H
  130.     RET         ; Who cares?
  131. ;
  132. QUESTN: DB    'Are you excited? (Y/N) $'
  133.     END
  134.  
  135.      At the point where this program RETurns, the ASCII value of
  136. the key you typed is in the A register. Sadly, we don't know how
  137. to examine or test this yet, so there's no more to do for now.
  138.  
  139.  
  140. 3. It Talks, It . . .
  141.      Now we can rewrite our "byte mover" program from Part II, so
  142. that it uses a neat subroutine to move each byte, and tells us
  143. what it's doing. Let's call this BYTEMOV2.ASM:
  144.  
  145. BDOS    EQU    0005H     ; Define the BDOS entry address
  146.     ORG    0100H     ; Code begins here
  147.     MVI    C,9     ; BDOS print string fn
  148.     LXI    D,HELLO  ; Ident. message
  149.     CALL    BDOS     ; Do it
  150.     MVI    C,9
  151.     LXI    D,DEST     ; Show the original string
  152.     CALL    BDOS
  153.     LXI    H,SOURCE ; Point to source
  154.     LXI    D,DEST     ; Point to destination
  155.     CALL    MOVBYT     ; Move one byte
  156.     CALL    MOVBYT     ; Move the second byte
  157.     MVI    C,9
  158.     LXI    D,DONE     ; Explain that it's changed
  159.     CALL    BDOS
  160.     MVI    C,9
  161.     LXI    D,DEST     ; Show what it is now
  162.     CALL    BDOS
  163.     RET         ; All done, return
  164. ;
  165. ; Subroutine to move a byte
  166. ;
  167. MOVBYT: MOV    A,M    ; Fetch byte from memory
  168.     XCHG        ; Point to destination
  169.     MOV    M,A    ; Store byte
  170.     XCHG        ; Point back to source
  171.     INX    H    ; Increment source
  172.     INX    D    ; Increment destination
  173.     RET        ; All done
  174. ;
  175. ; Data area... note "$" char so we can use BDOS 9
  176. ;
  177. SOURCE: DB    'Hi$'    ; Move bytes from here
  178. DEST:    DB    '??$'    : To here
  179. ;
  180. ; Messages
  181. ;
  182. HELLO:    DB    'Byte mover program 2-- string was: $'
  183. DONE:    DB    ' and it is now: $'
  184.     END
  185.  
  186.      When you assemble and run this program, you will know that
  187. it actually did something; what you should of course see is:
  188.  
  189. A>BYTEMOV2<ret>
  190.  
  191.       Byte mover program 2 string was ?? and it is now hi. Note
  192. how easy it would be to increase the string length -- just add in
  193. the extra characters at SOURCE and DEST, and call MOVBYT a few
  194. more times.
  195.  
  196.  
  197. 4. Coming Up . . .
  198.      In future installments we'll learn some more assembler
  199. instructions, including arithmetic and conditional branches.
  200.