Where to start with assembly?

717 views
Skip to first unread message

Shaun ONeil

unread,
Sep 21, 2017, 9:21:27 AM9/21/17
to RC2014-Z80
Hi all,

I feel like I'm banging my head against a wall trying to learn assembly.  It feels like everything either assumes a TI calculator, or starts at step5.

Does anyone have a 'hello world' of sorts that's intended for the rc2014?  And what toolchain is generally recommended?

So far I have asz80 from bleu-romtools, which appears to be expecting asm that looks nothing like Searle's.  And the Zaks book, which presents everything as fragments that I can't get to assemble.

It's starting to feel a whole lot like round shapes and square holes!

Thanks,
  Shaun

Mark Bramwell

unread,
Sep 21, 2017, 11:10:23 AM9/21/17
to RC2014-Z80
I am in the same boot as you.

The first thing is to consider *where* you are going to do your coding.
On the PC or on the RC2014?

I have found some assemblers that run on the RC2014 but different assemblers use different codes.
That means if you create a program using one, it might not 'compile' on another

Example:

a simple command is ORG.  It specifies where the code should ultimately reside.
In CPM, the default seems to be 100h
on one system, the assembler command should be:  "ORG 100"
on another, the command should be ".ORG 100"
pick the wrong one and it does not compile.
Many other differences exist.

Another related issue is, what editor would you use on the RC2014?

I think for sanity purposes, it might be easier to edit and cross-compile on the PC.

It would be interesting to hear from people that have gone past the start point.
I am guessing z88dk  (I think that is the spelling) is the most common right now

PS:  I have a hello world.asm for 2 different assembler systems and they look completely different yet use same system calls.


Shaun ONeil

unread,
Sep 21, 2017, 12:41:19 PM9/21/17
to RC2014-Z80
Ideally on a PC (well, linux or mac).  But this doesn't seem to be where I'm getting stuck.

eg, I've tried z88dk.  It seems horribly complex and seems to assume I want to use all its libraries, but that's by the by.
I cannot find an example that it will assemble.  Just a bare-bones example.  Anything.  So I'm having to try to guess its syntax.

This can't be normal.  I feel like I'm missing something huge and obvious, that's apparently so obvious that no-one feels like they need to point it out.

Mark Bramwell

unread,
Sep 21, 2017, 1:26:57 PM9/21/17
to RC2014-Z80
Here is a simple hello world program.
Load this text onto your RC2014 as x.asm

once on your RC2014, type:

# this cpm command will assemble/compile your program
c:asm x

# this turns the hex into a .com file
c:load x

# lets run our command
x



Here is the program:
Concept:  The BDOS functions give us input, output and various other CPM functions.
You usually load a register with a value then call the BDOS jump vector.
BDOS function #9 = print a string to the console.  String must end with $

org 100h

bdos equ 5h       ;address of BDOS entry point
writeline equ 9h  ; bdos call to write a line ending with $

lxi d,msg
mvi c, writeline
call bdos
ret                 ; return to CPM

msg:  db 'Hello World',13,10,'$' ; our message ending with %



Mark Bramwell

unread,
Sep 21, 2017, 1:29:29 PM9/21/17
to RC2014-Z80
To load some text onto the RC2014  (type program into windows notepad then paste into CPM)

D>   c:ed  x.asm
i     <---  insert mode
      <--- paste your program
hit control-z to exit insert mode
w    <--- write text to file
e    <--- exit back to cpm

D>  c:asm   x
D>  c:load   x
D>  x
Hello World

Mark Bramwell

unread,
Sep 21, 2017, 1:34:54 PM9/21/17
to RC2014-Z80
FYI:  Grant appears to be using TASM.EXE for DOS.

The codes for TASM are NOT the same as CPM asm located on the C> drive


Robert Liesenfeld

unread,
Sep 21, 2017, 2:08:14 PM9/21/17
to rc201...@googlegroups.com
I don't think there's any big obvious ah-ha concept you're missing.  Learning assembly language programming for the first time is a steep learning curve for several reasons:
- Every processor has different mnemonics, sometimes even between members of the same family
- Every assembler uses different directives, meta characters, and so forth - the concepts are all the same but assembly written for one assembler may require significant tweaking before it will assemble under a different one.
- Even getting to a "Hello World" is frustrating because such intimate knowledge of the underlying hardware is required

Have you done assembly on any platform before?  If not, I suggest checking out Easy 6502: https://skilldrick.github.io/easy6502/  It focuses on 6502 assembly, not Z80, which isn't useful for the RC2014 (unless you have Ben Chong's 6502 processor board) but teaches some of the concepts such as registers, the stack, addressing modes and so forth.  The specifics aren't applicable to the Z80 but the concepts are.

A couple books I recommend: 
Z80 Assembly Language Programming by Lance A. Leventhal - this is my go-to when I'm writing Z80 assembly, an excellent reference with several chapters of examples.
Programming the Z80 by Rodnay Zaks - not as good as he Leventhal book as a reference but spends more time on basic concepts.

As for choosing an assembler: I would just choose one, learn its syntax, and get comfortable with it; once you know how to wrangle one assembler, learning how to do the same things in another is pretty trivial.

Hope this helps.

-Rob
--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+...@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/1e42acf4-cfd5-4820-acdc-bbfddc9e7698%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Mark Bramwell

unread,
Sep 21, 2017, 3:22:43 PM9/21/17
to RC2014-Z80
Previously I gave you a hello world program.
as a compare, this sample prints a single character to the screen.
The character will be "!"

By comparing the two, you will see how easy it is to use the built in CPM functions.
Go here for the list: http://www.seasip.info/Cpm/bdos.html#2
This sample is using bdos function #2


org 100h

bdos equ 5h       ;address of BDOS entry point
writechar equ 2   ; bdos function to print 1 character

mvi e, '!'
mvi c, writechar

call bdos
ret                 ; return to CPM


Note: I am using some equate to define a pair of constants.
I could shorten the length of the source code by using numbers.
BUT it would make the source less readable.

example (same code without the 'equ' lines):

org 100h
mvi e, '!'
mvi c, 2
call 5
ret                 ; return to CPM




Mark Bramwell

unread,
Sep 21, 2017, 3:26:17 PM9/21/17
to RC2014-Z80

here is the screen shot from tera term of the asm session:

Hope this helps!


Dave Pucknell

unread,
Sep 21, 2017, 4:06:02 PM9/21/17
to rc201...@googlegroups.com

Is your RC2014 a standard version (Basic Rom, 32K Ram) ? 

If so then you need a hex loader basic program to load the code in. (If you need this shout and ill send you a link)
I use PASMO on linux to compile my code.    

pasmo --hex file.asm file.ihx

or use 


That will give you the file in intel hex and then you can past that in. 

As for a hello word...   well what about try a bit more simple........ Lets just print out a H

   ORG    09000h 

            LD      a,"H" 
            RST     08 
            RET 

Thats puts the ascii code for H in to the A register. then calls the print routine.

   ORG    09000h 

            LD      a,"H" 
            RST     08 
            LD      a,"e" 
            RST     08 
            LD      a,"l" 
            RST     08 
            LD      a,"l" 
            RST     08 
            LD      a,"o" 
            RST     08
            LD      a," " 
            RST     08 
            LD      a,"W" 
            RST     08 
            LD      a,"o" 
            RST     08 
            LD      a,"r" 
            RST     08 
            LD      a,"l" 
            RST     08 
            LD      a,"d" 
            RST     08 
            RET

Not pretty... but you get the idea... 


            ORG    09000h
           LD HL,STRING
           CALL PRINT_STR_1
           RET
          
PRINT_STR_1:        
            LD      a,(hl) ; Put the contents of HL in A
            CP      00 
            JR      Z,PRINT_STR_END ; End on 0
            RST     08 ; Call the Output routine
            INC     HL ; Add one to HL- Next Char
            JP      PRINT_STR_1 ; Loop and print more
PRINT_STR_END:   
            RET

STRING:
DB      "Hello World",00


Hope this helps....

DAVE
--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+...@googlegroups.com.
To post to this group, send email to rc201...@googlegroups.com.

Spencer Owen

unread,
Sep 21, 2017, 4:51:07 PM9/21/17
to rc201...@googlegroups.com
I mainly use either;
Or hand code stuff.  Yeah, I know there are better, easier ways, but those 3 work for me.

Spencer 

To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+unsubscribe@googlegroups.com.

To post to this group, send email to rc201...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/rc2014-z80/592f856c-5051-4f31-bb7b-9a7f480a5c50%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "RC2014-Z80" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rc2014-z80+unsubscribe@googlegroups.com.

To post to this group, send email to rc201...@googlegroups.com.

A A

unread,
Sep 21, 2017, 5:52:37 PM9/21/17
to RC2014-Z80


On Thursday, September 21, 2017 at 11:26:57 AM UTC-6, Mark Bramwell wrote:

org 100h

bdos equ 5h       ;address of BDOS entry point
writeline equ 9h  ; bdos call to write a line ending with $

lxi d,msg
mvi c, writeline
call bdos
ret                 ; return to CPM

msg:  db 'Hello World',13,10,'$' ; our message ending with %



Hmm that's all 8080 code though.   There should be many z80 assemblers to choose from on cpm too.

A A

unread,
Sep 21, 2017, 6:53:52 PM9/21/17
to RC2014-Z80


On Thursday, September 21, 2017 at 10:41:19 AM UTC-6, Shaun ONeil wrote:
eg, I've tried z88dk.  It seems horribly complex and seems to assume I want to use all its libraries, but that's by the by.
I cannot find an example that it will assemble.  Just a bare-bones example.  Anything.  So I'm having to try to guess its syntax.


The syntax is standard z80, however the assembler is not a simple two-pass - the tools are more like gcc than tasm, eg.  The assembler is a linking assembler with sections which means you define a memory map composed of sections with org.  Code does not use org - instead code and data is assigned to sections defined in the memory map.  You don't have to define a memory map as a default one will be provided by the tools.

You can use the tools in roughly three ways.  One is by using the the complete dev environment which includes optional access to all the library code (integer math, floating point, strings, data compression, stdlib, stdio, etc.) in which case your program is composed of a crt and your code (asm or c).  The crt is as little as a couple of dozen bytes that performs initialization, handles program exit, and so on and it will call "_main" to start your program.  That means if your program is asm, it must start at label "_main".  For the rc2014 in particular, there are several crts to choose from with the main difference being what io is automatically supported.  One is the basic_dcio crt which will put drivers on stdin/stdout/stderr to do line editing and character io using basic's rst 8 code.  You can then do io with line editing using the c library code from asm (the c library is written in asm and has asm entry points).  Another ("none" I think) provides nothing so you have a blank slate.  Library code is not foisted on you - it's only going to be attached if you use it.

A second way is to use a --no-crt compile.  In this case you define your own memory map in a separate file and then add it as the first file in the compile line.  The program will assemble with nothing except your code in it.  Unless your memory map defines the sections the library needs, you will not be able to use the library code in your project.

The last way is to invoke z80asm directly to assemble things like you would a regular 2-pass assembler.  However, the --no-crt compile is better IMO as it will make rc2014 defines available as well as supply zcc's front end which includes macros, list files, application maker, etc.

Yes there's more to it than a basic two-pass assembler but that's unavoidable for a non-trivial project :)


Simple example using the full dev environment with crt where the entry point is "_main"

SECTION code_user   ;; which section should this be placed in?
PUBLIC _main   ;; make this symbol visible outside this file with EXTERN (crt must see this symbol to start program)

_main:

   ld hl,10
   ret

zcc +rc2014 -vn -subtype=none -clib=sdcc_iy test.asm -o test -create-app

You will want to customize the crt by setting some pragmas that disable features you don't want.  This will bring the crt down in size to a couple dozen bytes.  Without the pragmas you will be getting default behaviour suitable for the c environment (a heap is made, eg).
https://www.z88dk.org/wiki/doku.php?id=libnew:target_embedded#crt_configuration



A no-crt compile:

"zmap.asm"
;;; define a memory map here
;;; very simple one with one section and one org

SECTION CODE
org 0x9000


"test.asm"
SECTION CODE
PUBLIC start

start:

   ld hl,10
   ret


zcc +rc2014 -vn --no-crt -m -clib=sdcc_iy zmap.asm test.asm -o test

Because there is no crt, the necessary symbols for -create-app are unavailable so you must take the output binaries and call appmake directly to generate ihx, etc if you need that.The output will be one binary per section with org in the memory map.  "appmake +glue" can be used to put those binaries together to form a single block with gaps filled with a filler byte.

phillip.stevens

unread,
Sep 21, 2017, 8:41:33 PM9/21/17
to RC2014-Z80
Hi Shaun,

I feel your pain. I was in exactly the same place in July last year.
I made a decision to learn Z80 from scratch in May, and in June I received my RC2014 kit.
Then, I had to learn to programme with assembly.
 
I feel like I'm banging my head against a wall trying to learn assembly.

You are. Learning hurts.
There is a guy called Zed, who wrote a book "Learn Python the Hard Way". Everything he says is correct.
Repetition generates experience, and experience is what you need. And it takes a lot of time and a lot of energy.

And what toolchain is generally recommended?

I started with TASM, because that is what MS BASIC and Grant's work is written for, but always with the idea of developing in C using z88dk. There is a big step up in complexity between the two. TASM is nothing more than a very good and flexible assembler, that can generate Intel Hex output. It runs in DOSBOX in Linux (v3.1), and in Windows (v3.2).

z88dk is a whole lot of tools, and capabilities, and despite it being very complex it is so far superior to anything else it is hardly worth looking elsewhere.

Also, the guys who are continually improving z88dk are incredibly responsive to change requests. Some examples.
We need RC2014 support, please.
Now, I want z180 support, please.
And, now I want to have page aligned sections please.
And now can you please put all these damn binaries into one hex file...

Each one of these only took days to get fixed. I don't think this can be found in any other tool set out there.
Let's just say I'm a big fan.

They're also working on the ZXNext support currently, which can bank switch up to 4MB of RAM, so learning z88dk is also a must if you're planning to get one of these systems too.

So far I have asz80 from bleu-romtools, which appears to be expecting asm that looks nothing like Searle's.  And the Zaks book, which presents everything as fragments that I can't get to assemble.
 
My build environment is z88dk (which goes through a make install-clean; git pull; ./build.sh; cycle every time I use it.
My target is almost always the -subtype=basic-dcio because I don't like to burn an eeprom each time I upload a version, so I have MS Basic as a kind of very powerful monitor programme.

If I'm doing assembler development, then the --no-crt option just gives me clean asm to upload.

I use my integrated HexLoadr program (which is just a faster version of Grant's initialisation code) to upload my code, check the .map file for the _main location, doke that into the Basic USR(n) jump location and go.

It's starting to feel a whole lot like round shapes and square holes!

Over the past year, I've spent months trying to get an understanding of (in hindsight) very simple things.
Don't worry. It takes time, and you don't have to learn it all in one day.

When I see what experts can generate in a day, I often feel embarrassed,
but then I look back to how much I've learned in a year and it does make it worth it.

Don't give up.

Cheers, Phillip

Shaun ONeil

unread,
Sep 23, 2017, 10:24:16 AM9/23/17
to RC2014-Z80
Trying to be a little more specific about the kinds of things I'm missing ..

All the way through Leventhal's books, Searle's code, and the Zilog manual, they're using EQU (or .EQU).  Am I going nuts or is this entirely missing in z88dk?  Is DEFC an appropriate replacement? (It seems to be 32bit, which has me slightly concerned).

This is the kind of gap I appear to be hitting everywhere, where the toolchain doesn't match the books at all.

Peter Willard

unread,
Sep 25, 2017, 7:17:39 AM9/25/17
to RC2014-Z80
you are not alone

phillip.stevens

unread,
Sep 25, 2017, 7:54:47 AM9/25/17
to RC2014-Z80
Shaun,
 
Trying to be a little more specific about the kinds of things I'm missing ..

All the way through Leventhal's books, Searle's code, and the Zilog manual, they're using EQU (or .EQU).  Am I going nuts or is this entirely missing in z88dk?  Is DEFC an appropriate replacement? (It seems to be 32bit, which has me slightly concerned).

Sorry I dropped the ball on replying.

This is a file in a repository, which is similar to Grant's code, compiled with TASM.
This is the file in the same repository converted to use z88dk. The code outcome has not changed at all, just the way it is generated.
I hope that helps.

Browse the history of this file, to see how it has been changed over time too.

Note, that this doesn't reflect best practice for z88dk. Rather, it reflects trying to change as little as possible to get TASM originatedcode to compile with z88dk.

And yes, DEFC is 32bits, but it doesn't matter at all.

Cheers, Phillip

Shaun ONeil

unread,
Sep 25, 2017, 10:34:47 AM9/25/17
to RC2014-Z80
Phillip, Sir, that was well worth the wait!

Thank you.  That's exactly what I've been missing.  I've always been used to tearing apart working examples and comparing them to 'the book'.  I'd been really, really struggling to find anything that was intended for z88dk's assembler.

Being able to compare both side by side is exactly how my head works.

Thanks again,
  Shaun
Reply all
Reply to author
Forward
0 new messages