AULA 5-2 - Microprocessadores - Graduação
CONJUNTO DE INSTRUÇÕES DO ARM
O conjunto de instruções também é chamado de "ISA - Instruction Set Architecture".
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.
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.
- 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.
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.
Quanto ao número de bits, as instruções podem ser dos seguintes tipos:
ARM
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.
Instruções de 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).
Condições:
Esta tabela contém os condicionantes, que podem ser aplicados em quase todas as instruções, após uma instrução CMP.
Instruções de 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;
As instruções de processamento também podem utilizar condições.
Exemplo 1:
Programa que executa operações aritméticas e lógicas nos operandos
mov r1,#4 mov r2,#80 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 ; R5 = 0 - R4 SUB R1, R3, R2, LSR R4 ;R1 = R3 - (R2 >> R4)
Exemplo 2:
Programa que atribui valor 0 a R8, se R1 > R2, e 1, se R1 <=R2
mov r1,#3
mov r2,#8
cmp r1,r2
bgt aux
mov r8,#1
b final
aux mov r8,#0
final
Código alternativo, sem branches, utilizando apenas as condições:
mov r1,#3
mov r2,#8
mov r8,#0
cmp r1,r2
addle r8,r8,#1
Outra versão, ainda mais simples e menor:
mov r1,#3
mov r2,#8
mov r8,#0
cmp r1,r2
movle r8,#1
Exemplo 3:
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 4:
Programa calculadora simples 4 op para rodar no VISUAL:
;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
Programa calculadora simples 4 op para rodar no ARMSIM:
;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:
Exercícios:
- 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 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 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 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
- 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).
- 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.
- Expanda o programa da calculadora de 4 operações para que ela também calcule potenciação, isto é, R3 = R2^R1. Exemplo de solução para potenciação
Instruções de acesso à memória
- 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 arquitetura ARM suporta dois tipos de instruções de load (ldr) e store (str) que transferem o conteúdo de um registrador para a memória ou ao contrário.
O primeiro tipo pode carregar ou escrever uma palavra 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.
<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 somente o byte L, senão, transfere toda a 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 atualiza o endereço
; em R2 com R2+R4.
LDR R1,[R2,#16] ; Carrega R1 do endereço R2+16, mas
; não atualiza R2.
Exemplo 1:
Programa que armazena um valor NA MEMÓRIA:
mov R0, #255 mov R3, #2000 mov R1, #0 str R0, [R3, R1]
Exemplo2
MOV R1,#0x1000 ; R1 = 4096d (=1000h), endereço base
MOV R3,#2000 ; R3 = 2000d (= 7D0h), dado
STRB R3,[R1] ; Armazena apenas D0h
; no endereço 1000h (=4096d)
STR R3,[R1,#4] ; Armazena 7D0h no endereço 1004h (=4100d)
Exemplo 3:
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,#400]
Ao final da execução, R3 continua contendo o valor 0X7D0 (endereço base = 2.000d)
Exemplo4
Salva valores em endereços de memória pré-fixados e pós-fixados. Roda tanto no ARMSIM quanto no VISUALArm.
mov r1,#0x1000
mov r2,#0x4
mov r3,#0x10
mov r4,#0x20
mov r5,#250
mov r6,#140
mov r7,#240
mov r8,#1
mov r9,#2
mov r10,#3
mov r11,#4
mov r12,#-1
str r5,[r1,r2] ; salva 250d (FAh) no endereço 1004h
str r6,[r1,r3] ; salva 140d (8Ch) no endereço 1010h
str r7,[r1,r4] ; salva 240d (F0h) no endereço 1020h
str r8,[r1],r2 ; salva 1d no endereço 1000h
; e faz R1=1004h
str r9,[r1],r2 ; salva 2d no endereço 1004h
; e faz R1=1008h
str r10,[r1],r2 ; salva 3d no endereço 1008h
;e faz R1=100Ch
str r11,[r1],r2 ; salva 4d no endereço 100Ch
; e faz R1=1010h
str r12,[r1],r2 ; salva -1d (FF FF FF FFh/32bits)
; no endereço 1010h e faz R1=1014h
Exemplo5
Salva valores contínuos (R3 -> [1d-20d]) em 20 endereços a partir do endereço base R1=1000h (=4096d). Para rodar no VisualArm (por causa da sintaxe e acesso à memória):
mov r1,#0x1000 ;endereço base
mov r2,#0x4 ;incremento de endereços
mov r3,#1 ;contadora de dados
mov r4,#20 ;contadora de endereços
loop str r3,[r1],r2 ; salva dado no endereço em R1
;e faz R1=R1+4
add r3,r3,#1 ; incrementa dado
sub r4,r4,#1 ; decrementa contadora endereços
cmp r4,#0 ; compara contadora com endereço final
ble fim ; termina se já zerou R4
b loop ; continua se ainda não
; atingiu 20 endereços
fim
Exemplo 6:
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 7
Armazena valores contínuos (R3 ->[1d;*=2;40d]) a partir do endereço base R1 = 1000h (=4096d) de forma 'alinhada' (de 4 em 4 endereços) e atualiza último valor calculado e armazenado em R6.
Para rodar no VisualArm (por causa da sintaxe e acesso à memória):
mov r1,#0x1000 ;endereço base
mov r2,#0x4 ;incremento de endereços
mov r3,#1 ;contadora de dados
mov r4,#20 ;contadora de endereços
loop mov r5,r1 ; registrador ponteiro
str r3,[r1],r2 ; salva dado no endereço em R1
;e faz R1=R1+4
lsl r3,r3,#1 ; r3 = r3x2 (uma rotação à esquerda)
sub r4,r4,#1 ; decrementa contadora endereços
ldr R6,[R5] ; Carrega dado do último
;endereço atualizado
cmp r4,#0
ble fim
b loop
fim
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, #0x1000 ;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:
- 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.
__________________________________
- 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.
Exemplo2:
Lê um inteiro do arquivo ArqEntrada.txt:
InFileName: .asciz "ArqEntrada1.txt" InFileError: .asciz "Não foi possível abrir\n" .align InFileHandle:.word 0 ldr r0,=InFileName ; configura o nome do arquivo a ser aberto mov r1,#0 ; modo leitura swi 0x66 ; abre arquivo para leitura bcs InFileError ; se houver erro ldr r1,=InFileHandle ;carrega handle de arquivo para leitura str r0,[r1] ; salva o handle ldr r0,=InFileHandle ldr r0,[r0] swi 0x6c ;lê inteiro do arquivo aberto bcs ReadError ReadError: swi 0x68
Exemplo 3:
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 9:
NomeArqEntrada: .asciz "ArqEntrada1.txt"
ErroArqEntrada: .asciz "Não foi possível abrir\n"
ArqEntrHandle:.word 0
.align
NomeArqSaida: .asciz "ArqSaida.txt"
ArqSaidaHandle: .word 0
Saidasoma: .asciz "Soma = "
Saidasub: .asciz "Subtracao = "
Saidamult: .asciz "Multiplicacao = "
Saidadiv1: .asciz "Divisao = "
Saidadiv2: .asciz "; Resto = "
Saidafim: .asciz "Fim\n"
;**** ABRE ARQUIVO DE ENTRADA PARA LEITURA
mov r1,#0 ; abre arquivo, modo leitura (0)
ldr r0,=NomeArqEntrada ; configura o nome do arquivo a ser aberto
swi 0x66 ; abre arquivo para leitura
bcs HouveErro ; se houver erro
ldr r1,=ArqEntrHandle
str r0,[r1]
swi 0x6c ;lê inteiro do arquivo aberto. Handle tem que estar em R0. Após-> R0 = inteiro
mov r4,r0 ; move inteiro lido para R4 - operação da calculadora selecionada!!!
;FECHA ARQUIVO DE ENTRADA
ldr r1,=ArqEntrHandle
ldr r0,[r1]
swi 0x68 ; fechar arquivo
;***** ABRIR ARQUIVO DE SAÍDA PARA IMPRIMIR RESULTADOS
mov r1, #1 ; abrir arq modo ESCRITA - append (adiciona sem apagar o que já tinha)
ldr r0, =NomeArqSaida; ; configura o nome do arquivo a ser aberto
swi 0x66 ;abre arq para escrita
bcs HouveErro ; se houver erro
ldr r1,=ArqEntrHandle
str r0,[r1]
ldr r1,=Saidasoma ;r1 = endereço da string de saída
swi 0x69 ;escreve string no arquivo
;******
mov r5,#6
mov r6,#2
mov r7,#0
cmp r4,#1
blt result
beq soma
;******
cmp r4,#2
beq subt
;******
cmp r4,#3
beq mult
;******
cmp r4,#4
bgt result
beq divisao
;******
soma: add r7,r5,r6
ldr r0,=Saidasoma ; address of a null terminated ASCII string
swi 0x02 ; Display String on Stdout
add r0,r7,#'0
swi 0x00 ;Display Character on Stdout
;*** Escreve resultados agora no arquivo de saída
ldr r9,=ArqSaidaHandle
ldr r0, [r9]
ldr r1,=Saidasoma ;R1 = address of string
swi 0x69 ;output string to file
mov r1, r7
swi 0x6b ;escreve o resultado no arquivo
b result
subt: sub r7,r5,r6
ldr r0,=Saidasub ; address of a null terminated ASCII string
swi 0x02 ; Display String on Stdout
add r0,r7,#'0
swi 0x00 ;Display Character on Stdout
ldr r9,=ArqSaidaHandle
ldr r0, [r9]
ldr r1,=Saidasub ;R1 = address of string
swi 0x69 ;output string to file
mov r1, r7
swi 0x6b ;escreve o resultado no arquivo
b result
mult: mul r7,r5,r6
ldr r0,=Saidamult ; address of a null terminated ASCII string
swi 0x02 ; Display String on Stdout
add r0,r7,#'0
swi 0x00 ;Display Character on Stdout
ldr r9,=ArqSaidaHandle
ldr r0, [r9]
ldr r1,=Saidamult ;R1 = address of string
swi 0x69 ;output string to file
mov r1, r7
swi 0x6b ;escreve o resultado no arquivo
b result
divisao: mov r8,r5
div2: subge r8,r8, r6
add r7, r7,#1
cmp r8,r5
bge div2
ldr r0,=Saidadiv1 ; address of a null terminated ASCII string
swi 0x02 ; Display String on Stdout
add r0,r7,#'0
swi 0x00
mov r0,#'\0
swi 0x00 ;Display Character on Stdout
ldr r0,=Saidadiv2 ; address of a null terminated ASCII string
swi 0x02 ; Display String on Stdout
add r0,r8,#'0
swi 0x00 ;Display Character on Stdout
ldr r9,=ArqSaidaHandle
ldr r0, [r9]
ldr r1,=Saidadiv1 ;R1 = address of string
swi 0x69 ;output string to file
mov r1, r7
swi 0x6b ;escreve o resultado no arquivo
b result
fim:
bcs HouveErro ; se houver erro
result:
;***** MONTA STRING RESULTADOS
ldr r1,=ArqSaidaHandle ; load the file handle
ldr r0,[r1]
swi 0x68 ; fechar arquivo
HouveErro: swi 0x68 ; fechar arquivo
O 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:
ASR, LSL, LSR, ROR e RRX - Instruções de deslocamento
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 Rd, Rf, Rn - realiza uma operação E bit-a-bit entre Rf e ~(Rn) e coloca o resultado em Rd. 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
Exemplos
AND R9, R2,#0xFF00 ORREQ R2, R0, R5 ANDS R9, R8, #0x19 EORS R7, R11, #0x18 BIC R0, R1, #0xab ORN R7, R11, R14, ROR #4 ORNS R7, R11, R14, ASR #32
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:
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:
mov r1, #16 mov r2, #36 loop cmp r1, r2 ; cmp sempre atualiza flags ble neg ; queremos testar se r1 > r2 subgt r1, r1, r2 ; se r1 > r2, faça r1:=r1-r2 bne loop neg ; senão teste por < sublt r2, r2, r1 ; se r1 < r2 faça r2:= r2 -r1 bne loop
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 | Livre para Periféricos Externos |
|
0x9FFFFFFF |
Livre para RAM Externa |
|
0x5FFFFFFF |
Periféricos definidos pelo fabricante do CHIP |
|
0x3FFFFFFF |
SRAM (Memória integrada no CHIP) |
|
0x1FFFFFFF |
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é 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.
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:
|
|
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 | op1 = op2 | 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 formdo 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
Aplicativo VISUAL (Arm)
Disponível para download em: Visual - IDE para programação ARM
Lista de instruções suportadas: INSTRUÇÕES ARM para Visual
Aplicativo 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
| << Página da disciplina | < Conjunto de instruções genéricas de microprocessador | Aula 6 - Conjunto de instruções do ARM | Estrutura e Funcionamento da CPU > |
|---|













