Exercícios em 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]

  Algorítimo 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.



  Referências:

  [1] - Z80 Assembly, por Patai Gergely.
  [2] - Z80 Vol. II - Software, Cypriano, Ed. Érica, 1984.


CURSOS/ASSEMBLY/AULA10