More CP/M Assembler Programming - CP/M
This is a discussion on More CP/M Assembler Programming - CP/M ; Greetings!
Here's the first program I got to work in CP/M using Assembler Language just a few days ago. It's written for a Z-80 processor which is the processor that my CP/M+ system uses (it's a Commodore 128). It simply ...
-
More CP/M Assembler Programming
Greetings!
Here's the first program I got to work in CP/M using Assembler Language just a few days ago. It's written for a Z-80 processor which is the processor that my CP/M+ system uses (it's a Commodore 128). It simply displays 'Hello, World!' on the system console.
Does anyone have any pointers or corrections on how I could have written this in a more efficient manner?
ORG 0100H
BDOS EQU 05H ;Call 5 to run BDOS Functions
LD C,9 ;Load C with 'Prnt String' rotine
LD DE,Msg ;point DE reg pair to Msg string
CALL BDOS ;Calling BDOS prints string to con
LD C,0 ;Load C with 'Terminate' routine
CALL BDOS ;Return to CP/M OS
Msg: DB 0DH,0AH,'Hello, World!',0DH,0AH,'$'
END
Hopefully this formatting turns out... I wrote this message using RTF in Courier so that it would line up but I don't know if it will line up correctly in your newsreaders. I could use some pointers on that as well..
Nate
-
Re: More CP/M Assembler Programming
"Nate Brazil" wrote:
Here's the first program I got to work in CP/M using Assembler Language just a few days ago. It's written for a Z-80 processor which is the processor that my CP/M+ system uses (it's a Commodore 128). It simply displays 'Hello, World!' on the system console
Does anyone have any pointers or corrections on how I could have written this in a more efficient manner?
ORG 0100H
BDOS EQU 05H ;Call 5 to run BDOS Function
LD C,9 ;Load C with 'Prnt String' rotine
LD DE,Msg ;point DE reg pair to Msg string
CALL BDOS ;Calling BDOS prints string to con
LD C,0 ;Load C with 'Terminate' routine
CALL BDOS ;Return to CP/M OS
Msg: DB 0DH,0AH,'Hello, World!',0DH,0AH,'$'
END
That's the simplest way to do it, using an absolute non-macro 8080 assembler like ASM. (Note that there is not one single extended Z-80 opcode in your program. ASM and SID will handle it without any problem.) My criticism is that it is too much compressed. When you will have source code files one hundred pages long, you will want to do what people writing long documents (like novels) do: use paragraphs, chapters, etc. (Macros are very useful in that they allow to compress repetitive code. For example, you could define a PRINT macro at the beginning of your program, and simply write: PRINT 'Hello, World!' in your program. This is explained in Chapter 11 of "The Amstrad CP/M Plus".)
; HELLO.ASM (I always put the name of the file INSIDE the file.)
; ---------
;
; Pseudo-ops (read below)
;
ORG 0100H ; Standard CP/M COMmand file
;
; Equates (the more the better)
;
lf EQU 0AH
cr EQU 0DH
BDOS EQU 05H ;Call 5 to run BDOS Function (No! Define the address of the entry point of BDOS...)
;
; Code area
;
LD C,9 ;Load C with 'Prnt String' rotine
LD DE,Msg ;point DE reg pair to Msg string
CALL BDOS ;Calling BDOS prints string to con
;
LD C,0 ;Load C with 'Terminate' routine
CALL BDOS ;Return to CP/M OS
;
; Data area
;
Msg: DB cr,lf,'Hello, World!',cr,lf,'$'
;
;Pseudo-op (Personally, I put "-----" lines before and after pseudo-ops, since they are not part of the program, but are directives to the assembler.)
;
END
This was the classical way. This classicism is coming from... punched cards, where each statement was punched on one cardboard card. Also, many assemblers, back then, were rigidly using the columns position of the text to decide: this is a pseudo-op, this is a label, this is a mnemonic, this is an operand, or this is a comment. With the free-format assemblers available under CP/M, you can rewrite the code area this way:
LD C,9! LD DE,Msg! CALL BDOS
;
LD C,0! CALL BDOS
Note how much it compress, vertically, the code. Note also that assembly language places the parameters in the opposite way of much high-level programming language. In this case, most commonly-used compilers would use something like: BDOS (Print_String, Msg) and BDOS (System_Reset). In fact, it is possible to define a macro that will look like very much like a procedure call from a high-level PL, so your program would be... 2 lines long!
Hopefully this formatting turns out... I wrote this message using RTF in Courier so that it would line up but I don't know if it will line up correctly in your newsreaders. I could use some pointers on that as well..
I am also interested in how to display correctly ASCII files (with HT) under Windows and Google, since (for years) all my listings have been displayed atrociously by Micro**** programs. (Since I access the Internet from a cybercafe, I cannot modify what is available as "standard". Since the computer is locked, I cannot even add a font to get rid of those awful proportional characters!)
To finish, your example was too much simple. Once you have tested all the system calls of CP/M Plus, the interesting thing becomes HOW to achieve a result (the algorithm). For the time being, get as much book as possible (I know that there are several books with titles like "(introduction to) CP/M assembly language". Personally, I started with "8080/Z-80 Assembly Language" by Alan Miller, who develops, step by step, a very rudimentary "debugger". What is interesting is not the result program, but the experience that you get by expanding, chapter after chapter, the program (not forgetting to debug it at each step!), study them (it took me one month just to follow all the steps in Alan Miller's book.), then come back.)
Also, it is always better to use the best available tools. SID is so much superior to DDT that it is simply stupîd to continue to use DDT. Get the manual, follow the sample debugging session until you know by hearth all the SID commands. Sooner or later, you will need a debugger, to debug your assembly language programs. Seeing the inside of an assembly language (the settings of the flags) as it is running is also VERY educative.
(Charles Falconer mentioned the SLR assemblers. They arrived at the end of CP/M. Their only advantage is that, coming at the end, standards had been established (The main problem of the Z-80 chip was that, at the beginning, there was no standard for the mnemonics. In fact, 4 variations of extended Intel mnemonics were widely used. That's why you will see so many programs using (for example) TDL mnemonics in the CP/M Software Library (available on the Internet) or in old microcomputer magazines (like DDJ).), so they concentrated on speed. The Z-80 version is about 6 times faster than Micro****'s M80. However, for the sort of very simple programs you are likely to deal with during the coming months, any assembler as simple as ASM will do, even on a floppy disk, even with a Z-80 at 4-MHz.)
Yours Sincerely,
"French Luser"
-
Re: More CP/M Assembler Programming
Hi Nate
When making comments try to not make redundent statements
and use equates more. as an example,
; BDOS Calls to C register *********
09 EQU PRTSTR ; Print String
00 EQU TERM ; Terminate Program
; ******************
Then in code
LD C,PRTSTR ; Setup to print string
Avoid such statements as "load C with". This is clear from the
assembly
code that that is being done. It is more important to comment why you
are doing it then a reduntant statement of what you are doing.
Commenting is probably the hardest part of coding. While some state
there should be a comment on every line, sometimes, common operations
don't require as many comments. An example might be:
..................
; Print my "HELLO WORLD" to the consol
; Setup and do BIOS CALL
LD DE,Msg
LD C,PRTSTR
CALL BDOS
; Print done
..................
The above is actually quite sufficient in commenting. Choice of names
for equates can improve the readability of the code without added
comments.
Do avoid redundent statements as comments. They are only clutter with
little added to the understanding of the code. Comments like:
LD C,PRTSTR ; Setup Print String for later BDOS call
It would be informative for code that might not be obvious( of course
a BDOS call is commonly used in CP/M and is more obvious ). It
might still be useful if the actual call to BDOS was not clearly inline
with the register assignment.
Most often, WHY is a better question to answer in a comment then
WHAT. ( Don't forget that WHEN and WERE may also be needed in
a comment )
Take Care
Dwight
Nate Brazil wrote:
> Greetings!
>
> Here's the first program I got to work in CP/M using Assembler Language just a few days ago. It's written for a Z-80 processor which is the processor that my CP/M+ system uses (it's a Commodore 128). It simply displays 'Hello, World!' on the system console.
>
> Does anyone have any pointers or corrections on how I could have written this in a more efficient manner?
>
> ORG 0100H
> BDOS EQU 05H ;Call 5 to run BDOS Functions
> LD C,9 ;Load C with 'Prnt String' rotine
> LD DE,Msg ;point DE reg pair to Msg string
> CALL BDOS ;Calling BDOS prints string to con
> LD C,0 ;Load C with 'Terminate' routine
> CALL BDOS ;Return to CP/M OS
> Msg: DB 0DH,0AH,'Hello, World!',0DH,0AH,'$'
> END
>
> Hopefully this formatting turns out... I wrote this message using RTF in Courier so that it would line up but I don't know if it will line up correctly in your newsreaders. I could use some pointers on that as well..
>
> Nate
>
>
-
Re: More CP/M Assembler Programming
On Sun, 16 Apr 2006 21:15:24 -0400
"Nate Brazil" wrote:
> Does anyone have any pointers or corrections on how I could have
> written this in a more efficient manner?
>
> ORG 0100H
> BDOS EQU 05H ;Call 5 to run BDOS Functions
You might develop some procedures to organize your programs, such as
grouping your equates (EQU) before your code declarations. It makes
programs a little more readable.
> LD C,9 ;Load C with 'Prnt String' rotine
> LD DE,Msg ;point DE reg pair to Msg string
> CALL BDOS ;Calling BDOS prints string to con
This is correct, and a standard way of printing a string through the
BDos.
> LD C,0 ;Load C with 'Terminate' routine
> CALL BDOS ;Return to CP/M OS
While the above sequence is correct, you might consider replacing the
"CALL" with a "JP" to reinforce the fact that the program is intended to
terminate here and not return from the CALL (which in this case would
attempt to execute the message as if it were code). Alternate methods
of terminating the program (with a warm boot) are:
JP 0 ; Jump to the Bios Warm Boot vector (3 bytes)
or:
RST 0 ; Execute a Restart 0 which 'calls' location 0 which
jumps to the Bios (or RSX) warm boot where the Stack pointer is reset
anyway. (1 byte)
A little 'white space' (a blank line or two) to separate data elements
from code elements might be a good thing here to improve readability.
> Msg: DB 0DH,0AH,'Hello, World!',0DH,0AH,'$'
> END
Rather than using Hex and decimal numbers in your programs, you might
consider using the following EQUates along with the one you already
have:
; BDos Functions used here
PRTLIN EQU 9
EXITV EQU 0
; Control Characters used in this program
CR EQU 0DH
LF EQU 0AH
Good Luck, and welcome to Assembly Programming
Hal
-
Re: More CP/M Assembler Programming
"Hal" wrote in message
news:20060418145232.0d24a7ca.halbower@verizon.net. ..
> On Sun, 16 Apr 2006 21:15:24 -0400
> "Nate Brazil" wrote:
>
>> Does anyone have any pointers or corrections on how I could have
>> written this in a more efficient manner?
>>
>> ORG 0100H
>> BDOS EQU 05H ;Call 5 to run BDOS Functions
>
> You might develop some procedures to organize your programs, such as
> grouping your equates (EQU) before your code declarations. It makes
> programs a little more readable.
>
>> LD C,9 ;Load C with 'Prnt String' rotine
>> LD DE,Msg ;point DE reg pair to Msg string
>> CALL BDOS ;Calling BDOS prints string to con
>
> This is correct, and a standard way of printing a string through the
> BDos.
>
>> LD C,0 ;Load C with 'Terminate' routine
>> CALL BDOS ;Return to CP/M OS
>
> While the above sequence is correct, you might consider replacing the
> "CALL" with a "JP" to reinforce the fact that the program is intended to
> terminate here and not return from the CALL (which in this case would
> attempt to execute the message as if it were code). Alternate methods
> of terminating the program (with a warm boot) are:
>
> JP 0 ; Jump to the Bios Warm Boot vector (3 bytes)
>
> or:
>
> RST 0 ; Execute a Restart 0 which 'calls' location 0 which
> jumps to the Bios (or RSX) warm boot where the Stack pointer is reset
> anyway. (1 byte)
>
> A little 'white space' (a blank line or two) to separate data elements
> from code elements might be a good thing here to improve readability.
>
>> Msg: DB 0DH,0AH,'Hello, World!',0DH,0AH,'$'
>> END
>
> Rather than using Hex and decimal numbers in your programs, you might
> consider using the following EQUates along with the one you already
> have:
>
> ; BDos Functions used here
> PRTLIN EQU 9
> EXITV EQU 0
> ; Control Characters used in this program
> CR EQU 0DH
> LF EQU 0AH
>
> Good Luck, and welcome to Assembly Programming
>
> Hal
Thanks everyone for the advice! I'm certainly glad I asked. I've received
several good tips from you all!
Nate
-
Re: More CP/M Assembler Programming
wrote in message
news:1145378969.145536.113360@t31g2000cwb.googlegr oups.com...
> Hi Nate
> When making comments try to not make redundent statements
> and use equates more. as an example,
>
[...snip...]
Good advice Dwight. Thanks.