Pré-visualização parcial do texto
Baixe criando em .linguagem de .maquina e outras Notas de estudo em PDF para Informática, somente na Docsity!
CRIANDO EM LINGUAGEM DE MAQUINA Nao basta se conhecer as instruções do ASSEMBLY para se criar um programa interessante: existem. truques e “dicas” indispensáveis para o bom programador. . Gerenciando a tela . Utilizando o teclado “ Usando o “Joystick | Gerando movimentos múltiplos - Criando opções: . Implementando “requintes Em cada capitulo um; jogo. original, totalmente explicado, ilustran- do os truques de programação utilizados. Uma: obra: indispensável para quem programa em. micros da linha SINCLAIR: CP 200 - RINGO — TK 82/83/65 — AS 1000. Samuel: Ejchel formou-se em Engenharia Mecânica na Poli (USP) em 1963 e voltou todos os seus estudos pa- ra, Uma carreira coerente com sua opção: profissional. Fez pós graduação: em Engenharia de Produção e frequentou vários cursos de atualização no Brasile no exterior. É por isso surpreendente se ver o diretor da Divisão: de Amortecedores da COFAP (que conta atualmente com mais de 1500 funcionários) publicar um livro de computa- ção onde ensina com muito bom humor e didática quais as “manhas” para se' elaborar um jogo: divertido em Assembly. A explicação é simples: ao adquirir seu computador. em: fins de 82, o Samuel também adquiriu um hobby: apai: xonante e envolvente: Para quem gosta de pensar e usar a inteligência, a arte de programação é mais estimulante que a Matemática ou O Xadrez, Para compartilhar deste entusiasmo como público cada vez maior de usuários, o Samuel escreveu este livro, 2a Usar a: inteligência é gostoso e o Samuel: faz isto como 0 O poucos! rasca te CRIANDO EM LINGUAGEM DE MAQUINA | CRIANDO EM LINGUAGEM DE | MAQUINA SAMUEL EICHEL SAMUEL EJCHEE MONTAGENS DE JOGOS EM ASSEMBLY Z 80 PARA CP 200, RINGO, TK 82/83/85, SINCLAIR ZX81 URANIA dao EDITORA MODERNA URANIA IR CRIANDO EM LINGUAGEM DE MÁQUINA SAMUEL EIJCHEL = URANIA ana MODERNA À Frida, Lilian, Beatriz e Flávia pelo apoio e compreensão. À Rita e Luiz pela ajuda. ÍNDICE Nota do Editor. Introdução ' Cap. 1-ATELA........... Cap. 2 — O TECLADO Cap. 3 — O JOYSTICK ........... Cap. 4 — MOVIMENTOS MÚLTIPLOS . Cap. 5 — OPÇÕES Cap. 6 — REQUINTES APÊNDICE A — BIBLIOGRAFIA APÊNDICE B — MONITOR .... APÊNDICE C — MAPA DA ROM Masarericaraaso APÊNDICE D — TABELA ...iiiccccececrrneaerarrerrrrs INTRODUÇÃO Este livro é destinado àqueles que, conhecedores de linguagem de má- quina, desejam aprender ou aprimorar-se na técnica de criar jogos no com- putador. Esta atividade, mais que outras, revela-se como um atraente e apai- xonante passatempo, tipo quebra-cabeças, que exige de quem o faz um gran- de esforço de atenção e concentração, constituindo-se portanto num exce- lente exercício para a mente. A satisfação que se sente ao terminar um de- senvolvimento, e ver na tela a materialização de uma idéia, é contagiante e altamente gratificante. Programar em linguagem de máquina já é de per si um desafio. Para jo- gos, O uso desta linguagem é indispensável, pelo menos nos microcomputado- res da linha Sinclair, por ser a única compatível com as velocidades exigidas no movimentos. Para usufruir deste livro o leitor deve conhecer as instruções de máqui- na, ou Assembly, do microprocessador Z-80. Algumas destas instruções são explicadas no texto, porém a maioria assume-se como conhecidas e, em caso de dúvida, recomenda-se consultar a bibliografia sobre o assunto. No apêndice A existem algumas indicações para isto. O equipamento a usar deve ser da linha Sinclair ou compatíveis, Ringo, ZX 81, CP 200, AS 1000, NEZ 8000, TK 82€, TK 85, TK 83, com capaci- dade maior ou igual a 2 Kbytes. Os programas apresentados necessitam para rodar, em sua maioria, algo perto deste limite. Assim se sua máquina tiver somente 2 Kbytes, convém conseguir uma expansão emprestada para permitir a digitação e carregamen- to dos programas. Para carregar os programas, separados em grupos, qualquer monitor ou carregador de linguagem de máquina, que o leitor disponha, pode ser usado. Após cada grupo, devidamente desassemblado, teinos à mesma listagem em heptassintático. Querendo usar esta opção, consulte o apêndice B. Este livro é dividido em 6 capítulos. Em cada um é enfatizada uma ca- racterística. relacionada com os jogos e é apresentado um programa ilustra- tivo detalhado e explicado em pequenos blocos. Vários destes contém rotinas de uso geral, que poderão ser copiadas e utilizadas de imediato em novas aplicações. Faça bom uso delas! este capítulo discuti- mos como gerenciar a tela do computador e como utilizá-la da mais eficiente forma. Apro- veitamos também para exemplificar o que foi dito, elaborando um jo- go deveras interessante denominado “Reverten- E do” onde também é ensinado como criar pseudo-registros. * Finalizando, o computador relembra o nível de dificuldade escolhido, e in- forma o número de jogadas ou lances feitos pelos jogador. A comparação des- tes dois valores dá a noção do desempenho atingido na partida. Embora não seja indispensável, é recomendável que se faça e use o diagrama de blocos do programa. Isto serve para fixar o raciocínio e evitar erros. FIGURA 3 SORTE E ZERA Ds MODIFICA CO» coifâdos O FEUDO 04 PO.| siçÃo E Dos O & uinhos ENTRA COM E COMPSE TELA xovo Jogo (5) O programa em Basic correspondente é o seguinte. “ A correlação entre as instruções do programa e os blocos é a seguinte: BLOCO INSTRUÇÕES 3e5 10 15a 28 30a 49 60a 106 1000 a 1019 125 200 205 a 230 235 241a 250 1050 a 1080 1090 a 1110 Observe agora o programa, a partir da linha 50 até a sub-rotina 1000 (inclusive), e veja como a tela está sendo alterada. A variável V da linha 50 na- da mais é senão o endereço que se encontra na Variável de Sistema DFilé que falamos acima, e portanto corresponde ao início do arquivo da tela. Para entender as instruções seguintes, convém fazer um esboço da tela como o que apresentamos na figura 4. Aliás, quando se programa em lingua- gem de máquina, a confecção deste esboço é praticamente indispensável, En- tão, caso você deseje prosseguir é bom já ir providenciando um bloco ou ca derno com papel quadriculado, ou tirando cópias do apêndice D. olil2/314/s|s|7 [819 polu [izfusfiapis he] r7)alis/zolas [22)zal24]25!20)27frelz0fo|a1 o BICIDIEIFIG [HIVIKICIMINTO PIO IRIS [TIL] E ISSBDRRCocAEBBBESSPERBREasHEs ajo( HA |+| +] ++ DOBDBDBEEBSSEEEE gl1|2 aloja pe epopeia r=lo ab sjaja pra + [+++ [HH pit beja aa [elf +|o|3[8. sjo 4 lala +[+[ +] E COBDBBEERSABBARABRA slglol+| INILVIEILO JDIEO DIE CIILIDIADIEL belxe/ [rlofole z|o| GH +++ +++ +++ |+]e]6]7 ajol7 per] Ivjoic CIOÍNISTEIG|UT[UL jp |el7]e slg/8 +[+[-+"H+H JEM YU IJIOICIAlD) EEE Imjals aog|9 deep peter pef efe oisho vpope Pepe pe ++ ReReeee io r epir E CORRROBBEEEHES tithz pi pEpEEH INfolvio: ojejo CISTZNDE [re 1i2hs aj 3peepeeia+ ep RARDGCEBABHEEs tapa asp já pera pepe fe [efe pele pe pe fe- pele peer le[+lepefeli Apos as peer pe peer peter ep fa-prle+f [ofs vp6ppepe pe pe pe pe Repete eee (ep oo as 17 pe fpee Re pen-+pe efe e =p 1iZhe [tg pr pe pe -pefedpepe [rj eee ee] 18! opa aeee peer je peter eee efe te ee] 2:E9 E ABICIDIE(FIG|HIL LMminfolPloirisITIu]y Y ] 2 a 3 ofiz sjelristoToimiafapafisheloiafo Bojo fazfaafeafas zeaofaofzoisorm FIGURA 4 Com o auxílio do esboço torna-se mais fácil observar que a variável x, gerada na instrução 105 e variando de 4 a 29, corresponde a uma das colunas identificadas pelas letras, e a Y, gerada na 106 variando de 2 a 19, está ligada às linhas. Com a variável P da instrução 1000, obtida a partir das anteriores, chega-se ao endereço no arquivo da tela da memória do ponto a ser converti- do. Correlacione a figura 1 com a 4 e entenda como isto se processa. Note que o quê está sendo dito é válido tanto para máquinas com mais ou com menos que 3,5 Kbytes que, neste último caso, como a tela está totalmente ocupada, o seu arquivo na memória estará completo e será igual ao daquele com mais de 3,5 Kbytes. As instruções seguintes, de 1010 a 1018, fazem a conversão, já que elas 13 No programa em linguagem de máquina vamos nos utilizar de quatro conjuntos de bytes, que funcionam como registradores, escolhidos para man- terem dados ou participarem na lógica de programação. Este tipo de “registra- dor improvisado” é comumente usado quando se programa em Assembly. Lugares bons para serem escolhidos são os bytes vazios na região das va- riáveis do Sistema, sejam o 16417 (4021 em hexadecimal), o par 16507/8 (407B/C) e os bytes do “buffer” da impressora 16444 a 16475 (403€ à 405B). Note-se que o buffer da impressora é apagado quando se retorna para o Basic, mas se mantém quando vai para a linguagem de máquina. Os motivos para escolher esses bytes são: * Eles não apresentam desvantagem em relação a qualquer outro que fosse es- colhido. * Normalmente um registrador não precisa (e talvez nem deva) ficar no meio programa. * Estes bytes representam pontos fixos na memória e assim, quando se move o programa de uma região a outra, não é necessário mudar o endereço de cha- mada. * Os três primeiros bytes citados são preservados pelo SAVE e não são apaga- dos por CLEAR ou RUN. Quando se utiliza este tipo de registrador é comum batizá-lo com um nome sugestivo para identificá-lo e facilitar a programação. Os quatro registra- dores que definimos são os seguintes: NOME . cóDIGO ENDEREÇO Contador Cont 16507/8 (407B/C em hexa) Transferência de X TrX 16444 (403€C em hexa) Transferência de Y Try 16445 (403D em hexa) Registro de Nível de TEX 16536 a 16538 (4098 a 40A0 Dificuldade (3 bytes) em hexa) O programa em linguagem de máquina será apresentado em grupos e sub-rotinas correlacionadas tanto quanto possível com os blocos do diagrama que apresentamos (fig. 3). Para carregar o mesmo, bem como todos os demais programas apresentados neste livro, o leitor poderá utilizar qualquer carrega- dor que disponha, assumindo sempre que o bloco em linguagem de máquina esteja concentrado numa única linha REM, partindo do endereço 16514 (4082 em hexa). Como foi dito na falta de um carregador próprio, apresenta- mos um no apêndice B. Como simbologia, espaços em branco serão apresenta- dos por b. 16 Grupo 1 — 16514 a 16576 (4082 a 40CO em hexa) B NÍVEL É DIFICULDADE BEBES VOCÊ E CONSEGUIU bt NOVO B JOGO? (S/N) b Este grupo é todo especial. Ele contém o texto que será usado na finali- zação (bloco 12), e apresenta mais uma particularidade interessante: os três bytes centrais dos 5 espaços que seguem a frase “Nível de Dificuldade” cor- respondem justamente ao registro TEX que foi criado. Note (pelo basic) que após o uso, no bloco 5, do nível escolhido pelo jogador esta informação só será necessária na finalização. Assim, nada melhor do que já deixá-la num lugar favorável para a tarefa final. Grupo 2 — 16577 a 16590 (40C1 a 40CE em hexa) a Es E Agora zeramos o contador (equivale ao bloco 7) e os dois últimos bytes dr: . Isto é necessário para evitar que ao réiniciarmos um jogo, permane- çam as informações do anterior. iBES Este grupo corresponde ao bloco 3, De início tomou-se o valor registra- do no campo das variáveis (VARS) que acabou de “entrar” (Input F8). A rotina do Sinclair localiza a String através da Variável de Sistema VARS (18400 ou 4010 em hexa) que informa o endereço onde ela foi arma- zenada. O byte deste endereço contém o código da letra associada ao string somado com 40, os dois seguintes são o comprimento da string, primeiro o menos significativo e o segundo mais significativo. Então em nossa rotina, ao fazer Inc HL — LDA, (HL) — CP4 — RetP — And À — RetZ — Inc HL — LD A, (HL) — And À — RetNZ, estamos verificando se o comprimento é maior que zero, mas menor que 3, e em caso contrário, retornando ao basic. Neste caso tornamos o V da instrução 740 diferente de zero já que, nesta si- tuação, BC já contém o endereço de TEX. Os bytes seguintes contém os dados da própria “String” que entrou, e as demais instruções de grupo verificam se eles são realmente números e os carregam no registro TEX. RED mica 1 19 Quando este programa foi inicialmente criado, pretendia-se usar uma única sub-rotina — a do bloco 6 — para gerar a tela (anexa ao bloco 5) como para “revertê-la” (anexa ao bloco 10). Posteriormente, para ganhar tempo e melhorar o programa, foi introduzida uma sub-rotina própria — com início em 4254 — para gerar a tela. O grupo 5 corresponde então ao bloco 6 asso- ciado à reversão (bloco 10). Três pontos merecem destaque neste grupo: * A forma como está sendo feita a comunicação entre o basic (Poke 16447, x) e a linguagem de máquina [LD HL, TRX — LDB, 00 — LDC, (HL)]. * A sistemática de “consumir” tempo que é extremamente usada em progra- mas, aplicável a qualquer par de registradores (no caso usamos o BC) — LD BC, 0300 — DEC BC — LD A, C— OR B — JRNZ — onde o valor que se car- rega os registradores, 0300 no caso, deve ser ajustado de forma a causar o efeito desejado. * Os 6 bytes vagos ao fim da sub-rotina ou do grupo são uma reserva para a eventualidade de ser necessária uma correção no programa, e prevê-la é uma prática muito recomendável mesmo para programadores bastante experientes. 22 Grupo 6 — 16837 a 16927 (41C5 a 421F em hexa) 23 Pepe e fo pego po po fo Neste grupo está se repetindo rotinas já conhecidas: do início até 16899 (4203 em hexa) tem-se o mesmo teste básico usado no grupo 3 e que corres- ponde ao bloco 9 do diagrama de blocos; em seguida há a chamada à sub- rotina de reversão (grupo 5) e o incremento no contador, para finalmente chegar-se ao bloco 11 de verificação de retorno à tela básica, cujas explicações e instruções foram dadas quando “melhoramos” o programa original total- mente em basic. E, ER 24 m m rm Este grupo corresponde ao bloco 12. Trata-se apenas de compor”a tela final, usando os dizeres preparados no grupo 1, que como foi visto, já contém a informação do nível de dificuldade eleito pelo jogador. Adicionalmente cabe chamar atenção sobre a técnica utilizada na trans- crição, com o uso da instrução LDIR, bem como o fato de carregarmos em BC o valor contido no contador de forma a levar para o basic, através da va- riável V, o número de jogadas utilizadas 25 0) TECLADO qui vemos como uti- A lizar a rotina de lei- rir tura do teclado simu- pm lando o INKEY$ em linguagem de máquina. Tudo que ora se discute é exemplificado na cria- ção do jogo “Crepe” onde se mostra também uma maneira muito ori- ginal de se criar núme- ros ao acaso sem que a sorte seja Iudibriada. Alea jacta est. CAPITULO 2 — O TECLADO A pesquisa ou “varredura” do teclado é feito, nos computadores da li- nha Sinclair, através de uma sub-rotina da ROM conhecida por KScan, abre- viatura do inglês Keyboard Scan. Esta sub-rotina acha-se situada no endereço 699, ou 02BB em hexade- cimal, e similarmente a qualquer outra, pode ser chamada através da instrução Call (CDBBO2). Como em sua utilização todos os registradores são afetados, se o conteúdo de algum deles precisar ser preservado, é necessário acumulá-lo no “stack” através da instrução PUSH, e após o Call, buscar a informação de volta através do POP, O resultado da aplicação do KScan é encontrado no par HL, que fun- ciona como um apontador ou indicador de qual tecla foi digitada, se é que al- guma foi. Para entender como achar a tecla pressionada através do resultado acumulado em HL devemos considerar o teclado dividido em grupos. No caso do registrador L tem-se os seguintes grupos e correspondentes valores do mes- mo: GRUPO DE TECLAS VALOR DE L Nenhuma foi pressionada FF Z-X-C—-V FE A-S-D-F-G FD QO-W-E-R-T FB 1-2-3-4-5 FZ 6-7-8-9-0 EF Y-U-I-O-P DF H-J-K—L — (ENTER ou NEW LINE) BF B-N—M-—(.,) — (Space) 7F Como vê-se a tecla “Shift” não participa de. grupo algum dos citados. Isto significa que o fato dela estar pressionada ou não, em nada altera o valor de L. O mesmo conceito se aplica ao registrador H, só que neste caso, seu valor muda se a tecla “Shift” estiver ou não pressionada. 30 GRUPOS DE TECLAS VALOR DE H Sem “Shift” Com “Shift” Nenhuma (além do “Shift”) FF FE A-Q-1-0-P- (Enter) — (Space) FD FC Z-S-W-2-9-0-L-(.) FB FA X-D-E-3-8-1-K-M F7 F6 C-F-R-4-7-U-J-N EF EE V-G-T-5-6-Y-H-B DF DE Observando o teclado do equipamento e-localizando os grupos citados, será fácil notar que o sistema é organizado como uma rede sobreposta ao con- junto. Dessa forma, só existe uma tecla que pertence simultaneamente a dois dos grupos citados, o que corresponde a uma relação direta entre a teclae o resultado em HL. Exemplificando, pressionar a teclar A, sem “Shift”, resulta em HL = FDFD, e em correspondência, não é possível chegar-se a este valor pressionando qualquer outra, ou conjunto de outras teclas. O funcionamento desta sub-rotina é similar ao da função INKEY$ do Basic, a qual aliás faz uso da KScan. Assim, num programa no qual se deseje que o sistema aguarde o pressionar de uma tecla, é preciso incluir um conjun- to de instruções equivalente a Caso isso não seja feito, ao atingir o KScan ter-se-á apenas o valor F EFF em HL e as instruções seguintes serão executadas sem maiores delongas. No programa que vem a seguir, chamado “CREPE”, existe uma rotina de espera incluída além da ilustração de outros conceitos que foram apresen- tados. : O “CREPE” é uma versão para o computador do famoso jogo de azar homônimo, também conhecido por “seven-eleven”. Para quem não frequenta cassinos descrevemos as regras básicas. * Um dos participantes do jogo assume a posição de “banqueiro” e enfrenta apostas dos demais. * Cabe à banca ou banqueiro o lançamento de um par de dados. *.A rodada se define em duas situações: ** No primeiro lance de dados, se a soma dos pontos for 2, 3 ou 12 a banca perde e se for 7 ou 11 a banca ganha. ** Não se resolvendo a rodada no primeiro lance, ou seja, se a soma dos pontos obtidos tiver sido um dos seguintes 4, 5,6, 8,9 ou 10, ele será chama- do de “ponto” e a banca joga com o mesmo contra o 7. Isto significa que o banqueiro irá lançar os dados tantas vezes quantas forem necessárias até sair 31 16389 o valor 128. Ora 128x 255+ O = 32768 que subtraído do início da Ram (16384), resulta em 16384 bytes disponíveis, que nada mais são que 16 vezes 1 Kbyte, já que 1 Kbyte = 1024 bytes. Ao dar o comando Poke 16389, 72 obtém-se 72 x 256 + O = 18432 que subtraído do início da Ram (16384) resulta em 2048 bytes ou 2 Kbytes. O comando NEW que segue é indispensável para que o sistema se conso- lide na nova configuração, agindo como tendo somente os 2 Kbytes disponí- veis. Após os comandos citados carrega-se o programa, usando o LOAD. Se então gravarmos a fita usando o GOTO 10 toda a vez que voltarmos a carre- gar o programa com o LOAD, ele entrará em execução automática e se com- portará adequadamente mesmo que não se tenha previamente executado a al- teração da RTP descrita. Isto já não será verdade, se ao invés do GOTO 10, for utilizado o comando direto SAVE “CREPE”. Convém analisar o que foi dito e entender bem a razão desta forma de ser. Como no exemplo do capítulo anterior vai-se agora desmembrar o pro- grama em grupos de instruções, correlacionando-os com os blocos do diagra- ma da figura 5. Grupo 1 — 16514 a 16549 (4082 a 40A5 em hexa) Aqui estão contidos os 36 resultados possíveis, ou opções, do lançamen- to dos dois dados, armazenados da seguinte forma: em cada byte os primeiros 4 bits contém o resultado de um dos dados, que é um número de 1a 6,e 05 4 restantes o do outro dado. Uma das opções será sorteada e utilizada para montar a figura dos dados na tela. Grupo 2 — 16550 a 16555 (4046 a 40AB em hexa) Nestes bytes está a palavra “Ganhou” que será utilizada para finalização da rodada, no bloco 16. 3a É uma prática comum e conveniente esta de armazenar no início do programa informações que não participam da lógica, e que são apenas usadas para consulta ou composição das telas de abertura e finalização. Outra alter- nativa adotada é fazer a armazenagem apés o fim do programa, deixando po- rém, por cautela, alguns bytes de reserva para o caso de ser necessário alguma alteração imprevista no programa. Este grupo contém as instruções e dados para montagem da tela de abertura e corresponde ao bloco 1 da figura 5, ou início do programa. A lógica utilizada nesta tarefa é bastante interessante. A instrução 20 do Basic faz uma chamada ao endereço 16568, e lá encontramos um Call para o início da lógica, em 16556 (40AC em hexa). Toda vez que um Call é feito, o endereço do byte imediatamente após a instrução é armazenado no “stack” para ser usado por ocasião do retorno. Surgindo a instrução Ret o endereço é retirado do “Stack” (como se fosse um “Pop”) e a próxima instrução que é executada é a deste endereço. Ora, após o CDAC40 está o primeiro byte a ser “escrito” na tela. Ele é então armazenado no “stack”, de lá retirado (E1 — Pop HL) e registrado em 35 A [7E — LDA, (HL)]. O endereço é então incrementado e novamente arma- zenado no “Stack”, substituíndo assim o anterior (23/E5 — Inc HL/ Push HL). O valor de A é comparado com FF, que é o indicador escolhido de fim do arquivo de compor a tela (FEFF — CP FF); sendo igual é dado o retorno (CB — Ret Z) ou um “jump” para a instrução cujo endereço está no stack, que é exatamente a primeira após FF, e corresponde ao início do bloco 2. O próximo passo é novamente um Call (CDO808), que é uma chamada a uma rotina da ROM de endereço 2056 (0808 em hexa), responsável por escrever o conteúdo do registrador A na tela; esta rotina faz uso do RST 10 citado no capítulo anterior. Finalmente tem-se um “jump” relativo para o reinício do ciclo. Em relação aos dados usados para compor a tela existem vários pontos dignos de nota: * Toda a vez que o valor de A for 118 (76 em hexa) a rotina CDO808 bem co- mo a RST10 entende que deve interromper a linha e pular para o início da seguinte. ** Existe uma superabundância de zeros a serem impressos. É claro que se poderia reduzir o número de bytes necessários para compor a tela, usando ro- tinas auxiliares. Mas em favor da didática e por não ser necessário economizar bytes, adotou-se esta apresentação. Como resultado, sabendo que se irá teori- camente trabalhar com uma capacidade de 2 Kbytes, tem-se entre 16571 e 16853 uma cópia fiel do arquivo da tela, o que facilitará o entendimento das etapas seguintes do programa. *** Também a título ilustrativo de recursos, e não para economizar memória neste caso, escolheu-se armazenar as palavras “Perdeu” e “Vai jogar? (S/N)” nos mesmos locais em que se reservaria espaço no arquivo da memória para escrevê-las, ou seja, nos endereços 16617 (40E9 em hexa) a 16839 (41C7 em hexa) respectivamente. Como consegiência, ao montar a tela ela aparece com a indicação equivalente a de já ter havido uma rodada anterior em que a banca perdeu. 36 Grupo 4 [E] [To de To: me a esa EE sa 16855 a 16879 (41D7 a 41EF em hexa) 37