Author Topic: My introduction, and my first assembly language program  (Read 1997 times)

0 Members and 1 Guest are viewing this topic.

Offline the graveborn

  • CPC464
  • **
  • Posts: 19
  • Country: gb
    • the graveborn
    • Awards
Hi! I've been a lurker here for a few weeks, not wanting to post an introduction thread 'til I had some source code to show... I'm a student, and I usually program in C, but I'm trying to broaden my mind so I've decided to try -- emphasis on try -- to learn to program in Z80 assembly language, specifically the Arnor MAXAM dialect, specifically for the 6128+ (I played a little on my older cousin's when I was younger); I've posted below the source code to my first assembly language program (which just prints "Hello!" to the screen -- I have a lot to learn...) -- it assembles/runs without any warnings or errors, but I'd appreciate it if anybody could tell me if I've made any egregious errors!

Hello!.Z80:
Code: [Select]
; The name of the assembled executable
write "Hello!"

; After starting the 6128+

; print himem
; 42619

; So I've assumed that using addresses
; 42600..42606 (storage for the string
; "Hello!" plus terminator) is okay...?

; Register pair HL holds the address
; 42600, to be set to the first
; character in the string
ld hl, 42600

; The memory at the address held by
; HL is set to the value 72 -
; - corresponding to the letter 'H' -
; then the address held by HL is
; incremented ready for the next
; character
ld (hl), 72  ; 'H'
inc hl

ld (hl), 101 ; 'e'
inc hl
ld (hl), 108 ; 'l'
inc hl
ld (hl), 108 ; 'l'
inc hl
ld (hl), 111 ; 'o'
inc hl
ld (hl), 33  ; '!'
inc hl

; Lastly, the memory at the address
; held by HL is set to the value 0,
; terminating the string
ld (hl), 0

ld hl, 42600
.loop
  ld a, 0

  ; Compare the value at the address
  ; held by HL to 0; if it *is* 0,
  ; that's the string terminator
  cp a, (hl)
  jp z, forever

  ; Set A to the value at the address
  ; held by HL, and use a firmware
  ; function to print A to the screen
  ld a, (hl)
  call &bb5a
  inc hl
  jp loop

.forever
  jp forever
« Last Edit: 21:04, 28 December 13 by the graveborn »
like
0
No reactions

Offline redbox

  • Supporter
  • 6128 Plus
  • *
  • Posts: 1.794
  • Country: gb
    • redbox
    • Awards
Re: My introduction, and my first assembly language program
« Reply #1 on: 22:57, 28 December 13 »
Welcome and nice to see you're learning Z80, it can only make your coding generally better and more efficient.

Your code is fine and works, so it's a good attempt. Locating it beneath HIMEM is fine but generally code is placed somewhere in 'normal' RAM.

Here is an optimised version for you to play with:

Code: [Select]
org &4000

ld hl,message
.loop
ld a,(hl)
cp 0
ret z
call &bb5a
inc hl
jr loop

.message
defb "Hello World!",0
like
0
No reactions

Offline redbox

  • Supporter
  • 6128 Plus
  • *
  • Posts: 1.794
  • Country: gb
    • redbox
    • Awards
Re: My introduction, and my first assembly language program
« Reply #2 on: 23:03, 28 December 13 »
...and you can replace the CP 0 here with OR A.

For bonus points can you work out why...? ;)
like
0
No reactions

Offline TFM

  • Visit the mysteries of the CPC at www.futureos.de
  • Supporter
  • 6128 Plus
  • *
  • Posts: 9.899
  • Country: aq
  • Space Chicken for FutureOS is free!
    • index.php?action=treasury
    • FutureOS - The revolution on CPC!
    • Awards
Re: My introduction, and my first assembly language program
« Reply #3 on: 00:24, 29 December 13 »
Welcome in the forum and a happy 2014 full of CPCs.
like
0
No reactions
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

Offline the graveborn

  • CPC464
  • **
  • Posts: 19
  • Country: gb
    • the graveborn
    • Awards
Re: My introduction, and my first assembly language program
« Reply #4 on: 14:57, 29 December 13 »
@redbox: Thanks for the welcome :) Comparing your version to mine... I knew my version was bad; I didn't know how bad :( (I didn't know about the defb directive; and I didn't think enough to realise that labels could be loaded into registers.)

(And I think cp 0 could be replaced with or a as or a would essentially be a no-op but would still set the z flag if the result was 0...?)

@TFM: Thanks for the welcome :)

Presenting my first (vaguely :blush:) useful assembly language routine (to print to the screen an 8bit value as binary):

print8b.Z80:
Code: [Select]
.print8b

; B  - The value to be printed (binary
; representation)
; HL - The address to return to after
; printing B
; Corrupts A, C, D

ld c, &80
.p8b_loop
  ld a, b
  and a, c
  ld d, &30 ; Set d to '0'
  jp nz, p8b_nz
  .p8b_nz_return
  ld a, d
  call &bb5a
  srl c
  ld a, c
  cp a, 0
  jp nz, p8b_loop
  ld a, &62 ; Set a to 'b'
  call &bb5a
  jp (hl)

.p8b_nz
  ld d, &31 ; Set d to '1'
  jp p8b_nz_return

print8b.tst (to test the above):
Code: [Select]
write "print8b"

ld b, 21
ld hl, goodbye
jp print8b
.goodbye
jp goodbye

read "print8b.z80"
like
0
No reactions

Offline ralferoo

  • Supporter
  • 6128 Plus
  • *
  • Posts: 1.035
  • Country: gb
    • Awards
Re: My introduction, and my first assembly language program
« Reply #5 on: 15:33, 29 December 13 »
Nice work, you're getting there. Here are another couple of variants you might like to make sure you understand... (IMHO, a good way to learn is to understand something that seems magical before!)

BTW, I'm not sure why you'd want to use HL as a return address here. Obviously there are occasions where it's useful, but more often you'd want to keep HL available as it's the second or first most useful register depending on what you're trying to do... In all these examples, I'll assume you're calling this function and using RET to return.

So, a simple example with RL and ADC to demonstrate carry:
Code: [Select]
; entry: B=value to be printed
; exit: A=corrupted, C=0
print8b:
ld c,8
print8bloop:
ld a,#30
rl b     ; try to think about what happens to B each loop and at the end of the loop
adc a,0   ; and why this works
call &bb5a
dec c
jr nz,print8bloop
ld a,#62
jp &bb5a

a slight optimsation:

Code: [Select]
; entry: B=value to be printed
; exit: A=corrupted, C=0
print8b:
ld c,8
print8bloop:
ld a,#18
rlc b
rla            ; try to understand why this works too!
call &bb5a
dec c
jr nz,print8bloop
ld a,#62
jp &bb5a

and now:

Code: [Select]
; entry: B=value to be printed
; exit: A=corrupted, B=0
print8b:
scf ; notice this!
print8bloop:
ld a,#18
rl b   ; what happens to B here the first time through the loop and then the subsequent times
jr z,print8end  ; if you didn't want the b at the end, ret z could be used
rla
call &bb5a
and a ; think why this is needed
jr print8bloop
print8end:
ld a,#62
jp &bb5a

Happy learning! :)
like
0
No reactions

Offline fano

  • Supporter
  • 6128 Plus
  • *
  • Posts: 836
  • Country: fr
  • Easter Egg Programmer
    • Easter Egg
    • Awards
Re: My introduction, and my first assembly language program
« Reply #6 on: 17:50, 29 December 13 »

Welcome to the marvellous world of Z80 programming (and CPC Z80 world where JR is faster than JP  :P  )
Note CPC firmware does not use C termination for string but it sets the last character bit 7 as string terminator.

(And I think cp 0 could be replaced with or a as or a would essentially be a no-op but would still set the z flag if the result was 0...?)
It is 1µs and 1 byte instead of 2µs and 2 bytes for cp 0.What is the result if you OR (or AND) a bit with ifself ?
like
0
No reactions
"NOP" is the perfect program : short , fast and (known) bug free

Follow Easter Egg products on Facebook !

Offline the graveborn

  • CPC464
  • **
  • Posts: 19
  • Country: gb
    • the graveborn
    • Awards
Re: My introduction, and my first assembly language program
« Reply #7 on: 17:54, 29 December 13 »
@ralferoo: Thanks for those examples; I'm still working to understand them, but after seeing the first of those examples I realised that --

Code: [Select]
ld a, &80
add a, &80 ; a is now 00000000b
adc a, 0   ; a is now 00000001b

-- thanks! :)

BTW, I'm not sure why you'd want to use HL as a return address here.

Because I haven't (yet...) figured out how to use ret to return from a jp :blush:

And after writing that I figured it out -- I shouldn't have been using jp, but call :blush:

(I'm trying to learn from pretty much a listing of assembler mnemonics -- a little less than ideal ;) I still have no idea what the m, p, pe, or po flags are for...)
like
0
No reactions

Offline the graveborn

  • CPC464
  • **
  • Posts: 19
  • Country: gb
    • the graveborn
    • Awards
Re: My introduction, and my first assembly language program
« Reply #8 on: 17:58, 29 December 13 »
@fano: Thanks for the welcome :)

I guessed that or instead of cp would be a time or memory saving, or redbox wouldn't have suggested it ;)

What I meant by no-op was that or a wouldn't change a, but would have the side-effect of setting z (and clearing nz) if a was 0... correct?
like
0
No reactions

Offline fano

  • Supporter
  • 6128 Plus
  • *
  • Posts: 836
  • Country: fr
  • Easter Egg Programmer
    • Easter Egg
    • Awards
Re: My introduction, and my first assembly language program
« Reply #9 on: 18:22, 29 December 13 »

Exact  ;)

I still have no idea what the m, p, pe, or po flags are for...)
pe and po stands for parity even and parity odd (bit count parity in result), related to P/V (or P) flag.m and p stands for negative or positive result (high bit of the operation result), related to S flag.
like
0
No reactions
"NOP" is the perfect program : short , fast and (known) bug free

Follow Easter Egg products on Facebook !

Offline ralferoo

  • Supporter
  • 6128 Plus
  • *
  • Posts: 1.035
  • Country: gb
    • Awards
Re: My introduction, and my first assembly language program
« Reply #10 on: 18:27, 29 December 13 »
Everything Z80 you could possibly need will be at Thomas Scherrer Z80-Family Official Support Page (although obviously nothing that's CPC specific)
like
0
No reactions