Curso de Assembly
Exercícios em Assembly Z80
Você está em: MarMSX >> Cursos >> Assembly Z80
Exercício 1
Como são utilizadas variáveis em assembly? E ponteiros?
Adaptado de [1]
Uma variável é um espaço na memória que serve para armazenar dados de um determinado tipo. No caso do Assembly, podemos utilizar os registradores do processador e também a própria memória para armazenar dados.
O programa a seguir ilustram como utilizar os dois recursos como variável.
10 ORG &HD000 ; Inicio do programa
20 LD HL,&D100 ; Endereço da variável na memória
30 LD A,3 ; "Variável" A recebe valor igual a 3
40 LD B,5 ; "Variável" B recebe valor igual a 5
50 ADD A,B ; "Variável" A armazena resultado da soma
60 LD (HL),A ; Resultado da soma armazenado na memória, referenciada por HL
70 RET ; Retorna
A diferença entre uma variável comum e um ponteiro, é que este em vez de conter o dado, possui o endereço do dado.
No exemplo anterior, registrador HL comporta-se como um ponteiro, enquanto que os registradores A e B como variáveis.
Exercício 2
Construa um vetor com 10 posições, com números pares e començando por 0.
Adaptado de [1]
Programa:
10 ORG &HD000
20 LD A,0 ; O registrador A contém o elemento a ser inserido no vetor
30 LD B,10 ; O registrador B contém o tamanho do vetor
40 LD HL,&HD100 ; Endereço inicial do vetor (ou lista)
50 LOOP: LD (HL),A ; Armazena dado na posição HL do vetor
60 INC HL ; Passa para a próxima posição
70 ADD A,2 ; Soma 2
80 DJNZ LOOP ; Enquanto B>0 repita o loop
90 RET ; Rertorna
Para testar no RSCII sem o utilizar o simulador, pode-se dar o comando PR <end>, que executará o código. No caso, utilize PR &HD000.
Nesse exercício, é necessário a visualização do resultado na memória. Para isso, utilize o comando VM <end_inicial>-<end_final>. No nosso caso, utilize VM &HD100-&HD109. O resultado deverá ser o seguinte:
D100 00 02 04 06 08 0A 0C 0E ........
D108 10 12 ..
Exercício 3
Converta o programa do exercício 2 em uma sub-rotina, onde o usuário informa o primeiro elemento, o tamanho da lista e sua localização.
Adaptado de [1]
Programa:
10 ORG &HD000
20 VETOR: LD (HL),A ; Armazena dado na posição HL do vetor
30 INC HL ; Passa para a próxima posição
40 ADD A,2 ; Soma 2
50 DJNZ VETOR ; Enquanto B>0 repita o loop
60 RET ; Rertorna
Configuração e uso:
VETOR
Endereço: &HD000
Nome: VETOR
Entradas: A=Elemento inicial, B=Tamanho do vetor, HL=Localização inicial do vetor
Saídas: Nenhuma
Exemplo de uso:
10 ORG &HC000
20 LD A,2 ; Define o primeiro elemento como 2
30 LD B,15 ; Define o tamanho do vetor como 15
40 LD HL,&D200 ; Define como endereço inicial a posição de memória &HD200
50 CALL VETOR ; Chama a sub-rotina
60 RET
Exercício 4
Criar um programa em Assembly que inverta a ordem dos elementos de um vetor de tamanho n.
Programa:
10 ORG &HD000
20 LD B,10 ; O registrador B contém o tamanho do vetor
30 LD HL,&HD100 ; Endereço inicial do vetor (ou lista)
40 LD D,H ; DE irá armazenar o final do vetor
50 LD E,L ; Copia HL em DE
60 LD A,B ; Copia B em
70 SRA B ; Divide o tamanho da lista pela metade
80 DEC A ; Decrementa A, pois DE = HL + B - 1
90 ADD A,E ; Adiciona o comprimento da lista a DE (já descontado o -1)
100 LD E,A ; Retorna cópia para E
110 JR NC,LOOP ; Se não estourar, pula
120 INC D ; Senão, incrementa D
130 LOOP: LD A,(HL) ; Pega elemento do ponteiro superior da lista
140 LD C,A ; Armazena em C
150 LD A,(DE) ; Pega elemento do ponteiro inferior da lista
160 LD (HL),A ; Efetua a troca
170 LD A,C ; Retona cópia
180 LD (DE),A ; Efetua a troca
190 INC HL ; Incrementa ponteiro superior
200 DEC DE ; Decrementa ponteiro inferior
210 DJNZ LOOP ; Loop enquanto B>0
220 RET
Obs: Para criar uma lista, pode-se utilizar o comando PO <end>. No caso, use PO &HD100,0, PO &HD101,1, ..., PO &HD109,9 para criar uma lista ordenada crescente.
Exercício 5
Crie um programa em Assembly que faça a cópia de um vetor de tamanho n em outra área de memória.
Adaptado de [2]
Programa:
10 ORG &HD000
20 XOR A ; Zera o acumulador
30 LD BC,10 ; O registrador BC contém o tamanho do vetor
40 LD HL,&HD100 ; Endereço inicial do vetor (ou lista)
50 LD DE,&HD110 ; DE irá armazenar o final do vetor
60 LOOP: LDI ; DE ← HL, incrementa HL e DE e decrementa BC
70 CP C ; Compara o registrador C com o valor 0 do acumulador
80 JR NZ,LOOP ; Continua o loop, enquanto C<>0
90 RET
Observe que o comando LDI na linha 60 substitui uma série de comandos.
Exercício 6
Crie uma sub-rotina para ordenar de forma crescente um vetor de tamanho n.
Adaptado de [1]
Algoritmo Bubble Sort. Programa:
10 ORG &HD000
20 LD C,10 ; Tamanho do vetor
30 DEC C ; O primeiro passo envolve N-1 comparações
40 LD HL,1 ; Ajusta valores de H=0 e L=1, para otimização
50 STEP: LD IX,&HD100 ; Inicio do passo, no endereço inicial
60 LD E,H ; Reseta flag de troca efetuada (fora do loop interno)
70 LD B,C ; Número de iterações do loop interno
80 LOOP: LD A,(IX+0) ; Loop interno / carrega elemento i
90 LD D,(IX+1) ; Carrega elemento i+1
100 CP D ; Se A < D, o flag de carry sera setado
110 JR C,CONTINUE ; Senão, continue e não troca elementos
120 LD (IX+0),D ; Efetua a troca
130 LD (IX+1),A ; Efetua a troca
140 LD E,L ; Seta flag de troca efetuada
150 CONTINUE: INC IX ; Passa para a próxima posição do vetor
160 DJNZ LOOP ; Enquanto B>0 vá para loop
170 DEC E ; Decrementa E
180 JR NZ,FINISH ; Caso não haja troca nessa iteração interna, E não será 0 e terminará
190 DEC C ; Decrementa o tamanho da lista
200 JR NZ,STEP ; Se não atingiu zero, continue em STEP
210 FINISH: RET ; Termina
Obs: Esse utiliza o registrador de índice IX, que permite operações sobre ele, como, por exemplo, IX+1.
Exercício 7
Crie uma sub-rotina para multiplicar dois números de 8 bits.
Adaptado de [1]
o Z80 não realiza operações de multiplicação e divisão. Assim, teremos que aplicar o conceito de multiplicação de AxB, que é uma soma sucessiva de A, B vezes.
Programa:
10 ORG &HD000 ; HL=D*E
20 LD DE,&H0504 ; Faz 5x4
30 LD HL,0 ; Utilizado para acumular o resultado
40 LD A,D ; Verifica o fator D
50 OR A ; A ou A é zero, somente se A for zero
60 RET Z ; Retorna, se zero
70 LD B,D ; Passa o fato D para o contador de loop B
80 LD D,H ; Zera o fator D, para utilizar E como fator isolado
90 LOOP: ADD HL,DE ; Acumula E em HL - por isso D foi zerado
100 DJNZ LOOP ; Repita B vezes
110 RET
Exercício 8
Crie uma sub-rotina para dividir dois números de 8 bits.
Adaptado de [1]
O Z80 não realiza operações de multiplicação e divisão. Assim, teremos que aplicar o conceito de divisão de A/B, que é uma subtração sucessiva de A, B vezes.
Programa:
10 ORG &HD000 ; BC=HL/E
20 LD HL,20 ;
30 LD E,4 ; Divide 20/4
40 LD A,E ; Verifica divisor
50 OR A ;
60 RET Z ; Retona se zero
70 LD BC,-1 ; BC irá acumular o resultado
80 LD D,0 ; Limpa D, pois DE receberá o divisor
90 LOOP: SBC HL,DE ; Subtrai HL de DE até estourar
100 INC BC ; Incrementa BC (conta o número de subtrações válidas)
110 JR NC,LOOP ; Not Carry significa que ainda não estourou
120 RET
Exercício 9
Quais são as instruções que "zeram" o acumulador A? E a instrução que seta os flags do acumulador, sem alterar o seu valor?
Adaptado de [2]
Zerar o registrador A:
1- LD A,0 ; Tamanho: 2 bytes / Ciclos: 7
2- SUB A ; Tamanho: 1 byte / Ciclos: 4
3- XOR A ; Tamanho: 1 byte / Ciclos: 4
Setar os flags do registrador A:
CP 0
Exercício 10
Quais os comandos em Assembly que realizam a multiplicação do valor do registrador A por dois?
Adaptado de [2]
1- ADD A,A
2- SLA A
Exercício 11
Crie um programa em Assembly que demonstre o funcionamento do bit de paridade P do registrador de flags.
Adaptado de [2]
O bit de paridade tem duas utilidades: contar o número de bits 1 do acumulador e verificar estouros em contas de números sinalizados.
O primeiro programa irá demonstrar o funcionamento da paridade:
10 ORG &HD000
20 ; TESTE 1
30 LD A,&B11110000
40 LD B,0
50 OR B ; P=1
60 ; TESTE 2
70 LD A,&B10000000
80 OR B ; P=0
90 RET
O segundo programa ilustra o estouro (vai um) de um número sinalizado:
10 ORG &HD000
20 LD A,&B0111111 ; A=127
30 INC A ; P=1
40 RET
Obs: Número sinalizado estoura no 7o. bit.
Exercício 12
Crie um programa em Assembly que dê um boot no MSX.
10 ORG &HD000
20 RST 0
A instrução de desvio RST b (retorno não mascarado) faz:
(SP-1) <- PCa;
(SP-2) <- PCb;
SP <- SP-2;
PC <- 8 x b.
Desviando PC para o endereço 0 da ROM, o MSX dá um boot.
Exercício 13
Copie um bloco de 16 KB da posição &H8100 para &H4000. Supor que o slot 1 do MSX está configurado para RAM.
10 ORG &HD000
20 LD HL,&H8100
30 LD DE,&H4000
40 LD BC,&H4000
50 LDIR
60 RET
A instrução LDIR faz:
Repete até BC = 0:
(DE) <- (HL);
DE <- DE + 1;
HL <- HL + 1;
BC <- BC - 1.
Referências:
[1] - Z80 Assembly, por Patai Gergely.
[2] - Z80 Vol. II - Software, Cypriano, Ed. Érica, 1984.