Autor
| First steps in ASM, but I (probably) need some guidance
| Mirg msx lover Mensajes: 84 | Publicado: Septiembre 24 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.
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.
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 | | sjoerd msx addict Mensajes: 449 | Publicado: Septiembre 24 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'... | | Mirg msx lover Mensajes: 84 | Publicado: Septiembre 24 2005, 17:04   | Thanks! I didn't know about DJNZ yet. At least I used the right register for the loop-counter.
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? | | jltursan msx professional Mensajes: 873 | Publicado: Septiembre 24 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!  | | sjoerd msx addict Mensajes: 449 | Publicado: Septiembre 24 2005, 20:51   | Quote:
| 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 is  ) 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
Quote:
| 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
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  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)
| | ARTRAG msx master Mensajes: 1686 | Publicado: Septiembre 25 2005, 00:12   | You mean:
So 'A=VPEEK(145)' is as follows:
ld hl,145
call SetRead
in a,(152)
| | sjoerd msx addict Mensajes: 449 | Publicado: Septiembre 25 2005, 03:06   | yes, ARTAG, you're right. thanks  | | BiFi msx guru Mensajes: 3142 | Publicado: Septiembre 25 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.
| | Mirg msx lover Mensajes: 84 | Publicado: Septiembre 25 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.
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!  | | Edwin msx professional Mensajes: 620 | Publicado: Septiembre 25 2005, 22:26   | Quote:
| 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. | | Tanni msx addict Mensajes: 303 | Publicado: Septiembre 26 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!
| | norakomi msx professional Mensajes: 861 | Publicado: Septiembre 26 2005, 11:22   | Quote:
|
And to make it a bit faster, you could replace 'CALL CHPUT' with 'OUT (152),A'...
|
Cool !! i didnt know that
do you also know with what I can replace call $5f (set screenmode)???? | | Tanni msx addict Mensajes: 303 | Publicado: Septiembre 26 2005, 11:33   | Quote:
| Quote:
|
And to make it a bit faster, you could replace 'CALL CHPUT' with 'OUT (152),A'...
|
Cool !! i didnt know that
do you also know with what I can replace call $5f (set screenmode)????
|
... unless you didn't read form the VDP before calling CHPUT. As far as I know, read and write operations change the VDP pointer to the next screen location accessed. So if you want to write to one address, but read from another, you must reset this pointer via a BIOS routine call to the correct location. | | [D-Tail]
 msx guru Mensajes: 3018 | Publicado: Septiembre 26 2005, 11:54   | norakomi: The Yamaha V9938 application manual describes the VDP register settings for the G4 mode, but you wouldn't want to set them up yourself, manually. Screen mode changing isn't something that you do very often, so it's easier to just use the BIOS routine for that. Unless of course, you're in DOS or anything and don't want to select the BIOS in slot 0  | | norakomi msx professional Mensajes: 861 | Publicado: Septiembre 26 2005, 12:23   | ORG $C000
CHGET: EQU $9F
CHPUT: EQU $A2
CALL CHGET
CALL BITS
RET
BITS:
LD E,A
CALL CHPUT
LD A,58
CALL CHPUT
LD A,32
CALL CHPUT
LD BC,8*256+48
BITS2:
XOR A
RL E
ADC A,C
OUT ($98),A
DJNZ BITSL
RET
Heey sjoerd, you said that call chput can be replaced by OUT ($98),A
I typed the above program in Wbass 2,
and at the end you see that I did replace call chput with
out ($98),a
But, funilly enough this doesnt work for the 1st 3 call chputs...
Why is that???
| |
| |
| |