segunda-feira, abril 24, 2023

MSX: Criando programas com mútiplos fontes usando o N80/LK80

 O N80/LK80 é uma releitura do clássico M80/L80 Macro Assembler da microsoft, agora refeitos e repaginados pelo Nestor Soriano.



Este é um mini artigo explicando como criar alguns tipos de programas com múltiplos fontes neste assembler.

Binário (bload)

Vamos criar em dois arquivos separados um programa para imprimir uma STRING na tela usando chamadas da BIOS:

msx.asm

CHPUT:  equ 0a2h

main.asm

include msx.asm
defb    0feh             ;Tipo de arquivo (binario)
defw    inicio           ;Endereco de inicio
defw    fim              ;Endereco final do bloco
defw    inicio           ;Endereco de execucao (bload,r)

cseg                     ;Inicio do segmento de codigo
extrn PRINT              ;Funcao PRINT vem do segundo arquivo
inicio:                  ;Endereco inicial do codigo
        ld hl,HELLO      ;Endereco da STRING em HL
        call PRINT       ;Imprime a STRING
        ret              ;Volta ao BASIC
dseg                     ;Segmento de dados
HELLO:  db "Hello!\0"    ;zSTRING
fim:    equ $            ;Endereco final do binario
end                      ;Fim do programa

print.asm

include msx.asm
cseg                     ;Segmento de codigo
public PRINT             ;Exporta funcao PRINT
PRINT:                   ;Inicio de PRINT
        ld a,(hl)        ;Carrega em A o caracter apontado por HL
        or a             ;Zero?
        ret z            ;Termina
        push hl          ;Salva registrador
        call CHPUT       ;Imprime um caracter
        pop hl           ;Recupera registrador
        inc hl           ;Proximo caracter
        jp PRINT         ;Loop
dseg                     ;Segmento de dados
end                      ;Fim do programa

Makefile

TARGET = msx
M80 = N80
L80 = LK80
LIB80 = LB80
LFLAGS = --code BFF9h --data C020h

INC = msx.asm
SRC = main.asm print.asm
OBJ = $(SRC:.asm=.rel)

.PHONY: clean

all: $(OBJ) $(TARGET).dsk

$(TARGET).dsk: $(TARGET).bin
    touch $(TARGET).dsk
    rm $(TARGET).dsk
    wrdsk $(TARGET).dsk *

$(TARGET).com: $(OBJ)
    $(L80) $(LFLAGS) --output-file $(TARGET).bin $(OBJ)

%.rel: %.asm
    $(M80) $< $@

clean:
    touch $(TARGET).rel
    touch $(TARGET).bin
    touch $(TARGET).dsk
    rm *.rel
    rm *.bin
    rm *.dsk

run:
    /usr/local/bin/openmsx -machine Boosted_MSX2_EN -diska ./$(TARGET).dsk

O processo é bem similar ao Macro-80, porém vale a pena ver as outras opções deste compilador/linkador pois tem algumas bem interessantes.

MSX-DOS (.com)

msx.asm

.CONOUT:    equ 002h
DOS:        equ 005h

main.asm

cseg
extrn PRINT
PROGRAM:
    ld hl,HELLO
    call PRINT
    ret
dseg
HELLO:  db "Hello!\0"
end

print.asm

include msx.asm
cseg
public PRINT

PRINT:
    ld a,(hl)
    or a
    ret z
    push hl
    ld e,a
    ld c,.CONOUT
    call DOS
    pop hl
    inc hl
    jp PRINT

dseg
end

Makefile

TARGET = msxdos
M80 = N80
L80 = LK80
LIB80 = LB80
LFLAGS = --code 0100h --data 0200h

INC = msx.asm
SRC = main.asm print.asm
OBJ = $(SRC:.asm=.rel)

.PHONY: clean

all: $(OBJ) $(TARGET).dsk

$(TARGET).dsk: $(TARGET).com
	touch $(TARGET).dsk
	rm $(TARGET).dsk
	wrdsk $(TARGET).dsk ../res/* *

$(TARGET).com: $(OBJ)
	$(L80) $(LFLAGS) --output-file $(TARGET).com $(OBJ)

%.rel: %.asm
	$(M80) $< $@

clean:
	touch $(TARGET).rel
	touch $(TARGET).com
	touch $(TARGET).dsk
	rm *.rel
	rm *.com
	rm *.dsk

run:
	/usr/local/bin/openmsx -machine Boosted_MSX2_EN -diska ./$(TARGET).dsk