First steps in ASM, but I (probably) need some guidance

Страница 1/7
| 2 | 3 | 4 | 5 | 6

By Mirg

Expert (88)

Аватар пользователя Mirg

24-09-2005, 14:29

I've written a tiny program that reads out a keypress, then displays the character and its binary value. It works just fine, but I'd really like some feedback on its structure and use of registers. Should I be using registers like this, or is there a "best practice" for it? If so, I'll gladly adapt to best practice. I'm just starting out, so I'm trying to get the basics just right. Smile

Also, if the code can be quicker, better, faster, nicer, etc (which, looking at the mess I've made is probably the case): please post. Big smile

Well, here's the little bit of code:

        ORG $C000

CHGET:  EQU $9F
CHPUT:  EQU $A2

        CALL CHGET
        CALL BITS
        RET

BITS:
        LD B,8
        LD C,A
        CALL CHPUT
        LD A,58
        CALL CHPUT
        LD A,32
        CALL CHPUT
BITSL:  RL C
        CALL C,BITSC
        CALL NC,BITSNC
        DEC B
        JP NZ,BITSL
        RET

BITSC:  LD A,49
        CALL CHPUT
        RET

BITSNC: LD A,48
        CALL CHPUT
        RET
Для того, чтобы оставить комментарий, необходимо регистрация или !login

By sjoerd

Hero (593)

Аватар пользователя sjoerd

24-09-2005, 16:24

I would replace the BITSL-loop with:

	LD DE,48
BITSL:  RL C
        LD A,E
        ADC A,D
	CALL CHPUT
	DJNZ BITSL
        RET

And to make it a bit faster, you could replace 'CALL CHPUT' with 'OUT (152),A'...

By Mirg

Expert (88)

Аватар пользователя Mirg

24-09-2005, 17:04

Thanks! I didn't know about DJNZ yet. At least I used the right register for the loop-counter. Big smile

I was wondering why you used ADC A,D instead of ADC A,0 but I looked it up and saw that ADC A,r was faster than ADC A,n. If I understand the Z80-architecture correctly (still reading chapter 2 of "Programming the Z80"), using r instead of n is always faster as the registers are available right away, right?

The OUT($98) works like a charm. I haven't read up on VDP programming that much, but how does this work? I thought the VDP only acted on commands instead of directly sending data without a command to it? Or does OUT($98) only work directly in textmode or something like that?

By jltursan

Prophet (2154)

Аватар пользователя jltursan

24-09-2005, 18:01

The OUT instructions is always used to send data to VDP, this could be raw VRAM data (like the case above) or could instruct VDP to do some task. On MSX1 computers there's no special "commands" like in the MSX2 VDP, so you have to deal with data manually...

...and if you want to save some bytes (and speed), you can always replace in your whole programs the following couple of opcodes:

CALL xxxxxx
RET

with:

JP xxxxxx

Happy coding! Smile

By sjoerd

Hero (593)

Аватар пользователя sjoerd

24-09-2005, 20:51

I was wondering why you used ADC A,D instead of ADC A,0 but I looked it up and saw that ADC A,r was faster than ADC A,n. If I understand the Z80-architecture correctly (still reading chapter 2 of "Programming the Z80"), using r instead of n is always faster as the registers are available right away, right?Right. But if the loop didn't loop 8 times, but only two or so, ADC A,n would have been faster because we have to load the D register with the correct value once before entering the loop...
It's possible to free the D register, and it would be even 'better' (whatever that isSmile ) to swap the purpose of C and E:

BITS:
        LD E,A
        CALL CHPUT
        LD A,58
        CALL CHPUT
        LD A,32
        CALL CHPUT
	LD BC,8*256+48
BITSL:  RL E
        XOR A
        ADC A,C
	OUT ($98),A
	DJNZ BITSL
        RET

The OUT($98) works like a charm. I haven't read up on VDP programming that much, but how does this work? I thought the VDP only acted on commands instead of directly sending data without a command to it? Or does OUT($98) only work directly in textmode or something like that?
The VDP has a couple of ports, but in textmodes we can't use commands; and we'll forget about the paletteport and status for now.
That leaves two ports: the data port on $98, and the command/addressport on 99$. The data port is used to move data to and from the VRAM, and the commandport is used to set the VRAM address where this data should go (or should come from). This port is also used to set the videoregisters, which we also will ignore now Smile

To put something on the screen, you should find out where the patternnametable starts, which is address 0 in screen 0, and 6144 in screen 1.

The following routine expects a VRAM address in HL: This address should not be higher than 16383.

SetWrite
  di
  ld a,l
  out (99h),a
  ld a,64
  or h
  out (99h),a
  ei
  ret

the following code does something like 'LOCATE 5,10: PRINT"S"' in SCREEN 0 in Basic:

  ld hl,5+10*40+0
  call SetWrite
  ld a,'S'
  out (152),a

Where '40' is the screenwidth Wink and '0' is the start of the patternnametable.

The VDP automatically increases the write address.

I almost never read from VRAM, but here is the SetRead anyway...

SetRead
  di
  ld a,l
  out (99h),a
  ld a,h
  out (99h),a
  ei
  ret

So 'A=VPEEK(145)' is as follows:

  ld a,145
  call SetRead
  in a,(152)

By ARTRAG

Enlighted (6234)

Аватар пользователя ARTRAG

25-09-2005, 00:12

You mean:

So 'A=VPEEK(145)' is as follows:

ld hl,145
call SetRead
in a,(152)

By sjoerd

Hero (593)

Аватар пользователя sjoerd

25-09-2005, 03:06

yes, ARTAG, you're right. thanks Smile

By BiFi

Enlighted (4348)

Аватар пользователя BiFi

25-09-2005, 08:45

it's not the MSX standard method though... one is required to fetch the first VDP read and first VDP write port from the BIOS ROM (addresses 6 and 7) and work with those values.

By Mirg

Expert (88)

Аватар пользователя Mirg

25-09-2005, 14:36

Thanks everyone! I'm starting to really understand how assembler works now and how to speed up
code. A lot of the sources that I downloaded or viewed make either complete or almost complete sense now, including the choice of instructions. Big smile

BiFi, I read somewhere that only MSX1 to MSX2 upgrade kits had their VDP ports on different addresses. Can I safely use port $98 - $9B when programming the VDP, or is it better to define four labels (VDP98 - VDP9B or something like that) in which I load the VDP registers when my program starts and use them for VDP stuff?

Jumps aren't completely clear to me, yet. What exactly is the difference between JP and JR? JR is a relative jump, right? How does that work in an assembler? Does it translate label-addresses into relative ones or something like that?

And thanks for clearing up the VDP textmode, Sjoerd! Big smile

By Edwin

Paragon (1182)

Аватар пользователя Edwin

25-09-2005, 22:26

Jumps aren't completely clear to me, yet. What exactly is the difference between JP and JR? JR is a relative jump, right? How does that work in an assembler? Does it translate label-addresses into relative ones or something like that?

JP uses an absolute address for the jump, JR uses a one byte offset added to the address after the JR instruction. Using labels in assembler is convenient so that the assembler calculates the offset. One thing to remember is that the offset must be within the range -128..+127 (with respect to the address *after* the JR instruction). But the assembler will give a warning when it doesn't fit.

By Tanni

Hero (556)

Аватар пользователя Tanni

26-09-2005, 11:05

Mirg, if you want your program to be able to run on every MSX, than you must read the contence of addresses 6 and 7 of the BIOS-ROM and use this values to access the VDP. This is because in future MSX systems, the VDP addresses might change due to technical or other reasons. Using OUT (99h),A and OUT (99h),A therefore is not recommented if you code not just for you and your special MSX computer, but if you want to distribute your programms. The same concerning the IN instructions!

Страница 1/7
| 2 | 3 | 4 | 5 | 6