Sie sind auf Seite 1von 15

3

1. INTRODUÇÃO

Este trabalho tem por base mostrar as especificações e exemplos sobre


Pseudo – Instruções e OpCode, ambos trabalham de forma ordenada no qual
representa a memória e sua constante variável, no trabalho pode ser
encontrado varias formas e exemplos sobre o construindo na memória e no
processador.
4

2. PSEUDO-INSTRUÇÕES

Uma pseudo-instrução é uma diretiva que não pertence ao repertório de


instruções de um processador, mas leva um montador a tomar certas ações em
relação ao programa. Por exemplo, reservar espaço na Unidade de Memória
para dados (p.ex., DS), atribuir um valor a um endereço da Unidade de
memória (p.ex., DW) e controlar o endereço onde o programa deve ser
carregado (p.ex., ORG).

Além das instruções do processador, um programa assembly preparado


para um montador também pode conter pseudo-instruções que estabelecem a
conexão entre referências simbólicas e valores a serem efetivamente
referenciados. Cada montador pode oferecer um conjunto de pseudo-
instruções diferenciado. As pseudo-instruções descritas a seguir representam
um subconjunto significativo de facilidades oferecidas por montadores.

2.1 Exemplos de Código Size EQU e Move

A pseudo-instrução de substituição simbólica, EQU, associa um valor


definido pelo programador a um símbolo. Por exemplo, a linha de instrução

SIZE EQU 100

Associa o valor decimal 100 ao símbolo SIZE, que pode ser


posteriormente referenciado em outras instruções.

MOVE #SIZE, D0

Para essa pseudo-instrução, o rótulo deve estar sempre presente e o


operando pode ser qualquer expressão que, quando avaliada, defina o valor
para o símbolo. Essa expressão pode envolver outros símbolos já definidos.
5

A pseudo-instrução EQU define símbolos que serão usados durante o


processo de montagem, mas que não farão parte do módulo-objeto. Para
definir constantes para a execução do código, ou seja, que ocuparão algum
espaço em memória durante a execução do programa gerado, as pseudo-
instruções DC e DS devem ser usadas.

2.2 Pseudo - Instrução DC E DS

A definição de variável inicializada, isto é, com algum valor constante


definido no momento da alocação de espaço para a variável, dá-se através da
pseudo-instrução DC, como nos exemplos.

CONTADOR DC. L 100


ARR1 DC. W 0, 1, 1, 2, 3, 5, 8,13
MENSAGEM DC. B 'Alo, pessoal!'

O rótulo deve estar presente nessa instrução para permitir referenciar a


posição de memória de cada variável ao longo do código. O sufixo no código
de operação indica o tamanho em bytes para cada variável, seguindo o padrão
das instruções da família 68K. Assim, CONTADOR fará referência a uma
posição de memória cujos quatro bytes seguintes terão inicialmente a
representação para o valor 100. ARR1 é uma referência para a posição de
memória que dá início a um bloco contíguo de oito palavras de dois bytes, cada
uma delas com o valor especificado na posição correspondente no operando.

De forma similar, MENSAGEM faz referência ao início de um bloco de


treze bytes representados em ASCII no operando. Outra forma de reservar um
espaço de memória para armazenar valores é através da pseudo-instrução de
declaração de variáveis, DS, que reserva a quantidade de espaço indicada,
mas não inicializa seu conteúdo. Por exemplo.

VALUE DS. W 1
6

Associa ao símbolo VALUE uma referência para um endereço de memória


que tem espaço suficiente para armazenar valores de uma variável de tamanho
dois bytes (word).

2.3 Pseudo - Instrução ORG

A pseudo-instrução ORG determina a origem do segmento. Um segmento


é um conjunto de palavras de máquina que deve ocupar um espaço contíguo
na memória principal. A posição de memória (endereço) associada ao início do
segmento é denominada a sua origem. O módulo-objeto gerado pelo montador
contém tipicamente pelo menos dois segmentos, um segmento de código de
máquina e um segmento de dados.

O efeito da pseudo-instrução ORG depende do tipo de montador que irá


interpretá-la. Em alguns casos, pode ser uma definição de um endereço
absoluto de memória no qual a origem do segmento deve ser posicionada. Em
outros, é apenas a definição de um nome para referências futuras ao segmento
quando sua posição de origem for definida. A forma genérica aqui adotada para
a instrução será.

ORG ident

Onde ident é um identificador que pode ser um valor constante já definido


(no caso dos montadores absolutos) ou estar sendo definido como o nome de
um segmento (nos demais casos).

Por exemplo, no trecho de programa a seguir:

SEG1 EQU $1000


ORG SEG1
MOVE. W DATA, D0
MOVE. W D0, DATA+2
RTS
7

Indica que a primeira instrução MOVE. W (na terceira linha) estará


alocada à posição $1000 da memória, dando início ao segmento de código do
módulo-objeto que será gerado. Uma outra pseudo-instrução importante é
END, que indica ao montador o fim do programa assembly.

END ident

Onde o identificador no operando está associado a um rótulo do início do


programa que está sendo encerrado por essa pseudo-instrução. Assim, esse
identificador só deve estar presente uma única vez no código, mesmo que o
programa fonte esteja distribuído entre diversos arquivos -- em geral, está
associado a um módulo principal. Nos demais módulos, a pseudo-instrução
END aparece sem argumentos, sempre na última linha.

2.4 Pseudo - Instrução GLOB

No caso de um programa cujo código-fonte está distribuído entre diversos


segmentos, pode ser preciso fazer referências desde um segmento a variáveis
definidas em outros arquivos-fontes. Para possibilitar essa conexão de
referências, a pseudo-instrução GLOB é usada para indicar que cada um dos
símbolos indicados pode ser reverenciável externamente, ou seja, torna o
símbolo visível globalmente.

GLOB idents

Onde idents é a lista de identificadores (separados por vírgulas, se mais


de um estiver presente) definidos nesse segmento com a pseudo-instrução que
podem ser referenciados a partir de outros módulos. Os demais símbolos
definidos no segmento são considerados de escopo local, ou seja, são
invisíveis para os módulos externos. Alguns montadores definem pseudo-
instruções tais como EXTERN para indicar que o símbolo que está sendo
usado no módulo foi definido externamente, em outro módulo. No entanto, essa
pseudo-instrução é desnecessária se for assumido que todos os símbolos
referenciados.
8

3. LINGUAGEM ASSEMBLY

A linguagem Assembly de uma máquina costuma ser um reflexo direto de


como são implementadas as instruções de um determinado processador.
Entretanto, nem todas as instruções que temos à disposição quando
programamos em Assembly são instruções verdadeiras para o processador.

Algumas delas são na verdade pseudo-instruções. Pseudo-instruções


costumam ser substituídas pelo montador ao gerar instruções para o
computador na forma de Linguagem de Máquina. Pseudo-Instruções são na
verdade combinações de mais de uma instrução.

3.1 A Pseudo-Instrução Move

move $r1, $r2 # Copia o conteúdo do registrador $r2 para $r1

Ela é na verdade implementada da seguinte forma:

addu $r1, $r0, $r2 # Soma $r2 com zero e coloca o resultado em $r1

O registrador $r0 usado acima não é um registrador comum. Ele sempre


possui o valor "0" e é um dos poucos registradores cujo valor nunca pode ser
alterado pelo programador.

3.2 A Pseudo-Instrução Load Address

la $r1, ENDEREÇO # Coloca o valor numérico de 32 bits "ENDEREÇO" em


$r1

Esta instrução é muito útil para fazer registradores receberem o valor de


ponteiros para outros locais de memória. De fato, usamos esta pseudo-
instrução no capítulo anterior quando convertemos um código em C para o
Assembly do MIPS.
9

Ela é na verdade implementada desta forma:

lui $r1, constHI # Carrega-se os 16 bits mais significativos em $r1


ori $r1, $r0, constLO # Executa-se um OR bit-a-bit entre o registrador
# com os 16 bits mais significativos e os 16 bits
# menos significativos

O que a instrução lui, ou Load Upper Immediate faz é uma operação shift
de 16 bits para a esquerda e coloca no registrador indicado. Este passo é
necessário porque valores imediatos passados para instruções só podem ter
16 bits por causa da limitação de espaço das instruções do Tipo I.

Também existe a instrução li, ou Load Immediate que faz exatamente a


mesma coisa que o la. Note que o montador que remove as pseudo-instruções
e as substitui por instruções que realmente existem no hardware sempre
podem verificar se o valor que queremos carregar no registrador cabe em 16
bits. Neste caso, a instrução gerada fica bem mais simples e rápida:

addu $r1, $r0, $r2 # Soma $r2 com 0 e coloca em $r1


10

4. OPCODE

Opcode é a referência à instrução que um determinado processador


possui para conseguir realizar determinadas tarefas.

Suas especificações e formatos são definidos no conjunto de instruções


da arquitetura do processador em questão (que pode ser um processador geral
ou uma unidade de tratamento mais especializado). Algumas ISAs (normas)
tem instruções que definem campos para opcodes e operandos, enquanto
outras (e.g. a arquitetura Intel x86) tem uma das mais complicadas integradas
estruturas. É a porção de uma instrução de linguagem de máquina que
especifica a operação a ser realizada. Sua especificação e formato serão
determinados pela arquitetura do conjunto de instruções (ISA) do componente
de hardware de computador - normalmente um CPU, mas possivelmente uma
unidade mais especializada. Uma instrução completa de linguagem de máquina
contém um opcode e, opcionalmente, a especificação de uns ou mais operando
s - sobre os que a operação deve atuar. Algumas operações têm operandos
implícitos, ou de fato nenhum. Algumas ISAs tem instruções com campos
definidos para os opcodes e operandos, enquanto outras (ej. a arquitectura
Intel x86) têm uma estrutura mais complicada e de propósito específico.

Os operandos sobre os quais os opcodes aplicam podem, dependendo da


arquitetura do CPU, consistir de. Registros, valores em Memória primária
memória, valores armazenados na pilha, portos de I/Ou, autocarro, etc. As
operações que um opcode pode especificar podem incluir aritmética, cópia de
dados, operações lógicas, e controle do programa. Os opcodes também podem
ser encontrados nos bytecodes interpretados por um interpretador de código de
byte (ou a máquina virtual, em um sentido desse termo). Nestes, uma
arquitetura de conjunto de instruções é criada para ser interpretada por
software em vez de um dispositivo de hardware. Com freqüência, os
interpretadores de código de byte trabalham com tipos de dados e operações o
mais alto nível, que o de um conjunto de instruções por hardware, mas são
construídas ao longo de linhas similares.
11

Exemplos incluem a máquina virtual de Java (JVM) da linguagem de


programação Java, o código de byte usado em GNU Emacs para o código
compilado de LISP, e muitos outros.

4.1 Processador Microcontrolador

Apenas instruções pré-informadas que são os Opcodes. O que não é um


Opcode é um código que não é possível efetuar a identificação pelo
processador ou pelo sistema. De entre as funções principais do processador.

Lógico - Instruções de condição e tomada de decisão. Representam em


média, 14% a 20% de todos os programas para plataformas com arquitetura
x86 para desktops. Devido à tomada de decisão ser algo "comum" em todos os
programas, o Pentium D foi um dos processadores que a Intel mais teve
prejuízos em desempenho. O Pentium D conta com mais de 20 estágios de
pipeline muito mais que processadores da linha anterior, para conseguir
resolver mais instruções em apenas 1 passagem, porém, as instruções ficam
esperando uma tomada de decisão para poderem passar pelo controle de
Branch e serem processadas.

Um exemplo de uma instrução de decisão em nosso cotidiano, é: "Ou


você estuda ou você faz outra coisa." Se você estuda, é um caso, se é outra
coisa, é outro caso. Você tem atividades diferentes para cada caso. O
processador, e os programas, também.
Aritmético - O lugar onde o processador realiza as contas de soma, diferença,
multiplicação e inversão. O processador não sabe fazer mais nada além destas
4 funções.

Load Constant - Carrega variáveis constantes na memória, ou seja, são


variáveis do tipo read-only (somente leitura), e nunca terão seus valores
alterados, até desligar o computador ou até finalizar o programa. Como
exemplo, a constante matemática Pi (π = 3,1415926...) possui um valor fixo
que não pode ser alterado.
12

Load and Store - Carrega em memória, um volume com informações das


variáveis, onde possuem dados que estão sendo manipulados ou não read-
only (somente leitura).

Branch - Formulado inicialmente pela Intel, o controle de Branch é um sistema


que determina antes de realizar as operações, resultados com base de
instruções pré-gravadas com resultados das instruções enviadas ao
processador. No caso, o Opcode enviado. As instruções de Branch são as
responsáveis por tratar das informações que estão sendo processadas, ou que
serão processadas, ou que já foram processadas (que passam pelo Pipeline).

Sistema - O processador mantêm um controle sobre o sistema, ao ponto de


criar e dimensionar suporte para ACPI (funções como desligar ou ligar o
computador) ou AHCI (placas controladoras SATA identificadas como IDE ao
sistema operacional), e outras funções similares como agendar um Wake
Event.

4.2 OpCode Para X86

Processador Intel/AMD/Outro plataforma x86 com nomes indiretos da


programação em Assembler.

Área do Processador, aritmético (co-processador).

add dst,src1,src2
sub dst,src1,src2
mul dst,src1,src2
inc dst,const8
13

Load constant
lc dst,const8
Bitwise/Logical

Unidade Lógica ou ULA


and dst,src1,src2
nor dst,src1,src2
shf dst,src1,src2

Load and store


ld1 dst,base,uconst4
st1 src,base,uconst4

Branch
beq tgt,src1,src2
bgt tgt,src1,src2
jmp uconst8

System
hlt
in dst,channel
out src,channel

4.3 Formação do OpCode

Basicamente forma-se na cadeia do Assembler, já que é muito difícil


humanamente entendermos códigos de máquina. Vejamos.

Um número que começa com "0x" em linguagem C trata-se de um número


hexadecimal. Trataremos dele por ser mais compacto do que o binário e seria
até meio que sem lógica colocar um monte de zeros e uns aqui para explicar.

O código de máquina com o número: 0x83EF.


14

O número "8", significa o Opcode utilizado na elaboração da instrução;


O número "3", significa o valor da primeira variável do código Assembler;
O número "E", significa o valor da segunda variável do código Assembler;
O número "F", significa o valor da terceira variável do código Assembler;

Um exemplo de soma em Assembler:

add r3, r14, r15

O "r3", "r14" e "r15" referem-se a um espaço armazenado na memória,


sendo que "r3" será a resposta da soma. Imaginando que, utilizando o opcode
"ld" para carregar na memória um número "5" para "r14" e um número "1" para
"r15", o resultado de "r3" seria exatamente o resultado da soma, que é "6".
15

5. BIBLIOGRAFIA

http://www.dca.fee.unicamp.br/cursos/EA876/apostila/HTML/node82.html

http://www.dca.fee.unicamp.br/~ting/Courses/ea869/faq5.html

http://pt.wikibooks.org/wiki/Introdu%C3%A7%C3%A3o_
%C3%A0_Arquitetura_de_Computadores/%C3%8Dndice/As_Pseudo-Instru
%C3%A7%C3%B5es

Harvard College (Faculdade de Harvard, Massachusets)


http://www.fas.harvard.edu/~cs50/podcasts/2007/lectures/week8.pdf

Aristóteles Machado, Cientista da Computação:


http://www.aristotelesmachado.com.br/

http://pt.wikilingue.com/es/Opcode
16

6. CONCLUSÃO

A Linguagem de maquina é assembly é complicada para seres humanos


programarem nela diretamente, então se a abstração conseguida por uma
linguagem de programação de alto-nivel não é desejada, uma linguagem
assembly é usada. Aqui, intruções mnemônicas são usadas que correspondem
ao opcode e as especificações do operando da instrução em linguagem de
máquina gerada. Ela dá um grande nível de legibilidade e compressibilidade
que trabalhando com as operações em linguagem de máquina diretamente,
enquanto continua dando controle apurado da linguagem de máquina gerada,
um programa chamado assembler transforma a linguagem assembly em código
de máquina.
17

SUMARIO