MI1022806 2021 1 AULA06

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar

Conjuntos de Instruções

Um programador de linguagem de alto nível normalmente conhece muito pouco acerca da arquitetura da máquina que está usando.

O conjunto de instruções da máquina é o limite em que o projetista de CPU e o programador de baixo nível enxergam, da mesma máquina.

Implementar uma CPU é uma tarefa que envolve, em grande parte, implementar um conjunto de instruções de máquina.

Já programar em linguagem de máquina (na verdade, em linguagem de montagem, Assembly) exige um conhecimento acerca do conjunto de registradores da CPU, a estrutura de memória, os tipos de dados disponíveis na máquina e o funcionamento da ULA.

Porém, da descrição do conjunto de instruções à uma compreensão sobre o funcionamento da CPU, há um longo caminho.

Características de Instruções de Máquinas

A operação de uma CPU é determinada pelas instruções que ela executa, conhecidas como instruções de máquina.

A coleção de instruções que uma determinada CPU é capaz de executar é conhecida como conjunto de instruções da CPU.

Elementos de Instrução de Máquina

Cada instrução deve conter toda a informação necessária para que a CPU possa executá-la.

Fig104 MI1022806.png

A figura acima ajuda a definir os elementos da instrução:

  • Código de operação (OPCODE) - Especifica a operação a ser efetuada (por exemplo, ADD, ou E/S, etc). A operação é especificada por um código binário.

Ex: Palavra de seleção (SMCn) em uma ULA de 4 bits

  • Referência a operando fonte - a operação pode envolver um ou mais operandos fonte, ou seja, que constituem dados de entrada para a operação. Exemplos:
    • operação com um único operando: INV(A)
    • operação com dois operandos: ADD(A,B)
    • operação com três ou mais operandos: DEV(GE(A,B),C,D)
  • Referência a um operando de destino - a operação pode eventualmente produzir um resultado, que deverá ser enviado a um endereço de memória, ou registrador
  • Endereço da próxima instrução - indica aonde a CPU deve buscar a próxima instrução (memória principal ou virtual), depois que a instrução corrente for completada, quando for o caso.

Os operandos fonte e destino podem estar localizados em:

  • Memória principal ou virtual - implica em busca na memória RAM, ou no HD (quando virtual)
  • Registrador da CPU - se houver apenas um registrador, a referência a ele poderá ser implícita. Quando há acumulador, a referência a ele é default. Caso hajam vários registradores, normalmente a referência a cada um, individualmente, é feita por um número inteiro correspondente.
  • Dispositivo de E/S - indicado diretamente na instrução. Se for usada a E/S mapeada na memória, esta informação se resumirá a um endereço de memória, como os demais. Pode ser também um registrador específico (Ex: porta serial).

Representação de Instruções

Internamente, cada instrução é representada por uma sequência de bits.

É dividida em campos, correspondentes aos elementos da instrução.

Exemplos:

4 bits 6 bits 6 bits
Código da operação Referência a operando Referência a operando
16 btis



Instrução na memória
0           7 8           19 20           27 28           39
OP1 END1 OP2 END2



Fig106 MI1022806.png


A maioria das CPUs têm mais de um formato de instrução.

Durante a execução, uma instrução é lida em um registrador de instruções (IR) da CPU. A CPU extrai os dados dos vários campos da instrução e efetua a operação correspondente.

Os códigos de operação normalmente são representados por abreviações, chamadas mnemônicos, que evitam que os programadores tenham que trabalhar diretamente com valores binários.

Alguns exemplos mais comuns são:

ADD  -------------  Adição
SUB  -------------  Subtração
MPY  -------------  Multiplição
DIV  -------------  Divisão
GT   -------------  Operação >
LT   -------------  Operação <
GE   -------------  Operação ≥
LE   -------------  Operação ≤

Os operandos também são representados por símbolos.

Por exemplo:

  ADD R, Y

pode significar adicionar o valor contido na posição Y, com o valor contido no registrador R. Neste caso, Y é um endereço de memória e R, um registrador da própria CPU.


Exercício

Em uma ULA de inteiros de 4 bits, com formato de instrução [OPCODE(5) A(4) B(4)], qual seria a instrução correspondente, se a intenção fosse executar a operação lógica Y = OR(A', B) , com A = 0001b e B = 1010?

Número de Endereços

Uma das maneiras tradicionais de se descrever uma arquitetura é em termos do número de endereços contidos em cada instrução.

Obviamente, instruções aritméticas e lógicas requerem um número maior de operandos (e de endereços, por conseguinte). Normalmente, precisam de dois operandos que serão submetidos a um cálculo ou comparação, e de um terceiro, pra armazenar o resultado.

O endereço da próxima instrução normalmente é implícito, armazenado no registrador PC.

A figura abaixo (a,b e c) compara o que seriam instruções típicas de um, dois ou três endereços, para computar a mesma linha de programação:

Y = (A - B) / (C + D x E)
Fig107 MI1022806.png

Note que as instruções com 3 endereços implementaram o comando com apenas 4 instruções de máquina. Porém, instruções de 3 endereços não são muito comuns, porque implicam em instruções grandes.

No caso das instruções de 2 endereços, foram necessárias 6 linhas de código, duas a mais, portanto. Nestas instruções é típico que um dos endereços referencie tanto o operando, quanto o resultado. Gera opcodes menores, porém gera códigos maiores e exige maior habilidade do programador.

As instruções de 1 único endereço exigem que um segundo endereço seja sempre implícito (normalmente, o Acumulador - AC). Neste caso, foram necessárias 8 instruções para resolver o problema.

É possível também usar-se em expressões aritméticas uma instrução com ZERO endereço. Neste caso, é necessária uma organização de memória especial, chamada pilha. As instruções com zero endereço sempre referenciam os valores nas duas posições no topo da pilha.

Número de Endereços Representação simbólica Interpretação
3 OP A, B, C A ← B OP C
2 OP A, B A ← A OP B
1 OP A AC ← AC OP A
0 OP T ← (T-1) OP T

Além de tudo que foi citado, as instruções podem variar muito de tamanho porque o endereço em questão de cada operando pode se referir à memória física ou a um dos registradores da CPU. Como as memórias são muito maiores que o número de registradores, vão utilizar endereços muito mais longos.

Assim, existem máquinas que, quando vão endereçar um valor NA MEMÓRIA externa (RAM) utilizam mais de uma instrução para acessar o dado.

Tudo sempre vai depender da arquitetura da máquina.

Tipo de Instrução

Como já vimos, uma única instrução escrita em linguagem de alto nível pode requerer várias instruções de máquina.

Os tipos de instrução de máquina que existem são:

  • Processamento de dados - instruções aritméticas e lógicas
  • Armazenamento/transferência de dados - instruções de memória
  • Movimentação de dados - instruções de E/S
  • Controle - instruções de teste e de desvio
Fig108 MI1022806.png
Fig109 MI1022806.png

Na maioria das vezes, as instruções são autoexplicativas.

As instruções do tipo transferência de controle, no entanto, podem ser muito complexas. Em todos os casos, exceto com elas a próxima instrução a ser executada é aquele que segue imediatamente a atual, na memória.

Nas instruções de transferência de controle, a CPU atualiza o PC com o endereço de alguma outra instrução, armazenada na memória de programa.

As instruções de transferência de controle são aquelas utilizadas quando há loops no código, ou comandos de decisão ou ainda quando o código teve que ser segmentado em vários arquivos, normalmente porque estava muito extenso.

Instruções de desvio

Nestas, um dos operandos é o endereço da próxima instrução a ser executada.

Com frequência, essa instrução é do tipo desvio condicional, isto é, o desvio só ocorrerá se uma determinada condição for satisfeita. Caso contrário, o programa segue com a próxima instrução adjacente, sem alterações no PC além do incremento normal.

Estas instruções normalmente têm o nome de BRANCH ou JUMP e podem depender de uma condição, ou ser incondicionais.

Exemplo:

Fig110 MI1022806.png

Instruções de chamada de procedimento

Um procedimento, ou função, ou ainda subrotina é um trecho de código independente que modulariza um programa.

O mecanismo de controle de procedimentos envolve duas instruções básicas: uma instrução de chamada, que desvia a instrução corrente para o início do procedimento, e uma instrução de retorno, que provoca o retorno da execução para o endereço onde ocorreu a chamada. Ambas são condições de desvio.

A figura abaixo ilustra o uso de procedimentos na execução de um programa.

Fig111 MI1022806.png

Instruções do Pentium II e do PowerPC

Para exemplificar, apresentamos o caso especial de conjunto de instruções de um processador de propósito geral que foi muito utilizado até o início da década de (20)00.

Fig112 MI1022806.png
Fig113 MI1022806.png
Fig114 MI1022806.png

Conjunto de Instruções do ARM

O conjunto de instruções também é chamado de "ISA - Instruction Set Architecture".


Fig115 MI1022806.png

A arquitetura ARM trabalha com três tipos de instruções: o ARM, THUMB e o THUMB-2.

O conjunto THUMB de instruções de 16 bits trabalha com registradores de 32 bits.

O código THUMB é capaz de reduzir em até 65% o tamanho de um código ARM (maior densidade de código), e aumentar em até 160% o desempenho, em relação a um processador ARM equivalente, conectado a um sistema de 16 bits, apenas.

Fig116 MI1022806.png

Características do ISA ARM

  • 13 registradores de propósito geral:
    • R0 a R7 (low registers)
    • R8 a R12 (high registers)
  • 3 registradores de uso/significado especial
    • r13: stack pointer (SP)
    • r14: link (LR)
    • r15: (PC)
  • 1 registrador de propósito especial
    • xPSR = Program Status Register
  • Registradores xPSR, PC, LR, R12, R3, R2, R1 e R0 são armazenados automaticamente na pilha quando uma interrupção ocorre.
Fig117 MI1022806.png
Fig118 MI1022806.png
  • Arquitetura load-store: as instruções somente lidam com valores que estejam nos registradores (ou imediatos) e sempre armazenam resultados em algum registrador. O acesso à memória é feito apenas através das instruções load (para carregar o valor da memória em um registrador) e store (para armazenar o valor de um registrador na memória).
  • Permite a execução condicional de várias instruções.
  • Máquina de 3 endereços – dois registradores operandos e um registrador de resultado são especificados.
    • 1º operando: especifica o local onde será armazenado o resultado da operação.
    • Outros: valores imediatos ou locais onde se encontram os dados.
 Exemplo: ADD R1, R2, #4 
  R1 ← (R2) + 4
  • Uniformidade e tamanhos fixos dos campos das instruções para facilitar a decodificação.
  • I/O mapeado em memória: a comunicação com dispositivos periféricos é feita no próprio espaço de endereçamento de memória (via load e store).
  • Endereços de memória se referem a bytes individuais.

Formato de Instruções

Apesar das diferenças entre as instruções, os projetistas mantiveram certa regularidade no formato delas, facilitando a decodificação. O formato geral é do bit menos significativo ao mais significativo, o seguinte:

  • 4 bits para condição de execução;
  • 3 bits para o tipo de instrução;
  • 5 bits para o opcode;
  • 20 bits, cujo uso e repartição varia para acomodar endereços, referências a registradores,

deslocamentos e rotações.

Operandos:

Registradores:

ADD r1, r2, r3
MOV r1, r2

Imediatos: identificados pelo símbolo #

ADD r1, r2, #10
MOV r1, #0


Maiores detalhes sobre o formato das instruções podem ser vistos na figura.

Fig119 MI1022806.png


Estas condições são ativadas através de sufixos que são colocados junto com os minemônicos das instruções.

Por exemplo, um salto (B) pode ser acompanhado de um NE (not equal), o que gera uma expressão BNE.

Essa instrução só será executada caso a condição seja verdadeira.

Conjunto de Instruções ARM

Quanto ao número de bits, as instruções podem ser dos seguintes tipos:

ARM

Fig120 MI1022806.png


THUMB

  • Operações de 32 bits, em instruções de 16 bits
  • Introduzido no processador ARM7TDMI (Datasheet)
  • Suportado por todos os processadores ARM, desde então


THUMB-2

  • Permite uma mistura com performance otimizada de instruções de 16/32 bits
  • Todas as operações do processador podem ser realizadas no estado "Thumb"
  • Suportado por todos os processadores da linha Cortex-M, desde então.
Fig121 MI1022806.png


Quanto ao tipo de operação, tipos de instruções oferecidos são:

  • Load/Store: Instruções de carregamento e escrita de dados na memória. Podem ler/escrever

palavras inteiras(32 bits), meias-palavras(16 bits), bytes sem sinal, e podem ler e estender o sinal de meias-palavras.

A sintaxe é:

Instruções de acesso à memória

  <LDR|STR> {cond} {B} {T} Rd,<Address>

onde:

  • LDR carrega um valor da memória para um registrador
  • STR armazena um valor de registrador para a memória
  • {cond} mnemônico condicional de 2 caracteres
  • {B} se B estiver presente, transfere um byte, senão, transfere uma palavra
  • {T} se T estiver presente, the bit W será setado em um instrução pós-indexada, forçando um modo não-privilegiado para o ciclo de transferência. Não permitido para modo pré-indexado.
  • Rd é o nome do registrador
  • <Address> pode ser:
    • Uma expressão que gere um endereço:
<expression>
    • Uma especificação de endereço pré-fixada:
[Rn] endereço base
[Rn,<#expression>]{!} offset de <expression> bytes
[Rn,{+/-}Rm{,<shift>}]{!} offset de +/- conteúdos do registrador de índice, deslocado de <shift>
    • Uma especificação de endereçamento pós-fixada:
 [Rn],<#expression> offset de <expression> bytes
 [Rn],{+/-}Rm{,<shift>} offset de +/- conteúdos do registrador de índice, deslocado de <shift>
Exemplos
STR R1,[R2,R4]   ; Armazena R1 em R2+R4 (ambos os quais são
                  ; registradores) 
STR R1,[R2],R4    ; Armazena R1 em R2 e escreve de volta
                  ; R2+R4 em R2.
LDR R1,[R2,#16]   ; Carrega R1 do endereço R2+16, mas
                  ; não escreve de volta.
LDR R1,[R2,R3,LSL#2] ; Carrega R1 do endereço R2+R3*4.
LDREQBR1,[R6,#5]  ; Carrega condicionalmente o byte de R6+5 em
                  ; R1 bits 0 a 7, preenchendo os bits 8 a 31
                  ; com zeros.
STR R1,PLACE      ; Gera um offset em PC relativo ao
                  ; endereço PLACE.

A arquitetura ARM suporta dois tipos de instruções de load e store que transferem o conteúdo de um registrador para a memória ou ao contrário.

O primeiro tipo pode carregar ou escrever uma parava de 32 bits ou um byte sem sinal.

O segundo tipo pode ler ou escrever meia palavra de 16 bit sem sinal, e pode carregar e sinalizar meia palavra de 16 bit ou um byte. Este tipo de instrução está disponível apenas para a arquitetura ARM versão 4 ou posterior.

Fig122 MI1022806.png
  • Load/Store em blocos: são instruções que permitem definir a leitura/escrita de blocos de até 16 registradores em uma única instrução. Isso é feito com uma máscara de 16 bits na instrução

que define quais registradores serão usados, e permite atingir uma banda de comunicação quatro vezes maior do que uma instrução que usa um único registrador. Essas instruções podem ser usadas para início e retorno de chamadas, assim como para ler blocos de memória.


  • Desvio: Todos os processadores ARM suportam instruções de branch com saltos condicionais para frente ou para trás de até 32M. A condição é dada por um campo de 4 bits. Saltos mais longos podem ser feitos através de chamadas de subrotinas como por exemplo o Branch whith Link (BL), que mantem o endereço de retorno no LR (R14).


  • Processamento de Dados: são operações de adição e subtração, operações lógicas AND, OR e XOR, e instruções de comparação e teste;
    • Multiplicação de inteiros: as multiplicações de inteiros podem ser feitas com operandos de 32 ou 16 bits, e o resultado pode ocupar 32 ou 64 bits;
    • Adição/Subtração paralelas: essas instruções permitem aplicar a operação em partes dos operandos, de forma paralela.

Um exemplo é a instrução ADD16, que adiciona as primeiras meias-palavras dos operandos para formar a meia palavra superior do resultado, enquanto faz o mesmo com as meias-palavras inferiores para formar a parte inferior do resultado. Essas instruções são úteis para processamento de imagens

Fig123 MI1022806.png
Fig124 MI1022806.png
  • Extensão: são instruções para reagrupar dados;
  • Acesso a registrador de estado: é permitido ler e escrever em partes do registrador de estados. Existem duas instruções para mover os conteúdos de um registrador de propósito geral e de um registrador de estado, que são as seguintes:
    • MRS – move o conteúdo do registrador de estado para um registrador de propósito geral.
    • MSR – move o conteúdo do registrador de propósito para um registrador de estado.
  • Interface para coprocessadores: há um grupo de instruções para trocas de dados com coprocessadores, assim como para controle destes. Elas permitem ao processador ARM iniciar uma operação de processamento de um coprocessador. Permite fazer transferências entre os registradores do processador e dos coprocessadores. Permitem também o processador criar endereços para o coprocessador carregar e escrever instruções. Todo o tratamento de ponto flutuante é feito por um coprocessador, cuja presença nos chips é opcional.
  • Intercâmbio com Thumb: são instruções para indicar se serão executadas instruções de 32 ou 16 bits. A instrução BX permite a troca entre o estado ARM e o estado THUMB. Esta instrução copia o conteúdo de um registrador de propósito geral para o PC. Caso o bit[0] do valor transferido para o PC seja 1, o processador troca para o estado THUMB.
  • instruções geradoras de exceções. Existe duas instruções deste tipo:
    • a SWI que causa uma interrupção de software. É o mecanismo principal utilizado pelo ARM para poder executar códigos do Sistema Operacional no modo de usuário (User Mode).
    • E existe o BKPT. Esta instrução é usada para breakpoints na arquitetura ARM da versão 5 em diante.

 

Programas em Instruções ARM

Exemplo 1
Programa calculadora simples 4 operações:
 
 ;PROGRAMA CALCULADORA DE 4 OPERAÇÕES
 ;		R4 = 1 -> R3 = R2 + R1
 ;		R4 = 2 -> R3 = R2 - R1
 ;		R4 = 3 -> R3 = R2 X R1
 ;		R4 = 4 -> R3 = R2 / R1
 mov		r4,#4 ; valor de R4 define operação
 mov		r2,#60
 mov		r1,#12
 mov		r3,#0
 cmp		r4,#1
 blt		fim
 beq		soma
 ;******
 cmp		r4,#2
 beq		subt  ; se r4=2 pula para subtração
 ;******
 cmp		r4,#3
 beq		mult
 ;******
 cmp		r4,#4
 bgt		fim
 beq		divisao
 ;******
 ;******; ALGORITMO DE SOMA:
 soma	add		r3,r2,r1
     b	fim
 ;******; ALGORITMO DE SUBTRAÇÃO:
 subt	sub		r3,r2,r1
     b	fim
 ;******; ALGORITMO DE MULTIPLICAÇÃO:
 mult	add		r3, r3, r2
        sub		r1, r1, #1
        cmp		r1, #1
        bge		mult
        b		fim
 ;******; ALGORITMO DE DIVISÃO:
 divisao	mov		r4,r2
 div2		subge	r4,r4, r1
                add		r3, r3,#1
                cmp		r4,r1
                bge		div2
                b		fim
 fim


Exemplo 2
Programa em instruções ARM que implementa uma calculadora de 4 operações inteiras e grava os resultados em arquivo de saída (ARMSIM):
 
 ;************************
 ; programa CALCULADORA
 ; R3 = R2 op R1
 ;
 ;onde 'op':
 ; R4 = 1 - SOMA
 ; R4 = 2 - SUBTRACAO
 ; R4 = 3 - MULTIPLICACAO
 ; R4 = 4 - DIVISAO
 ;*************************
 OutFileHandle: .word 0
 InFileHandle: .word 0
 InFileName:  .asciz "arqentrada.txt"
 OutFileName: .asciz "ArqSaida.txt"
 Saidasoma: .asciz "Soma = "
 Saidasub:  .asciz "Subtracao = "
 Saidamult: .asciz "Multiplicacao = "
 Saidadiv1: .asciz "Divisao = "
 Saidadiv2: .asciz "\n Resto = "
 Saidafim:  .asciz "\n Fim do processamento! "
      ldr r0,=InFileName
      mov r1,#0
      swi 0x66
      swi 0x6c
 ;******
      mov r4,r0
      mov r2,#6
      mov r1,#2
      mov r3,#0
     cmp r4,#1
      blt fim
      beq soma
 ;******
      cmp r4,#2
      beq subt
 ;******
      cmp r4,#3
      beq mult
 ;******
      cmp r4,#4
      bgt fim
      beq divisao
 ;******
 soma: add r3,r2,r1
      ldr r0,=Saidasoma
      swi 0x02
      add r0,r3,#'0
      swi 0x00
      b fim
 subt: sub r3,r2,r1
      ldr r0,=Saidasub
      swi 0x02
      add r0,r3,#'0
      swi 0x00
      b fim
 mult: mul r3,r2,r1
      ldr r0,=Saidasoma
      swi 0x02
      add r0,r3,#'0
      swi 0x00
      b fim
 divisao:  mov r4,r2
 div2:    subge r4,r4, r1
         add r3, r3,#1
         cmp r4,r1
         bge div2
         ldr r0,=Saidadiv1
         swi 0x02
         add r0,r3,#'0
         swi 0x00
         mov r0,#'\0
         swi 0x00
         ldr r0,=Saidadiv2
         swi 0x02
         add r0,r4,#'0
         swi 0x00
         b fim
 fim: ldr r0, =Saidafim
     swi 0x02


Exemplo 3
Programa que executa operações aritméticas e lógicas nos operandos:
  mov		r1,#4
  mov		r2,#30
  mov		r3,#1
  mov		r4, #5
  ORR		R1, R2, #0x20		;R1 = R2 | 0x20
  ADD		R3, R2, R4, LSL #3	; R3 = R2 + (R4 << 3)
  RSB		R5, R4, #0		; R4 = 0 - R5
  SUB		R1, R3, R2, LSR R4	;R1 = R2 - (R3 >> R4)


Exemplo 4
Programa que executa multiplicação sem uso da instrução MUL e checando se os operandos são negativos:
 
 ;		EXERCÍCIO 2 DISCIPLINA MICROPROCESSADORES
 ;		PROFA. FERNANDA
 ;		AULA 26/03/2019
  mov		r0,#8
  mov		r1,#-5
  mov		r4,#0   ; registrador  de SAÍDA
 inicio
  cmp		r1,#0
  beq		fim ;r1 = 0 -> r4 = 0
  bgt		set ;r1 >0
  ; r1 negativo:
  rsb		r3, r1, #0
  rsb		r2,r0, #0
  b		loop
 set
  mov		r3,r1
  mov		r2,r0
 loop
  add		r4,r4,r2
  sub		r3, r3, #1
  cmp		r3,#0
  ble		fim
  b		loop
 fim


Exemplo 5
Programa que armazena um valor NA MEMÓRIA:
 
  mov R0, #255
  mov R3, #2000
  mov R1, #0
  str R0, [R3, R1]


Exemplo 6
Programa que armazena valores em espaços seguidos da memória:
 
  mov R0, #255
  mov R1, #0
  mov R2, #100  //100 endereços depois do endereço-base
  mov R3, #2000  //endereço base
 loop
  str R0, [R3,R1]
  add R1, R1, #4 //endereços têm que ser múltiplos de 4
  add R0, R0, #1
  cmp R1, R2
  blt loop
  ldr R5,[R3,#20]

Ao final da execução, R3 continua contendo o valor 0X7D0 (endereço base = 2.000d)


Exemplo 7
Programa que armazena valores em espaços seguidos da memória e atualiza variável:
 
  mov R0, #255
  mov R1, #0
  mov R2, #100  //100 endereços depois do endereço-base
  mov R3, #2000  //endereço base
 loop
  str R0, [R3,R1]!
  add R1, R1, #4 //endereços têm que ser múltiplos de 4
  add R0, R0, #1
  cmp R1, R2
  blt loop
  ldr R5,[R3,#-200]

Ao final da execução, R3 contém o valor 0X908 (endereço base = 2.312d)


Exemplo 8
Programa que salva dois vetores de 8 valores na memória (A, no endereço 2000 e B, no endereço 2032) e executa a operação:
c =  ∑ Ai.Bi, com i variando de 0 a 7.

O produto final C será armazenado no endereço 1000 da memória

 
  mov		R0, #4 ; passo de memória
  mov		R10, #2000 ;endereço de A
  mov		R11, #2032 ;endereço de B
  mov		R12, #1000 ;endereço de C
  
  ;valores	do vetor A
  mov		R2, #30
  mov		R3, #27
  mov		R4, #21
  mov		R5, #17
  mov		R6, #10
  mov		R7, #3
  mov		R8, #-1
  mov		R9, #-2
  	
  ;grava	valores de A na memória
  mov		R1, R10
  str		R2, [R1],R0
  str		R3, [R1],R0
  str		R4, [R1],R0
  str		R5, [R1],R0
  str		R6, [R1],R0
  str		R7, [R1],R0
  str		R8, [R1],R0
  str		R9, [R1]
  		
  ;valores	do vetor B
  mov		R2, #-3
  mov		R3, #1
  mov		R4, #7
  mov		R5, #11
  mov		R6, #13
  mov		R7, #23
  mov		R8, #4
  mov		R9, #5
  		
  ;grava	valores de B na memória
  mov		R1, R11
  str		R2, [R1],R0
  str		R3, [R1],R0
  str		R4, [R1],R0
  str		R5, [R1],R0
  str		R6, [R1],R0
  str		R7, [R1],R0
  str		R8, [R1],R0
  str		R9, [R1]
   	
  ;rotina	para multiplicação dos valores
  mov		R1, R10
  mov		R2, R11
  mov		R3, #0
  mov		R4, #7
  mov		R8, #0 ;registrador de saída
   	
  somatorio	mov		R5, #0
  ldr		R6, [R1],R0
  ldr		R7, [R2],R0
  cmp		R7, #0
  bge		multpos ;se 2o op >0 => mult positiva
  beq		final  ;se 2o op = 0 => não acumula
    	
  ;se		2o. op < 0 :
  multneg	sub		R5, R5, R6
  add		R7, R7, #1
  cmp		R7, #0
  bne		multneg
  b		final
  	
  multpos	add		R5, R5, R6
  sub		R7, R7, #1
  cmp		R7, #0
  bne		multpos
  	
  final	add		R8, R8, R5
  add		R3, R3, #1
  cmp		R3, R4
  ble		somatorio
    	
  str		R8, [R12]

Exercícios

1. Escreva o programa que implementa um loop com 40 iterações, incrementando uma variável do valor 0 a 39 e somando o valor 3, a cada iteração, ao valor inicial (=3) armazenado em R1.
Exemplo de solução 1

Loop com 40 iterações e soma 3 a R1, em cada iteração

  ;PROGRAMA	QUE IMPLEMENTA R1 = R1 + 5, 40 VEZES
  ;		i.e., R1 = R1 x 200
  ;*******
  mov		r1, #5      ;valor inicial de R1
  mov		r2, #3      ;incremento de R1
  mov		r3, #40     ;numero de loops
  mov          r4, #0      ;valor inicial
;***INICIA LOOP ***
loop   add r1, r1, r2  ;r1 = r1 + 3
       add r4,r4, #1
       cmp r3,r4
       blt loop
fim
2. Escreva o programa que implementa as operações lógicas (AND, OR, XOR, NXOR, NAND E NOR) entre dois valores, armazenados em R4 e R5.
Exemplo de solução 2

Todas as operações são bit-a-bit, e não lógicas:

mov		r4, #13
mov		r5, #6
and		r0, r4,r5  ;r0 = r4 & r5
orr		r1, r4, r5 ;r1 = r4 | r5
eor		r2, r4, r5 ;r2 = r4 ^ r5
mvn		r3, r2     ;r3 = nxor(r4, r5)
mvn		r6, r0     ;r6 = nand(r4, r5) 
mvn		r7, r1     ;r7 = nor(r4, r5)
3. Implemente, no ARMSIM, o programa Arm que resolve a equação: Y = (A - B) / (C + D x E). Dica: armazene A em R0, B, em R1, C, em R2, D, em R3 e E, em R4.
Exemplo de solução 3

Programa que resolve a equação Y = (A - B)/(C + DxE), com o resultado em R8

;PROGRAMA	QUE IMPLEMENTA Y = (A - B) / (C + D x E)
;COM:
   ;		A = 10, B = 4, C = 2, D = 3, E = 9
   ;		e Y -> R8
   ;******************
   mov		r0, #100   ;A
   mov		r1, #4    ;B
   mov		r2, #2    ;C
   mov		r3, #3    ;D
   mov		r4, #9    ;E
   sub		r5, r0, r1 ; R5 = A - B
   ;***		ROTINA PARA D X E ***
   mov		r6,r3
   mov		r7,r4
loop		add		r6, r6, r3  ; R6 = R6 + D
   sub		r7,r7, #1   ; REPETE R7 = R4 VEZES
   cmp		r7,#1
   bgt		loop
   add		r6,r6,r2 ; R6 = (DxE) + C
  ;***		ROTINA PARA R8 = R5/R6 , ie, (A - B)/(C + D x E)
   mov		r8,#0
div		subge	r5,r5, r6
   add		r8, r8,#1
   cmp		r5,r6
   bge		div
fim
4. Implemente, no ARMSIM, o programa que lê compara os valores armazenados em R1, R2 e R3 e devolve o maior dentre eles em R4, e o menor, em R5.
Exemplo de solução 4

Compara R1, R2 e R3 e armazena o maior valor, dentre os 3, em R4 e o menor valor, em R5

  ;PROGRAMA	QUE COMPARA 3 VALORES EM R1, R2 E R3
  ;		E ARMAZENA O MAIOR EM R4
  ;		E O MENOR, EM R5
  mov		r1, #50
  mov		r2, #20
  mov		r3, #6
  cmp		r1,r2
  blt		r2maior
  cmp		r1, r3
  blt		r3maior
  mov		r4,r1  ; R1 eh o maior
  cmp		r2,r3
  movge	r5,r3
  movlt	r5,r2
  b		fim
r2maior	cmp		r2,r3
  blt		r3maior
  mov		r4, r2  ; R2 eh o maior
  cmp		r1,r3
  movge	r5,r3
  movlt	r5,r1
  b		fim
r3maior	mov		r4, r3  ; R3 eh o maior
  cmp		r1,r2
  movge	r5,r2
  movlt	r5,r1
  b		fim
fim
5. Escreva o programa com menu para resolver operações lógicas E, OU e NÃO entre dois valores armazenados em R4 e R5, assumindo que a variável é false quando tiver valor igual a 0 (=0).
6. Implemente o programa que calcula (X * 2^N), apenas pelos deslocamentos à esquerda ou direita, de um valor X armazenado em R0 e com N armazenado em R1.

Conjunto de Instruções THUMB

O THUMB possui instruções com as mesmas finalidades das instruções ARM, porém são codificadas com 16 bits.

Estas instruções THUMB geram códigos menores porém muitas vezes ocorre de aumentar o número de instruções que o processador deve executar.

Uma solução para isso são aplicações que utilizam ambos tipos de instruções (ARM e THUMB).

Aplicações deste tipo conseguem reduzir o tamanho do seu código significativamente e conseguem manter o consumo de energia baixo.

Algumas instruções THUMB são:


Instruções de deslocamento: ASR, LSL, LSR, ROR e RRX

As instruções a seguir são, na verdade, sinônimos para a instrução

MOV Rd, Rm, XXX #n 

onde XXX é um dentre LSR, LSL, ASR, ROR e n é uma constante variando de 0-31.

Obs: se o sufixo S for acrecentado a XXX então o último bit deslocado de Rd entra no bit C (Carry) da palavra de estado.

Obs: os bits de uma palavra são numerados de 0 a 31, do menos significativo ao mais significativo

Sintaxe:

op{S}{cond} Rd, Rm, Rs
op{S}{cond} Rd, Rm, #n
RRX{S}{cond} Rd, Rm

onde:

  • op is one of:
    • ASR: Deslocamento à direita aritmético
    • LSL: Deslocamento à esquerda lógico
    • LSR: Deslocamento à direita lógico
    • ROR: Rotaciona à direita
  • S é um sufixo opcional. Se S for especificado, as flags condicionais são atualizadas no resultado da operação.
  • Rd é o registrador destino
  • Rm é o registrador contendo o valor a ser deslocado
  • Rs é o registrador contendo o comprimento de deslocamento a ser aplicado ao valor em Rm. Apenas o byte menos significativo é usado e deve variar entre [0,255].
  • n é o comprimento de deslocamento. Depende da instrução:
    • ASR: comprimento de deslocamento de 1 a 32
    • LSL: comprimento de deslocamento de 0 a 31
    • LSR: comprimento de deslocamento de 1 a 32
    • ROR: comprimento de deslocamento de 1 a 31
LSR Rd, #n  - desloca Rd n bits para a direita inserindo n 0s à esquerda (divide Rd por 2**n)
LSL Rd, #n  - desloca Rd n bits para a esquerda inserindo n 0s à direita (multiplica Rd por 2**n)
ASR Rd, #n  - desloca Rd n bits para a direita, replicando o bit 31 (preserva o bit de sinal)
                   - divide um inteiro com sinal por 2**n
ROR Rd, #n  - rotaciona para a direita n bits de Rd (o bit 0, - significativo, entra no lugar do bit 31)
XXX Rd, Rm,#n - variante permitida das instruções acima; Rm não muda
RRX Rd, Rm  - rotaciona um bit do par (Rm,C) como se fosse uma palavra de 33 bits:  Rd0->C, C->Rd31, etc 
                   - resultado vai para Rd, Rm não é alterado, exceto se Rd=Rm.

Operação

ASR, LSL, LSR e ROR movem os bits no registrador Rm para a esquerda ou para a direita, pelo número de lugares especificado pela constante n, ou registrador Rs.

RRX move os bits no registrador Rm para a direita 1 vez.

Em todas estas instruções, o resultado é escrito para Rd, mas o valor em Rm continua inalterado.

Restrições

Não use com SP ou PC.


Flags de condição

Se S for especificado:

  • estas instruções atualizam as flags N e Z de acordo com o resultado
  • a flag C é atualizada com o último bit deslocado, exceto quando o comprimento do deslocamento é 0.
Exemplos
ASR R7, R8, #9; arithmetic shift right by 9 bits
LSLS R1, R2, #3; logical shift left by 3 bits with flag update
LSR R4, R5, #6; logical shift right by 6 bits
ROR R4, R5, R6; rotate right by the value in the bottom byte of R6
RRX R4, R5; rotate right with extend
  mov		r1, #-200
  mov		r2, #200
  mov		r3, #5
  
  asr		r9, r1, #3
  lsls		r5, r2, #4
  lsl		r4, r3, #6
  ror		r6, r1, #6
  rrx		r7, r3

BFC - Bit field clear e BFI - Bit field insert

Sintaxe

BFC{cond} Rd, #lsb, #width
BFI{cond} Rd, Rn, #lsb, #width

onde:

  • cond é o código condicional, cc.
  • Rd é o registrador destino.
  • Rn é o registrador fonte.
  • lsb é a posição do bit menos significativo no campo de bits [0-31].
  • width é a largura do campo de bits [1-32].

Operação

BFC zera um campo de bits em um registrador. Limpa width bits em Rd, iniciando da posição inferior lsb. Os demais bits permanecem inalterados.

BFI copia um campo de bits de um registrador para outro. Substitui width bits em Rd, iniciando da posição inferior lsb, pelos width bits em Rn, iniciando da posição bit[0]. Os demais bits permanecem inalterados.

Restrições

Não é permitido utilizar os registradores SP e PC com estas instruções.

Estas instruções não afetam as flags.

Exemplos
BFC R4, #8, #12 ; Limpa o bit 8 até bit 19 (12 bits) de R4
BFI R9, R2, #8, #12 ; Substitui bits 8 a 19 (12 bits) de R9 com bits 0 a 11 de R2

AND, ORR, EOR, BIC, and ORN

E, OU, OU EXCLUSIVO, Zera bit, E NÃO-OU lógicos.

Sintaxe

op{S}{cond} {Rd,} Rn, Operand2

onde:

  • op é uma das operações:
    • AND: E lógico
    • ORR: OU lógico ou seta-bit
    • EOR: OU exclusivo lógico
    • BIC: NÃO-E lógico ou zera bit
    • ORN: NÃO-OU lógico
  • S é o sufixo opcional. Se S for especificado, as flags de código condicional serão atualizadas como resultado da operação.
  • cond é o código de condição opcional
  • Rd é o registrador destino
  • Rn é o registrador que contém o primeiro operando
  • Operand2 é o segundo operando

Operação

As instruções AND, EOR, e ORR realizam operações E, OU-EXC e OR bit-a-bit nos valores de Rn e operand2. A instrução BIC realiza uma operação E nos bits de Rn com o complemento dos correspondentes bits no valor de operand2. A instrução ORN realiza uma operação OU nos bits de Rn com o complemento dos bits correspondentes no valor de operand2.

Restrições

Não usar em SP e PC.

Flags de condição

Se S for especificado, estas instruções:

  • Atualizam as flags N e Z de acordo com o resultado.
  • Podem atualizar a flag C durante o cálculo de operand2
  • Não afetam a flag V
Exemplo
AND R9, R2,#0xFF00
ORREQ R2, R0, R5
ANDS R9, R8, #0x19
EORS R7, R11, #0x18181818
BIC R0, R1, #0xab
ORN R7, R11, R14, ROR #4
ORNS R7, R11, R14, ASR #32

ADD, ADC, SUB, SBC, and RSB

Soma, soma com carry, subtrai, subtrai com carry e subtrai reverso.

Sintaxe

op{S}{cond} {Rd,} Rn, Operand2
op{cond} {Rd,} Rn, #imm12; ADD and SUB only

onde:

  • op é:
    • ADD: Soma
    • ADC: Soma com carry
    • SUB: Subtração
    • SBC: Subtração com carry
    • RSB: Subtração reversa
  • S é o sufixo opcional. Se S for especificado, as flags serão atualizadas no final da operação.
  • cond é o cc
  • Rd é o registrador destino. Se for omitido, o destino é o próprio Rn.
  • Rn é o registrador contendo o primeiro operando
  • Operand2 é o segundo operando flexível
  • imm12 é qualquer valor na faixa de 0-4095

Operação

A instrução ADD adiciona o valor do operand2, ou imm12, ao valor de Rn.

A instrução ADC adiciona o valor do Rn e operand2, junto com a flag de carry.

A instrução SUB subtrai o valor de operand2 do valor em Rn. Se a flag de carry estiver zerada, o resultado é diminuído de um.

A instrução SBC subtrai o valor em Rn de operand2. Esta instrução é útil porque operand2 permite uma faixa maior de valores.

A instrução RSB subtrai o valor do operand2, ou imm12, ao valor de Rn.

A instrução ADDW é equivalente à instrução ADD, que usa o operando imm12. SUBW é equivalente à instrução SUB, que usa o operando imm12.

CBZ and CBNZ

Compara e desviam se zero; compara e desvia se não-zero.

Sintaxe:

CBZ Rn, label
CBNZ Rn, label

onde:

  • Rn é o registrador contendo o operando.
  • label é o destino do desvio.

Operação

Use as instruções CBZ e CBNZ para evitar mudar as flags de cc e reduzir o número de instruções

A instrução CBZ Rn, label não altera as flags de condição, mas, ao contrário, é equivalente a:

CMP Rn, #0
BEQ label

A instrução CBNZ Rn, label não altera as flags de condição, mas, ao contrário, é equivalente a:

CMP Rn, #0
BNE label

Restrições

  • Rn deve ser R0 a R7
  • O destino do desvio deve estar entre 4 e até 130 bytes após a instrução
  • Estas instruções não podem ser usadas dentro de um bloco IT.

Flags de condição

Não alteram as flags

Exemplos
CBZ R5, target ; Forward branch if R5 is zero
CBNZ R0, target ; Forward branch if R0 is not zero

CMP and CMN

Compara e compara negativo.

Sintaxe:

CMP{cond} Rn, Operand2
CMN{cond} Rn, Operand2

onde:

  • cond é um código de condição opcional (c.c.)
  • Rn é o registrador do primeiro operando
  • Operand2 é o segundo operando

Operação

As instruções comparam o valor do registrador com operand2.

Elas atualizam a condição da flag no resultado, mas não escrevem o resultado em um registrador.

A instrução CMP subtrai o valor de operand2 do valor em Rn. Faz o mesmo que a instrução SUBS, exceto que o resultado é descartado.

A instrução CMN adiciona o valor de operand2 ao valor em Rn. Faz o mesmo que a instrução ADDS, exceto que o resultado é descartado.

Restrições

Não é permitido usar PC e operand2 não pode ser SP.

Flags de condição

As instruções atualizam as flags N, Z, C e V, de acordo com o resultado.


Exemplos
CMP R2, R9
CMN R0, #6400
CMPGTSP, R7, LSL #2

CLZ - Count leading zeros

Sintaxe:

CLZ{cond} Rd, Rm

onde:

  • cond é o cc opcional.
  • Rd é o registrador destino
  • Rm é registrador operando

Operação

A instrução CLZ conta o número de zeros no valor em Rm e retorna o resultado em Rd. O valor resultante é 32 se nenhum bit está setado no registrador fonte, e zero, se bit[31] é setado.

Restrições

Não use com SP e PC.

Flags de condição

Esta instrução não altera as flags.


Exemplos
CLZ R4,R9
CLZNE R2,R3

IT - If-Then condition instruction

Sintaxe
IT{x{y{z}}} cond

onde:

  • x especifica a condição chave para a segunda instrução no bloco IT.
  • y especifica a condição chave para a terceira instrução no bloco IT.
  • z especifica a condição chave para a quarta instrução no bloco IT.
  • cond especifica a condição chave para a primeira instrução no bloco IT.

As condições chave para segunda, terceira e quarta instruções do bloco podem ser:

  • T: Then - Então. Aplica a condição cond à instrução.
  • E: Else - Senão. aplica a condição inversa de cond à instrução.

Exemplo:

Fig125 MI1022806.png
Fig126 MI1022806.png

Operação

A instrução IT realiza um das quatro instruções condicionais seguintes.

As condições podem ser as mesmas, ou algumas podem ser o inverso lógico das outras. As instruções que seguem a instrução IT formam o "bloco IT".

As instruções no bloco IT, incluindo os branches, devem especificar a condição {cond} como parte de suas sintaxes.

Podem ser geradas exceções nos blocos IT.

Restrições

As seguintes instruções não são permitidas num bloco IT:

  • IT
  • CBZ e CBNZ
  • CPSID e CPSIE.

Um branch ou qualquer outra instrução que modifique o PC deve estar fora de um bloco IT, ou deve ser a última instrução dentro do bloco IT. São:

  • ADD PC, PC, Rm
  • MOV PC, Rm
  • B, BL, BX, BLX
  • qualquer instrução LDM, LDR, ou POP que escreva no PC
  • TBB e TBH

Não desvie para qualquer instrução INTERNA a um bloco IT, exceto quando retornando de um Exception Handler.

Para restrições adicionais, consulte o manual do seu Arm Assembler.

Flags de condição

Esta instrução não altera as flags.

Exemplos
ITTE NE ; Proximas 3 instruções são condicionais
ANDNE R0, R0, R1 ; ANDNE não atualiza as flags de condicao 
ADDSNE R2, R2, #1 ; ADDSNE atualiza as flags de condicao
MOVEQ R2, R3 ; Move Conditional
CMP R0, #9 ; Converte valor hexa R0 (0 a 15) para ASCII
; ('0'-'9', 'A'-'F')
ITE GT ; Proximas 2 instrucoes sao condicionais
ADDGT R1, R0, #55 ; Converte 0xA -> 'A'
ADDLE R1, R0, #48 ; Converte 0x0 -> '0'
IT GT ; bloco IT com apenas uma instrucao condicional
ADDGT R1, R1, #1 ; Incrementa R1 condicionalmente
ITTEE EQ ; Proximas 4 instrucoes são condicionais
MOVEQ R0, R1 ; move Condicional
ADDEQ R2, R2, #10 ; add Condicional
ANDNE R3, R3, #1 ; AND Condicional
BNE.W dloop ; Instrucao Branch instruction apenas pode ser usada no final 
; de um bloco IT 
IT NE ; proxima instrucao é condicional
ADD R0, R0, R1 ; erro de sintaxe: nenhum codigo condicional

Execução condicional de instruções

As instruções lógico-aritméticas podem ser condicionalmente executadas dependendo dos flags da palavra de estado que foram atualizados numa instrução anterior (usualmente imediatamente anterior).

Existem 15 condições que podem ser usadas como sufixo da instrução, e que são as mesmas usadas nas instruções de salto condicional:

eq, ne, cs ou hs, cc ou lo, mi, pl, vs, vc, hi, ls, ge, lt, gt, le, al. 

Para que a execução condicional seja possível até 4 instruções devem ser precedidas pela instrução especial "If-Then condition instruction":

  it cond, 

onde cond é uma das 15 siglas de 2 letrasi citadas anteriormente (existem outros 3 possíveis parâmetros).

Exemplos:

(1) suponha que r1 contem um inteiro com sinal: colocar em r0 o valor absoluto desse inteiro:

movs r0, r1	@ atualiza flags
it mi		@ queremos tomar o negativo caso r0 <0
rsbmi r0, #0    @ faça r0 := 0 - r0 caso o bit N estivesse ligado

Obs: o mesmo código em instruções ARM seria:

mov r0, #12
mov r1, #8
mov r2, #4
loop:   cmp  r1, r2         @ cmp sempre atualiza flags 
@ queremos testar se r1 > r2
subgt  r1, r1 ,r2     @ se r1 > r2, faça r1:=r1-r2      
sublt  r2, r2 ,r1     @ se r1 < r2 faça  r2:= r2-r1
bne  loop             @ se r1 # r2 volte ao laço

(2) algoritmo para calcular o máximo divisor comum de dois inteiros em r1 e r2, devolvendo o resultado em r1 e r2:

loop:   cmp  r1, r2         @ cmp sempre atualiza flags 
 it gt               @ queremos testar se r1 > r2
 subgt r1, r2        @ se r1 > r2, faça r1:=r1-r2 
 it lt               @ senão teste por <
 sublt  r2, r1       @ se r1 < r2 faça  r2:= r2 -r1
 bne  loop           @ se r1 # r2 volte ao laço

@ senão mdc=r1=r2



Outras instruções THUMB:

  • RBIT - Reverse bits - p-81
  • REV - Reverse byte order in a word - p-81 (passa uma palavre de "little endian" para "big endian" e vice-versa)
  • SXTB - Sign extend a byte - p-90
  • TBB - Table branch byte - p-96
  • UDIV - Unsigned divide - p-86
  • UMULL - Unsigned multiply (32x32), 64 bit result
  • UXTB - Zero extend a byte - p-90
  • CPSID/CPSIE - Interrupts Disable/Enable - p-98


Maiores informações: The Cortex-M3 instruction set

Conjunto de instruções THUMB2

Tradicionalmente todas as instruções da arquitetura ARM tem tamanho regular de 32 bits (4 bytes)

Na geração 4 de processadores ARM (Tipo ARM7-TDMI) foi incuido o conjunto de instruções alternativo THUMB em que a maioria das instruções tem 2 bytes.

Nos processadores ARM7-TDMI os conjuntos de instruções ARM e THUMB são implementados como dois modos de operação diferentes, necessitando de uma instrução especial para trocar de modo.

Na geração 7 (Cortex) foi introduzido o conjunto de instruções THUMB2 com instuções de 2 e 4 bytes que podem acessar todos os recursos do processador.

Desta forma podem-se usar instruções de 16 bits ou de 32 bits arbitrariamente sem que seja necessário trocar o modo de operação.

Nos processadores Cortex M0, M1, M2 e M3 existem apenas as instruções THUMB2. O suporte ao conjunto ARM é desabilitado.

Na família Cortex o processador de interrupções NVIC foi incorporado ao core do processador, de modo a tornar o uso de interrupções mais simples e mais eficiente que nos chips anteriores da família ARM.


Mapa de Memória

Sistemas baseados no Cortex-M3 devem ter um mapa de memória definido:

0xFFFFFFFF
0xE0000000
Periféricos do sistema: NVIC, debug
0xDFFFFFFF
0xA0000000
Livre para Periféricos Externos
0x9FFFFFFF
0x60000000
Livre para RAM Externa
0x5FFFFFFF
0x40000000
Periféricos definidos pelo fabricante do CHIP
0x3FFFFFFF
0x20000000
SRAM (Memória integrada no CHIP)
0x1FFFFFFF
0x00000000
Memória FLASH integrada para firmware

O arquivo de registradores

A arquitetura Cortex-M3, assim como o ARM7, tem 16 registradores (R0 a R15) de 32bits com acesso direto à ULA. Algumas instruções THUMB só podem acessar os registradores de R0 a R7.

Tres registradores tem propósito especial:

R0 a R7
Registradores do usuário baixos: Todas as instruções tem acesso.
R8 a R12
Registradores do usuário altos: Algumas instruções THUMB não tem acesso.
R13 ou SP
Stack Pointer. Apontador de pilha. Existem dois apontadores de pilha, ambos acessíveis como R3:
  • MSP Main Stack Pointer: Este é o apontador de pilha principal, usado no núcleo do sistema operacional e no tratamento de exceções.
  • PSP Process Stack Pointer: Usada em programas aplicativos (modo usuário).

As intruções PUSH e POP armazenam ou restauram dados da pilha.

PUSH	{R0}	; R13 = R13-4,  Memoria[R3] = R0
POP	{R0}	; R0 = Memoria[R3], R13 = R13+4;

As intruções PUSH e POP podem usar uma lista de registradores:

PUSH	{R0, R1, R2, R5}
POP	{R0-R2, R5}	; Restaura R0, R1, R2 e R5
R14 ou LR
Link Register. Contém o endereço de retorno para chamadas de subrotina. A instrução BL <endereço > funciona como uma chamada de subrotina. Ela salva automaticamete o endereço da intrução seuinte no LR e salta para o local indicado pelo operando. Se for necessário aninhar chamadas de subrotina, o LR deve ser salvo na pilha.
R15 ou PC
Program Counter. Este registrador tem o endereço da próxima instrução que será executada.

Registradores Especiais

Fora do banco de registradores R0 a R15 existem alguns registradores que controlam ou indicam aspectos especiais do processador.

Eles podem ser classificados em tres grupos:

  • xPSR - APSR, IPSR, EPSR: Program Status Registers: Tem os bits de estado da ULA: NZCVQ
  • PRIMASK, FAULTMASK e BASEPRI: Prioridade e mascaramento de interrupções
  • CONTROL: Indica o modo de operação: Privilegiado, Usuário ou executando uma excessão


Os bits NZCV do xPSR são chamados "Condition Code" abreviado como cc.

Em geral, os códigos cc refletem o resultado da última instrução da unidade aritmética.

N Negative: É uma cópia do bit mais significativo do resultado, que indica o sinal. Resultado com bit mais significativo 1 é considerado como negativo. Setado, quando o resultado da operação for negativo, ou zerado, caso contrário

Z Zero: Indica que deu resultado ZERO na última operação. Setado, quando o resultado da operação for zero, ou zerado, caso contrário

C Carry: Bit de transporte na soma ou empréstimo na subtração. Setado, quando o resultado da operação resultar em um carry, ou zerado, caso contrário

V oVerflow: Indica overflow em uma operação com sinal. Ocorre quando mudou o sinal sem a ativação do carry. Setado, quando o resultado da operação resultar em overflow, ou zerado, caso contrário

Um carry ocorre quando:

  • o resultado de uma adição for maior ou igual a 2^32
  • se o resultado de uma subtração for positivo ou zero
  • como resultado de um deslocamento para a direita ou esquerda.

O overflow ocorre quando o resultado de uma soma, subtração, ou comparação for maior ou igual a 2^31, ou menor que -2^31.

Muitas instruções de processamento de dados podem atualizar as flags de condição do APSR, de acordo com o resultado da operação. Algumas instruções vão atualizar todas as flags, e algumas, apenas um subconjunto. Se a flag não for atualizada, o valor original é preservado.

Você pode executar uma instrução condicionalmente, baseado em um ou mais flags atualizadas por meio de outra instrução:

  • imediatamente após a instrução que atualizou as flags;
  • Após um determinado intervalo de instruções que não tenham atualizado as flags.

A execução condicional está disponível pelo uso condicional de branches, ou adicionando os sufixos cc às instruções.

Tabela de Sufixos de Condição de Código
Sufixo Flags Significado
EQ Z=1 Equal
NE Z=0 Not equal
CS or HS C=1 Higher or same, unsigned >=
CC or LO C=0 Lower, unsigned <
MI N=1 Negative
PL N=0 Positive or zero
VS V=1 Overflow
VC V=0 No overflow
HI C=1 and Z=0 Higher, unsigned >
LS C=0 or Z=1 Lower or same, unsigned <=
GE N=V Greater than or equal, signed >=
LT N!=V Less than, signed <
GT Z=0 and N=V Greater than, signed >
LE Z=1 an N!=V Less than or equal, signed <=
Al Can have any value Always. This is the default when no suffix is specified.


Os sufixos de condição de código (cc) permitem ao processador testar uma condição baseado nas flags dos registradores. Se a condição falhar, a instrução:

  • Não executa
  • Não escreve nenhum valor no registrador de destino
  • Não afeta nenhuma flag
  • Não gera nenhuma exceção


Use as instruções CBZ e CBNZ para comparar o valor de um registrador com zero e desviar, dependendo do resultado.


Todas as instruções tem um campo que permite a sua execução condicional de acordo com o estado dos bits NZCV do xPSR. Na linguagem assembly esta execução condicional é indicada por um sufixo de duas letras no mnemonico da instrução de acordo com a tabela a seguir:

Tabela de Sufixos de Condição de Código
CC Condição CC Condição
CS C=1 Carry Set CC C=0 Carry Clear
EQ Z=1 Equal (zero) NE Z=0 Not Equal (não zero)
VS V=1 Overflow Set VC V=0 Overflow Clear
GT Greater Then (com sinal) LT Less Then (com sinal)
GE Greater or Equal (com sinal) LE Less or Equal (com sinal)
PL N=0 PLus (Positivo) (com sinal) MI N=1 Minus (negativo)
HI HIgher (maior que) (sem sinal) LO Lower (menor que) (sem sinal)
HS Higher or Same (sem sinal) (mesmo que CS) LS Lower or Same (sem sinal)

A maioria das instruções pode afetar ou não os indicadores de estado no CPSR. Na linguagem assembly coloca-se um sufixo com a letra s no mnemonico da instrução para indicar que os flags devem ser modificados. Por exemplo:

	subs	R1, R2, R3	/* Calcula R1=R2-R3 e ajusta flags */
	addge	R4, R4, #1	/* Soma 1 no R4 se o resultado da subs for >= 0 */
	AND	R5, #7		/* R5 = R5 & 7  Quado tem 2 operandos o destino=primeiro op */

As instruções de processamento de dados geralmente tem 3 argumentos:

  • op1: O primeiro argumento é um registrador onde o resultado é armazenado
  • op2: O segundo argumento é um registrador usado como primeiro operando da operação
  • op3: O terceiro argumento é o segundo operando da operação, que pode ser um valor imediato de 8 bits, um registrador ou um registrador com deslocamento.


As instruções de 3 argumentos são as seguintes:

Instruções de 3 argumentos
AND op1,op2,op3 op1 = op2 & op3 E bit a bit
EOR op1,op2,op3 op1 = op2 ^ op3 Ou exclusivo
ADD op1,op2,op3 op1 = op2 + op3 Soma
SUB op1,op2,op3 op1 = op2 - op3 Subtração
RSB op1,op2,op3 op1 = op3 - op2 Subtração reversa
ADC op1,op2,op3 op1 = op2 + op3 Soma com carry
SBC op1,op2,op3 op1 = op2 - op3 Subtração com carry
RSC op1,op2,op3 op1 = op3 - op2 Subtração reversa com carry
ORR op1,op2,op3 op3 Ou bit a bit
BIC op1,op2,op3 op1 = op2 & ~op3 Bit clear (zera bits)

Nas instruções com 2 operandos o primeiro deve ser um registrador e o segundo pode ser um valor imediato de 8 bits, um registrador ou um registrador com deslocamento.

Exemplos de intruções de 3 operandos
	ORR	R1, R2, #0x20		@ R1 = R2 | 0x20
	ADD	R2, R3, R4, LSL #3	@ R2 = R3 + (R4 << 3)
	RSB	R4, R5, #0		@ R5 = 0 - R5
	SUB	R1, R2, R3, LSR R4	@ R1 = R2 - (R3 >> R4)
Instruções de 2 argumentos
MOV op1, op2 op1 = op2 Copia op2 em op1
MVN op1, op2 op1 = ~op2 Copia op2 negado em op1
CMP op1, op2 op1 - op2 Compara: Subtrai ajustando CPSR sem armazenar o resultado
CMN op1, op2 op1 - ~op2 Compara com o segundo operando negado
TST op1, op2 op1 & op2 Testa bits: Faz E ajustando CPSR sem armazenar o resultado
TEQ op1, op2 op1 ^ op2 Testa bits: Faz XOR ajustando CPSR sem armazenar o resultado

Instruções de leitura da memória

Nesta listagem Rd e Re podem ser registradores R0 a R15.

Rd é o registrador que recebe o valor lido da memória; Re é o reg que contém o endereço de memória que será lido. offset é uma constante positiva ou negaiva de 12 bits usada para modificar o endereço.


Instruções de leitura da Memória para Registrador
LDR Rd,[Re, #offset] Rd := memória[Re + offset]; Le 32 bits
LDRH Rd,[Re, #offset] Rd := memória[Re + offset]; Le 16 bits (Half word)
LDRB Rd,[Re, #offset] Rd := memória[Re + offset]; Le 8 bits (Byte)
LDR Rd,[Re, #offset]! Rd := memória[Re + offset];
Re := Re + offset;
Le 32 bits e modifica Re
LDR Rd,[Re, Ri] Rd := memória[Re + Ri] Le memória com endereço formado pela soma de 2 registradores
LDR Rd,[Re], #offset Rd := memória[Re];
Re := Re + offset;
Le 32 bits e modifica Re com pós incremento

Instruções de escrita na memória

Nesta listagem Rf e Re podem ser registradores R0 a R15.

Rf é o registrador que será armazenado na memória; Re é o reg que contém o endereço na memória. offset é uma constante positiva ou negaiva de 12 bits usada para modificar o endereço.

Instruções escrita de Registrador na Memória
STR Rf,[Re, #offset] memória[Re + offset]:= Rf; Escreve 32 bits
STRH Rf,[Re, #offset] memória[Re + offset]:= Rf; Escreve 16 bits (Half word)
STRB Rf,[Re, #offset] memória[Re + offset]:= Rf; Escreve 8 bits (Byte)
STR Rf,[Re, #offset]! memória[Re + offset]:= Rf;
Re := Re + offset;
Le 32 bits e modifica Re
STR Rd,[Re], #offset memória[Re]:= Rf;
Re := Re + offset;
Escreve 32 bits e modifica Re com pós incremento

Instruções de salto

Salto relativo ao PC:

	B	enderco_destino		@ Salto incondicional
	BEQ	iguais			@ Salta se Z=1 (Iguais)
	BCS	carry_set

Chamada de subrotina:

	BL	subrotina1

A instrução BL salva o endereço de retorno no R14 (que é o LR Link-Rgister) e salta para a subrotina. Para reornar, da subrotina pode-se copiar o LR no PC com

subrotina1:
	@ Operações da subrotina
	MOV	PC,LR	@ Retorna da subrotina

O método acima não é aninhável. Não se poderia chamar outra subrotina de dentro desta subrotina porque o valor do LR seria alterado.
Subrotinas que chamam subrotinas, devem salvar o LR na pilha:

subrotina2:
	PUSH	{R1, R2, LR}	@ Salva na pilha R1, R2, LR
	@ Operações da subrotina
	POP	{R1, R2, PC}	@ Restaura R1 e R2 e retorna da subrotina



Aplicativos

VISUAL (Arm)

Disponível para download em: Visual - IDE para programação ARM
Lista de instruções suportadas: INSTRUÇÕES ARM para Visual
Exemplo
Mostrar como é compilado um programa, como são acessados os registradores, os comandos mov, add, sub e str.
;--------------------------------------------------------------------
;	Exercicio adaptado para ARM de Patterson pags. 54/55/56
;
;	Mostra a compilacao de um comando de atribuicao em C
;
;--------------------------------------------------------------------
	
;	Trecho em C:
;
;	f = (g + h) - (i + j)
		
	mov		r1, #1		; g=1
	mov		r2, #2		; h=2
	mov		r3, #10		; i=10
	mov		r4, #20		; j=20
	add		r10, r1, r2      ; r10 = g + h
	add		r11, r3, r4      ; r11 = i + j
	sub		r0, r10, r11     ; f = r10 - r11
	mov		r1, #0x10000
	str		r0, [r1,#4]
fim


Lista de instruções Suportadas
Summary Opcode Syntax
Move MOV MOV{S}{cond} dest, op1 {, SHIFT_op #expression}
Move Negated MVN MVN{S}{cond} dest, op1 {, SHIFT_op #expression}
Address Load ADR ADR{S}{cond} dest, expression
LDR Psuedo-Instruction LDR LDR{S}{cond} dest, =expression
Add ADD ADD{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
Add with Carry ADC ADC{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
Subtract SUB SUB{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
Subtract with Carry SBC SBC{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
Reverse Subtract RSB RSB{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
Reverse Subtract with Carry RSC RSC{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
Bitwise And AND AND{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
Bitwise Exclusive Or EOR EOR{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
Bitwise Clear BIC BIC{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
Bitwise Or ORR ORR{S}{cond} dest, op1, op2 {, SHIFT_op #expression}
Logical Shift Left LSL LSL{S}{cond} dest, op1, op2
Logical Shift Right LSR LSR{S}{cond} dest, op1, op2
Arithmetic Shift Right ASR ASR{S}{cond} dest, op1, op2
Rotate Right ROR ROR{S}{cond} dest, op1, op2
Rotate Right and Extend RRX RRX{S}{cond} op1, op2
Compare CMP CMP{cond} op1, op2 {, SHIFT_op #expression}
Compare Negated CMN CMN{cond} op1, op2 {, SHIFT_op #expression}
Test Bit(s) Set TST TST{cond} op1, op2 {, SHIFT_op #expression}
Test Equals TEQ TEQ{cond} op1, op2 {, SHIFT_op #expression}
Load Register LDR LDR{B}{cond} dest, [source {, OFFSET}] Offset addressing
LDR{B}{cond} dest, [source, OFFSET]! Pre-indexed addressing
LDR{B}{cond} dest, [source], OFFSET Post-indexed addressing
Store Register STR STR{B}{cond} source, [dest {, OFFSET}] Offset addressing
STR{B}{cond} source, [dest, OFFSET]! Pre-indexed addressing
STR{B}{cond} source, [dest], OFFSET Post-indexed addressing
Load Multiple Registers LDM[dir] LDM[dir]{cond} source, {list of registers}
Store Multiple Registers STM[dir] STM[dir]{cond} dest, {list of registers}
Branch B B{cond} target
Branch with Link BL BL{cond} target
Declare Word(s) in Memory DCD name DCD value_1, value_2, ... value_N
Declare Constant EQU name equ expression
Declare Empty Word(s) in Memory FILL {name} FILL N
N must be a multiple of 4
Stop Emulation END END{cond}

ArmSim

Disponível para download em: ARMSim - IDE para programação ARM

Referências

Maiores informações sobre programação em ARM:
The Definitive Guide to the ARM CORTEX-M3 2nd ed
Processador ARM:
https://www.youtube.com/watch?v=7LqPJGnBPMM
Curso completo de programação para sistemas embarcados:
https://www.youtube.com/playlist?list=PLPW8O6W-1chwyTzI3BHwBLbGQoPFxPAPM
VisUAL - Instruções Suportadas:
https://salmanarif.bitbucket.io/visual/supported_instructions.html



Icone voltar.png Icone menu.png Icone prox.png