News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_roudoudou

Rasm Z80 assembler

Started by roudoudou, 08:58, 22 February 17

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Fessor

#400
IMHO, structs are meant to save you the work of calculating the index numbers and so that you don't always have to remember these index numbers when you want to work with LD (IX+num)/(IY+num).

struct spritedef
    ptrGFXdata defw
    coordx     defb
    coordy     defb
endstruct

struct spritedef Sprite1

     org 0x4000
     ld ix,Sprite1
     ld a,(ix+spritedef.coordx)
     ld b,(ix+spritedef.coordy)
     ...
     ...
     ret

Sprite1
    defw 0xc000
    defb 20
    defb 10
(If I understood the documentary correctly)

With LD a,(ix+spritedef.coordx) you know immediately where you stand instead of ld a,(ix+3).

roudoudou

#401
Quote from: HAL6128 on 15:40, 25 June 24Ok, thanks. I need the offset structure. The naming as object is just a (misleading) coincidence.

 So, object.item3 point to memory position (in this case defb = 1 Byte + defw = 2 Bytes  = #00 + 3)?


Out of curiosity: what is the difference between structure and object declaration you mentioned?
an object is located in memory so calling him will return his absolute address

a structure is only a definition of offset

in fact the structure definition is a hack, it's kindah like

nocode
org 0
random_structname
.offset1 defb 0
.offset2 defb 0
.offset3 defb 0
code

then random_structname.offset3 will be equal to 2

roudoudou

Summer fixes :)

https://github.com/EdouardBERGE/rasm/releases/tag/v2.2.6

RASM 2.2.6
  • Added new option in order to ROMBANK NEXT
  • Bugfix sizeof on an unknown struct may not trigger error all the time

roudoudou

https://github.com/EdouardBERGE/rasm/releases/tag/v2.2.9

QuoteAbility to export native breakpoints for ACE-DL emulator
documentation up to date
update ACE-DL to benefit this new functionnality

zhulien

whats your thougths on the following I didn't see it and it is a little unusual.

If you take the following code, it of course runs the logic backwards:

POSITIONCURSOR  equ #<address>
STRINGOUTPUT equ #<address>

org #100

push START
ret

dw INFINITELOOP
dw STRINGOUTPUT
dw SETSTRINGHELLO
dw POSITIONCURSOR
dw SETCURSORPOSCENTRE
START: dw CLEARSCREEN

CLEARSCREEN:
;clear the screen
ret

SETCURSORPOSCENTRE:
ld h,40
ld l,13
ret

SETSTRINGHELLO:
ld hl,STRHELLO
ret

STRHELLO: db "Hello", 0

INFINITELOOP:
jr INFINITELOOP


But if you had a REVERSEON and REVERSOFF directive then we can think forward and type the instructions into the assembler forward, like (it would reverse the instructions, not the bytes within an instruction):

POSITIONCURSOR  equ #<address>
STRINGOUTPUT equ #<address>

org #100

push START
ret

REVERSEON

START: dw CLEARSCREEN
dw SETCURSORPOSCENTRE
dw POSITIONCURSOR
dw SETSTRINGHELLO
dw STRINGOUTPUT
dw INFINITELOOP

REVERSEOFF

CLEARSCREEN:
;clear the screen
ret

SETCURSORPOSCENTRE:
ld h,40
ld l,13
ret

SETSTRINGHELLO:
ld hl,STRHELLO
ret

STRHELLO: db "Hello", 0

INFINITELOOP:
jr INFINITELOOP


zhulien

#405
Quote from: zhulien on 02:25, 28 October 24whats your thougths on the following I didn't see it and it is a little unusual.
Why? I am still tinkering but I believe compiled code is more efficient like this for some languages, such as a Locomotive BASIC compiler.  It takes less space, it executes a little faster.  Also, a compiler can optimise somewhat easily for the prepare parameters functions, especially if constants are used, the same prepare subroutines can be repeatitively used very simply, no need for peephole optimisations in there.  I would label my subroutines a bit differently if not handcoded, like LOCATE_40_13 (as an example) if it was hardcoded, or LOCATE_X_Y (for example) if variables.

roudoudou

i do not understand what you mean by reversing instructions

pelrun

I think he wants to be able to define stack contents in the opposite order to how they'll be in memory, since the code is popping them off in reverse order.

I don't think it's a good idea; the use case is extremely small, the implementation would be non-trivial, and most people doing weird stuff like this can handle having to manually define things just the way they want them.

andycadley

Yeah, Im not sure there is a massive use case for RoP on a Z80 (although it can be efficient) and the practical aspects of actually trying to implement that in an assembler don't really seem worth it to me.

roudoudou

it's again a code generator issue more than an assembler issue? We agree no humain would write that way ?

lightforce6128

Quote from: zhulien on 02:25, 28 October 24whats your thougths on the following I didn't see it and it is a little unusual.

If I understand this right, it is about a list of consecutively called function addresses. With RET they are read from the stack. The stack growths downwards. The stack pointer is decremented on PUSH or CALL, but incremented on POP or RET. This means, the order for RET is the same as the reading order in the source code - there is no need to reverse it. Not only the Z80, but many other processors handle it this way.

I used this concept for a current project to avoid several costly CALL commands. The starting commands were "LD SP,uppermostEntryOfList : RET". The lowermost entry of the list needs to be an address that jumps back into the calling program to end the sequence of function calls.

zhulien

I was just hoping to generate assembly language in 1 parse, not have to sore it and write it out at the end.

Prodatron

Quote from: lightforce6128 on 14:33, 28 October 24This means, the order for RET is the same as the reading order in the source code - there is no need to reverse it.
Exactly. No idea, why zhulien thinks it should be listed in revers oder? Doesn't make any sense at all.

Here is an example, which is really WORKING (not like these from zhulien  :D ) on a Z80:

org #4000

ld (rout_end+1),sp
ld sp,start
ret

rout_end
ld sp,0
ret

start
dw rout_1
dw rout_2
dw rout_3
dw rout_end

rout_1
 ld a,1
 ret
rout_2
 ld a,2
 ret
rout_3
 ld a,3
 ret


As you can see, rout_1, 2, 3 are in the ascending order, and when you execute it, they will be called in this order as well.

@zhulien, maybe you didn't try out your own sources, but just had some theoretical thoughts?

GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

lightforce6128

The very first version of my software also contained reversed addresses ... ;D
It is tempting to get from the downward growth of the stack to the reverse order.
But this is only true for CALL and PUSH.
E.g. if PUSH is used for drawing, then it will draw backwards (right to left).

Prodatron


Quote from: lightforce6128 on 02:15, 29 October 24The very first version of my software also contained reversed addresses ... ;D
It is tempting to get from the downward growth of the stack to the reverse order.
But this is only true for CALL and PUSH.

You mean something like this?

org #4000

ld hl,rout_end    ;backward
push hl
ld hl,rout_3
push hl
ld hl,rout_2
push hl
ld hl,rout_1
push hl

rout_end
ret

rout_1
 ld a,1
 ret
rout_2
 ld a,2
 ret
rout_3
 ld a,3
 ret


(sorry for off-topic)

GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

zhulien

#415
Quote from: Prodatron on 22:43, 28 October 24
Quote from: lightforce6128 on 14:33, 28 October 24This means, the order for RET is the same as the reading order in the source code - there is no need to reverse it.
Exactly. No idea, why zhulien thinks it should be listed in revers oder? Doesn't make any sense at all.

Here is an example, which is really WORKING (not like these from zhulien  :D ) on a Z80:

org #4000

ld (rout_end+1),sp
ld sp,start
ret

rout_end
ld sp,0
ret

start
dw rout_1
dw rout_2
dw rout_3
dw rout_end

rout_1
 ld a,1
 ret
rout_2
 ld a,2
 ret
rout_3
 ld a,3
 ret


As you can see, rout_1, 2, 3 are in the ascending order, and when you execute it, they will be called in this order as well.

@zhulien, maybe you didn't try out your own sources, but just had some theoretical thoughts?

Yes Prodatron you are correct,  I didn't test i am brainstorming for my compiler code generator, the stack does go down but I am leveraging off ret which goes up. It was in the end a bogus thought, but good I posted it.

I am considering it as the code to generate for a new basic compiler,  I have 2 related ideas currently.  But, one allows for romable code and one doesn't.  Its great stack popping does allow for romable code and very small code too.

lightforce6128

#416
Quote from: Prodatron on 09:09, 29 October 24You mean something like this?

...
ld hl,rout_end    ;backward
push hl
ld hl,rout_3
push hl
ld hl,rout_2
push hl
ld hl,rout_1
push hl
...


No, like this it would also work. In my first version, I simply used the list "DEFW rout_end, rout_3, rout_2, rout_1" and wondered what was going on. In the second version I chose the correct order.

zhulien

Quote from: lightforce6128 on 01:06, 30 October 24
Quote from: Prodatron on 09:09, 29 October 24You mean something like this?

...
ld hl,rout_end    ;backward
push hl
ld hl,rout_3
push hl
ld hl,rout_2
push hl
ld hl,rout_1
push hl
...


No, like this it would also work. In my first version, I simply used the list "DEFW rout_end, rout_3, rout_2, rout_1" and wondered what was going on. In the second version I chose the correct order.

Yes but thats because it's pushing in reverse first  then leveraging off the rest to execute. That is one non romable way. 

krusty_benediction

Quote from: zhulien on 04:05, 30 October 24
Quote from: lightforce6128 on 01:06, 30 October 24
Quote from: Prodatron on 09:09, 29 October 24You mean something like this?

...
ld hl,rout_end    ;backward
push hl
ld hl,rout_3
push hl
ld hl,rout_2
push hl
ld hl,rout_1
push hl
...


No, like this it would also work. In my first version, I simply used the list "DEFW rout_end, rout_3, rout_2, rout_1" and wondered what was going on. In the second version I chose the correct order.

Yes but thats because it's pushing in reverse first  then leveraging off the rest to execute. That is one non romable way.
Could'nt you create a new thread? You are quite polluting Rasm's one

roudoudou

https://github.com/EdouardBERGE/rasm/releases/tag/v2.3.0

Rasm 2.3.0 - Beacon 2025

- READ directive is now DEPRECATED! (replace them with INCLUDE)
- new ability to initialise structure objects
- bugfix segfault with structure self-recursive declaration
- documentation updated
- Thanks to Sid for Mac binary

Powered by SMFPacks Menu Editor Mod