Você está na página 1de 202

Assembly para o Assemblador da GNU Arquitectura Intel IA-32

Verso 0.4 a

Filipe Machado de Arajo u Outubro de 2005

Assembly para o Assemblador da GNU Arquitectura Intel IA-32


Verso 0.4 a

UNIVERSIDADE DE LISBOA FACULDADE DE CIENCIAS DEPARTAMENTO DE INFORMATICA

Filipe Machado de Arajo u Lisboa Outubro de 2005

Agradecimentos
Agradeo ao Professor Vasco Vasconcelos pelas importantes indicaes que c co tornaram o texto mais rigoroso. Agradeo tambm ao Dr. Alexandre Pinto e ` Dr.a Teresa Chambel c e a que ajudaram na reviso de alguns cap a tulos e contribu ram com algumas sugestes. o As gralhas e os erros que existirem so todos da minha responsabilidade a e no da deles. a Lisboa, Outubro de 2005 Filipe Machado de Arajo u

Indice
1 Assembly 1.1 1.2 1.3 1.4 1.5 Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ca Pressupostos . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vantagens e Desvantagens do Assembly . . . . . . . . . . . . . Assemblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . Compilao vs. Assemblagem . . . . . . . . . . . . . . . . . . ca 1 1 3 5 7 9 11

2 Arquitectura 2.1 2.2

Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 ca Registos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.2.1 2.2.2 2.2.3 2.2.4 Registos de Utilizao Geral . . . . . . . . . . . . . . . 13 ca Registo de Segmento ou Selectores . . . . . . . . . . . 14 Registo Contador de Programa . . . . . . . . . . . . . 15 Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.3 2.4

Conjunto de Instrues Abstractas . . . . . . . . . . . . . . . 18 co Simbologia e Nomenclatura . . . . . . . . . . . . . . . . . . . 18 27

3 Endereamento c 3.1 3.2

Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 ca Conceitos Bsicos . . . . . . . . . . . . . . . . . . . . . . . . . 27 a i

3.3 3.4

Diviso em segmentos a

. . . . . . . . . . . . . . . . . . . . . . 30

Modos de endereamento . . . . . . . . . . . . . . . . . . . . . 34 c 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 Endereamento literal ou imediato c . . . . . . . . . . . 35

Endereamento por Registo . . . . . . . . . . . . . . . 35 c Endereamento Directo . . . . . . . . . . . . . . . . . . 36 c Endereamento Indirecto por Registo . . . . . . . . . . 36 c Endereamento Relativo ` Base . . . . . . . . . . . . . 37 c a Endereamento Indexado Directo . . . . . . . . . . . . 37 c Endereamento Indexado ` Base . . . . . . . . . . . . . 38 c a Endereamento Indexado . . . . . . . . . . . . . . . . . 39 c

3.5

Pilha . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 45

4 Instrues Gerais co 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9

Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 ca Instruo mov . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 ca Instruo xchg . . . . . . . . . . . . . . . . . . . . . . . . . . 50 ca Instruo nop . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 ca Instruo lea . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 ca Instrues lds, les, lfs, lgs e lss . . . . . . . . . . . . . . . 54 co Instrues push e pop . . . . . . . . . . . . . . . . . . . . . . . 57 co Instrues pusha e popa . . . . . . . . . . . . . . . . . . . . . 60 co Instrues pushf e popf . . . . . . . . . . . . . . . . . . . . . 61 co 63

5 Instrues de Controlo de Fluxo co 5.1 5.2 5.3 5.4

Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 ca Instruo jmp . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 ca Rtulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 o Saltos Condicionais Instruo jcc . . . . . . . . . . . . . . 66 ca ii

5.5 5.6 5.7

Instruo cmp . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 ca Instrues loop e loopcc . . . . . . . . . . . . . . . . . . . . . 69 co Instrues std, cld, sti, cli, stc, clc, cmc . . . . . . . . . . 71 co 75

6 Instrues Aritmticas co e 6.1 6.2 6.3 6.4

Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 ca Adio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 ca Subtraco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 ca Multiplicao . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 ca 6.4.1 6.4.2 Multiplicao Sem Sinal . . . . . . . . . . . . . . . . . 80 ca Multiplicao Com Sinal . . . . . . . . . . . . . . . . . 81 ca

6.5 6.6 6.7 6.8 6.9

Diviso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 a Extenso de Nmeros Com Sinal . . . . . . . . . . . . . . . . 84 a u Incrementao e Decrementao . . . . . . . . . . . . . . . . . 87 ca ca Negao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 ca Restries `s operaes aritmticas . . . . . . . . . . . . . . . 87 co a co e 89

7 Operaes com bits co 7.1 7.2 7.3 7.4 7.5

Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 ca Instrues and, or e xor . . . . . . . . . . . . . . . . . . . . . 89 co Instrues sar, shr, sal e shl . . . . . . . . . . . . . . . . . . 92 co Instrues rcl, rcr, rol e ror . . . . . . . . . . . . . . . . . . 95 co Instruo test . . . . . . . . . . . . . . . . . . . . . . . . . . 96 ca 99

8 Denio de Dados ca 8.1 8.2 8.3

Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 ca S mbolo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 Tipos e Tamanhos . . . . . . . . . . . . . . . . . . . . . . . . 100 8.3.1 Nmeros inteiros . . . . . . . . . . . . . . . . . . . . . 100 u iii

8.3.2 8.3.3 8.3.4 8.3.5 8.3.6 8.4 8.5

Ponteiros . . . . . . . . . . . . . . . . . . . . . . . . . 102 Cadeias de Caracteres (Strings) . . . . . . . . . . . . . 104 Nmeros de V u rgula Flutuante . . . . . . . . . . . . . . 105 Vectores e Tabelas . . . . . . . . . . . . . . . . . . . . 106 Declarao de Dados No Inicializados . . . . . . . . . 109 ca a

Ambito dos s mbolos (Locais vs. Globais) . . . . . . . . . . . . 109 Seces de Dados . . . . . . . . . . . . . . . . . . . . . . . . . 110 co 115

9 Funes co 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9

Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 ca Diviso de um Programa em Funes . . . . . . . . . . . . . . 115 a co Necessidade e Utilidade das Funes co . . . . . . . . . . . . . . 117

Instruo call . . . . . . . . . . . . . . . . . . . . . . . . . . 118 ca Instruo ret . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 ca Cdigo das Funes . . . . . . . . . . . . . . . . . . . . . . . . 121 o co Variveis Locais . . . . . . . . . . . . . . . . . . . . . . . . . . 125 a Passagem de Parmetros para uma Funo . . . . . . . . . . . 130 a ca Retorno de Valores duma Funo . . . . . . . . . . . . . . . . 136 ca

9.10 Instruo enter . . . . . . . . . . . . . . . . . . . . . . . . . . 141 ca 9.11 Instruo leave . . . . . . . . . . . . . . . . . . . . . . . . . . 143 ca 10 Bibliotecas de funes co 145

10.1 Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 ca 10.2 Bibliotecas Dinmicas . . . . . . . . . . . . . . . . . . . . . . 148 a 10.3 Ferramentas de Manipulao de Bibliotecas ca . . . . . . . . . . 150

10.4 Biblioteca do C . . . . . . . . . . . . . . . . . . . . . . . . . . 152 10.4.1 Funo printf() . . . . . . . . . . . . . . . . . . . . . 152 ca 10.4.2 Funo scanf() . . . . . . . . . . . . . . . . . . . . . . 153 ca iv

10.4.3 Funo getchar() . . . . . . . . . . . . . . . . . . . . 154 ca 10.4.4 Exemplo de Utilizao das Funes da Biblioteca do C 154 ca co 11 Interrupes e Chamadas ao Sistema co 159

11.1 Interrupes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 co 11.2 Instruo int . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 ca 11.3 Instruo iret . . . . . . . . . . . . . . . . . . . . . . . . . . 166 ca 11.4 Instruo cli . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 ca 11.5 Instruo sti . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 ca 11.6 Chamadas ao Sistema 12 Exemplos de Programas . . . . . . . . . . . . . . . . . . . . . . 168 175

12.1 Programa Ol Mundo . . . . . . . . . . . . . . . . . . . . . . . 175 a 12.2 Programa Soma 100 primeiros . . . . . . . . . . . . . . . . . . 176 12.3 Programa Opera dois nmeros . . . . . . . . . . . . . . . . . . 177 u References 183

vi

Lista de Figuras
1.1 1.2 Construo de um executvel a partir do assembly . . . . . . . ca a Construo de um executvel a partir de uma linguagem de ca a alto n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 vel 2.1 2.2 2.3 2.4 2.5 3.1 3.2 3.3 3.4 3.5 3.6 4.1 Registos de utilizao geral . . . . . . . . . . . . . . . . . . . . 13 ca Registos de segmentos ou selectores . . . . . . . . . . . . . . . 15 Representao do registo eip . . . . . . . . . . . . . . . . . . 16 ca Exemplo de utilizao do registo eip . . . . . . . . . . . . . . 16 ca Representao do registo eflags . . . . . . . . . . . . . . . . 17 ca Representao de uma memria com 16 K . . . . . . . . . . . 28 ca o byte, palavra e longo . . . . . . . . . . . . . . . . . . . . . . . 30 Traduo de um endereo de 48 bits num endereo virtual . . 32 ca c c Exemplo de endereamento indexado . . . . . . . . . . . . . . 40 c Descartar e reservar espao na pilha . . . . . . . . . . . . . . . 42 c Acesso a parmetros e variveis locais dentro duma funo . . 42 a a ca Valor armazenado em memria, no endereo designado por o c numero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 4.2 4.3 4.4 Resultado da instruo lea ca . . . . . . . . . . . . . . . . . . . 53 8

Ponteiro de 48 bits para a instruo lds . . . . . . . . . . . . 55 ca Instruo push . . . . . . . . . . . . . . . . . . . . . . . . . . 58 ca vii

4.5 6.1 6.2 7.1 7.2 8.1 8.2 8.3 8.4 8.5 8.6 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8

Instruo pop . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 ca Subtraco em complementos para 2 . . . . . . . . . . . . . . 79 ca Exemplos de utilizao da instruo imul . . . . . . . . . . . . 83 ca ca Exemplo de cada uma das operaes lgicas . . . . . . . . . . 91 co o Operaes rol, ror, rcl e rcr . . . . . . . . . . . . . . . . . . 96 co Denio de um ponteiro . . . . . . . . . . . . . . . . . . . . . 103 ca Representao em memria das cadeias de caracteres . . . . . 105 ca o Diferena entre vector e tabela . . . . . . . . . . . . . . . . . . 106 c Endereos relativos das clulas do horrio . . . . . . . . . . . . 108 c e a Agrupamento das vrias seces dum programa . . . . . . . . 112 a co Seces de um programa . . . . . . . . . . . . . . . . . . . . . 113 co Funcionamento das instrues call e ret . . . . . . . . . . . . 120 co Utilizao de variveis locais na pilha . . . . . . . . . . . . . . 128 ca a Funo com muitas variveis locais . . . . . . . . . . . . . . . 130 ca a Passagem de parmetros pela pilha . . . . . . . . . . . . . . . 132 a Parmetros passados pela pilha . . . . . . . . . . . . . . . . . 135 a Devoluo de resultados pela pilha . . . . . . . . . . . . . . . 137 ca Devoluo de resultados pela pilha com existncia de parmetros140 ca e a Passagem de parmetros por referncia . . . . . . . . . . . . . 142 a e

10.1 Construo e execuo dum programa que utiliza uma bibca ca lioteca esttica . . . . . . . . . . . . . . . . . . . . . . . . . . 149 a 10.2 Construo e execuo dum programa que utiliza uma bibca ca lioteca dinmica . . . . . . . . . . . . . . . . . . . . . . . . . . 149 a 11.1 Acesso ` tabela de descritores de interrupo . . . . . . . . . . 162 a ca viii

11.2 Encadeamento de controladores de interrupes . . . . . . . . 165 co

ix

Lista de Tabelas
1.1 2.1 2.2 2.3 3.1 4.1 4.2 4.3 4.4 5.1 5.2 6.1 6.2 6.3 6.4 6.5 Codicao da linguagem assembly em linguagem mquina . . ca a 7

Descrio das ags mais importantes . . . . . . . . . . . . . . 22 ca Lista das instrues abstractas . . . . . . . . . . . . . . . . . . 23 co Denio de s ca mbolos e nomes . . . . . . . . . . . . . . . . . . 25 Registos de segmento ou selectores . . . . . . . . . . . . . . . 34 Tipos de operandos . . . . . . . . . . . . . . . . . . . . . . . . 47 Restries aos operandos na instruo mov . . . . . . . . . . . 49 co ca Restries aos operandos na instruo xchg . . . . . . . . . . . 51 co ca Restries aos operandos na instruo lea . . . . . . . . . . . 53 co ca Instrues de salto condicional . . . . . . . . . . . . . . . . . . 72 co Instrues para alterao das ags co ca . . . . . . . . . . . . . . . 73

Dimenso das operaes mul e imul . . . . . . . . . . . . . . . 80 a co Operaes div e idiv . . . . . . . . . . . . . . . . . . . . . . . 84 co Exemplos de extenses realizadas correcta e incorrectamente . 85 o Instrues para extenso de nmeros com sinal . . . . . . . . . 86 co a u Restries aos operandos nas instrues aritmticas multiplicao, co co e ca diviso, adio e subtraco . . . . . . . . . . . . . . . . . . . 88 a ca ca xi

7.1 7.2 7.3 8.1 8.2 8.3 8.4 9.1 9.2 9.3

Operao lgica and . . . . . . . . . . . . . . . . . . . . . . . 90 ca o Operao lgica or . . . . . . . . . . . . . . . . . . . . . . . . 90 ca o Operao lgica xor . . . . . . . . . . . . . . . . . . . . . . . . 90 ca o Tipos de nmeros inteiros . . . . . . . . . . . . . . . . . . . . 101 u Tipos de nmeros inteiros . . . . . . . . . . . . . . . . . . . . 101 u Tipos de cadeias de caracteres . . . . . . . . . . . . . . . . . . 104 Tipos de nmeros de v u rgula utuante . . . . . . . . . . . . . 105 Tipos de nmeros inteiros . . . . . . . . . . . . . . . . . . . . 129 u Acesso `s variveis locais e aos parmetros . . . . . . . . . . . 132 a a a Registos a utilizar na devoluo de resultados . . . . . . . . . 136 ca

10.1 Execuo do comando nm /lib/libc.so.6 . . . . . . . . . . . 151 ca 11.1 Tabela de interrupes e excepes em modo protegido . . . . 164 co co 11.2 Correspondncia entre IRQs e nmeros vector de interrupo . 165 e u ca

xii

Assembly
1.1 Introduo ca

De todos os elementos que compem um computador o mais importante , o e sem dvida, a unidade central de processamento (CPU Central Processing u Unit), tambm designada simplesmente por processador. e O processador um complexo circuito electrnico digital integrado, capaz e o de executar sequncias de instrues. O conjunto destas instrues e respectie co co vas regras de utilizao compem a linguagem que o processador compreende ca o e capaz de executar, que designada por linguagem ou cdigo mquina. e e o a A programao directa em linguagem mquina extremamente penosa e ca a e demorada para um ser humano, porque as instrues e os operandos so repco a resentados como nmeros inteiros, o que signica que um programa nesta linu guagem uma lista, eventualmente longa, de nmeros inteiros. Para resolver e u este problema existe uma linguagem alternativa com as mesmas instrues, co mas representadas por mnemnicas em vez de nmeros inteiros. O mesmo o u se passa com os operandos que, a menos que sejam precisamente nmeros, u so designados por mnemnicas. No caso das operaes mais complexas as a o co mnemnicas que representam operandos podem ser combinadas. No entanto, o o resultado ser sempre mais percept do que aquele que seria poss com a vel vel uma simples representao numrica. ca e 1

CAP ITULO 1. ASSEMBLY Note-se que, normalmente, haver uma traduo directa de todas as ina ca

strues assembly em instrues do processador. Por esta proximidade que co co existe entre a linguagem mquina e a linguagem assembly esta ultima cata e egorizada como linguagem de baixo n vel. Esta categoria est em oposio ` a ca a das linguagens de alto n vel, onde se incluem o Pascal, C, Java, etc. Nestas, no tem que existir qualquer correspondncia directa entre as respectivas ina e strues e operandos e as instrues e operandos do processador. Nem seria, co co alis, desejvel que essa correspondncia existisse. a a e E de realar ainda, que no existe apenas uma unica linguagem assembly c a poss vel, mas muitas diferentes. Se este facto mais ou menos evidente no e caso em que se consideram processadores diferentes 1 , que tm instrues e co diferentes, menos evidente quando o processador em causa o mesmo. e e Mas, na verdade, para o mesmo processador podem existir vrias linguaa gens assembly, por motivos que se relacionam com a existncia de sistemas e operativos e fabricantes de software diferentes que produzem assembladores incompat veis entre si. As linguagens assembly diferem entre si essencialmente na sintaxe das operaes co
2

porque, geralmente, as mesmas instrues usam mnemnicas co o

idnticas ou, pelo menos, parecidas. Os operandos que so representados por e a uma certa ordem podem aparecer trocados noutro assemblador, por exemplo. Um caso concreto que ilustra este facto o MASM Microsoft Assembler e que usa a sintaxe Intel, em que os operandos aparecem pela ordem inversa relativamente ` sintaxe AT&T usada pelo Gas. a
Ainda assim h assembladores, como sejam o Gas Gnu Assembler, de que falaremos a adiante que produzem cdigo para processadores diferentes e que concretizam alguma o independncia em relao ` plataforma (microprocessador + sistema operativo). e ca a 2 Outro aspecto em que no propriamente as linguagens, mas os assembladores que a as interpretam diferem consideravelmente nas directivas, que aparecem muitas vezes e misturadas com o cdigo na linguagem assembly. o
1

1.2. PRESSUPOSTOS

De qualquer forma, para um mesmo processador todas as instrues duma co linguagem assembly encontram correspondncia com as instrues das outras e co linguagens assembly. Neste texto vai ser considerada a utilizao da linguagem assembly para o ca assemblador Gas, para a arquitectura de 32 bits da Intel, designada de IA-32 (Intel Architecture), que se iniciou com o processador 80386 3 . O sistema operativo considerado, sempre que este aspecto for relevante o Unix e mais e particularmente o Linux.

1.2

Pressupostos

Quando um programador decide utilizar assembly tem que possuir um conjunto prvio de conhecimentos. e Em primeiro lugar, tem que ter algum

conhecimento da arquitectura da mquina. Este conhecimento inclui as ina strues existentes, os registos e a organizao de memria. co ca o A organizao da memria, por exemplo, abrange a questo de saber se ca o a a memria linear ou segmentada e que tamanho tm os segmentos. Estes o e e aspectos so relevantes porque, nalgumas plataformas, necessrio denir a e a os segmentos dum programa de tal forma que o cdigo seja arrumado num o segmento, os dados noutro(s) e a pilha ainda noutro. Era, por exemplo, o caso da programao em assembly para o sistema operativo MS-DOS. No ca Unix a situao ligeiramente diferente, como se ver no cap ca e a tulo 8. Este e o tipo de problemas que normalmente passam completamente despercebidos
O primeiro processador da Intel de 32 bits foi o 80386. No entanto, a Intel considera que a arquitectura IA-32 se iniciou antes, remontando ao 8086. Isto deve-se ao facto de haver uma linha de continuidade entre este processador e os mais recentes processadores desta arquitectura que mantm sempre retrocompatibilidade. Retrocompatibilidade sige nica que o mais moderno dos Pentium consegue correr cdigo mquina escrito para o o a 8086. Mesmo os processadores Itanium da prxima gerao, os primeiros pertencentes ` o ca a arquitectura IA-64, de 64 bits, vo manter esta capacidade. a
3

CAP ITULO 1. ASSEMBLY

a um programador duma linguagem de alto n vel. Outro problema relevante para quem programa em assembly tem a ver com os registos. Tambm aqui o programador precisa de saber quantos regise tos tem dispon veis e o que poss fazer com cada um deles. O contraponto e vel so mais uma vez as linguagens de alto n onde esta questo nem sequer a vel a se pe o programador limita-se a denir variveis e a utiliz-las sem saber o a a quando, onde e se h correspondncia com os registos. a e No que diz respeito `s instrues mais uma vez necessrio saber o que a co e a e ou no poss fazer com uma instruo ou o que requer mltiplas instrues, a vel ca u co estando muitas vezes em jogo, em caso de se tomar uma deciso errada, o a desempenho do programa. Outro tipo de situaes em que particularmente relevante o conhecco e imento profundo da arquitectura, quando se escreve um programa em assembly e estes so precisamente os casos em que a utilizao do assema ca bly muitas vezes mais se justica pe-se para realizar o controlo de um o perifrico ou para sincronizar duas tarefas diferentes, por exemplo. e Outro aspecto que exige um grande dom nio por parte do programador diz respeito ` utilizao das bases de numerao binria e hexadecimal por a ca ca a um lado e ` representao dos diversos tipos de dados em memria. Este a ca o tipo de conhecimento mostra-se relevante muito mais vezes do que seria de calcular, especialmente quando necessrio fazer a depurao do programa e a ca com as respectivas inspeces ao contedo da memria, que essa actividade co u o normalmente implica. Finalmente, uma palavra para a organizao do programador propriaca mente dita. Dada a pouca estruturao da linguagem especialmente imporca e tante que o programa seja cuidadosamente organizado em termos de funes, co mdulos e denies de variveis, sob pena de se tornar incompreens e o co a vel

1.3. VANTAGENS E DESVANTAGENS DO ASSEMBLY

imposs de depurar ou alterar. Este muitas vezes o ponto que separa o vel e programador experimentado do principiante.

1.3

Vantagens e Desvantagens do Assembly

Actualmente, quando um programador decide escrever um programa opta, normalmente, por uma linguagem de alto n vel. Nem sempre assim foi, mas o conjunto dos prs e dos contras quando pesado tende a favorecer uma o linguagem como o C em detrimento do assembly. Uma das maiores vantagens do assembly era a velocidade, mas esse factor tende a tornar-se irrelevante a cada nova gerao de microprocessadores, ca cada vez mais rpidos. Outra das vantagens do assembly prende-se com a a capacidade que a linguagem oferece para aceder directamente aos recursos de hardware da mquina, o que nem sempre sucede nas linguagens de alto n a vel. Igualmente, num programa escrito em assembly, poss ao programador e vel ter um controlo rigoroso do tempo de execuo, pois ele/a) que escolhe ca e as instrues de linguagem mquina e tem possibilidade de saber quanto co a tempo leva cada uma delas a executar-se. O acesso directo ao hardware e o controlo do tempo de execuo fazem do assembly uma opo a considerar (ou ca ca simplesmente a unica opo) para escrever determinados fragmentos cr ca ticos de cdigo, especialmente, cdigo do prprio sistema operativo 4 . o o o Ainda outra vantagem da linguagem assembly consiste na possibilidade de se escrever cdigo especializado na interface entre mdulos escritos em o o linguagens de alto n diferentes e que utilizam interfaces incompat vel veis. O ultimo argumento favorvel ao assembly tem a ver com a natureza hu a mana: muitos programadores consideram muito mais compensador escrever
Note-se que os sistemas operativos actuais so escritos em linguagens de alto n a vel. Por exemplo, o Linux quase todo escrito em C. e
4

CAP ITULO 1. ASSEMBLY

cdigo em assembly, onde a proximidade com a mquina muito maior, do o a e que numa linguagem de alto n vel. As desvantagens, por outro lado, so mais numerosas e signicativas. a Talvez por estes motivos o assembly no praticamente utilizado nos proa e gramas actuais, seno em pequenas seces de cdigo, que se revelem fundaa co o mentais para o desempenho global. Em primeiro lugar, o assembly uma linguagem pouco estruturada. Isto e signica que se exige do programador um esforo de organizao adicional, c ca sob pena de se tornar imposs vel manter um programa (i.e., corrigi-lo ou adicion-lo). a Outro dos problemas do assembly, que est relacionado com este, prendea se com o elevado nmero de instrues que so necessrias para fazer qualquer u co a a tarefa. Isto signica que a programao trabalhosa e muito propensa a erca e ros, ao ponto de se perder mais tempo com detalhes inerentes ` linguagem a do que com os problemas propriamente ditos. Isto, porque tambm muito e e complicado fazer a depurao dos erros dum programa escrito em assemca bly mais do que numa linguagem de alto n vel, onde ` partida ocorrem a muito menos erros, porque alguns deles so imediatamente detectados pelo a compilador. Estes so, sem dvida, defeitos de peso. a u Um outro problema do assembly prende-se com a portabilidade, que e pouca ou nenhuma. Um programa escrito em assembly para uma dada plataforma dicilmente pode ser transportado para uma plataforma diferente. Este facto est em tudo relacionado com a necessidade de conhecer a pormenorizadamente a arquitectura em que se est a programar. Note-se a que esta situao de certa forma contrria ` abstraco que normalmente ca e a a ca se deseja na resoluo de um problema qualquer. ca

1.4. ASSEMBLADOR

1.4

Assemblador

Como no se agura fcil ao programador xar ou consultar numa tabela toa a dos os cdigos das instrues de linguagem mquina de um microprocessador, o co a bem como os respectivos operandos e comprimentos (em nmero de bytes), u existem programas chamados assembladores para resolver o problema. Um assemblador permite designar as instrues e respectivos operandos por co mnemnicas em vez de nmeros inteiros. O programa ento escrito como o u e a uma lista de mnemnicas que so depois traduzidas pelo assemblador para o a linguagem mquina. Note-se que se trata duma traduo directa, i.e., ao a ca assemblador no compete pelo menos em teoria nenhuma tarefa de a compilao ou sequer de optimizao (veja-se a seco 1.5). ca ca ca A tabela 1.1 pretende ilustrar a diferena entre linguagem assembly e c linguagem mquina. Para isso apresentado um pequeno programa em asa e sembly e a respectiva codicao em linguagem mquina. Na primeira coluna ca a da tabela est representado o endereo de memria onde se encontra a ina c o struo, na segunda a dimenso da instruo, depois a sua mnemnica e ca a ca o nalmente a instruo correspondente e respectivos operandos em linguagem ca mquina (em hexadecimal). a Endereo c 0x8048440 0x8048443 0x8048446 0x8048448 Dimenso a 3 3 2 1 Mnemnica o movl 0x8(%ebp), %ebx movl 0xc(%ebp), %eax addl %ebx, %eax ret Linguagem Mquina a 0x8b5d08 0x8b450c 0x01d8 0xc3

Tabela 1.1: Codicao da linguagem assembly em linguagem mquina ca a

A assemblagem no , no entanto, o unico processo pelo qual um proa e grama em assembly tem que passar antes de se tornar num executvel. Desde a o seu in so necessrios os seguintes passos: cio a a

CAP ITULO 1. ASSEMBLY escrever o programa em assembly com recurso a um editor de texto. Guard-lo num cheiro de texto (com extenso s no caso do assema a blador Gas); assemblar o programa assim escrito. O resultado ser um cheiro oba jecto (usa-se o programa as Gas para este m); o(s) cheiro(s) objecto assim produzido(s) so editados pelo editor de a ligaes (linker, em ingls programa ld no Unix), que liga as vrias co e a referncias e recoloca os objectos, construindo no m desse processo e um cheiro executvel. a A gura 1.1 resume este processo.
Ficheiro Assembly (.s)

Assemblador (as )

Biblioteca(s) (opcional)

Ficheiro Objecto (.o)

Outro(s) Ficheiro(s) Objecto (opcional)

Editor de Ligaes (ld )

Ficheiro Executvel

Figura 1.1: Construo de um executvel a partir do assembly ca a

Para simplicar a tarefa do programador pode-se utilizar o compilador

1.5. COMPILACAO VS. ASSEMBLAGEM

de C, gcc. Este compilador permite fazer a assemblagem e/ou a ligao. ca Para isso, invoca os programas as e ld, fornecendo-lhes todos os parmetros a necessrios que no caso do ld no so triviais. Sendo assim, para criar um a a a executvel a partir dum cheiro de cdigo fonte assembly chamado ficheiro.s a o basta fazer gcc ficheiro.s. Se o cheiro contiver tudo o que for necessrio para constituir um proa grama, isto ser suciente para criar um cheiro executvel de nome a.out. a a

1.5

Compilao vs. Assemblagem ca

Pese embora o facto de no ser objectivo deste texto apresentar uma lina guagem de alto n vel, convm perceber o papel de um compilador na cone cepo dum programa e a diferena entre compilao e assemblagem. ca c ca Como j se disse, um assemblador faz a traduo directa de mnemnicas a ca o para cdigos de linguagem mquina. Pelo contrrio, um compilador tem o a a uma tarefa muito mais complexa, que consiste em construir um programa assembly, a partir do programa escrito numa linguagem de alto n 5 , com vel respectivas estruturas, instrues e tipos de dados, que podero ser arbitrarico a amente complicados. A complexidade de construir um programa em parte passada do proe gramador para o compilador embora, naturalmente, no seja este ultimo a a resolver os problemas propriamente ditos.
Isto no signica que todos os compiladores de todas as linguagens faam uma traduo a c ca da linguagem de alto n vel para assembly, antes de ser feita a traduo para linguagem ca mquina. Um bom exemplo duma situao diferente o compilador de Java, que passa a ca e o programa para uma linguagem de baixo n vel universal bytecode, que pode no ter a e provavelmente no ter correspondncia directa com qualquer linguagem assembly da a a e plataforma em questo. a
5

10

CAP ITULO 1. ASSEMBLY A gura 1.2 ilustra o papel do compilador na concepo dum programa. ca

Compare-se esta gura com a gura 1.1 que foi apresentada atrs. a
Linguagem de Alto Nvel (C)

Compilador (gcc )

Ficheiro Assembly (.s)

Assemblador (as )

Biblioteca(s) (opcional)

Ficheiro Objecto (.o)

Outro(s) Ficheiro(s) Objecto (opcional)

Editor de Ligaes (ld )

Ficheiro Executvel

Figura 1.2: Construo de um executvel a partir de uma linguagem de alto ca a n vel

Arquitectura
2.1 Introduo ca

Para um programa que utilize linguagens de alto n parecem existir essenvel cialmente dois n veis hierrquicos distintos de memria: primria e secundria a o a a ou, respectivamente, memria central (RAM Random Access Memory) e o disco. Na realidade existe um outro n vel de memria, mais prxima do o o processador do que as outras, utilizvel pelo programador de linguagem asa sembly: os registos 1 . Em termos breves, um registo uma clula de memria, identicada por e e o um nome, capaz de guardar um unico valor de cada vez. Consoante a arqui tectura do microprocessador pode haver mais ou menos registos, sendo que no 80386 h pouco mais do que 10, embora o nmero de registos suscept a u veis de serem manipulados livremente seja inferior a este. A vantagem de utilizar registos, em vez de usar directamente a memria esta na muito maior veo locidade de acesso. Esta alis uma questo relevante e que se tem vindo a a e a agravar ao longo dos anos: o desempenho do processador tem evolu muito do mais rapidamente que o da memria; por este motivo os acessos ` memria o a o so, em termos relativos, cada vez mais dispendiosos. a
Em C tambm poss aconselhar o compilador a utilizar registos, mas no existe e e vel a garantia de que este o faa. c
1

11

12

CAP ITULO 2. ARQUITECTURA O 80386 e os seus sucessores at ` data (Pentium 4) so microprocese a a

sadores de 32 bits. Entre outras coisas, isto signica que, geralmente, as instrues que estes microprocessadores executam lidam com operandos de co 32 bits no mximo e que a dimenso dos registos corresponde tambm a a a e este valor. Operandos de 32 bits signicam caminhos de dados de acesso ` a memria (bus de dados) de 32 bits. Por razes histricas todos os registos o o o de 32 bits podem em determinadas condies ser usados como registos de 16 co bits. Alguns deles podem ainda ser divididos num par de registos de 8 bits. Como se ver, tambm continuam, apesar disto, a existir registos com apenas a e 16 bits, que servem de selectores de segmentos de memria (o conceito de o segmento de memria ca adiado para o cap o tulo 3).

E de referir que, apesar da arquitectura ser de 32 bits, permite ainda utilizar operaes e operandos de 16 bits, mesmo no modo protegido (ver co seco 3.3 para uma descrio sobre os modos existentes nesta arquitectura). ca ca Isto poss graas a uma ag, designada por ag D. Esta ag armazena e vel c um atributo presente em todos os descritores de segmentos de cdigo, que o determina o tamanho por omisso das operaes e dos operandos (D = 0 a co para operaes e operandos de 16 bits, D = 1, para 32 bits). No entanto, co o valor desta ag pode ser invertido separadamente para as operaes ou co para os operandos de um unica instruo, atravs de prexos que se aplicam ca e apenas a essa instruo. Veja-se (IA-32 developers manual-I, 2001). Neste ca texto, sempre que necessrio, assumiremos que operaes e operandos de 32 a co bits.

2.2. REGISTOS

13

2.2
2.2.1

Registos
Registos de Utilizao Geral ca

H oito registos de 32 bits que so considerados de utilizao geral. Os seus a a ca nomes so eax, ebx, ecx, edx, esp, ebp, esi e edi. Antes do 80386 estes a registos tinham apenas 16 bits, sendo os seus nomes iguais a menos da letra e no in (ax, bx, ..., di). Ainda assim, continua a ser poss utilizar cio vel apenas os 16 bits menos signicativos dos novos registos, bastando para isso aplicar as designaes antigas. co Os 16 bits menos signicativos dos registos ax, bx, cx e dx podem ainda ser divididos em dois registos de 8 bits, de acesso separado. Os oito registos de utilizao geral e respectivas divises esto representados na gura 2.1. ca o a

32 bits 16 bits 8 bits eax ebx ecx edx ah bh ch dh ax bx cx dx 16 bits 8 bits al bl cl dl

esp ebp esi edi


bits mais significativos

sp bp si di
bits menos significativos

Figura 2.1: Registos de utilizao geral ca

14

CAP ITULO 2. ARQUITECTURA O nome de registos de utilizao geral aqui um pouco enganador, ca e

porque nem todos estes registos podem ser manipulados livremente e alguns deles apresentam funes espec co cas. No 80386 as diferenas entre os registos c so menores do que nos seus antecessores mas, no entanto, continuam a a existir. Os registos esp e ebp so utilizados na manipulao da pilha (veremos a ca adiante o que uma pilha). O registo esp Extended Stack Pointer e indica o topo da pilha. Alterar este registo signica mexer na localizao ca do topo da pilha, pelo que estas alteraes no podem ser arbitrrias. O co a a registo ebp Extended Base Pointer um registo auxiliar que permite e manipular valores armazenados na pilha. E especialmente util quando se utiliza a pilha para armazenar variveis locais e para passar parmetros a a a funes. co Os registos esi e edi chamam-se registos de ndice, porque so muitas a vezes usados para aceder a vectores ou tabelas (i.e., indexar vectores ou tabelas). A sigla esi signica Extended Source Index enquanto edi signica Extended Destination Index. Os outros quatro registos tm, de facto, uma utilizao mais geral, sendo e ca eax conhecido por acumulador, ebx por base, ecx por contador e edx por registo de dados. Estes nomes reectem algumas diferenas que se prendem c com determinadas instrues que lhe esto individualmente associadas, como co a se ver ao longo do texto. a

2.2.2

Registo de Segmento ou Selectores

No cap tulo 3 ser feita uma abordagem ` organizao da memria na arquia a ca o tectura do 80386. Nessa altura ser abordada com algum detalhe a questo a a da diviso de um programa em partes designadas de segmentos. Durante a a

2.2. REGISTOS

15

execuo do programa a indicao dos segmentos feita por registos destica ca e nados exclusivamente para esse m. So eles os registos cs, ss, ds, es, fs a e gs, todos de 16 bits e indivis veis. Na gura 2.2 esto representados estes a registos. No cap tulo 3 ser apresentada a tabela 3.1 onde esto resumidas a a as respectivas funes. co
16 bits

cs ss ds es fs gs
bits mais significativos bits menos significativos

Figura 2.2: Registos de segmentos ou selectores

2.2.3

Registo Contador de Programa

Um registo que nenhum microprocessador pode dispensar o contador de e programa, que indica qual a prxima instruo a ser executada. Isto porque, o ca depois de se carregar o programa para memria primria, necessrio saber, o a e a em cada momento, o endereo de memria onde pode ser encontrada a c o prxima instruo e respectivos operandos guardar este endereo a o ca c e funo do Contador de Programa. ca Contador de Programa um nome genrico, sendo o verdadeiro nome e e deste registo, no 80386, Extended Instruction Pointer eip, ou Ponteiro de Instrues Estendido. A sua representao est feita na gura 2.3. Antes co ca a

16

CAP ITULO 2. ARQUITECTURA

do 80386 este registo tinha apenas 16 bits e chamava-se ip. Na gura 2.4 encontra-se um exemplo onde se pode ver que o eip armazena o endereo c da prxima instruo a ser executada (e no da que est a ser executada no o ca a a instante actual). Confrontando esta gura com a tabela 1.1, facilmente se verica que a prxima instruo a executar ser movl 0xc(%ebp), %eax. o ca a
32 bits 16 bits eip
bits mais significativos

ip
bits menos significativos

Figura 2.3: Representao do registo eip ca

Memria

Endereos 0x8048449

Prxima Instruo

0xc3 0xd8 0x01 0x0c 0x45 0x8b 0x08 0x5d 0x8b

...

0x8048441 0x8048440

eip

0x8048443

Figura 2.4: Exemplo de utilizao do registo eip ca

2.2.4

Flags

Existe tambm um registo registo eflags, Extended Flags destinado e a assinalar a ocorrncia de determinadas condies. Estas condies dizem e co co

2.2. REGISTOS

17

respeito a certos eventos no cdigo em execuo, que podem ser, por exemplo, o ca uma operao aritmtica cujo resultado ultrapassou a capacidade do registo ca e onde iria ser armazenado; pode ser tambm um resultado igual a 0 na ultima e operao ou um resultado negativo, entre outros, que sero enumerados mais ca a adiante. O registo eflags encontra-se representado na gura 2.5 e a lista das ags mais importantes encontra-se descrita na tabela 2.1.
VM RF 31 ... 15 30 NT 14 29 28 IOPL 13 12 27 26 25 24 23 22 21 20 AF 5 4 3 19 18 PF 2 1 17 16 CF 0 ... Flag Bit Flag Bit

OF DF IF TF SF ZF 11 10 9 8 7 6

Figura 2.5: Representao do registo eflags ca

Estas ags so essenciais ao funcionamento dum programa. Com efeito, a algumas das instrues utilizadas em estruturas de deciso (ver instrues co a co cmp e j) seguem um procedimento que primeiro altera as ags em funo de ca dois operandos e depois, em funo dessas alteraes, efectuam, ou no, um ca co a salto na sequncia de instrues do programa. Sem esta capacidade escrever e co um programa de computador seria muito mais dif se no imposs cil a vel. Os acrnimos das restantes ags signicam: o TF : Trap Flag; IF : Interrupt Enable Flag (ag de habilitao das interrupes); ca co IOPL: Input/Output Privilege Level Flag (ag de privilgio de ene tradas/sa das); NT : Nested Task Flag;

18

CAP ITULO 2. ARQUITECTURA VM : Virtual Memory Flag (ag de memria virtual); o RF : Resume Flag (ag de continuao). ca A utilidade destas ags pode ser encontrada em (Murray & Pappas,

1986).

2.3

Conjunto de Instrues Abstractas co

Ao longo deste texto sero apresentadas muitas das instrues da arquiteca co tura de 32 bits dos processadores Intel. Para auxiliar nos comentrios a efeca tuar utilizaremos um conjunto de instrues abstractas. Pretende-se que esco tas instrues no tenham qualquer relao com esta arquitectura espec co a ca ca. Pelo contrrio, estas instrues devero ser independentes de qualquer arquia co a tectura e idealmente devero permitir a descrio das instrues de qualquer a ca co processador. Este conjunto de instrues est representada na tabela 2.2. co a Muitas das operaes, sobretudo aritmticas e operaes que envolvem bits, co e co mas no s, so idnticas `s da linguagem de programao C. a o a e a ca

2.4

Simbologia e Nomenclatura

Antes de se entrar no estudo do assemblador Gas propriamente dito necessrio e a apresentar a conveno utilizada pelo assemblador e que ser tambm adopca a e tada neste texto, relativa ` simbologia. Em particular, interessa saber o a seguinte: como se acede ao contedo duma clula de memria; u e o como se utiliza o endereo duma clula de memria; c e o

2.4. SIMBOLOGIA E NOMENCLATURA como se acede a um registo; como se denem constantes; como se efectuam comentrios; a qual a nomenclatura adoptada para a dimenso dos dados. a

19

No que diz respeito ao acesso ao contedo duma clula de memria, este u e o faz-se em dois passos, que so dados, normalmente, em momentos distintos a dum programa. Primeiro, na denio das variveis do programa (so) ca a e a especicada(s) a(s) clula(s) de memria (num total de 1, 2, 4, 8 ou mais e o clulas, sempre em grupos que sejam potncias de 2) onde armazenada e e e essa varivel e qual o nome que a(s) identica, que tambm o nome dessa a e e varivel. O segundo passo do acesso faz-se com referncia directa ao seu a e nome e acontece, normalmente, no corpo do programa. Note-se que se a clula de memria inicial no estivesse identicada pelo nome poder-se-ia e o a utilizar directamente o nmero que corresponde ao seu endereo se este fosse u c conhecido na prtica dicilmente ser. a a Assim, se houver uma instruo chamada xpto, que recebe um operando ca e se existir uma clula de memria que corresponde a uma varivel designada e o a por numero a instruo ca xpto numero
numero M[numero]

faz um acesso ao contedo da(s) clula(s) de memria que armazena(m) u e o a varivel numero (i.e., um acesso ` memria). a a o De igual forma, se em vez de um nome for utilizado um nmero, esse u nmero vai ser interpretado como um endereo absoluto (na prtica o enu c a dereo ser virtual). Isto signica tambm que um nmero nunca interc a e u e pretado literalmente, mas sempre como um endereo de memria. Por este c o

20

CAP ITULO 2. ARQUITECTURA

motivo, sempre que for necessrio usar um valor numrico literal tem de ser a e usado um cifro ($) antes do nmero. Assim, a instruo a u ca xpto $4
$4 4

no resultar em nenhum acesso ao endereo 4, sendo em vez disso usado a a c o valor literal 4. De igual forma, tambm a expresso $numero seria intere a pretada como um valor literal, sendo este valor igual ao endereo atribu c do a ` varivel nmero. a u Para diferenciar o acesso aos registos da mquina dos acessos a variveis, a a os nomes dos registos aparecem sempre precedidos do sinal de percentagem (%). Por exemplo: %eax, %ebx, %ax, %al, etc. No que toca ` denio de constantes (como o 4do exemplo anterior) a ca e vo ser referidos dois tipos de constantes: numricas e cadeias de caracteres. a e As constantes numricas podem ser denidas de vrias formas diferentes e e a usando, inclusivamente, quatro bases de numerao diferentes, o que no ca a deixa de ser util quando se est a programar em assembly. A forma mais a simples de denir uma constante numrica escrevendo-a directamente na e e base 10, como se fez no exemplo anterior com o 4. Para escrever um nmero u na base 2 ter de ser usado o prexo 0b, enquanto que na base 8 e na base a 16 os prexos so, respectivamente 0 e 0x. Assim o nmero 16 seria escrito a u como 0b10000, 020 e 0x10 em binrio, octal e hexadecimal, respectivamente. a Uma constante em v rgula utuante, por sua vez, recebe o prexo 0f, sendo admitida a notao cient ca ca com o expoente a surgir depois de um e (maisculo ou minsculo). Por exemplo, 0f1.3 ou 0f1.3e2. u u E ainda poss vel tomar directamente o valor ASCII
2

de um caracter

escrevendo o caracter entre plicas (a, por exemplo) ou depois de uma plica (a).
2

American Standard Code for Information Interchange.

2.4. SIMBOLOGIA E NOMENCLATURA

21

Em qualquer destes casos sempre que se quiser tomar o valor literal da constante obrigatria a utilizao do cifro ($) (quando o que estiver em e o ca a causa for uma instruo e no uma directiva do assemblador). ca a As constantes que representam cadeias de caracteres, por sua vez, so a denidas entre aspas. Finalmente, o cardinal (#) utilizado para iniciar comentrios. Numa e a linha de um programa em assembly do Gas tudo o que est depois do (#) a e ignorado. No que se refere a dimenses, o Gas utiliza as seguintes designaes: byte o co 8 bits; word (palavra) 16 bits; long 32 bits. Na seco 3.2 este assunto ca voltar a ser abordado e sero apresentadas designaes alternativas. A a a co cada uma destas dimenses corresponde um suxo, que dever ser adicionado o a a `s instrues conforme o tamanho dos dados em que estas devero operar: co a respectivamente b, w ou l. Assim, se a instruo xpto operar sobre as ca clulas de memria que referenciam a varivel de 32 bits numero, a instruo e o a ca dever ser rescrita para a xptol numero Muitas vezes, a utilizao deste suxo no obrigatria, mas aconselca a e o e hada por uma questo de clareza na leitura do cdigo. a o A tabela 2.3 resume a denio dos s ca mbolos e da nomenclatura que tem vindo a ser feita.

22

CAP ITULO 2. ARQUITECTURA

Sigla CF

Descrio ca Carry Flag (Flag de Transporte)

PF

Parity Flag (Flag de Paridade)

AF

ZF SF OF

Auxiliary Carry Flag (Flag de Transporte Auxiliar) Zero Flag (Flag de Zero) Signal Flag (Flag de Sinal) Overow Flag (Flag de Transbordo)

Signicado Posta a 1 quando gerado um transporte ou e um emprstimo numa operao aritmtica. Caso e ca e contrrio posta a 0. Note-se que a ocorrncia de a e e transporte ou emprstimo no implica transbordo. e a Indica se nos 8 bits menos signicativos de um resultado h um nmero a u mpar de bits a 1 (caso em que posta a 0) ou se h um nmero par de e a u bits a 1 (caso em que posta a 1). e Usada em aritmtica BCD para indicar transporte e ou emprstimo. e

DF

Direction Flag (Flag de Direco) ca

E posta a 1 quando um resultado der 0, posta a 0, caso contrrio. a Posta a 1 quando o sinal do resultado negativo, e limpa, no caso contrrio. a Indica a ocorrncia de transbordo no resultado e duma operao em complemento para dois, caso ca em que posta a 1. E posta a 0, no caso contrrio. e a O transbordo d-se quando o nmero de bits utia u lizados para armazenar o resultado no sua e ciente. Em adies em complemento para dois co esta situao ocorre quando o transporte que enca tra no bit mais signicativo diferente do transe porte que sai. Esta situao no deve ser confunca a dida com o transbordo em operaes sem sinal, co que ocorre quando h transporte que sai do bit a mais signicativo (ver ag de transporte). Indica a direco das operaes com strings. ca co Quando a ag de direco est a 0, os registos ca a de ndice, esi e edi, so automaticamente increa mentados no m de certas operaes utilizadas em co cpias de dados (nomeadamente de strings) em o memria. Caso a ag de direco esteja a 1, esses o ca registos so automaticamente decrementados. a

Tabela 2.1: Descrio das ags mais importantes ca

2.4. SIMBOLOGIA E NOMENCLATURA

23

S mbolo Signicado Representao dum registo. Note-se a ausncia do sinal de perca e centagem (%) antes do nome do registo. As ags representam-se eax de forma semelhante. Por exemplo, a ag de sinal representa-se como SF. 25 Representao dum literal. Neste caso do 25. ca Operao toma o valor de. Ao operando (que pode resultar duma ca expresso) que se encontra do lado esquerdo atribu o valor a e do da expresso que se encontra do lado direito. Exemplo: eip a eip + 2. Neste caso o registo eip incrementado de duas e unidades. Operao toma um valor convertido para x bits . Idntica ` ca e a operao anterior, mas antes da atribuio a expresso da diretia ca ca a convertida para x bits, se for de tamanho diferente. Exemplo: e x eax 4. E feita a extenso do nmero 4 para 32 bits e o a u 32 respectivo valor atribu ao registo eax. e do Refere-se ao contedo duma ou mais clulas de memria. x repu e o resenta o endereo de memria a que se faz o acesso. O nmero c o u de clulas referenciadas depende do contexto, mas poder ser 1, e a 2, 4 ou 8. Normalmente este operando surge numa expresso em a que aprece . Sempre que isso acontece o nmero de clulas u e M[x]
t

||,
x

referenciadas ser de t/8, uma vez que t dado em bits. Exema e plo: M[eax] 4. Neste caso, o valor decimal 4 convertido e 32 para um valor binrio de 32 bits a armazenar nas quatro clulas a e de memria com in no endereo eax. o cio c Operao representa. A expresso que est ` esquerda, escrita ca a a a em assembly representa a expresso que est ` direita. A exa a a presso da direita obedece `s convenes desta tabela. Exemplo: a a co 20(%ebx, %eax, 4) M[ebx + 4 * eax + 20]. Operao troca de valor com. O valor esquerdo e o direito trocam ca de valores. Exemplo: eax ebx. Se eax valesse 6 e ebx 14, no m da instruo eax valeria 14 e ebx 6. ca Operao troca de valor de x bits com. Idntico ao anterior, mas ca e aqui indicado o tamanho dos operandos. Exemplo: M[eax] e ebx. O contedo das 4 clulas de memria cujo endereo se u e o c 32 inicia em eax trocam de valor com o registo ebx. Operao altera as ags sem atribuir o valor de. Semelhante ` ca a operao , mas sendo o operando esquerdo o registo das ags, ca que alterado como na instruo . O resultado do clculo da e ca a expresso que ca ` direita descartado. a a e Operao toma o valor de, sem alterar as ags.. Semelhante ` ca a operao , mas no altera as ags. ca a Operaes atribuio sem sinal. Semelhantes ` operao , co ca a ca mas a expresso da direita avaliada considerando os nmeros a e u como sendo sempre positivos. Exemplo: edx:eax ecx 64 eax. Os dois factores da multiplicao ecx e eax so, neste caso, ca a considerados como nmeros positivos. u

24

CAP ITULO 2. ARQUITECTURA

S mbolo Signicado Operao rotao para a esquerda/direita de x bits . Estas ca ca x, operaes sero denidas adiante. Exemplo: eax co a 4. Neste x caso, o registo eax sofre uma rotao de 4 bits para a esquerda. ca Operao rotao para a esquerda/direita de x bits pela ag de ca ca transporte. Estas operaes sero igualmente denidas adiante. co a x, C C Exemplo: eax 4. Neste caso, o registo eax sofre uma rotao ca x C de 4 bits para a esquerda com passagem pela ag de transporte. Operao deslocamento para esquerda/direita de x bits . A denir ca << adiante, tambm. Exemplo: eax >> 4. Neste caso o registo eax e >> sofre um deslocamento de 4 bits para a direita. Representao da justaposio de dois registos como se de um s ca ca o edx:eax se tratasse. ,/, Operaes aritmticas. Respectivamente: multiplicao, diviso, co e ca a %, +, mdulo, adio e subtraco. o ca ca Operaes de comparao. Respectivamente: igual e diferente. co ca A operao igual devolve verdade se a avaliao da expresso ca ca a a ` esquerda resultar idntica ` avaliao da expresso ` direita. e a ca a a ==,!= Exemplo: 4 + 3 == 7 avalia como verdade, mas eax == 8 avalia como falso, se eax armazenar o valor 20. A operao diferente ca devolve sempre o resultado complementar da operao igual. ca Operaes binrias bit a bit. Respectivamente: e, ou e ouco a &, |, exclusivo. Exemplo: eax & ebx. Estas operaes sero apreco a ^ sentadas mais adiante. Operao unria de negao. Complementa todos os bits do ca a ca ~ operando indicado. Exemplo: ~ebx. Esta operao ser apreca a sentada mais adiante. Operaes aritmticas lgicas. Respectivamente: e lgico e ou co e o o lgico. Exemplo: ZF == 0 && SF == OF. Esta expresso avalio a e &&, || ada como verdade se a ag ZF for igual a 0 e as ags SF e OF forem iguais. Operao de controlo de uxo se-ento. Se a expresso ` esquerda ca a a a do operador ? for avaliada como verdade executada a instruo e ca que se encontrar ` direita. Exemplo: ecx != 0 ? eip eip a 32 ? - 10. Neste caso se o registo ecx for diferente de 0 o registo eip e decrementado em 10 unidades, caso contrrio passa-se ` instruo a a ca seguinte. Operao de controlo de uxo se-ento-seno. Se a expresso ` ca a a a a esquerda do operador ? for avaliada como verdade executada a e instruo que se encontrar entre os sinais ? e :. Caso contrrio ca a e executada a instruo ` direita de :. Exemplo: ecx != 0 ? eip ca a ?: eip - 10 : eax eax + 2. A diferena relativamente c 32 32 ao caso anterior, que agora o registo eax incrementado de duas e e unidades caso ecx seja igual a 0. Tabela 2.2: Lista das instrues abstractas (cont.) co

2.4. SIMBOLOGIA E NOMENCLATURA

25

Tipo de s mbolo Variveis a Valores literais Constantes

Comentrios a Registos Nomenclatura

Suxos

Representao ca Designadas por um nome que equivale a um endereo duma clula de memria. c e o Obtidos por um cifro ($) a Nmeros em binrio: 0b01001110. u a Nmeros em octal: 07431. u Nmeros em hexadecimal: 0x1f00. u Nmeros de v u rgula utuante: 0f1.3e2. Caracteres: a. Strings: "Entre aspas". Precedidos por um cardinal (#). Precedidos por um sinal de percentagem (%). byte: 8 bits. Palavra: 16 bits. Inteiro/Longo: 32 bits. Double (depende do contexto): 32 ou 64 bits ou nmero de v u rgula utuante. byte: b. Palavra: w. Longo: l.

Tabela 2.3: Denio de s ca mbolos e nomes

26

CAP ITULO 2. ARQUITECTURA

Enderecamento
3.1 Introduo ca

Neste cap tulo vai ser estudada a organizao da memria dum computador. ca o Em particular, veremos algumas caracter sticas que so espec a cas ` fam a lia Intel 80x86. Veremos tambm algumas das diferenas que separam o 80386 e c dos seus antecessores e em que que essas diferenas se reectem em termos e c de programao. ca O cap tulo termina com um estudo das diferentes formas de aceder ` a memria na linguagem assembly do Gas. o

3.2

Conceitos Bsicos a

Em termos lgicos, a memria dum computador pode ser encarada como o o um vector de bytes, indexado por um nmero inteiro, desde 0 at um limite u e mximo, que igual ` sua dimenso menos uma unidade. a e a a Neste modelo esto representados vrios aspectos relativos ao funcionaa a mento duma memria que convm compreender: o e uma memria tem capacidade nita de armazenar informao; o ca a informao tem que ser armazenada em mltiplos de 8 bits (1 byte); ca u 27

28

CAP ITULO 3. ENDERECAMENTO a cada byte armazenado na memria est associado um o a ndice a que chamaremos endereo que indica a sua localizao exacta; c ca estruturas de dados com dimenso superior a 1 byte tero de ser ara a mazenadas em vrias posies de memria diferentes. Geralmente estas a co o posies so cont co a guas, em particular no caso das estruturas de dados mais simples, como o caso dos inteiros com vrios bytes, por exmeplo. e a A gura 3.1 procura ilustrar este modelo para uma memria com dio

menso de 16 Kbytes (16.384 bytes). a

Memria

Endereos 16.383 16.382

... 3 2 1 0
Figura 3.1: Representao de uma memria com 16 K ca o

As memrias modernas so tambm designadas de memrias de acesso o a e o aleatrio (Random Access Memories RAM) por oposio ao que sucedia o ca no passado em certo tipo de memrias. o E de notar, e isso resulta do que j dissemos, que a memria, em termos a o f sicos acess duma forma totalmente linear: quaisquer duas posies de e vel co

3.2. CONCEITOS BASICOS

29

memria consecutivas so referenciadas por dois nmeros inteiros tambm o a u e consecutivos. Este facto que ao n do endereamento f vel c sico parece bvio o no vai encontrar paralelo ao n a vel de um programa, onde dois endereos c consecutivos podem no referenciar clulas de memria consecutivas. Este a e o facto deve-se a um mecanismo, designado de memria virtual, que ultrapassa o o mbito deste texto. Veja-se (Silbertschatz & Galvin, 1998). De qualquer a forma o programador no tem que ter conscincia desse facto, quando escreve a e um programa. Se verdade que a memria est dividida em bytes, a realidade que e o a e muitas vezes, e como j dissemos, esta unidade se revela inadequada ou a mesmo insuciente em certas situaes. O caso mais vulgar ser aquele em co a que necessrio armazenar um nmero que no pode ser representado com e a u a apenas 8 bits. No caso do 80386 esto previstas outras dimenses bsicas a o a para estruturas de dados, que podem ser acedidas com uma unica instruo: ca a palavra (word ), de 16 bits e o inteiro ou longo (integer e long, respectivamente), de 32 bits. Estes trs tipos de dados esto representados na e a gura 3.2. Os processadores da fam 80x86, a partir do 80386, permitem aceder lia directamente a tipos de dados de 32 bits numa unica instruo. Esse mximo ca a era, at ao 80286, inclusive, de 16 bits 1 . e Quanto ao armazenamento em memria de dados de 32 bits este sempre o e feito em quatro posies de memria consecutivas. Assim, se um inteiro de co o 32 bits est armazenado no endereo 400, por exemplo, o inteiro seguinte s a c o poder ser armazenado da posio 404 em diante. a ca

Com raras excepes, como as instrues div e mul. co co

30
Byte
8 bits

CAP ITULO 3. ENDERECAMENTO

Palavra
16 bits

Inteiro/Longo
32 bits

Figura 3.2: byte, palavra e longo

3.3

Diviso em segmentos a

Se do ponto de vista f sico a memria perfeitamente linear, por outro lado, o e para um programa em execuo faz sentido que a memria se divida em vrias ca o a zonas, uma vez que ele prprio composto por mltiplas partes: o cdigo, a o e u o zona de dados inicializados, a zona de dados no inicializados, a pilha (onde a so muitas vezes guardados dados locais) e nos sistemas operativos modernos a incluem-se ainda um conjunto de funes, que no pertencem ao programa co a propriamente dito, mas que so por ele invocadas estas funes pertencem a co a bibliotecas partilhadas 2 . A existncia de todas estas partes justica a diviso da memria em zonas e a o chamadas segmentos. Cada segmento tem um tamanho mximo de 232 bytes a (4 Gbytes) e endereado linearmente este tamanho deve-se ao facto de e c
No Linux, talvez a biblioteca partilha mais conhecida seja a libc, que utilizada por e virtualmente todos os programas escritos em C. Isto signica que h um determinado a nmero de funes (printf, por exemplo que permite escrever na sa padro), cujo u co da a cdigo no est inclu nos programas, mas que todos eles invocam e que se encontra o a a do numa biblioteca dinmica a que todos tm acesso. a e
2

3.3. DIVISAO EM SEGMENTOS

31

os registos usados para indicar o deslocamento dentro do segmento, esp, ebp, eip, etc. terem 32 bits. Para designar os segmentos so utilizados registos a de segmento ou selectores (cs, ss, ds, es, fs e gs) que tm 16 bits, dos quais e apenas os 14 primeiros so usados para endereamento (os outros dois so a c a usados para indicar a proteco que se aplica ao segmento). Por este motivo ca um programa pode aceder a um limite terico de 246 bytes (64 Tbytes), sendo o que metade deste espao tem que ser partilhado entre todos, porque o ultimo c dos 14 bits de endereamento dos selectores est reservado para separar os c a segmentos individuais dos comuns. Cabe ao hardware e ao sistema operativo garantir que a distribuio e o ca acesso ` memria f a o sica existente (que inferior em vrias ordens de grandeza e a a ` dimenso de memria enderevel pelos processos) se faz de forma coerente, a o ca em funo do endereo, que ser dado por um par {segmento, endereo}. ca c a c Os endereos de 48 bits dados pelos registos de segmento mais os registos c de deslocamento acabam por ser traduzidos num endereo de 32 bits que c e o mximo que um 80386 consegue, de facto, enderear. O microprocessador a c utiliza, para isso, tabelas preparadas pelo sistema operativo. Acresce ainda a isto que a memria paginada, mas como este facto totalmente transparente o e e para os programadores no vai ser abordado. Por este motivo, o endereo a c de 32 bits no ainda um endereo f a e c sico, mas um endereo virtual que c ter de ser traduzido num endereo f a c sico. Veja-se (Silbertschatz & Galvin, 1998). A gura 3.3 procura ilustrar a converso de um endereo da forma a c {segmento, endereo} de 48 bits para um endereo virtual de 32 bits. Notec c se que um programa s lida com endereos virtuais, nunca lhe interessando o c saber qual a correspondncia que existe entre estes e os endereos f e e c sicos. A correspondncia, tambm aqui, garantida por uma cooperao entre o e e e ca hardware e o sistema operativo.

32
16 bits

CAP ITULO 3. ENDERECAMENTO


32 bits

Segmento

Deslocamento

Tabela de Segmentos

Incio da Tabela de Segmentos Endereo Virtual


32 bits

Figura 3.3: Traduo de um endereo de 48 bits num endereo virtual ca c c

E importante referir dois aspectos: a existncia do endereamento virtual e c justica-se porque permite que cada programa utilize a gama de endereos c que mais lhe convm, sem haver problemas quanto ` coincidncia de gamas e a e entre programas diferentes. Por outro lado, um programa no pode tentar a aceder a um endereo que ultrapasse os limites especicados para o segmento c em causa, nem to pouco tentar aceder a um segmento que no lhe pera a tence. Ao tentar faz-lo o microprocessador gera uma excepo que poder e ca a ser tratada pelo sistema operativo de diferentes formas. O Unix em geral e o Linux em particular, enviam um sinal SIGSEGV ao processo que tentou o acesso ilegal 3 . A resposta do programa a este evento geralmente no exa iste, embora possa ser especicada, pelo que o programa terminado, sendo e
3

Para consultar uma lista completa de sinais veja-se (Stevens, 1990).

3.3. DIVISAO EM SEGMENTOS

33

gerado um cheiro com o estado em que este se encontrava no momento da terminao (coredump). ca Apesar da diviso que feita da memria em segmentos, na prtica, e a e o a tradicionalmente, o Unix no suporta a diviso da memria em segmentos, a a o razo pela qual um programa todo constru no mesmo segmento e o ena e do dereamento linear em vez de ser segmentado. De qualquer forma, isto no c e a invalida que o mecanismo dos segmentos inerente ao prprio microproceso sador tenha que ser preparado de forma totalmente coerente. O 80386 suporta o modo de funcionamento que acabmos de descrever a em que o endereamento virtual e em que todos os acessos ilegais so imc e a poss veis, designado de protegido. Alm deste, suporta o modo real, que e permite executar programas escritos para os microprocessadores 8086/8088 e para os pouco conhecidos 80186/80188 4 . Neste modo de endereamento o c processador comporta-se como se fosse um processador 8086 de grande velocidade. Existe ainda um terceiro modo de endereamento, conhecido por c modo virtual 8086. Este modo foi criado para suportar no modo protegido programas escritos para o 8086. Isto permite que estes programas possam executar-se concorrentemente com outros programas. Na verdade o modo virtual 8086 no um verdadeiro modo, sendo apenas uma tarefa que corre a e em modo protegido com um determinado atributo seleccionado. Qualquer tarefa pode seleccionar esse atributo. Quando o sistema operativo comuta de contexto para uma destas tarefas o processador passa a emular um processador 8086. Para mais detalhes veja-se (IA-32 developers manual-I, 2001; IA-32 developers manual-II, 2001; IA-32 developers manual-III, 2001).

Alm destes tambm podemos considerar programas escritos explicitamente para o e e modo real dos processadores subsequentes a comear no 80286. c

34

CAP ITULO 3. ENDERECAMENTO

3.4

Modos de endereamento c

Como se viu, para aceder `s vrias posies de memria podem ser utilizados a a co o registos, sendo sempre necessrio indicar o segmento e o deslocamento 5 . a O segmento ser ento indicado num dos registos de 16 bits concebidos a a para o efeito, cs, ss, ds, es, fs ou gs. Alguns destes tm funes espec e co cas que no podem ser alteradas: o caso dos registos cs, ss e ds. As funes a e co destes e dos restantes registos selectores est resumida na tabela 3.1. a Registo CS SS DS ES FS GS Nome Code Segment Stack Segment Data Segment Extra Segment (no tem nome) a (no tem nome) a Descrio ca Segmento de cdigo o Segmento da pilha Segmento de dados Segmento de dados extra Outro segmento de dados extra Outro segmento de dados extra

Tabela 3.1: Registos de segmento ou selectores

A determinao do deslocamento dentro de um segmento normalmente ca ser feita com um registo, desta vez de 32 bits, embora existam outras formas a de o fazer. Antes disso tem de ser alargado o conceito de endereamento, de forma a c incluir tambm a noo de acesso a um valor armazenado num registo (notee ca se que um registo tambm memria) ou, simplesmente, um valor numrico e e o e literal. O 80386 tem sete formas diferentes de endereamento, que so apresenc a tadas a seguir. Note-se que algumas no passam de variantes de outras. A a convenao adoptada neste texto a mesma que em (Murray & Pappas, 1986). c e
Por vezes o segmento no indicado, mas nesse caso ele assumido implicitamente a e e pela situao. Por exemplo, nos acessos ` pilha quando no indicado o segmento ca a a e e assumida implicitamente a utilizao do registo de segmento da pilha. ca
5

3.4. MODOS DE ENDERECAMENTO

35

3.4.1

Endereamento literal ou imediato c

Este o tipo de endereamento mais simples e que permite atribuir directae c mente um valor numrico literal a um registo ou a uma clula de memria, e e o como nos seguintes exemplos (a instruo movl ser abordada na seco 4.2 ca a ca e no relevante para a compreenso do modo de endereamento): a e a c

movl $84, %eax movb $-10, %al movw $0x42af, numero

eax 84
32

al -10
8

M[numero] 0x42af
16

Note-se a necessidade do cifro ($) antes do valor numrico. Na sua a e ausncia o assemblador interpretaria os nmeros como endereos de memria e u c o e o resultado de qualquer uma destas instrues quando executadas seria um co mais que provvel acesso ilegal ` memria. a a o

3.4.2

Endereamento por Registo c

Este modo de endereamento que tambm muito simples permite aceder c e e ao valor que tenha sido armazenado previamente num registo, como nos seguintes exemplos, em que so lidos os registo ebx, bx e bl, por esta ordem: a

movl %ebx, %eax movw %bx, %cx movb %bl, %al

eax ebx
32

cx bx
16

al bl
8

Este tipo de endereamento tambm pode ser considerado directo, que c e ser o prximo tipo de endereamento a abordar. a o c

36

CAP ITULO 3. ENDERECAMENTO

3.4.3

Endereamento Directo c

Neste modo de endereamento so usados explicitamente os endereos das c a c clulas de memria. O endereo indicado contm apenas o deslocamento e o c e dentro do segmento indicado ou, em caso de omisso, pelo registo que estiver a impl cito na operao que ser geralmente ds. Felizmente para o prograca a mador no necessrio denir os endereos manualmente porque o assema e a c blador permite utilizar rtulos que depois se encarrega de converter para o endereos concretos. As prprias variveis no so mais do que rtulos com c o a a a o espao reservado. c O cdigo 3.1 e 3.2 so exemplos de endereamento directo relativo `s o a c a clulas de memria meu valor e meu byte, respectivamente. e o movl meu valor, %eax movb meu byte, %al
eax M[meu valor]
32

(3.1) (3.2)

al M[meu byte]
8

H alguns aspectos a referir. Em primeiro lugar, note-se que no usado a a e qualquer cifro ($) para aceder ao valor das variveis; note-se tambm que a a e no indicado o segmento, mas apenas o deslocamento j dissemos que h a e a a um segmento, o ds neste caso, que est impl a cito. Finalmente, convm que e os dados tenham um tamanho adequado `s instrues em que so usados: a co a neste caso, meu valor dever ter 4 bytes, enquanto meu byte necessita de a apenas 1 byte.

3.4.4

Endereamento Indirecto por Registo c

Este modo de endereamento difere do anterior, no facto de agora o endereo c c da clula de memria no ser indicado por um rtulo, mas por um registo. e o a o Reutilizando os exemplos do modo de endereamento anterior e supondo que c

3.4. MODOS DE ENDERECAMENTO

37

o registo ebx tem armazenado o endereo da clula de memria meu valor, c e o a instruo ca movl (%ebx), %eax
eax M[ebx]
32

(3.3)

tem um resultado idntico ao do exemplo 3.1. A forma de atribuir esse e valor ao registo ebx ser introduzida mais adiante, quando for estudada a a instruo lea. ca Antes do 80386 nem todos os registos podiam desempenhar o papel de armazenar o endereo para fazer endereamento indirecto apenas os registos c c bx e nalgumas circunstncias o registo bp. a

3.4.5

Endereamento Relativo ` Base c a

Este modo de endereamento apresenta um grau de complexidade adicional, c relativamente ao anterior: aqui poss e vel, a partir dum registo base, aceder `s a clulas e memria imediatas, quer para a frente, quer para trs. No cdigo 3.4 e o a o o registo eax vai tomar o valor do inteiro armazenado quatro bytes ` frente a do endereo presente em ebx. c movl 4(%ebx), %eax
eax M[ebx + 4]
32

(3.4)

Este exemplo difere do anterior porque, neste caso, eax iria receber o inteiro seguinte ao que est na posio indicada, de facto, por ebx (note-se a ca que cada inteiro ocupa 4 bytes).

3.4.6

Endereamento Indexado Directo c

Neste modo de endereamento suposto existir um vector ou uma tabela c e (veja-se a subseco 8.3.5) que tem in numa clula de memria cujo enca cio e o dereo referenciado por um rtulo. A ideia conseguir aceder a qualquer c e o e

38

CAP ITULO 3. ENDERECAMENTO

elemento dessa tabela, utilizando o rtulo para indicar o in da tabela e o cio um registo para indicar a posio do elemento a ler. Admitindo que se queca ria ler o quinto elemento da tabela de inteiros minha tab para o registo ecx executar-se-ia, depois de guardar o valor 16 no registo eax, o cdigo 3.5. o movl minha tab(, %eax), %ecx
ecx M[minha tab + eax]
32

(3.5) A razo de ser da v a rgula antes do registo de ndice ser evidente na a subsecao 3.4.8. c

3.4.7

Endereamento Indexado ` Base c a

Este modo de endereamento semelhante ao anterior, na medida em que c e tambm existe um registo que indica a posio do elemento que se quer ler e ca dentro dum vector ou duma tabela. A diferena que aqui a base no uma c e a e varivel designada por um rtulo, mas um registo. a o Assim, se o registo ebx tivesse o valor do endereo de minha tab, o c cdigo 3.6 seguinte teria o mesmo efeito do cdigo 3.5 o o movl (%ebx, %eax), %ecx
ecx M[ebx + eax]
32

(3.6)

Este tipo de endereamento, bem como o anterior, so casos particulares c a do endereamento indexado, que ser visto j de seguida. Em ambos os casos c a a poss adicionar ao registo de e vel ndice um inteiro que indique o tamanho de cada elemento do vector (ou tabela). Isto permite que o ndice represente a posio a aceder independentemente da dimenso do tipo em questo. No ca a a exemplo, que tem vindo a ser usado essa dimenso 4, pelo que eax seria a e tambm 4, uma vez que se deseja aceder ao quinto elemento (i.e., ` posio e a ca

3.4. MODOS DE ENDERECAMENTO

39

4, porque o primeiro elemento est na posio 0). A forma de fazer o que a ca est a ser dito est representada no cdigo 3.7. Note-se que o nmero que a a o u indica a dimenso dos elementos do vector no precedido de um cifro. a a e a movl $4, %eax
eax 4
32

movl (%ebx, %eax, 4), %ecx


ecx M[ebx + eax 4]
32

(3.7)

3.4.8

Endereamento Indexado c

Este o modo de endereamento mais complexo e engloba praticamente e c todos os outros. Permite indicar um rtulo que referencie uma tabela, um o registo de base e um registo de ndice, alm do tamanho dos elementos da e tabela, sendo o seguinte endereo calculado pela frmula que lhe sucede: c o rotulo + const(base, ndice, tamanho) Endereo = rotulo + const + base + ndice * tamanho c A presena de todos estes parmetros opcional embora, naturalmente, c a e no possam ser omitidos todos ao mesmo tempo. Se o parmetro a omitir a a for a base utiliza-se a seguinte sintaxe, ` semelhana do que j se tinha dito: a c a rotulo + const(, ndice, tamanho) Os exemplos 3.8, 3.9 e 3.10 pretendem ilustrar duas situaes em que so co a utilizadas formas de endereamento indexadas. c movl minha tab(, %eax, 4), %ecx
ecx M[minha tab + 4 eax]
32

(3.8)

40

CAP ITULO 3. ENDERECAMENTO

movl minha tab(%ebx, %eax, 4), %ecx


ecx M[minha tab + ebx + 4 eax]
32

(3.9) movl (%ebx, %eax, 4), %ecx


ecx M[ebx + 4 eax]
32

(3.10)

Os valores armazenados em ecx nos exemplos 3.8 e 3.9 esto ilustrados a na gura 3.4, para exemplos de valores concretos armazenados em eax e ebx.

a) b) ... meu_vector + 8 meu_vector + 4 meu_vector

eax 3 ebx 4 Inteiro a) meu_vector(%ebx, %eax, 4)

eax 3 ebx $meu_vector Inteiro b) (%ebx, %eax, 4)

Figura 3.4: Exemplo de endereamento indexado c

3.5. PILHA

41

3.5

Pilha

Um dos segmentos de memria que o 80386 tem capacidade suportar o o e segmento da pilha. A pilha pode ser encarada como uma zona de dimenso a varivel, capaz de fazer o armazenamento temporrio de dados. a a O nome de pilha advm do facto de o acesso ser normalmente feito a e partir do topo, de tal forma que novos dados deixam-se no topo e so os a dados que esto no topo que saem primeiro. A esta disciplina de entradas a e sa das chama-se Last In First Out (LIFO - ultimo a entrar, primeiro a sair). As instrues bsicas de manipulao da pilha chamam-se push e pop e co a ca servem, respectivamente, para pr e tirar dados da pilha. Sero apresentadas o a com detalhe no cap tulo 4. Estas instrues alteram o valor do registo esp que co armazena o deslocamento do topo da pilha. Quanto ao segmento da pilha, este armazenado em SS, como j vimos. Uma instruo push diminui o e a ca valor de esp, enquanto que a instruo pop aumenta o mesmo registo. Por ca este motivo a pilha cresce para baixo (i.e., para endereos mais baixos). E c tambm poss descartar dados da pilha ou reservar espao, adicionando ou e vel c subtraindo de esp o nmero desejado de bytes, de acordo com a gura 3.5. u Note-se que o registo esp aponta para o ultimo item ocupado na pilha. Tambm so poss e a veis acessos mais complexos ` pilha, utilizando para o a efeito o registo ebp. Neste caso, o acesso ` pilha faz-se praticamente como se a a pilha fosse uma tabela, sendo guardado o in dessa tabela em ebp. Esta cio capacidade especialmente aproveitada nas chamadas a funes para passar e co parmetros e para guardar variveis locais a uma funo. a a ca Consideremos como exemplo uma funo que recebe trs parmetros e ca e a que utiliza duas variveis locais (a e b) todos com 4 bytes. O estado da a pilha dentro desta funo est representado na gura 3.6. ca a

42
628 624 esp 620 616 -16 612 608 esp-16 604 600 Reservar 16 bytes (4 longos) na pilha

CAP ITULO 3. ENDERECAMENTO


828 esp+16 824 820 +16 816 812 esp 808 804 800 Descartar 16 bytes (4 longos) na pilha

Figura 3.5: Descartar e reservar espao na pilha c

param3 param2 param1 ebp eip a esp b

4832 4828 4824 4820 4816 4812

Figura 3.6: Acesso a parmetros e variveis locais dentro duma funo a a ca

Uma forma de fazer o acesso aos parmetros e aos dados ser usando o a a registo ebp como base. Para aceder aos parmetros utiliza-se um deslocaa mento ou ndice positivo, enquanto que para aceder aos dados se utiliza um ndice negativo. No cdigo 3.11 est exemplicada a forma de armazenar o parmetro o a a param3 no registo eax, estando no cdigo 3.12 uma forma alternativa de o o fazer. No cdigo 3.13 est exemplicado o acesso ` varivel b. E de notar o a a a que a instruo mov s ser apresentada na seco 4.2. Funes, respectivos ca o a ca co

3.5. PILHA parmetros e variveis locais sero abordados mais abaixo 6 . a a a movl 12(%ebp), %eax movl $3, %ecx
eax M[ebp + 12]
32

43

(3.11)

ecx 3
32

movl (%ebp, %ecx, 4), %eax


eax M[ebp + 4 ecx]
32

(3.12)

movl -8(%ebp), %eax

eax M[ebp - 8]
32

(3.13)

No entanto ainda no esto dispon a a veis nesta verso do texto. a

44

CAP ITULO 3. ENDERECAMENTO

Instrucoes Gerais
4.1 Introduo ca

Antes de mais vai ser denido o conceito de instruo. Neste contexto, inca struo uma frase, escrita na sintaxe prpria do assemblador e que este ca e o traduz para cdigo mquina. Cada instruo inclui uma mnemnica e respeco a ca o tivos operandos (se os houver). A cada mnemnica corresponde um nmero o u inteiro (cdigo) segundo uma dada correspondncia 1 . Uma instruo pode o e ca ter 0, 1 ou mais operandos, de acordo com o seguinte modelo (em que so a apresentados dois operandos): nome+sufixo operando1, operando2 Naturalmente que se a instruo s tiver um operando no se utiliza ca o a o segundo operando nem a v rgula, assim como se a instruo no tiver ca a operandos indica-se apenas o nome. Podem-se adicionar mais operandos, se for caso disso, mas sempre separados por v rgulas. Note-se que algumas instrues no utilizam suxo. co a Uma questo a esclarecer a de que, normalmente, quando referida a e e uma instruo em particular mov, push, xchg, etc. est a ser cometido ca a
A uma mnemnica s corresponde um cdigo, mas o contrrio no necessariamente o o o a a e verdade, porque h vrias mnemnicas que tm o mesmo cdigo, i.e., correspondem todas a a o e o a ` mesma instruo de linguagem mquina. ca a
1

45

46

CAP ITULO 4. INSTRUCOES GERAIS

um pequeno abuso de linguagem. Com efeito, seria mais correcto falar em conjunto ou fam de instrues, porque a cada combinao diferente de lia co ca operandos pode corresponder uma instruo de mquina diferente, identica a cada por um cdigo unico. o Tome-se como exemplo a instruo mov. Cada uma das quatro instrues ca co (sem suxo), ilustradas no cdigo 4.1 apresenta uma combinao diferente o ca de operandos, que podem ser registos de vrios tamanhos, uma clula de a e memria ou um valor literal. o mov %eax, %ebx mov $1500, %eax mov $25, %ax mov $25, %ah
ebx eax
32

eax 1500
32

(4.1)

ax 25
16 8

ah 25

Apesar de, em termos lgicos, e para o programador estas quatro ino strues formarem uma unica unidade, a realidade que para o microprocesco e sador elas so distintas e, como tal, cada uma delas necessita do seu prprio a o identicador. Elas podem inclusivamente nem sequer ter o mesmo tamanho. Por exemplo, para estes quatro exemplo os cdigos das instrues mov so, o co a pela ordem em que eles aparecem: 0x89, 0xc7, 0xb8 e 0xb0. De qualquer forma, ao longo deste texto, referida sempre a instruo e ca mov e no o conjunto de instrues mov, mas chama-se a ateno para o a co ca facto de que isto se trata de um abuso de linguagem, do ponto de vista do processador. E de referir que a sintaxe do assemblador que se descreve (Gas) ajuda a fazer esta distino entre instrues pertencentes ao mesmo conjunto, j que ca co a permite alterar o nome da instruo de forma a identicar a dimenso dos ca a operandos envolvidos, atravs de um suxo b, w ou l (byte - 8 bits, word e - 16 bits ou longo - 32 bits) como se poder ver pelas instrues atrs aprea co a

4.1. INTRODUCAO

47

sentadas. Esta distino no obrigatria, podendo ser omitida sempre que ca a e o for poss ao assemblador deduzir implicitamente a dimenso da operao. vel a ca Na instruo mov $150, %eax, por exemplo, poss saber que se trata de ca e vel uma instruo de 32 bits, pelo que no obrigatrio escrever movl. Para o ca a e o programador, tambm aqui, a regra clara: tornar o cdigo o mais leg e e o vel poss vel. Por este motivo aconselhvel a utilizao do suxo que indica a e a ca dimenso da operao. a ca Quanto aos operandos das instrues a apresentar, estes recebero nomes co a diferentes conforme a situao em que venham a ser utilizados e, em particca ular, conforme as restries que se aplicam ` instruo em causa. Assim, a co a ca tabela 4.1 resume todos os tipos de operandos existentes. Mnemnica o Signicado Operando que aparece frequentemente ` esquerda do a sinal de atribuio . No poder ser um literal. ca a a Designado por valor esquerdo ou destino. Poder ser a um registo ou uma clula de memria. Por este motivo e o tem a designao alternativa de reg-mem. Conforme ca o contexto ser utilizada uma das designaes. a co Operando que aparece ` direita do sinal de atribuio a ca . Designado por valor direito ou origem. Poder a ser um operando qualquer, inclusive um literal. Por este motivo, tambm poder ter a designao alternae a ca tiva de op. Conforme o contexto ser utilizada uma a das designaes. co Operando tem que forosamente ser um registo. c Operando tem forosamente que referir-se a um enc dereo duma clula de memria. c e o Operando s poder ser um literal. o a Tabela 4.1: Tipos de operandos

dst, reg-mem

org, op

reg mem literal

Alm dos tipos de operandos que aparecem na tabela ainda necessrio e e a ter em conta o conjunto de restries que se aplicam a cada um deles, que co

48

CAP ITULO 4. INSTRUCOES GERAIS

sero necessariamente enumeradas ` medida que forem sendo apresentadas a a as instrues. Sobre os operandos dst e org h que referir que estes operanco a dos so intrinsecamente diferentes, como se poder constatar na seguinte a a expresso: a dst org E evidente que o operando dst nunca poder ser um literal, enquanto o a operando org pode perfeitamente ser um literal (o nmero 5 por exemplo). u Nem todas as instrues tm obrigatoriamente um operando origem e um co e destino: o caso da instruo xchg, que ser apresentada na seco 4.3, que e ca a ca no usa um operando origem, sendo ambos operandos destino. a Outra restrio que se aplica sistematicamente diz respeito ao registo ca eip. A utilizao directa deste registo pura e simplesmente imposs ca e vel. As formas de o alterar sero sempre indirectas como veremos mais adiante. a

4.2

Instruo mov ca
mov org, dst
dst org

Instruo de atribuio. ca ca A instruo mov possivelmente, e de entre todas as que existem na ca e fam de processadores 80x86, a mais utilizada. lia Esta instruo inclui sempre dois operandos e destina-se a atribuir o valor ca do operando org ao operando dst. O operando org ser, assim, a origem que a no afectada pela operao e dst o destino, que no m da instruo toma a e ca ca o valor do operando org, destruindo irremediavelmente qualquer valor que l estivesse armazenado previamente. Trata-se, portanto, duma instruo de a ca atribuio. ca

4.2. INSTRUCAO MOV

49

Os operandos org e dst podem ser diversos, embora com algumas limitaes. co Na tabela 4.1 esto ilustradas as vrias formas poss a a veis para os dois operan dos e na tabela 4.2 as respectivas restries. E de notar que a posio em que co ca aparecem os operandos na tabela relevante. Assim, quando numa determie nada linha aparece um operando sozinho isto signica que este operando no a pode ser utilizado. E o caso do registo eip quer como operando destino, quer como operando origem. Quando aparecem dois operandos na mesma linha, isso signica que essa combinao no existe. Por exemplo, o operando ca a destino e o operando origem no podem ser endereos de clulas de memria a c e o em simultneo. a Note-se tambm que conforme a dimenso dos operandos haver difere a a entes instrues mov: movb (8 bits), movw (16 bits) e movl (32 bits). Como co e natural, s poss fazer atribuies entre operandos da mesma dimenso oe vel co a e em funo desta dimenso que se aplica uma das vrias instrues mov e ca a a co existentes.

Valor direito (org) clula de memria e o registo eip/ip literal registo de segmento

Valor esquerdo (dst) clula de memria e o registo registo registo registo eip/ip de segmento de segmento cs

Tabela 4.2: Restries aos operandos na instruo mov co ca

De seguida so apresentados alguns exemplos ilustrados no cdigo 4.2. a o Os dois primeiros exemplos so bvios e esto comentados. a o a

50 movl $25, %eax movb %ah, %al movl $numero, %eax movl numero, %eax

CAP ITULO 4. INSTRUCOES GERAIS


eax 25
32

al ah
8

(4.2)
32 32

eax numero eax M[numero]

A diferena entre os dois ultimos exemplos subtil, mas importante. c e Considere-se a situao da gura 4.1, onde existe uma clula de memria com ca e o 32 bits (na realidade so quatro posies de memria diferentes) designada a co o por numero. O endereo do primeiro byte desta clula 5000 e o seu contedo c e e u 20. e
numero = 5000 20 eax ?

Figura 4.1: Valor armazenado em memria, no endereo designado por o c numero

Aps a instruo movl numero, %eax, o registo eax vai valer 20. Se, o ca porm, se zer movl $numero, %eax, o registo eax car com o valor 5000. e a

4.3

Instruo xchg ca
xchg dst1, dst2
dst2 dst1

Troca o contedo de dois operandos. u A instruo xchg (exchange que em ingls signica trocar) recebe ca e dois operandos e permite trocar o seu contedo. u Ao contrrio do que sucede na instruo mov, aqui no existe o conceito a ca a de operando origem nem destino, uma vez que ambos so, em simultneo, a a

4.4. INSTRUCAO NOP

51

origem e destino. Seguem-se no cdigo 4.3 alguns exemplos de utilizao o ca desta instruo. ca xchgb valor, %al xchgw %ax, %si xchgl %eax, %esi
al M[valor]
8

si ax
16

(4.3)

esi eax
32

As duas primeiras restrio so bvias, estando a primeira j impl ca a o a cita na conveno adoptada neste texto para os operandos destino: nesta instruo ca ca nenhum dos operandos pode ser um valor literal. A outra restrio tem a ca ver com os tamanhos dos operandos que tm de ser iguais. Tambm no e e a e poss trocar directamente duas clulas de memria, nem trocar um registo vel e o de segmento com qualquer outro registo. Aplicam-se, alm destas, todas as e outras restries da tabela 4.3. co Operandos da instruo xchg ca literal registo eip/ip registo de segmento Tabela 4.3: Restries aos operandos na instruo xchg co ca

4.4

Instruo nop ca
nop
(nenhuma operao) ca

Instruo No operation. ca Esta instruo no faz nada e no tem qualquer operando. Porm, pode ca a a e apresentar alguma utilidade em determinadas circunstncias relativas a proba lemas de alinhamento e ` depurao de erros. Veja-se (Hahn, 1992). a ca

52

CAP ITULO 4. INSTRUCOES GERAIS

4.5

Instruo lea ca
lea mem, reg
reg mem
32

Carrega o endereo efectivo para registo de 32 bits. c A instruo lea (Load Eective Address Oset que em ingls signica ca e Carrega Deslocamento do Endereo Efectivo, numa traduo ` letra) perc ca a mite atribuir a um registo indicado em reg o deslocamento de memria repo resentado pelo operando mem (ver gura 3.3). Este operando tanto pode ser o nome duma varivel, como aparece no exemplo de cdigo 4.4, como poder a o a ser uma expresso mais complexa que indexa uma tabela em memria, como a o nos exemplos 4.5 e 4.6, respectivamente. leaw valor, %ax #S para 80286 o
ax valor
16

(4.4)

movl $16, %eax leal tabela(,%eax), %ecx


ecx tabela + eax
32

(4.5)

leal tabela, %ebx movl $4, %eax

ebx tabela
32

eax 4
32

(4.6)

leal (%ebx, %eax, 4), %ecx


ecx ebx + eax * 4
32

Como acontece em muitas instrues pode ser adicionado um suxo para co indicar a dimenso da operao, que neste caso ser sempre de 16 ou 32 bits a ca a (w ou l, respectivamente), uma vez que o valor a armazenar em op2 ser a sempre um endereo 2 . c
2

No 80286 a dimenso era de 16 bits, enquanto que no 80386 essa dimenso de 32. a a e

4.5. INSTRUCAO LEA

53

No exemplo 4.4 o registo ax toma o valor do deslocamento presente na varivel valor (80286). a Os exemplo 4.5 e 4.6 so mais complexos e iguais entre si, sendo que a o deslocamento efectivamente carregado no registo ecx o endereo onde e c comea a quinta posio do vector de inteiros tabela, tal como est reprec ca a sentado na gura 4.2. Note-se que, enquanto o primeiro exemplo equivalente ` instruo movl e a ca $valor, %ax, no poss s com instrues mov substituir as instrues a e vel o co co dos exemplos subsequentes, embora tal fosse poss e relativamente trivial vel de fazer com uma combinao das instrues mov e add, a apresentar mais ca co adiante, embora com claro preju de desempenho. zo
452 448 444 440 436 tabela 432

tabela + 16

Figura 4.2: Resultado da instruo lea ca

As restries a aplicar ` instruo lea so as que esto impl co a ca a a citas nos tipos de operandos, alm das representadas na tabela 4.4. e reg registo eip/ip registo de segmento registo de 8 bits Tabela 4.4: Restries aos operandos na instruo lea co ca

54

CAP ITULO 4. INSTRUCOES GERAIS Como se ver na seco 6.2 a instruo lea pode ser usada para efectuar a ca ca

adies. co

4.6

Instrues lds, les, lfs, lgs e lss co


lds mem, reg
reg M[mem]
32

ds M[mem + 4]
16

Carrega endereo efectivo para registo de segmento ds e para registo de c 32 bits. Nesta seco sero apresentadas vrias instrues, que apesar de algumas ca a a co diferenas, so muito semelhantes entre si. Por este motivo, sempre que for c a necessrio concretizar alguma explicao, vai ser utilizada a instruo lds, a ca ca no sendo, por regra, dif generalizar essas mesmas explicaes `s restantes a cil co a instrues. co O operando mem dever ser o endereo duma clula de memria; reg um a c e o registo. As restries que afectam os operandos so as mesmas que afectavam co a a instruo lea. Note-se que no h restries ao operando que referencia ca a a co uma clula de memria (alm da restrio que este facto constitui). As e o e ca restries esto, ento, representadas na tabela 4.4. co a a lds, que signica Load Data Segment(Carrega Segmento de Dados) tem um duplo efeito: altera o registo especicado em reg e altera o registo do segmento de dados ds. Para isso a partir da clula de memria e o especicada em mem dever estar um endereo vlido de 48 bits (segmento a c a + deslocamento), sendo atribu dos a reg os primeiros 32 bits relativos ao deslocamento e a ds os ultimos 16 bits relativos ao segmento. A gura 4.3 procura ilustrar o funcionamento desta instruo, em particular como que ca e se representa um ponteiro completo em memria. o

4.6. INSTRUCOES LDS, LES, LFS, LGS E LSS


numero
16 bits
Endereo

55

xxxxxxxx
segmento: 0x23 deslocamento: 0x8048440

0x23 0x8048440
32 bits

ptr_completo + 4

ptr_completo

Figura 4.3: Ponteiro de 48 bits para a instruo lds ca

No m da instruo ca lds ptr completo, %ebx


ebx M[ptr completo]
32

ds M[ptr completo + 4]
16

o registo ebx toma o valor do endereo da varivel numero (0x8048440) e c a o registo de segmento ds o valor do segmento 0x23 (onde se assume estar a varivel numero). a As instrues les (Load Extended Data Segment- Carrega Segmento de co Dados Estendido), lfs, lgs e lss so em tudo equivalentes, com a diferena a c de que o registo de segmento afectado , respectivamente, e como o nome e indica es, fs, gs, e ss. Estas instrues so pouco uteis no Unix, porque um programa utiliza co a apenas um unico segmento. Por este motivo, no h necessidade de alterar a a os registos de segmento. E importante referir que uma tentativa de carregar um valor invlido num a registo de segmento resulta na gerao duma excepo que termina com um ca ca envio do sinal SIGSEGV ao processo que faz essa tentativa (a que se segue, em geral, um coredump). Isto signica que o operando mem tem que se referir a uma zona de memria correctamente preparada para a instruo lds ou o ca

56

CAP ITULO 4. INSTRUCOES GERAIS

para uma das suas congneres. O cdigo 4.7 mostra como poderia ser feita e o a inicializao conducente ` situao da gura 4.3, seguido da instruo lds ca a ca ca propriamente dita.

movl $numero, ptr completo


M[ptr completo] numero
32

movw %ds, %ax

ax ds
16

movw %ax, ptr completo + 4


M[ptr completo + 4] ax
16

lds ptr completo, %ebx

ebx M[ptr completo]


32

ds M[ptr completo + 4]
16

(4.7)

Usando tambm directivas de denio de dados (a apresentar no cap e ca tulo 8), ter amos a situao ilustrada no cdigo 4.8. ca o

numero:

.int 1225 #Um valor qualquer .long $numero


M[ptr completo] numero
32

ptr completo:

movw %ds, %ax

ax ds
16

movw %ax, ptr completo + 4


M[ptr completo + 4] ax
32

lds ptr completo, %ebx

ebx M[ptr completo]


32

ds M[ptr completo + 4]
16

(4.8)

4.7. INSTRUCOES PUSH E POP

57

4.7

Instrues push e pop co


push op
esp esp - 4
32

M[esp] op
32

pop reg-mem

op M[esp]
32

esp esp + 4
32

Instruo push: carrega dados de operando para a pilha. Instruo pop: ca ca descarrega dados da pilha para operando. As instrues push e pop admitem um unico operando. A instruo push co ca armazena o valor do operando op na pilha, enquanto que a operao pop ca faz precisamente o contrrio, i.e., retira um valor da pilha e armazena-o no a operando reg-mem. O armazenamento dum valor qualquer na pilha, atravs da instruo e ca push, feito em dois passos: e em primeiro lugar, o registo que indica onde est o topo da pilha (esp) a actualizado (decrementado) de forma a reservar espao para o novo e c valor; depois, o valor passado no operando op copiado para a zona de e memria apontada pelo deslocamento esp (relativamente ao in do o cio segmento ss stack segment). Em termos de instrues, estes dois passos correspondem ao cdigo 4.9. co o No cdigo assume-se que o operando op tem a dimenso de quatro bytes. o a Caso fosse apenas de dois a primeira instruo decrementaria apenas duas ca unidades ao registo esp e a segunda seria relativa a uma palavra (movw). subl $4, %esp movl op, (%esp)
esp esp - 4
32

(4.9)
32

M[esp] op

58

CAP ITULO 4. INSTRUCOES GERAIS A instruo pop faz precisamente o contrrio, i.e., retira primeiro o valor ca a

da pilha e, depois, incrementa o registo esp no nmero de unidades necessrias. u a O funcionamento das instrues push e pop com 32 bits encontra-se repreco sentado nas guras 4.4 e 4.5. As setas cinzentas indicam a posio nal do ca topo da pilha (registo esp).
op yyyyyy op xxxxxx

esp esp-4 yyyyyy

esp+4 esp xxxxxx

pushl op esp esp - 4


32

popl op op M[esp]
32

M[esp] op
32

esp esp + 4
32

Figura 4.4: Instruo push ca

Figura 4.5: Instruo pop ca

Como se poder inferir da descrio feita, a pilha cresce dos endereos a ca c mais altos para os mais baixos, sendo normal dizer-se, por este motivo, que a pilha cresce para baixo. Note-se que isto no se trata de nenhuma conveno, a ca mas de um facto concreto inerente ao funcionamento dos microprocessadores da fam 80x86, onde o registo esp decrementado pela instruo push e lia e ca incrementado pela instruo pop. ca Embora ` primeira vista possa no ser muito evidente a utilidade de a a ter uma pilha e de usar estas instrues, ` medida que forem apresentados co a alguns exemplos de programas reais, essa utilidade vai tornar-se cada vez mais evidente. Para j ca registado que a pilha serve para os seguintes ns a (o segundo e o terceiro itens desta lista no so evidentes para j): a a a armazenar valores temporrios sem ser necessrio recorrer a variveis a a a

4.7. INSTRUCOES PUSH E POP

59

ou a registos; esta capacidade tanto mais util quanto menos registos e houver na mquina; a armazenar o endereo de retorno duma funo; c ca passar parmetros ou receber resultados duma funo. a ca Os operandos admitidos pelas duas instrues podem ter 16 ou 32 bits; co podem ser registos (qualquer um) ou clulas de memria. Como sempre, e o quando os operandos tm 16 bits usa-se o suxo w, quando tm 32 bits, e e usa-se o suxo l. Como exemplo, vamos pensar num caso em que fosse necessrio trocar a o contedo do registo ax com o es. Infelizmente no poss efectuar a u a e vel troca directamente com a instruo xchg, pelo que poder ca amos, recorrendo a ` pilha, usar a soluo apresentada no cdigo 4.10. ca o pushw %ax pushw %es popw %ax popw %es Este exemplo ilustra tambm o facto de os elementos serem retirados e da pilha pela ordem inversa em que a so colocados (neste caso como esse a requisito no cumprido os registos acabam trocados) da o nome de pilha a e que foi dado a esta estrutura de dados. No pode ser omitida aqui uma informao de importncia essencial: a ca a para que o programa funcione e, em particular, termine correctamente e necessrio que se retirem todos os objectos colocados na pilha. Tambm no a e a podem ser retirados objectos a mais. Isto signica que o registo esp antes da ultima instruo do programa (ret, como teremos ocasio de ver) deve ca a ser precisamente igual ao que era no in cio. (4.10)

60

CAP ITULO 4. INSTRUCOES GERAIS Outro aspecto importante tem a ver com a localizao da pilha: quando ca

um programa arranca tem j forosamente que incluir uma zona de memria a c o reservada para esse efeito.

4.8

Instrues pusha e popa co


pusha
M[esp - 4] eax
32 32

M[esp - 8] ecx M[esp - 12] edx


32

... M[esp - 32] edi


32

esp esp - 32
32

popa

edi M[esp]
32

esi M[esp + 4]
32

ebp M[esp + 8]
32

ebx M[esp + 16]


32

... ebp M[esp + 28]


32

esp esp + 32
32

Instruo pusha: carrega todos os registos para a pilha. Instruo popa: ca ca descarrega todos os registos da pilha. As instrues pusha e popa so invocadas sem qualquer parmetro. Reco a a spectivamente, guardam e retiram os seguintes registos da pilha, pela ordem em que so aqui enumerados: eax, ecx, edx, ebx, esp original, ebp, esi a e edi. Da instruo pusha resulta um decremento de 32 bytes no registo ca esp, enquanto que da instruo rec ca proca, popa, resulta um incremento de

4.9. INSTRUCOES PUSHF E POPF

61

32 bytes no mesmo registo. A instruo popa no altera o registo esp, sendo ca a o valor armazenado na pilha descartado. Estas instrues podem ser uteis numa situao em que se pretenda salco ca vaguardar o valor de todos os registos, para os recuperar mais tarde. Ser a o caso duma funo, por exemplo, que utilize os registos no seu cdigo, mas ca o que lhes reponha o valor original antes de terminar.

4.9

Instrues pushf e popf co


pushf
esp esp - 4
32

M[esp] eags
32

popf

eags M[esp]
32

esp esp + 4
32

Instruo pushf: carrega o registo eflags na pilha. Instruo popf: ca ca descarrega o registo eflags da pilha. pushf e popf no tm operandos. Respectivamente, guardam e retiram a e o registo das ags, eflags, da pilha.

62

CAP ITULO 4. INSTRUCOES GERAIS

Instrucoes de Controlo de Fluxo


5.1 Introduo ca

No cap tulo 4 foi apresentado um conjunto de instrues que sero utilizadas co a com muita frequncia. No entanto, no poss e a e vel escrever um programa dispondo apenas deste conjunto. Com efeito, nenhuma destas instrues perco mite alterar o uxo de execuo do programa. Quer isto dizer que a sequncia ca e de instrues executadas permanece inalterada, independentemente de quaisco quer entradas externas ao programa. Naturalmente que esta situao no ca a e razovel e qualquer microprocessador tem que incluir um conjunto adicional a de instrues, chamadas de controlo de uxo. Grosso modo, estas inco strues permitem que em determinados pontos dum programa seja poss co vel optar por uma sequncia de instrues ou por outra. e co

5.2

Instruo jmp ca
jmp mem
eip mem
32

Salto incondicional. De entre as instrues de controlo de uxo, a instruo jmp (jump co ca salto) a mais simples de todas. Posto de uma forma simples, o resultado da e 63

64

CAP ITULO 5. INSTRUCOES DE CONTROLO DE FLUXO

instruo jmp equivale a alterar o valor do registo eip com uma instruo mov ca ca (embora isso no seja poss de fazer), tal como se encontra neste exemplo a vel de cdigo: o movl $0x08400000, %eip #impossvel
eip 0x08400000
32

(5.1)

jmp $0x08400000 #certo

eip 0x08400000
32

Como o registo eip guarda o endereo da prxima instruo a executar, c o ca o resultado prtico de alterar o valor deste registo traduz-se num salto na a ordem pela qual so executadas as instrues. a co Antes de se passar a um exemplo concreto, tem que ser introduzido o conceito de rtulo, que se apresentar de seguida. A esta instruo no se o a ca a aplica qualquer restrio para alm do facto de ser necessrio que o operando ca e a tenha 32 bits. Desta forma, o operando poder ser um literal, um registo ou a um deslocamento de memria. o

5.3

Rtulos o

A realizao de cdigo com o aspecto apresentado no exemplo 5.1 no muito ca o a e prtica. No razovel exigir ao programador que saiba em que endereo a a e a c e que se encontra cada uma das instrues do cdigo para onde pretende fazer co o um salto no uxo de execuo (com a instruo jmp) 1 . ca ca Para resolver esse problema, existem os rtulos, que permitem identio car, atravs dum nome intelig para o programador, endereos concretos e vel c
Alis, o caso no exactamente este, porque s numa fase que se sucede ` assemblagem a a e o a essa fase a edio de ligaes, como se ver que ca determinado o endereo onde e ca co a e c caro localizadas as partes dum programa, incluindo o cdigo executvel. Portanto, a o a quando muito seria poss fazer referncias relativas ao in da seco de cdigo. vel e cio ca o
1

5.3. ROTULOS

65

de partes do programa. No caso presente interessa-nos que os rtulos identio quem o in duma instruo para onde se deseja saltar. cio ca Um rtulo um s o e mbolo seguido por dois pontos (:). O nome de um s mbolo pode comear por qualquer letra, pelo ponto ou pela barra inferior c (. e , respectivamente). Os restantes caracteres, que podem ser em nmero arbitrrio, podem ser tambm algarismos. O cifro ($) pode ser u a e a inclu no nome de um rtulo. Nos nomes assim denidos a distino entre do o ca maisculas e minsculas relevante, sendo o rtulo Lixo diferente de lixo, u u e o por exemplo. E essencial compreender que o conceito de rtulo existe num n acima o vel do microprocessador e que um rtulo no tem (como dever ser evidente) o a a qualquer traduo em termos de instrues de cdigo mquina. Quando o ca co o a microprocessador executa o cdigo a que no programa assembly corresponde o jmp nome do rotulo, o que encontra de facto no lugar do rtulo um eno e dereo, i.e., jmp 0x08000000. c Podem-se ento apresentar dois exemplos de utilizao da instruo jmp. a ca ca No primeiro, representado no cdigo 5.2 a instruo que se segue ao jmp o ca nunca executada; no segundo, ilustrado no cdigo 5.3, os saltos so feitos e o a a partir de endereamentos indexados. Neste caso, o endereo de destino do c c salto vai ser encontrado algures numa clula de memria. Este um caso e o e interessante em que o destino do salto no conhecido ` partida. a e a

movl $20, %eax jmp ignora ebx movl %eax, %ebx ignora ebx: movl %eax, %ecx

eax 20
32

eip ignora ebx


32

ebx eax
32

(5.2)

ecx eax
32

...

66

CAP ITULO 5. INSTRUCOES DE CONTROLO DE FLUXO jmp tabela(, %esi) ... jmp (%ebx, %ecx, 1)
eip M[ebx + 1 ecx]
32

eip M[tabela + esi]


32

(5.3)

5.4

Saltos Condicionais Instruo jcc ca


jcc mem
cc ? eip eip + mem
32

Salto condicional. Mesmo depois de apresentada a instruo jmp muitas das limitaes que ca co descrevemos no in deste cap cio tulo continuam a aplicar-se, uma vez que a instruo jmp permite fazer, apenas, saltos incondicionais 2 . ca Para realizar saltos condicionais, existem as instrues jcc. Ao j co e acrescentado um suxo, que varia consoante o teste que dever ser efectuado a pela instruo (representado por cc). Ao j e ao suxo, que compem o nome ca o da instruo, acresce um operando, de acordo com a forma atrs apresenca a tada. O operando da instruo jcc dever ser um nmero inteiro (positivo ca a u ou negativo), que representa a distncia relativamente ` posio actual do a a ca registo eip. Na prtica, e para simplicar a programao, poss utilizar a ca e vel um deslocamento de memria representado por um rtulo, em vez de ser o o necessrio indicar a distncia, cabendo ao assemblador fazer as contas que a a forem necessrias. a No cdigo 5.4, utilizado o rtulo ptoA, sendo sempre o assemblador o e o responsvel por determinar a distncia em termos de bytes, desde o ponto a a da instruo jcc, que faz a referncia ao rtulo ptoA at esse mesmo rtulo. ca e o e o
Isto no signica, no entanto, que o destino do salto seja sempre o mesmo. Veja-se a por exemplo o cdigo 5.3. o
2

5.4. SALTOS CONDICIONAIS INSTRUCAO JCC jz ptoA movl %eax, %ebx ptoA: movl %eax, %ecx
ecx eax
32

67

ZF == 1 ? eip eip + 2
32

ebx eax
32

(5.4)

Ao contrrio do que sucedia com o JMP, aqui o operando no indica um a a endereo absoluto, mas um endereo relativo ` instruo actual. Isto sigc c a ca nica que se o teste, que a prpria instruo efectua, for verdadeiro vai ser o ca adicionado o valor do operando ao registo eip. Caso contrrio, o uxo de a execuo prossegue na instruo imediatamente a seguir. ca ca Tambm aqui, e felizmente para o programador, no necessrio saber a e a e a localizao absoluta, nem to pouco relativa, das instrues. Continua a ser ca a co poss usar rtulos, cabendo ao assemblador fazer o clculo das distncias vel o a a a usar na linguagem mquina. a Quase todas as instrues jcc tem duas representaes diferentes em co co cdigo mquina (uma excepo a instruo jcxz). Isto tem a ver com uma o a ca e ca optimizao que poss fazer caso o deslocamento relativo esteja contido ca e vel no intervalo [128, 127]. Neste caso bastam apenas 8 bits para representar o deslocamento sendo, ento, poss representar toda a instruo com apea vel ca nas 2 bytes (um byte para o cdigo da instruo outro para o deslocamento). o ca Quando o deslocamento relativo sai fora desta gama, passam a ser usados deslocamentos de 32 bits, que acrescentados aos 2 bytes para o cdigo da o instruo, totalizam 6 bytes por instruo. Isto o triplo da situao anca ca e ca terior. Por este motivo, o assemblador deve ter o cuidado de vericar se o deslocamento pode ser representado com apenas 1 byte. Na tabela 5.1 apresentada uma lista completa das instrues de salto e co condicional. Nesta tabela encontram-se representadas tambm as ags que e so vericadas e o valor que devem assumir para que cada um dos saltos a

68

CAP ITULO 5. INSTRUCOES DE CONTROLO DE FLUXO

condicionais se verique. Naturalmente que antes de o cdigo atingir uma instruo de salto condio ca cional jcc o programador tem que saber exactamente o valor que as ags assumem em cada situao poss ca vel e que ags so vericadas pelo salto a condicional, sob pena de o programa se comportar duma forma inesperada. Para facilitar esta tarefa existe uma operao que permite manipular as ags ca e que ser apresentada de seguida. A utilizao desta instruo vai permitir a ca ca utilizar os saltos condicionais jcc duma forma muito mais intuitiva, ao ponto de no ser necessrio ao programador conhecer exactamente quais as ags a a avaliadas por cada instruo de salto condicional. ca

5.5

Instruo cmp ca
cmp org, dst
eags dst org

Compara dois operandos. Esta operao efectua a subtraco dst- org, afectando as ags em funo ca ca ca do resultado, mas sem afectar qualquer dos operandos. A ideia que, depois e de um cmp, venha um salto condicional, cujo resultado como se viu depende de uma ou mais ags. As restries que se aplicam aos operandos da instruo cmp so as mesco ca a mas que se aplicavam ` instruo mov e esto descritas na tabela 4.2. Alm a ca a e destas restries, aplica-se uma outra que diz que nenhum dos operandos co poder ser um registo de segmento. a Para que se compreenda melhor a utilizao desta instruo, apresenca ca e tado de seguida um exemplo, que corresponde ` estrutura de deciso if-else a a habitualmente existente nas linguagens de alto n vel. No exemplo apresentado verica-se se o valor presente no registo eax positivo. Se for, efece e

5.6. INSTRUCOES LOOP E LOOPCC tuada uma adio, caso contrrio uma subtraco: ca a ca

69

cmpl $0, %eax jg L1 jmp L2 L1: #efectua a adi~o ca jmp L3 L2: #efectua a subtrac~o ca L3:

eags

eax - 0
32

se (ZF == 0 && SF == OF) ento eip eip + x1 a eip eip + x2


32

eip eip + x3
32

(5.5)

5.6

Instrues loop e loopcc co


ecx ecx - 1
F

loop rotulo

ecx != 0 ? eip eip + yy

loopz rotulo

ecx ecx - 1
F

ecx != 0 && ZF == 1 ? eip eip + yy

loope rotulo

ecx ecx - 1
F

ecx != 0 && ZF == 1 ? eip eip + yy

loopnz rotulo

ecx ecx - 1
F

ecx != 0 && ZF == 0 ? eip eip + yy

loopne rotulo

ecx ecx - 1
F

ecx != 0 && ZF == 0 ? eip eip + yy

70

CAP ITULO 5. INSTRUCOES DE CONTROLO DE FLUXO Instruo loop: usa o registo ecx para controlar um ciclo. Instrues ca co

loopcc: usam o registo ecx e a ag ZF para controlar um ciclo. A instruo loop admite apenas um operando com signicado idntico ca e ao da instruo jcc: distncia do salto a efectuar, sendo que esta distncia ca a a relativa ` instruo actual e representada apenas por um byte. No caso e a ca e da instruo loop no existem deslocamentos relativos de 32 bits. Por este ca a motivo, a distncia do salto est limitada aos 128 bytes anteriores e aos 127 a a bytes posteriores ` instruo seguinte ao salto. O seu modo de operao o a ca ca e seguinte: decrementa o registo ecx em uma unidade (sem afectar qualquer ag); se ecx = 0 salta para o ponto indicado pelo operando (a partir do valor corrente do registo eip), seno continua normalmente na instruo seguinte. a ca Considere-se como exemplo a seguinte situao: existe uma tabela com ca dez nmeros inteiros em memria e o objectivo adicionar esses dez nmeros. u o e u Uma forma de resolver o problema seria criando um ciclo controlado por um par de instrues cmp e jcc. Em vez disso, poderemos utilizar a instruo co ca loop, tal como aparece no exemplo de cdigo 5.6. o movl $10, %ecx movl $0, %eax ciclo: addl tabela - 4(, %ecx, 4), %eax
eax M[tabela - 4 + 4 ecx]
32 F

ecx 10
32

eax 0
32

loop ciclo

ecx ecx - 1 ecx != 0 ? eip eip + yy

(5.6) A instruo loop apresenta duas variantes, que alm de decrementarem ca e e testarem o valor de ecx, vericam tambm o valor da ag ZF: e

5.7. INSTRUCOES STD, CLD, STI, CLI, STC, CLC, CMC loope/loopz: salta se ecx != 0 e ZF == 1; loopne/loopnz: salta se ecx != 0 e ZF == 0.

71

Estas verses do loop permitem utilizar a instruo cmp antes (ou qualo ca quer outra que afecte a ag ZF), o que poder constituir uma vantagem, a sempre que se pretender uma conjugao de condies. ca co

5.7

Instrues std, cld, sti, cli, stc, clc, cmc co


std cld stc clc cmc
DF 1
1 1

DF 0 CF 1
1

CF 0
1

CF CF
1

Afectao das ags. ca Nenhuma das instrues de afectao das ags aceita operandos. O nome co ca e a funo destas instrues est resumida na tabela 5.2. Alm destas inca co a e strues para limpar e activar ags existem ainda as instrues sti e cli, co co que sero apresentadas nas Seces 11.4 e 11.5. a co

72

CAP ITULO 5. INSTRUCOES DE CONTROLO DE FLUXO

Instruo ca ja jnbe jae jnb jb jnae jbe jna je jz jne jnz jg jnle jge jnl jnge jl jle jng jb jc jnc jno jo jnp jpo jp jpe jns js jcxz

Descrio ca Jumps if Above Jumps if Not Below or Equal Jumps if Above or Equal Jumps if Not Below Jumps if Below Jumps if Not Above or Equal Jumps if Below or Equal Jumps if Not Above Jumps if Equal Jumps if Zero Jumps if Not Equal Jumps if Not Zero Jumps if Greater Jumps if Not Less or Equal Jumps if Greater or Equal Jumps if Not Less Jumps if Not Greater or Equal Jumps if Less Jumps if Less or Equal Jumps if Not Greater Jumps if Borrow Jumps if Carry Jumps if Not Carry Jumps if Not Overow Jumps if Overow Jumps if Not Parity Jumps if Parity Odd Jumps if Parity Jumps if Parity Even Jumps if Not Signal Jumps if Signal Jumps if CX zero

Flags testadas CF = 0 e ZF = 0 CF = 0 e ZF = 0 CF = 0 CF = 0 CF = 1 CF = 1 CF = 1 ou ZF = 1 CF = 1 ou ZF = 1 ZF = 1 ZF = 1 ZF = 0 ZF = 0 ZF = 0 e SF = OF ZF = 0 e SF = OF SF = OF SF = OF SF = OF SF = OF ZF = 1 ou SF = OF ZF = 1 ou SF = OF CF = 1 CF = 1 CF = 0 OF = 0 OF = 1 PF = 0 PF = 0 PF = 1 PF = 1 SF = 0 SF = 1 cx = 0

Tabela 5.1: Instrues de salto condicional co

5.7. INSTRUCOES STD, CLD, STI, CLI, STC, CLC, CMC

73

Instruo ca std cld sti cli stc clc cmc

Acrnimo o Set Direction Flag Clear Direction Flag Set Interrupt Flag Clear Interrupt Flag Set Carry Flag Clear Carry Flag Complement Carry Flag

Descrio ca Assinala ag DF Limpa ag DF Assinala ag IF Limpa ag IF Assinala ag CF Limpa ag CF Troca valor de ag CF

Tabela 5.2: Instrues para alterao das ags co ca

74

CAP ITULO 5. INSTRUCOES DE CONTROLO DE FLUXO

Instrucoes Aritm ticas e


6.1 Introduo ca

Neste cap tulo so apresentadas as instrues do 80386 que permitem efeca co tuar operaes aritmticas e as mnemnicas que lhes correspondem na linco e o guagem assembly. Naturalmente que este um conjunto de instrues que e co um microprocessador no poderia dispensar. a Antes de se introduzirem as instrues, chama-se a ateno para dois co ca aspectos importantes. Em primeiro lugar, todas as operaes aritmticas que co e estas instrues realizam so inteiras. Para realizar operaes com v co a co rgula utuante tero de ser usadas instrues do co-processador aritmtico, no a co e a abordado neste texto. Veja-se sobre este assunto (Murray & Pappas, 1986). O outro aspecto importante a ter em conta prende-se com a dimenso a das operaes. Como no 80386 os registos tm 32 bits, as operaes esto co e co a limitadas a esta dimenso, embora com duas importantes excepes: nas dia co vises o dividendo pode ter at 64 bits, nas multiplicaes o produto tambm o e co e pode ser armazenado em 64 bits. No m deste cap tulo, na seco 6.9 encontram-se resumidas em forma de ca tabela as restries que se aplicam aos operandos das operaes aritmticas. co co e 75

76

CAP ITULO 6. INSTRUCOES ARITMETICAS

6.2

Adio ca
add org, dst adc org, dst
dst dst + org dst dst + org + CF

Instruo add: adio. Instruo adc: adio com transporte. ca ca ca ca Existem duas operaes de adio diferentes: add e adc. Ambas recebem co ca dois operandos e adicionam-nos, deixando a soma no segundo operando (dst) que , portanto, alterado por esta instruo. A diferena entre add e adc e ca c e que adc considera na adio o valor actual da ag de transporte (CF). Isto ca signica que a soma depender no s das parcelas, mas tambm do resultado a a o e da ultima instruo que tenha alterado a CF antes da adio. ca ca As restries que se aplicam aos operandos so anlogas `s que se aplico a a a cavam ` instruo mov, por exemplo, e esto representadas na tabela 4.2. Ver a ca a tambm 6.5. e A t tulo de regra poder dizer-se que quase sempre ser utilizada a ina a struo add, exceptuando alguns casos excepcionais em que a CF seja releca vante. Entre estes casos podero ser dados dois exemplos: a para calcular adies em complementos para um, a CF tem de ser reinco troduzida na soma 1 ; quando se pretende alargar a gama de representao dos nmeros para ca u alm do limite do processador (de 32 para 64 bits, por exemplo) ser e a necessrio efectuar a adio em duas partes: primeiro os bits menos a ca signicativos, depois os bits mais signicativos, sendo que nesta segunda adio tem que ser inclu o transporte resultante da primeira ca do (o mesmo se aplicaria na subtraco). ca
Um caso concreto em que necessrio calcular adies em complementos para um pee a co o se no clculo de somas de vericao dos segmentos TCP (Transmission Control Protocol ). a ca
1

6.2. ADICAO

77

Como exemplo de utilizao destas instrues, vamos considerar o cdigo 6.1 ca co o onde se adicionam os nmeros de 64 bits contidos nos registos edx:eax e u ecx:ebx, sendo a soma armazenada no primeiro par de registos. add %ebx, %eax #parte baixa
eax eax + ebx
32

(6.1)

adc %ecx, %edx #parte alta


edx edx + ecx + CF
32

Seguem-se outros exemplos mais simples. De referir que no terceiro exemplo o endereo da clula de memria que armazena a varivel end literal c e o a (e no o seu contedo) adicionado ao registo ecx, enquanto que no ultimo a u e adicionado ao registo eax o elemento de vector no caso uma palavra e que se inicia na posio dada pelo registo esi relativamente ao in do ca cio vector:

addb $8, %al addw %bx, memoria addl $end literal, %ecx

al al + 8
8

M[memoria] M[memoria] + bx
16

ecx ecx + end literal


32

addw vector(, %esi), %eax


eax eax + M[vector + esi]
32

A operao adio pode ser realizada duma forma alternativa, em algo ca ca que se poder classicar como uma caracter a stica curiosa dos processadores da fam x86. Neste caso, a instruo lea (veja-se seco 4.5) pode assumir lia ca ca um papel para o qual possivelmente no teria sido pensada. Veja-se, nesta a seco, o exemplo de cdigo 4.6, por exemplo. Em particular, para adicionar ca o os registos eax, ebx e o nmero 18 e guardar o resultado em ecx, poder-se-ia u fazer como se encontra no cdigo 6.2. Esta alternativa tem uma vantagem o

78

CAP ITULO 6. INSTRUCOES ARITMETICAS

clara em termos de codicao, uma vez que com a instruo add no seria ca ca a poss usar uma unica instruo. Em termos de desempenho a vantagem vel ca pende tambm para a instruo lea, que segundo (Murray & Pappas, 1986) e ca precisa apenas de 2 ciclos de relgio, contra 2 a 7 ciclos por cada instruo o ca add. leal 18(%eax, %ebx), %ecx (6.2)

6.3

Subtraco ca
sub org, dst sbb org, dst
dst dst org dst dst org CF

Instruo sub: subtraco. Instruo sbb: subtraco com emprstimo. ca ca ca ca e ` A semelhana do que sucede na adio, na subtraco existem tambm c ca ca e duas variantes: so elas sub e sbb na primeira no considerada a CF, a a e ao contrrio do que sucede na segunda. A mnemnica sbb signica suba o tract with borrow (subtrair com emprstimo). A situao mais normal ser e ca a utilizar-se a instruo sub, cando a instruo sbb remetida para casos mais ca ca invulgares, semelhantes aos que serviram de exemplo quando foi apresentada a adio. ca A diferena ser armazenada no operando dst, permanecendo org inalc a terado. As restries que se aplicam aos dois operandos so as mesmas que co a vigoram para as instrues add e adc. co Um aspecto muito relevante a ter em conta tem a ver com o formato em que so representados os nmeros negativos. De forma a efectuar as suba u traces directamente, ignorando o sinal dos operandos utilizada a repreco e sentao em complementos para dois, representao esta no abordada neste ca ca a texto. Conrma-se apenas o que se est a dizer atravs da apresentao dos a e ca

6.4. MULTIPLICACAO

79

exemplos representados na gura 6.1. E de referir que o aparecimento dum emprstimo para o bit mais signicativo resulta no assinalar da CF, mas que e esse facto no sinnimo de transbordo (que ser assinalado na OF). a e o a 00000000 00000001 11111111 11111111 0 11111111 11111110 11111111 11111100 = - 00000000 00001000 = 11111111 11110100 = 1 = +1 = -1 = +2 -4 +8 -12

Figura 6.1: Subtraco em complementos para 2 ca Sendo a subtraco efectuada desta forma evidente que os nmeros ca e u tambm podem ser considerados como no tendo sinal mas, neste caso, e a e preciso tomar ateno ao tratamento das subtraces de que resultariam ca co nmeros negativos: esta situao, que corresponde ` ocorrncia de transu ca a e bordo , desta vez, detectvel pela ag de transporte e no pela ag de e a a transbordo propriamente dita (i.e., pela CF e no pela OF). a

6.4

Multiplicao ca

A multiplicao outra das operaes aritmticas bsicas que aqui vo ser ca e co e a a apresentadas. Ao contrrio do que sucede na adio e na subtraco, onde o a ca ca facto de se considerarem os nmeros como tendo ou no sinal era irrelevante, u a graas ` representao em complementos para dois, aqui j no se passa o c a ca a a mesmo. Para perceber este facto considere-se o nmero binrio 1111, de u a apenas quatro bits. Importa saber se este nmero tem sinal, caso em que u representar o valor -1 ou se no tem, caso em que valer 15. Isto porque, a a a se este nmero for o multiplicador e se o multiplicando fosse igual a 2, por u exemplo, o resultado seria 11111110 (-2), se se considerasse sinal ou 00011110

80

CAP ITULO 6. INSTRUCOES ARITMETICAS

(30), caso contrrio e considerando que h 8 bits dispon a a veis para o resultado. Posto de outra forma, isto quer dizer que tem de haver duas multiplicaes co diferentes.

6.4.1

Multiplicao Sem Sinal ca


mul reg-mem
edx:eax reg-mem eax
64

Multiplicao sem sinal. ca A mais simples das multiplicaes a que no considera sinal. A instruo co e a ca que efectua esta operao chama-se mul. ca Recebe um unico operando que s pode ser uma clula de memria ou um o e o registo. No poder ser um literal. A instruo a efectuar, de facto, depende a a ca da dimenso do operando que poder ter 8, 16 ou 32 bits, de acordo com a a a tabela 6.1. Tamanho 1o Factor byte palavra longo 2o Factor al ax eax Produto ax dx:ax edx:eax

Tabela 6.1: Dimenso das operaes mul e imul a co

Sempre que o operando for uma clula de memria obrigatrio indicar e o e o a sua dimenso com um dos suxos habituais b, w ou l que se a adiciona como sempre ao nome da instruo. Caso contrrio no ser poss ca a a a vel ao assemblador saber a dimenso da operao em causa. a ca No sero apresentados exemplos desta instruo. Estes so, em tudo, a a ca a idnticos aos da instruo imul a apresentar j de seguida. e ca a No caso da multiplicao sem sinal (e tambm no caso da multiplicao ca e ca com sinal instruo imul quando esta s recebe um operando) nunca ca o

6.4. MULTIPLICACAO

81

pode ocorrer transbordo, uma vez que o espao para armazenar o produto c tem sempre o dobro dos bits dos factores. No entanto, se o produto exceder a dimenso dos factores iniciais (i.e., no couber em al, ax ou eax, conforme a a o caso) esse facto registado nas ags CF e OF que so postas a 1. Caso e a contrrio estas ags so limpas. a a

6.4.2

Multiplicao Com Sinal ca


imul reg-mem imul op, reg
edx:eax reg-mem eax
32

reg reg op

imul literal, reg-mem, reg


reg reg-mem literal

Multiplicao com sinal. ca A instruo que efectua a multiplicao com sinal a imul (multiplicao ca ca e ca inteira). Esta instruo tem trs variantes que diferem entre si no nmero e ca e u no signicado dos seus operandos. E de referir que a descrio apresentada ca da primeira verso desta instruo pressupe a utilizao de registos de 32 a ca o ca bits. Em termos de linguagem assembly utilizar-se-ia o suxo l para a instruo, nesse caso, ou seja, imull. Importa referir que tambm so poss ca e a veis operandos com 8 e com 16 bits. A primeira das trs , em tudo, semelhante ` multiplicao sem sinal e e a ca mul. Tambm aqui, reg-mem poder ser um registo ou uma clula de e a e memria, mas no um literal. O(s) registo(s) de armazenamento do resultado o a dependem do tamanho da operao em causa (8, 16 ou 32 bits), de acordo ca com a tabela 6.1. A afectao das ags tambm idntica. ca e e e Na segunda verso, que recebe dois operandos efectuado o produto do a e operando reg pelo valor do operando op, sendo o resultado armazenado em reg. Este operando tem de ser um registo com, pelo menos, 16 bits. O

82

CAP ITULO 6. INSTRUCOES ARITMETICAS

operando op ter de ter o mesmo tamanho de reg, a menos que aquele se a trate de um literal. Nesse caso o literal poder ter menos bits, cabendo a ao assemblador em alguns dos casos fazer a converso para nmeros com o a u nmero de bits adequado. Neste caso a converso ter de ter forosamente u a a c em conta o sinal desse nmero (ver subseco 6.6). u ca A terceira verso da instruo imul recebe trs parmetros, sendo cala ca e a culado o produto de reg-mem pelo valor literal com o resultado a car armazenado em reg. Aqui, tanto reg como reg-mem tm de ser registos com e a mesma dimenso (16 ou 32 bits). O literal poder ser menor. a a Nas mltiplas verses desta instruo, caso haja uma ultrapassagem da u o ca capacidade do registo ou clula(s) de memria que armazena(m) o resultado e o (o que no de todo imposs a e vel, porque se dois operandos tm n bits, podero e a ser necessrios at 2 n bits para armazenar o seu produto) esse facto a e e assinalado pelas ags CF e OF, que so postas a 1. Caso no haja transbordo a a CF e OF so limpas. As ags SF, ZF, AF e PF cam indenidas no m da a operao. ca De forma a exemplicar o funcionamento desta instruo, so apresenca a tados na gura 6.2 trs exemplos de cdigo e para cada um deles so ape o a resentados os registos eax e edx no seu estado nal. H alguns aspectos a a considerar, que facilitam a compreenso dos exemplos: a a extenso do nmero de bits de um nmero em complementos para a u u dois faz-se introduzindo nas posies mais signicativas bits com o valor co do sinal (ver subseco 6.6); ca eax e edx so iniciados a 0 para simplicar a anlise do resultado nal; a a em todos os casos sempre feita a multiplicao de -1 por 2, sendo e ca usado o registo ecx como multiplicador; s muda o espao dispon o c vel

6.5. DIVISAO para armazenar o resultado. movl $0, %edx movl $0x2, %eax movb $-1, %cl imulb %cl eax 00 edx 00 movl $0, %edx movl $0x2, %eax movw $-1, %cx imulw %cx eax 00 edx 00 movl $0, %edx movl $0x2, %eax movl $-1, %ecx imull %ecx eax edx

83

00 00

00

fe 00

00 00

fe

fe

Figura 6.2: Exemplos de utilizao da instruo imul ca ca

6.5

Diviso a
div reg-mem idiv reg-mem
eax edx:eax / reg-mem
32

eax edx:eax / reg-mem


32

Instruo div: diviso sem sinal. Instruo idiv: diviso com sinal. ca a ca a No caso da diviso, as instrues que consideram a existncia, ou no, de a co e a sinal so perfeitamente idnticas, pelo que prefer a e e vel serem apresentadas ` em conjunto. A semelhana do que acontecia na multiplicao, tambm aqui c ca e o prexo i designa a operao com sinal. Assim, a instruo div designa ca ca uma diviso sem sinal, enquanto idiv se refere a uma diviso com sinal. a a O operando recebido pela instrues div e idiv, que pode ser uma clula co e de memria ou um registo o divisor da operao. O dividendo a utilizar o e ca est dependente do tamanho do divisor, mas no pass a a e vel de ser seleccionado pelo programador poder ser um registo ou uma composio de a ca registos desde 16 at 64 bits: ax, dx:ax, edx:eax. O quociente e o resto so e a armazenados tambm em registos; quais, depende da dimenso da operao. e a ca A correspondncia exacta apresentada na tabela 6.2. e e

84

CAP ITULO 6. INSTRUCOES ARITMETICAS Divisor (op) byte Palavra Longo Dividendo ax dx:ax edx:eax Quociente al ax eax Resto ah dx edx

Tabela 6.2: Operaes div e idiv co

Como exemplo considere-se o caso em que se pretende dividir um valor armazenado em memria de 32 bits, pelo nmero 7. A soluo est ilustrada o u ca a no cdigo 6.3. Como no h garantia de o quociente caber em 16 bits convm o a a e efectuar uma diviso longa. Admite-se que nmero positivo. a u e

movl numero, %eax movl $0, %edx movl $7, %ecx idivl %ecx

eax M[numero]
32

edx 0
32

ecx 7
32

(6.3)

eax edx:eax / ecx


32 32

eax edx:eax % ecx

Se numero fosse negativo (i.e., tivesse 1 no bit mais signicativo) o cdigo 6.3 o estaria errado. A instruo movl $0, %edx teria de ser substitu por ca da outra(s) que zessem a extenso do nmero com sinal armazenado em eax a u de forma correcta. Esse ser o tema da prxima seco. a o ca

6.6

Extenso de N meros Com Sinal a u


cbtw cwtl cwtd cltd
ax al
16

eax ax
32

dx:ax ax
32

edx:eax eax
64

6.6. EXTENSAO DE NUMEROS COM SINAL

85

Instruo cbtw: Converte byte para palavra. Instruo cwtl: Converte ca ca palavra para longo. Instruo cwtd: Converte palavra para duplo. Instruo ca ca cltd: Converte longo para duplo. Em certas ocasies, nomeadamente para efectuar operaes aritmticas, o co e torna-se necessrio fazer o aumento do nmero de bits da representao dum a u ca nmero. Se esse nmero no tiver sinal esse aumento feito de forma trivu u a e ial, bastando para o efeito introduzir 0 em todos os bits que sero sempre a adicionados ` esquerda do nmero inicial. Na tabela 6.3 est ilustrada a a u a extenso do nmero 15 (1111) de 4 para 8 bits. a u Se fosse usada a mesma tcnica para estender nmero com sinal o mesmo e u padro binrio (1111), que representaria neste caso o nmero -1, seria estena a u dido para 15 o que estaria manifestamente incorrecto. Se em vez do nmero u anterior, fosse estendido o 7 (01111) introduzindo zeros, desta vez, o resultado estaria novamente correcto. Postos estes exemplos, pode-se avanar c para uma regra: um nmero com sinal estende-se introduzindo ` esquerda u a do nmero, em todos os bits que correspondem ` extenso, o valor do sinal. u a a ou seja, a extenso correcta de 1111 seria 11111111, uma vez que o sinal (i.e. a o bit mais signicativo igual a 1). Todos os exemplos que tm vindo a ser e e apresentados esto representados na tabela 6.3. a Com sinal? No a Sim Sim Sim Nmero u 1111 1111 0111 1111 Decimal 15 -1 7 -1 Extenso a 00001111 00001111 00000111 11111111 Decimal 15 15 7 -1 Correcto? Sim No a Sim Sim

Tabela 6.3: Exemplos de extenses realizadas correcta e incorrectamente o

Para facilitar a vida do programador existem vrias instrues capazes de a co efectuar extenses de nmeros com sinal para as dimenses mais utilizadas o u o

86

CAP ITULO 6. INSTRUCOES ARITMETICAS

no 80386. So elas cbtw, cwtl, cwtd e cltd, que convertem, respectivamente, a de 8 para 16, de 16 para 32, de 16 para 32 e de 32 para 64 bits. O c inicial e o t na terceira posio signicam, respectivamente, converte to; o b, ca o w, o l e o d referem-se ao comprimento dos dados e tm o signicado e habitual. Respectivamente, byte, word, long e double. Note-se que a palavra double tem aqui um signicado duplo porque tanto se refere a nmeros de u 32 como de 64 bits. Todas estas instrues operam sobre o registo eax (ou subregistos). O co modo de operar destas instrues est representado na tabela 6.4. co a Instruo ca cbtw cwtl cwtd cltd Reg. Inicial al ax ax eax Reg. Final ax eax dx:ax edx:eax Dim. Inicial 8 16 16 32 Dim. Final 16 32 32 64

Tabela 6.4: Instrues para extenso de nmeros com sinal co a u

Note-se que nenhuma destas instrues recebe operandos, uma vez que co estes esto impl a citos. O exemplo de cdigo 6.3 atrs apresentado e que s o a o funciona para nmeros positivos pode agora ser rescrito com uma soluo que u ca funciona em todos os casos. Esta soluo est representada no cdigo 6.4. ca a o

movl numero, %eax cltd movl $7, %ecx idivl %ecx

eax M[numero]
32

edx:eax eax
64

ecx 7
32

(6.4)

eax edx:eax / ecx


32

edx edx:eax % ecx


32

6.7. INCREMENTACAO E DECREMENTACAO

87

6.7

Incrementao e Decrementao ca ca
inc reg-mem dec reg-mem
reg-mem reg-mem + 1 reg-mem reg-mem 1

Instruo inc: incrementao. Instruo dec: decrementao. ca ca ca ca Estas instrues so extremamente simples: inc incrementa o operando co a reg-mem; dec decrementa-o. O operando ter de ser um registo ou uma a clula de memria, sendo que neste segundo caso ter de ser forosamente e o a c indicada a dimenso da operao. a ca Nenhuma destas instrues afecta a ag de transporte (CF). co

6.8

Negao ca
neg reg-mem
reg-mem reg-mem

Negao bit a bit. ca Calcula o simtrico do operando reg-mem (registo ou endereo de memria). e c o Em termos de representaes em complementos para 2 esta operao correco ca sponde a calcular o complemento para 2 do operando reg-mem (trocar todos os bits e adicionar uma unidade).

6.9

Restries `s operaes aritmticas co a co e

As restries que se aplicam `s operaes aritmticas esto representadas por co a co e a operao na tabela 6.5, alm das limitaes prprias do tipo de operando, ca e co o representadas na tabela 4.1 e das restries que se aplicam a cada uma das co operaes quando apresentadas na respectiva seco. co ca

88

CAP ITULO 6. INSTRUCOES ARITMETICAS

Registo ou memria (reg-mem), registo (reg), o valor direito (org), valor esquerdo (dst) Registo eip/ip Registo de segmento Tabela 6.5: Restries aos operandos nas instrues aritmticas multico co e plicao, diviso, adio e subtraco ca a ca ca

Operacoes com bits


7.1 Introduo ca

Neste cap tulo vai ser apresentado um conjunto de instrues que permitem co efectuar manipulaes aritmticas sobre os seus operandos. Como estas inco e strues tm a capacidade de considerar os bits individualmente, ou ento, co e a conjuntos de bits, so designadas por operaes com bits. a co

7.2

Instrues and, or e xor co


and org, dst or org, dst xor org, dst
dst dst & org dst dst | org dst dst org

Instruo and: e bit a bit. Instruo or: ou bit a bit. Instruo xor: ca ca ca ou-exclusivo bit a bit. Como habitualmente, os operandos org e org podem ser um registo, um valor literal ou uma clula de memria. Aplicam-se entre eles as mesmas e o restries que foram apresentadas na tabela 4.2. co Todas as trs operaes podem ser efectuadas com bytes, palavras ou e co longos. O resultado da operao em causa armazenado no operando dst. ca e 89

90

CAP ITULO 7. OPERACOES COM BITS

Na tabela 7.1 est denida a funo and. As funes or e xor esto denidas a ca co a nas tabelas 7.2 e 7.3, respectivamente. A 0 0 1 1 B 0 1 0 1 AND 0 0 0 1 A 0 0 1 1 B 0 1 0 1 OR 0 1 1 1

Tabela 7.1: Operao lgica and ca o A 0 0 1 1 B 0 1 0 1

Tabela 7.2: Operao lgica or ca o XOR 0 1 1 0

Tabela 7.3: Operao lgica xor ca o

As operaes lgicas esto denidas apenas no dom co o a nio {0, 1}. Por este motivo, quando efectuadas sobre um inteiro, estas operaes lgicas conco o sideram os bits desse inteiro individualmente, pelo que os operandos numa operao deste tipo devero ter sempre o mesmo tamanho. Assim sendo, ca a quando executada uma destas instrues o and digamos , na verdade, e co no calculado apenas um E lgico, mas sim um E lgico para cada bit do a e o o nmero inteiro. O mesmo se passa com as outras duas instrues. u co Vamos considerar, a t tulo de exemplo, dois nmeros de oito bits: 185 e u 233. A sua representao em binrio sem sinal a seguinte: ca a e 185 = 10111001 233 = 11101001 Os resultados de efectuar cada uma das trs operaes sobre estes dois e co nmeros seria o que est representado na gura 7.1. u a De seguida apresentamos o exemplo de cdigo 7.1 que permitiria efectuar o estas trs operaes armazenando os resultados em ah (and), bl (or) e cl e co

7.2. INSTRUCOES AND, OR E XOR 10111001 = 185 11101001 = 233 or 10101001 = 169 10111001 11101001 11111001 = 185 = 233 = 249 10111001 11101001 01010000

91 = 185 = 233 = 80

and

xor

Figura 7.1: Exemplo de cada uma das operaes lgicas co o

(xor).

movb $185, %al movb $233, %ah andb %al, %ah movb $233, %bl orb %al, %bl movb $233, %cl xorb %al, %cl

al 185
8

ah 233
8 8

ah ah & al bl 233
8

(7.1)

bl bl & al
8

cl 233
8 8

cl cl l a

E ainda de referir que vulgar utilizar-se a instruo xor para zerar um e ca nmero, em vez de fazer uma atribuio do valor literal zero: u ca

xorl %eax, %eax

eax 0
32

92

CAP ITULO 7. OPERACOES COM BITS

7.3

Instrues sar, shr, sal e shl co


sal 1, dst sal %cl, dst sal literal, dst sar 1, dst sar %cl, dst sar literal, dst shl 1, dst shl %cl, dst shl literal, dst shr 1, dst shr %cl, dst shr literal, dst
dst dst << 1 dst dst << cl dst dst << literal dst dst >> 1 dst dst >> cl dst dst >> literal dst || dst << 1 dst || dst << cl dst || dst << literal dst || dst >> 1 dst || dst >> cl dst || dst >> literal

Instruo sal: deslocamento para a esquerda com sinal. Instruo sar: ca ca deslocamento para a direita com sinal. Instruo shl: deslocamento para a ca esquerda sem sinal. Instruo shr: deslocamento para a direita sem sinal. ca O operando org, pode ser o registo cl, um valor literal diferente de 1 ou pode ser 1 (a razo desta distino prende-se com um comportamento a ca ligeiramente diferente que estas instrues apresentam neste ultimo caso). O co operando dst ser o registo ou endereo duma clula de memria afectado a c e o pela instruo. ca As instrues sal e shl so a mesma instruo, mas com mnemnicas co a ca o diferentes, e deslocam os bits de dst para a esquerda um determinado nmero u de unidades. Se o deslocamento for de n unidades os n bits mais signicativos saem de dst e entram por sua vez n zeros para o lugar dos n bits menos signicativos. Este deslocamento de n bits corresponde a fazer uma

7.3. INSTRUCOES SAR, SHR, SAL E SHL multiplicao por 2n . ca

93

No que diz respeito a deslocamentos para a direita, a instruo shr faz ca um deslocamento de n bits para a direita, introduzindo zeros (0) nas posies co mais signicativas. Isto corresponde a fazer uma diviso sem sinal por 2. A a instruo sar difere apenas no facto de fazer uma diviso com sinal. Para ca a isso, os bits introduzidos nas posies mais signicativas so idnticos ao bit co a e mais signicativo antes da operao. ca E de referir que, no deslocamento ` esquerda, a multiplicao sempre a ca e feita com sinal, quando os nmeros negativos so representados em cdigos u a o de complementos para dois. Com efeito, se houver uma mudana de sinal c ou, por outras palavras, do bit mais signicativo, isto signicar que houve a transbordo. Note-se que quando os dois bits mais signicativos tm sinais e diferentes no poss efectuar uma multiplicao por dois sem que ocorra a e vel ca transbordo. Em qualquer uma das operaes que foram introduzidas, a CF (carry ag) co sempre envolvida: e quando o deslocamento de apenas 1 bit a CF guarda o valor do bit e que saiu do operando (bit mais signicativo se o deslocamento foi para esquerda, bit menos signicativo se o deslocamento foi para a direita); os deslocamentos superiores a 1 bit podem ser pensados como mltiplos u deslocamentos de apenas 1 bit, pelo que a CF armazena o valor do ultimo bit que saiu do operando. A ag de transbordo (OF) tambm afectada, embora apenas nos deslocae e mentos de 1 bit. A ideia que, como fazer um deslocamento equivale a fazer e uma multiplicao ou diviso (conforme o deslocamento seja para a esquerda ca a ou para a direita, respectivamente), ento a OF deve reectir a existncia ou a e

94

CAP ITULO 7. OPERACOES COM BITS

ausncia de transbordo na instruo. A regra ser ento a seguinte: para e ca a a deslocamentos ` esquerda a OF reposta a 0 se o bit mais signicativo do a e resultado for igual ` CF (isto signica que no houve mudana de sinal na a a c multiplicao, ou seja, que no houve transbordo); para a operao sar a OF ca a ca posta a 0 e para a instruo shr (diviso sem sinal) a ag de transbordo e ca a armazena o sinal (i.e., o bit mais signicativo) do operando inicial Consideremos como exemplos destas operaes os seguintes casos: co dividir o registo eax por 16; multiplicar um nmero por 2. Se o nmero inicial for negativo vericar u u se houve transbordo. O primeiro caso est representado no cdigo 7.2 e bastante simples a o e de resolver, alis, basta uma instruo. O segundo caso, representado no a ca cdigo 7.3 ligeiramente mais complexo. o e sarl $4, %eax movl numero, %eax shll $1, %eax jc negativo jmp ok negativo: jo overflow jmp ok overflow: #Nmero negativo e overflow - faz qq coisa u ok: #Nmero positivo ou n~o overflow - continua u a
OF ? eip eip + x
32

eax eax / 16
32

(7.2)

eax M[numero]
32 32

eax eax 2 CF ? eip eip + x


32

eip ok
32

(7.3)

eip ok
32

7.4. INSTRUCOES RCL, RCR, ROL E ROR

95

7.4

Instrues rcl, rcr, rol e ror co


rcl 1, reg-mem rcl %cl, reg-mem rcl literal, reg-mem rcr 1, reg-mem rcr %cl, reg-mem rcr literal, reg-mem rol 1, reg-mem rol %cl, reg-mem rol literal, reg-mem ror 1, reg-mem ror %cl, reg-mem ror literal, reg-mem
reg-mem
C

1 cl
C

reg-mem reg-mem
C

literal 1
C

reg-mem reg-mem
C

cl literal
C

reg-mem reg-mem reg-mem reg-mem reg-mem reg-mem reg-mem

1 cl literal 1 cl literal

Instruo rcl: rotao para a esquerda pela ag de transporte. Instruo ca ca ca rcr: rotao para a direita pela ag de transporte. Instruo rol: rotao ca ca ca para a esquerda. Instruo ror: rotao para a direita. ca ca A forma de utilizao destas instrues idntica ` das instrues anterica co e e a co ores de deslocamento. Tambm aqui, dst o operando que sofrer a rotao, e e a ca enquanto org pode ser um valor literal igual a 1, diferente de 1 ou poder, a ainda, ser o registo cl. As restries que se aplicam ao operando reg-mem co so as de sempre (ver tabela 4.1). Quanto ao primeiro operando, este poder a a ser uma unidade, o registo cl ou um literal de apenas 8 bits. No caso das instrues rol e ror, uma rotao consiste num deslocaco ca mento, respectivamente, para a esquerda ou para a direita de todos os bits, mas onde o bit que sai, que ser o bit mais signicativo, no caso da rol, a

96

CAP ITULO 7. OPERACOES COM BITS

reentra na posio menos signicativa (exactamente o oposto na instruo ca ca ror). No caso da instruo rol o valor inicial do bit mais signicativo ca e passado tambm para a CF. Na instruo ror ao contrrio, sendo passado e ca e a para a CF o valor do bit menos signicativo. As instrues rcl e rcr diferem das anteriores porque aqui a CF tambm co e participa na rotao. Para isso o bit mais signicativo (no caso da rcl) ou o ca bit menos signicativo (no caso da rcr) saem para a CF e o contedo da CF u passa para a posio deixada livre pelo deslocamento dos bits do operando. ca A gura 7.2 ilustra o funcionamento destas quatro operaes. co
RCL
CF op op

RCR
CF

ROL
CF op

ROR
op CF

Figura 7.2: Operaes rol, ror, rcl e rcr co

Naturalmente que a CF afectada nesta operao. Alm desta, tambm a e ca e e OF afectada, apenas em rotaes de 1 bit, segundo a seguinte regra: se a CF e co for igual ao bit mais signicativo, a OF posta a 0, caso contrrio posta a e a e 1. Para as operaes rcl, rol e ror, o teste ` OF feito no m da operao. co a e ca Para a instruo rcr o teste ` OF feito antes da rotao. ca a e ca

7.5

Instruo test ca
test org, dst
eags dst & org

7.5. INSTRUCAO TEST

97

Efectua em e lgico, alterando apenas as ags (i.e., sem alterar os operano dos). Os operandos org e dst podem ser quaisquer, com as restries presentes co na tabela 4.2. Esta operao efectua um E lgico dos dois operandos sem os ca o alterar. Afecta apenas as seguintes ags: OF = 0 e CF = 0, sendo as ags SF, ZF e PF afectadas de acordo com o resultado da operao. ca A situao em que expectvel encontrar esta instruo ser antes de um ca e a ca a salto condicional jcc.

98

CAP ITULO 7. OPERACOES COM BITS

Denicao de Dados
8.1 Introduo ca

A memria dum computador organizada como uma sequncia endereada o e e c de bytes, capaz de armazenar qualquer tipo de informao, desde que traduzida ca para os habituais 0 e 1 agrupados em conjuntos de 8 bits ou em mltiplos. u A memria e as questes que lhe esto relacionadas foram, alis, o tema o o a a do cap tulo 3. Isto signica que, num endereo qualquer, poder ` partida c aa ser armazenado um dado de um tipo arbitrrio (caracter, palavra, inteiro, a nmero de v u rgula utuante, etc.), o que o mesmo que dizer que a memria e o no tipada. a e Este facto reecte-se tambm na linguagem assembly, que apresenta apee nas um suporte m nimo para tipos, mas sem que haja por isso qualquer espcie de vericaes. Apesar disto, a utilizao de tipos justica-se essene co ca cialmente por dois motivos: mais fcil e directo reservar espao em memria para as variveis e a c o a necessrias; a mais fcil iniciar essas variveis. e a a A denio de um tipo para uma varivel no impede, porm, que se ca a a e atribua ` varivel em questo um valor representado noutro tipo diferente, a a a 99

100

CAP ITULO 8. DEFINICAO DE DADOS

mesmo quando este tenha um tamanho diferente. A consequncia de o fazer e a possibilidade de introduzir erros no programa, mas a deciso ca sempre e a nas mos do programador, pois o assemblador Gas no efectua vericao a a ca dos tipos.

8.2

S mbolo

No contexto deste cap tulo, poderemos denir s mbolo como sendo o conjunto de um ou mais caracteres, que representam alguma coisa. Um s mbolo poder a ser ento um rtulo, um nome duma instruo ou o nome duma varivel, por a o ca a exemplo.

8.3

Tipos e Tamanhos

O assemblador Gas prev a existncia de trs tipos de variveis: e e e a nmeros inteiros; u cadeias de caracteres (strings); nmeros de v u rgula utuante. Cada um destes grandes tipos divide-se posteriormente em subtipos, que diferem entre si nalguns aspectos, nomeadamente o tamanho. De entre estes comeamos com os nmeros inteiros. c u

8.3.1

N meros inteiros u

Os nmeros inteiros podem ter diversos tamanhos, que se encontram repreu sentados na tabela 8.1.

8.3. TIPOS E TAMANHOS Nome Byte Palavra Longo Quadword Octaword Dimenso a 8 bits 16 bits 32 bits 64 bits 128 bits Gama sem sinal [0, 255] [0, 65535] [0, 4.294.967.295] [0; 1, 844 1019 ] [0; 3, 403 1038 ]

101 Gama com sinal [128, 127] [32768, 32767] [2.147.483.648, 2.147.483.647] [9, 223 1018 , 9, 223 1018 ] [1, 701 1038 ; 1, 701 1038 ]

Tabela 8.1: Tipos de nmeros inteiros u

A cada um destes tipos est associada uma directiva que permite denir a variveis do tipo respectivo. Como facilmente se compreender, se for denida a a uma varivel do tipo longo, por exemplo, ser reservado em memria espao a a o c para armazenar 32 bits (4 bytes) consecutivos. Chama-se novamente a ateno ca para o facto de que nestes 4 bytes se pode armazenar informao de qualquer ca espcie e no apenas um conjunto de 32 bits que representem um nmero e a u inteiro. A tabela 8.2 lista as directivas a utilizar para cada tipo. Nome Byte Palavra Longo Quadword Octaword Dimenso a 1 byte 2 bytes 4 bytes 8 bytes 16 bytes Directiva .byte .word, .short, .hword .long, .int .quad .octa

Tabela 8.2: Tipos de nmeros inteiros u

A sintaxe da denio de uma varivel de qualquer tipo e em particular ca a de variveis inteiras apresentada de seguida: a e nome: .directiva valor_inicial {, valor_inicial} A denio comea obrigatoriamente por um nome, que pode ser esca c colhido segundo as mesmas regras que se aplicam aos restantes s mbolos, nomeadamente rtulos. A directiva pode ser uma das que se encontram o

102

CAP ITULO 8. DEFINICAO DE DADOS

na tabela 8.2 ou qualquer outra relativa a um tipo de dados diferente. Na denio de uma varivel sempre indicado o seu valor inicial, que a varivel ca a e a garantidamente assume quando o programa se inicia. Entre {} encontra-se uma parte opcional e que pode ser repetida um nmero arbitrrio de vezes. u a Para cada valor inicial introduzido reservado espao para mais uma varivel e c a do mesmo tipo, num endereo cont c guo de memria, de forma que na mesma o denio podem-se especicar vectores ou tabelas. Uma forma alternativa ca de denir um vector consiste em por noutra linha, ou na mesma linha, mas separada por um ponto e v rgula (;), a mesma directiva com outra inicializao. ca No cdigo 8.1 apresentam-se alguns exemplos, sendo a varivel var em hexa o a e a varivel filtro iniciadas com valores em hexadecimal e em binrio, rea a spectivamente. letra: pontos: mto_gde: .byte a .int 0 .quad 8895321 (8.1)

var_em_hexa: .word 0x844f filtro: .int 0b01001011

8.3.2

Ponteiros

Um tipo especial de nmeros inteiros so os ponteiros, que guardam valores u a que representam endereos de outras variveis. No objectivo deste texto c a a e aprofundar muito este tema, mas interessa de qualquer forma saber como se dene um ponteiro. O espao necessrio para um ponteiro pode ser de 48 bits ou de 32 bits. c a Depende do facto de se estar a considerar o endereo completo (segmento c + deslocamento) ou apenas o deslocamento. Normalmente, este segundo

8.3. TIPOS E TAMANHOS

103

elemento suciente porque o programa reside todo no mesmo segmento. e Note-se que isto no se verica em todas as plataformas. a O exemplo de cdigo 8.2 ilustra a forma de denir e iniciar um ponteiro o (ptr numero) capaz de armazenar um deslocamento. A gura 8.1 representa a situao que se obtm depois desta denio. Em termos conceptuais, ca e ca ptr numero aponta para numero; da a seta da gura e a utilizao do nome ca ponteiro. Para armazenar um endereo completo seria necessrio reservar espao c a c para o segmento (depois do deslocamento) e fazer a inicializao do segmento ca a ` parte no cdigo. Isto est ilustrado no cdigo 4.7, apresentado na o a o seco 4.6, relativa `s instrues lxs. ca a co numero: .int 15 ptr_numero: .int numero (8.2)

ptr_numero 0x8000

numero xxxxxxxx 0x8000

Figura 8.1: Denio de um ponteiro ca

E de referir que a utilizao de ponteiros j tinha sido feita anteriorca a mente, embora esse facto no tivesse sido referido antes. Por exemplo, no a endereamento indirecto, quando se escreve (%ebx) (entre parntesis) o regc e isto ebx tem de conter o endereo vlido duma clula de memria onde se c a e o encontre um determinado dado, o que o mesmo que dizer que ebx um e e ponteiro para essa zona de memria. o

104

CAP ITULO 8. DEFINICAO DE DADOS

8.3.3

Cadeias de Caracteres (Strings)

E suposto neste texto que o leitor esteja familiarizado com o conceito de cadeia de caracteres. Por isso, aqui, no vai ser feita mais do que uma a enumerao a que adicionada uma curta descrio dos tipos de cadeias ca e ca suportados pelo assemblador Gas, que se encontram ilustradas na tabela 8.3, juntamente com a directiva a utilizar.

Directiva .ascii .asciz .string

Descrio ca Cadeia de caracteres no terminada a Cadeia de caracteres terminada com \0 Cadeia de caracteres terminada com \0 (igual a .asciz no 80386) Tabela 8.3: Tipos de cadeias de caracteres

E de referir que a utilizao de cadeias do tipo asciz e string se revela ca especialmente util quando se pretende utilizar algumas bibliotecas, em partic ular a biblioteca do C (libc). Isto porque muitas funes destas bibliotecas co assumem que a representao de cadeias de caracteres feita segundo a regra ca e normalmente utilizada pelos programadores de C, onde todas as cadeias de caracteres devem terminar com o caracter \0 (cdigo 0), que no representa o a nenhum caracter vlido na tabela ASCII. a A sintaxe para denio de cadeias de caracteres a mesma que se usa ca e para denio de variveis inteiras. As cadeias de caracteres constantes usca a adas para atribuir o valor inicial so escritas entre aspas (). Seguem-se a alguns exemplos no cdigo 8.3. A representao em memria destas cadeias o ca o de caracteres assim denidas encontra-se na gura 8.2. Por uma questo a de simplicidade assumiu-se que todas as cadeias se iniciam na posio de ca memria 0. o

8.3. TIPOS E TAMANHOS nome: .string "Eusbio da Silva Ferreira" e

105

posicao: .ascii "Avanado" c pais: .asciz "Portugal"

(8.3)

0 1 2 3 4

...

24 23 25

E
nome

S ... F

a \0

0 1 2 3 4

5 6 7

posicao 0 1 2 3 5 4 6 7 8

P
pais

\0

Figura 8.2: Representao em memria das cadeias de caracteres ca o

8.3.4

N meros de V u rgula Flutuante

Este tpico extravasa o mbito deste documento, pelo que apenas so enuo a a meradas na tabela 8.4 as directivas que permitem denir variveis de v a rgula utuante, que podem ser de dois tipos diferentes: oat e double. Nome Float Double Dimenso a 4 bytes 8 bytes Directiva .float .double

Tabela 8.4: Tipos de nmeros de v u rgula utuante

A denio de constantes em v ca rgula utuante feita com o prexo 0f, e sendo vlida a utilizao do s a ca mbolo E (maisculo ou minsculo) para desigu u nar o expoente, mas tanto a mantissa como o expoente tm de ser escritos e em decimal. Alguns exemplos:

106 numero: peso:

CAP ITULO 8. DEFINICAO DE DADOS .float 0f2.178 .float 0f1E2

distancia: .double 0f3.84e8

8.3.5

Vectores e Tabelas

Muitas vezes faz sentido armazenar em espaos cont c guos de memria um o conjunto de dados do mesmo tipo. Uma estrutura de dados deste tipo designa-se por vector ou tabela, conforme tenha uma ou mais dimenses, o respectivamente. Um exemplo do quotidiano de utilizao de um vector poder ser uma ca a pauta com as notas dos alunos, sendo que o vector neste caso a coluna e com as notas. Um exemplo de uma tabela poder ser um horrio, sendo a a nos elementos da tabela armazenadas as salas onde decorrero as aulas. E a importante compreender a diferena entre os dois exemplos: no primeiro caso c a indexao feita apenas por uma varivel (nome do aluno); no segundo ca e a caso, a indexao dos valores armazenados feita a partir de duas variveis ca e a (hora e dia da semana). Por este motivo um vector unidimensional e uma e tabela bidimensional (eventualmente poder ter uma dimenso superior). A a a gura 8.3 ilustra a diferena. c 10 16 14 9 12 11 18 Vector 3.1.6 3.1.9 8.2.30 ... Tabela Figura 8.3: Diferena entre vector e tabela c 3.2.14 3.1.10 3.1.10 3.2.14 8.2.10 3.1.7 3.1.7 8.2.39

8.3. TIPOS E TAMANHOS Vectores e Tabelas inicializados

107

A denio de um vector extremamente simples e passa apenas por denir ca e uma sequncia de variveis do mesmo tipo, mas sob o mesmo nome. Como e a vimos, isto muito simples de fazer, basta especicar uma lista de valores e separados por v rgulas, depois da directiva que indica o tipo dos elementos em questo. A sintaxe exacta pode ser encontrada na subseco 8.3.1. a ca Uma pauta como a da gura 8.3 seria ento denida da seguinte forma: a pauta: .int 18, 11, 12, 9, 14, 16, 10 No momento da denio de dados, as dimenses mximas dos vectores ca o a ou das tabelas tero de ser conhecidas, pois no ser poss a a a vel a posteriori adicionar-lhes ou retirar-lhes espao. c Uma das muitas vantagem de se utilizar um vector em vez de se utilizarem variveis distintas consiste na possibilidade de utilizao de formas a ca de endereamento mais complexas e que permitem escrever programas duma c forma mais ex vel. O acesso ` nota do quarto aluno poderia ser ento armazenado no registo a a eax da forma que se apresenta de seguida (ecx regista a posio do aluno ca em questo, sendo que a primeira de todas a posio 0, motivo pelo qual o a e ca quarto aluno est na posio 3): a ca movl $3, %ecx movl pauta(, %ecx, 4), %eax O endereo do elemento genrico i seria calculado de acordo com a c e frmula seguinte: o Endereo = vector + i * tamanho c

108

CAP ITULO 8. DEFINICAO DE DADOS

Uma tabela, pelo contrrio, uma estrutura de dados com que mais a e e dif de lidar porque, na prtica, com um tabela feita uma correspondncia cil a e e entre a memria que linear (uma dimenso) e uma unidade de dados abo e a stracta que tem mais do que uma dimenso. Isto signica que necessrio a e a aplicar alguma forma de correspondncia entre as clulas duma tabela e as e e clulas duma memria. Uma forma de o fazer est expressa na frmula e o a o seguinte, onde i a linha e j a coluna. Tanto as linhas como as colunas e comeam na posio 0: c ca Endereo = tabela + tamanho * (colunas * i + j) c Na gura 8.4 est ilustrado o endereo em que seriam armazenadas as a c clulas da tabela da gura 8.3, se fossem necessrios 4 bytes para guardar e a o nmero da sala. Estes endereos so relativos ao endereo de origem da u c a c tabela. 0 20 40 60 4 24 44 64 8 28 48 68 ... Figura 8.4: Endereos relativos das clulas do horrio c e a 12 32 52 72 16 36 56 76

Seria naturalmente poss vel trocar o papel das linhas e das colunas na equao utilizada para calcular o endereo duma clula da tabela. No caso ca c e que apresentmos, diz-se que a ordem row-major, enquanto que esta a e ultima hiptese seria column-major. o Em termos de denio, uma tabela no diferente dum vector. Se a ca a e tabela tiver x clulas, necessrio iniciar os seus x elementos exactamente e e a

8.4. AMBITO DOS S IMBOLOS (LOCAIS VS. GLOBAIS)

109

da mesma forma que se fazia para um vector. Alis, o assemblador no a a distingue uma tabela de um vector, sendo essa diferena assumida apenas c pelo programador, que tem sempre que respeitar a ordem pela qual as clulas e so armazenadas em memria, tal como ilustrado na gura 8.4. a o

8.3.6

Declarao de Dados No Inicializados ca a

Neste momento deve ser trivial calcular o espao necessrio para armazenar c a uma tabela ou um vector. Este espao ser igual ao produto do nmero de c a u elementos da tabela ou do vector pela dimenso de cada uma desses elemena tos. A necessidade deste clculo pe-se numa situao em que, por qualquer a o ca motivo, no se pretenda inicializar o vector ou a tabela (por s ser poss a o vel conhecer os valores iniciais no momento de execuo do programa, por exca emplo). Neste caso, poss reservar espao, usando a directiva .lcomm, e vel c de acordo com a seguinte sintaxe (em parntesis rectos est um parmetro e a a opcional): .lcomm nome_da_var, espao [alinhamento] c .comm nome_da_var, espao [alinhamento] c A diferena entre as directivas .lcomm e .comm ser abordada na seco 8.4. c a ca E de referir que esta directiva permite reservar espao para outras variveis c a no inicializadas que no apenas tabelas ou vecores s questo de se cala a e o a cular a dimenso dessas variveis, eventualmente escalares. a a

8.4

Ambito dos s mbolos (Locais vs. Globais)

Sempre que denido um rtulo ou uma varivel, o nome em questo e o a a e vis apenas no mdulo (i.e., no cheiro) onde se encontra a sua denio. vel o ca

110

CAP ITULO 8. DEFINICAO DE DADOS

Como facilmente se compreende tem de haver uma forma de tornar os s mbolos existentes vis veis noutros mdulos diferentes. Quanto mais no o a seja, o s mbolo (rtulo) que marca o in do programa tem que ser vis o cio vel para que se possa fazer a entrada nesse programa. Para tornar um s mbolo vis utiliza-se a directiva .global (ou apenas vel .globl). A sintaxe a seguinte: e .global smbolo Mais concretamente, aps a utilizao da directiva .global sobre um o ca s mbolo qualquer, este passa a ser pblico para o editor de ligaes (ld, por u co exemplo) e car, desta forma, acess para outros programas parciais que a vel sejam ligados em conjunto. No que diz respeito `s variveis no iniciadas, a diferena entre as variveis a a a c a declaradas com as directivas .lcomm e .comm, que as primeiras tm um e e a mbito local ao cheiro onde esto declaradas, enquanto que as segundas so a a globais a todos os programas parciais que componham o programa total.

8.5

Seces de Dados co

Um programa composto por mltiplas seces 1 . Trs delas assumem partice u co e ular relevncia. Uma a seco de texto, que a zona de memria onde pode a e ca e o ser encontrado o cdigo do programa (eventualmente tambm constantes). o e Esta seco difere das outras porque normalmente o seu contedo no alca u a e tervel e porque pode ser partilhada entre diferentes processos. a Outra seco importante a de dados, chamada data, que utilizada, ca e e normalmente, para armazenar variveis do programa. A seco de texto e a a ca
Mas depois, como no Unix um programa composto por um unico segmento todas e elas so agrupadas nesse segmento. a
1

8.5. SECCOES DE DADOS

111

seco de dados pertencem a uma mesma categoria de seces. Juntam-se a ca co esta categoria todas as seces criadas pelo programador e que recebam um co nome, qualquer que ele seja. Uma seco diferente e que no encaixa nesta categoria a seco bss, ca a e ca que contm espao para variveis no iniciadas. Entre estas incluem-se todas e c a a as que so denidas com as directivas .lcomm e .comm. Quando reservado a e o espao relativo a esta seco, todas as variveis so iniciadas a 0. c ca a a Acrescem a estes dois tipos de seces a seco absoluta, que contm co ca e endereos preestabelecidos e no relativos a uma determinada posio de c a ca memria (veja a pgina de info do as o a
2

e a seco indenida. Todos os ca

s mbolos que sejam utilizados mas no denidos so, no momento da asa a semblagem, categorizados nesta seco. Isto s pode acontecer quando um ca o programa composto por vrios mdulos. Neste caso, se o mdulo A dene e a o o a varivel A, que utilizada pelo mdulo B, ento, para o assemblador, no a e o a momento da assemblagem do mdulo B, a varivel A pertencer ` seco o a a a ca indenida. Este problema da indenio s ser resolvido quando os dois ca o a mdulos j em formato objecto forem ligados. o a Na gura 8.5 est representada a forma como so agrupadas as diversas a a seces existentes nos diferentes mdulos que compem um programa. E de co o o referir que as seces correspondentes so agrupadas entre si e que depois co a as seces unicadas ocupam posies relativas xas no programa nal. O co co espao de todas estas seces depois reservado num unico segmento do c co e programa isto no caso do sistema operativo Unix. Num cheiro de cdigo assembly poss comutar entre seces usando o e vel co a directiva .section, de acordo com a seguinte sintaxe: .section NOME
2

info as, na linha de comando duma shell Unix.

112
Programa parcial n 1 TTT texto Programa parcial n 2 ttt texto TTT ttt

CAP ITULO 8. DEFINICAO DE DADOS


DDD dados ddd dados DDD 000 bss 000 bss ddd 000 000 Programa final

Figura 8.5: Agrupamento das vrias seces dum programa a co

Todo o cdigo ou denio de variveis inicializadas que se faa imedio ca a c atamente depois desta directiva (e antes de outra que comute novamente a seco) ser inclu na seco com o nome NOME indicado. ca a da ca Para simplicar a tarefa, no caso das seces de dados e de texto, podemco se usar as directivas .data e .text, respectivamente. Note-se que a utilizao desta directiva .section s faz sentido para a ca o primeira categoria de seces que foi referida as que tm nome. co e Alm das seces que foram referidas, existe tambm a seco da pilha e co e ca que no tem de ser explicitamente denida no programa. a O programa executvel nal ento composto por mltiplas seces disa e a u co tintas (todas no mesmo segmento). Cada seco ocupa uma posio preestaca ca belecida relativamente `s outras seces, mas a sua dimenso pode variar. A a co a gura 8.6 ilustra a posio de cada seco no espao de endereamento do ca ca c c segmento onde o programa ser executado (i.e., do espao de endereamento a c c do processo que executa o programa).

8.5. SECCOES DE DADOS

113

Memria do kernel o Variveis de ambiente a Argumentos do programa Pilha Dados (bss) Dados Cdigo o Figura 8.6: Seces de um programa co

114

CAP ITULO 8. DEFINICAO DE DADOS

Funcoes
9.1 Introduo ca

Neste cap tulo ser apresentado um conceito de importncia fundamental a a para a realizao dum programa: as funes. Para isso, procura-se inicialca co mente compreender as razes que justicam a existncia de funes. De o e co seguida, so apresentadas as instrues do assembly que permitem implea co mentar funes, passando-se depois para as convenes utilizadas na sua co co programao. O cap ca tulo termina com a apresentao de funes exemplo. ca co

9.2

Diviso de um Programa em Funes a co

Uma caracter stica que tem sido comum a todos os fragmentos de cdigo o apresentados at aqui a sua curta extenso. Nem sempre assim. Muitos e e a e programas so, na verdade, extremamente longos. E o caso de praticamente a todos os programas populares: editores e processadores de texto, folhas de clculo, browsers de Internet, servidores de bases de dados, etc.. Tambm os a e sistemas operativos so, por norma, bastante extensos. Todos estes prograa mas tm tambm em comum que em determinados pontos efectuam aces e e co que se repetem ou que se assemelham consideravelmente, sendo exemplos prosaicos de situaes destas, a impresso de informao no monitor ou a co a ca 115

116

CAP ITULO 9. FUNCOES

leitura de dados do disco. Estas so aces repetitivas e que tendem a ocora co rer mltiplas vezes. u Por exemplo, considere-se um programa em que se pretendem ler os primeiros 20 bytes dum cheiro qualquer num dado momento e que mais tarde se desejam ler outros 30 bytes. Repetir praticamente o mesmo cdigo nas o duas situaes no seria apropriado melhor ser escrever cdigo genrico, co a a o e que sirva para ambas. O comportamento deste cdigo poder ser ditado por o a um conjunto de parmetros: uma referncia para o cheiro, o nmero de a e u bytes a ler e o local a partir do qual ser armazenada a informao que intera ca essa. Um outro exemplo ainda mais simples ocorre com funes matemticas co a ser o caso da raiz quadrada ou da potenciao isto para nomear apenas a ca duas. Aqui, haver um mecanismo cujo funcionamento no relevante (exa a e cepto, claro, para quem o concebeu) capaz de produzir o resultado correcto dependendo do(s) parmetro(s) de entrada da funo. a ca O cdigo que resolve um subproblema ento agrupado numa unidade o e a que constitui um subprograma, a que se chama normalmente funo ou proca cedimento. Em muitas linguagens de programao pode haver uma diferena ca c objectiva entre estes dois conceitos. No Pascal, por exemplo, uma funo ca devolve sempre um valor, sendo invocada na posio de um valor direito. ca Se existisse uma funo chamada raiz quadrada(), esta seria invocada da ca seguinte forma: y = raiz quadrada(x), onde x seria o argumento e y o resultado. Um procedimento, pelo contrrio, no devolve qualquer valor e no a a a nem um valor esquerdo nem um valor direito. Por exemplo, em Pascal e existe um procedimento chamado writeln() que escreve no monitor. Este procedimento deve ser invocado sem receber nem devolve qualquer valor. Ser simplesmente writeln(Ol) para imprimir a palavra Ol no mona a a itor. Noutras linguagens, como o C no existe diferenciao entre estas a ca

9.3. NECESSIDADE E UTILIDADE DAS FUNCOES

117

situaes, sendo todos os subprogramas chamados de funes. Neste texto co co ser adoptada esta conveno, de forma que os termos funo e procedimento a ca ca sero usados de forma comutvel. a a

9.3

Necessidade e Utilidade das Funes co

A utilizao de funes nos casos exemplicados permite reduzir a redundncia ca co a dum programa, mas este no o unico argumento a favor da sua utilizao. a e ca Um outro argumento tem a ver com a modularizao do programa. Por ca modularizao entende-se a diviso do problema inicial em subproblemas. ca a Quando escrito de forma descuidada e monol tica, um programa, mesmo que no seja muito grande, facilmente se torna ileg a vel, inclusivamente para o seu programador. Isto torna o programa dif de manter e de alterar. cil Para evitar que isso acontea o programador deve sempre preocupar-se c em modularizar devidamente o seu programa. A cada mdulo caber uma ou o a mais tarefas e a alterao dum destes mdulos no implicar a alterao dos ca o a a ca restantes. Esta denio poder ser recursiva, sendo poss dividir novaca a vel mente os mdulos iniciais em mdulos mais pequenos e mais simples. Cada o o mdulo elementar assim obtido ser depois implementado por um conjunto o a de linhas de cdigo isoladas no interior duma funo. Cada funo agrupa as o ca ca linhas de cdigo que dizem respeito ` operao de um determinado mdulo o a ca o e deve ser to independente das restantes quanto poss a vel. No entanto, no objectivo deste texto aprofundar as condies que dea e co vem presidir ` denio duma funo. Aqui interessa perceber o seguinte: a ca ca como se dene uma funo; ca como se invoca uma funo; ca

118

CAP ITULO 9. FUNCOES

como se passam parmetros para uma funo; a ca

como se recebem resultados duma funo. ca

9.4

Instruo call ca
call reg-mem
esp esp - 4
32

M[esp] eip
32

eip reg-mem
32

A instruo call serve para invocar uma funo. A instruo call reca ca ca cebe um operando, que pode ser um endereo de memria ou um registo c o que represente esse endereo. Este ser o endereo da primeira instruo c a c ca da funao que se est a invocar. O efeito mais bvio da sua invocao c a o ca e a alterao do registo eip e consequentemente a alterao da sequncia de ca ca e execuo do programa. Neste aspecto a instruo call assemelha-se ` inca ca a struo jmp. A grande diferena que na instruo call o valor inicial do ca c e ca registo eip salvaguardado na pilha. Isto no acontece na instruo jmp, e a ca onde o ponteiro de instrues eip pura e simplesmente obliterado. A razo co e a para armazenar o valor original de eip na pilha prende-se com a necessidade de retornar ao ponto seguinte ` chamada da instruo call 1 . Este assunto a ca ser, posteriormente, abordado com mais detalhe. a
Neste ponto merece a pena fazer uma chamada de ateno para o seguinte: o valor ca do registo eip armazenado na pilha o da instruo que se segue ao call uma vez que e ca o microprocessador avana automaticamente o ponteiro de instrues eip quando faz a c co leitura de cada instruo. ca
1

9.5. INSTRUCAO RET

119

9.5

Instruo ret ca
ret
eip M[esp]
32

esp esp + 4
32

ret literal

eip M[esp]
32

esp esp + literal + 4


32

A instruo ret pode ser considerada como a instruo rec ca ca proca da instruo call. Se o microprocessador encontrar uma instruo ret imediataca ca mente depois duma instruo call, o efeito de ambas anula-se e o microca processador vai encontrar-se na instruo imediatamente aps o call inicial. ca o Este seria o caso duma funo vazia, i.e., que no contivesse qualquer inca a struo. No ser esta, evidentemente, a situao normal, uma vez que ca a a ca habitualmente existem outras instrues entre o call e o ret. No entanto, co independentemente de quantas instrues existirem entre o call e o ret, co estas devero aparecer sempre conjugadas para cada call dever existir a a sempre um ret correspondente, cando entre elas as instrues que compem co o a funo chamada 2 . Resumindo, o call usado por quem chama, mais exca e actamente, pela funo chamante. O ret usado pela funo chamada para ca e ca terminar. O funcionamento deste par de instrues est ilustrado na gura 9.1. co a Assume-se a existncia duma funo chamada soma(), cujo cdigo omitido, e ca o e por no ser relevante. a A sequncia temporal onde so considerados cinco estados est assinalada e a a na gura por nmeros dentro dum c u rculo. Pela ordem em que ocorrem as aces representadas so as seguintes: co a
Note-se que isto no implica que o nmero de instrues call e ret num programa a u co tenha que ser precisamente igual. E perfeitamente poss que uma funo inclua muitos vel ca pontos diferentes por onde seja poss vel sair, i.e., pode ter muitos ret, mas apenas um deles ser executado para terminar a funo. a ca
2

120
Seco de Texto

CAP ITULO 9. FUNCOES


Seco da Pilha

1 2

esp call soma instruo seguinte 0x8048398 esp

5 3

0x8048398

soma

...
4

ret

Figura 9.1: Funcionamento das instrues call e ret co

Na instruo anterior ao call o ponteiro esp encontra-se na posio ca ca indicada na gura com o nmero 1; u a instruo call soma introduz na pilha o endereo correspondente ` ca c a instruo que se lhe segue no cdigo; ca o a instruo que o microprocessador executa de facto a que corresponde ca e ao endereo onde se encontra a funo soma(). O ponteiro esp mudou c ca de posio; ca a funo soma decorre normalmente at ser atingida a instruo ret. ca e ca Aqui, o microprocessador encontra a pilha exactamente no mesmo estado em que esta se encontrava quando a funo teve o seu in ca cio. Isto no signica, porm, que a pilha no tenha sido utilizada, mas apenas a e a que tem de ser deixada exactamente no mesmo estado. A instruo ca

9.6. CODIGO DAS FUNCOES

121

ret altera mais uma vez a sequncia normal de execuo do cdigo. e ca o A prxima instruo a executar no a que se lhe segue na seco de o ca a e ca texto, mas a instruo seguinte ao call soma. Esta instruo correca ca sponde ao endereo retirado da pilha; c terminada a chamada ` funo a pilha encontra-se no estado em que a ca se encontrava inicialmente, assinalada com o nmero 5. u A sequncia descrita mostra, nalmente, porque razo que todos os e a e objectos que entram na pilha tm de ser retirados, de acordo com o que foi e armado na seco 4.7. ca

9.6

Cdigo das Funes o co

Viu-se atrs que a execuo duma funo vai desde a instruo seguinte ao a ca ca ca call da funo chamante at ao ultimo ret da funo chamada 3 . Isto ca e ca pressupe que haja um rtulo associado ` primeira instruo da funo, de o o a ca ca forma a ser poss vel fazer a chamada ` funo atravs da instruo call a ca e ca rotulo. No cdigo 9.1 est representada uma funo que efectua a adio o a ca ca dos registos ebx, ecx e edx e devolve o resultado em eax. soma regs: movl %ebx, %eax addl %ecx, %eax addl %edx, %eax ret Interessa referir que os rtulos que identicam funes so processados o co a pelo assemblador de forma idntica ` dos rtulos que identicam dados. Com e a o
Pode ainda acontecer que dentro da funo chamada seja invocada outra funo e ca ca assim sucessivamente.
3

eax ebx
32 32 32

eax eax + ecx eax eax + edx

(9.1)

122

CAP ITULO 9. FUNCOES

efeito, durante o processo de assemblagem, o assemblador mantm um contae dor relativo ao in da seco corrente. Suponhamos que o assemblador se cio ca ` encontra na seco de texto. A medida que vai processando instrues tem ca co que as converter de assembly para cdigo mquina e calcular o espao que o a c estas ocupam. Isto permite-lhe saber exactamente quantos bytes j passaram a desde o in da seco. Quando encontra um rtulo, o valor atribu a cio ca o do esse rtulo depende da distncia relativa ao in dessa mesma seco. Se a o a cio ca seco no for de texto, mas de dados, a unica diferena que o espao ser ca a c e c a normalmente ocupado por dados e no por instrues. Evidentemente que o a co assemblador sabe o tamanho que os dados denidos pelo programador ocupam, sendo novamente poss atribuir valores aos rtulos. Uma diferena vel o c importante reside no facto de a maior parte dos dados terem rtulos, no o a sendo estes to necessrios para as instrues. A razo para isto que nem a a co a e todas as instrues so destinos de saltos mas, quanto aos dados, ser normal co a a que todos sejam individualmente acedidos. Outro aspecto que importa referir diz respeito `s funes que compem a co o um programa. Um programa pode incluir muitas funes que se invocam co umas `s outras. Poder acontecer, por exemplo, haver uma funo A, que a a ca invoca uma funo B, que, por sua vez, invoca uma funo C e depois uma ca ca D, etc., num processo que tem algo de recursivo 4 . Entre as vrias questes que se levantam uma delas em que ponto que o a o e e programa comea, mais precisamente, qual a primeira funo do programa c e ca a ser chamada e como que essa chamada acontece. A resposta ` segunda e a pergunta est no sistema operativo, que inclui ele prprio uma funo 5 capaz a o ca
Existe tambm uma classe de funes em que estas se invocam a elas prprias de forma e co o controlada. Estas funes so conhecidas por funes recursivas. A sua utilizao justicaco a co ca se essencialmente para manipular estruturas, elas prprias, eminentemente recursivas como o sejam rvores, por exemplo. a 5 Mais exactamente, uma chamada ao sistema.
4

9.6. CODIGO DAS FUNCOES

123

de fazer uma troca de programas trata-se da funo exec() 6 . A invocao ca ca da chamada ao sistema exec() permite comutar de programa e passar a executar um novo programa, que poder ser um editor de texto, por exemplo. a A resposta ` outra pergunta est numa funo chamada main(). A chamada a a ca ao sistema exec() recebe o nome do cheiro executvel onde se encontra o a novo programa. O programa ento carregado total ou parcialmente para e a memria e a funo exec() procura uma funo especial do programa com o ca ca o nome main() 7 . Importante tambm a noo de processo. A norma POSIX dene proe e ca cesso como um espao de endereamento com um ou mais uxos de execuo. c c ca Espao de endereamento so as zonas de memria reservadas para a seco c c a o ca de texto, dados, pilha, etc.. Fluxo de execuo refere-se ` efectiva utilizao ca a ca dum microprocessador para executar as instrues do programa. Para uma co denio mais detalhada de processo veja-se (Silbertschatz & Galvin, 1998). ca E precisamente na funo main() que o novo programa se inicia. Note-se ca que parece haver aqui um problema de recorrncia, uma vez que um proe grama sempre iniciado por outro programa. A chave da resposta reside e nos processos, que se podem multiplicar. Na verdade h um processo a conhecido por init que origem ancestral de todos os processos que exee cutam programas na mquina. Digamos que poss construir uma espcie a e vel e de rvore genealgica dos processos, sendo o processo init a raiz de todos eles. a o Cada novo processo que criado, por norma (embora no seja obrigatrio) ine a o voca a chamada ao sistema exec() para correr um programa diferente. Este programa tem, por sua vez, o in na funo main(). A partir da funo cio ca ca main() invoca depois outro nmero de funes at que a funo main() enu co e ca
Para informao sobre a fam de funes exec() execute-se man exec na linha de ca lia co comandos duma shell Unix. 7 Na verdade isto uma simplicao. A funo exec() procura uma funo chamada e ca ca ca start() mas, por norma, esta no precisa de ser denida pelo programador. a
6

124

CAP ITULO 9. FUNCOES

contra o seu m numa instruo ret 8 . Ento, por norma, novos programas ca a executam-se aps aparecimento de novos processos, quando estes invocam a o chamada ao sistema exec().

Na realizao de funes, h ainda aspectos a considerar. Como se viu ca co a atrs, a pilha deve ser deixada intacta pela funo. Quanto aos registos do a ca microprocessador, a situao ligeiramente diferente. O programador da ca e funo pode optar, ou no, por manter os registos inalterados ` sa da ca a a da funo. Por exemplo, o compilador gcc adopta a seguinte conveno: os ca ca registos ebp, esi, edi e ebx so salvaguardados pela funo chamada; o a ca registo eax utilizado para devolver o resultado (se o resultado necessitar e de 64 bits so usados os registos edx:eax); os restantes registos devero, se a a necessrio, ser salvaguardados pela funo chamante. Fundamental sempre a ca ser guardar o registo ebp, pelas razes que se vero adiante. a o a

Caso se pretenda fazer a salvaguarda de registos no interior duma funo ca ser normal utilizar-se a pilha para o efeito. No cdigo 9.2 apresentado o a o e exemplo duma funo que salvaguarda os registos ebp, esi, edi e ebx. ca

Note-se que aqui h uma nova simplicao: o programa no acaba num ret, mas a ca a numa funo chamada exit(), que uma fachada para a primeira de todas as chamadas ca e ao sistema. Depois do ret da funo main() o programa volta ` funo start(), onde ca a ca feito o exit(). e

9.7. VARIAVEIS LOCAIS minha func: pushl %ebp pushl %esi pushl %edi pushl %ebx # cdigo da fun~o aqui o ca popl %ebx popl %edi popl %esi popl %ebp ret
Reposio dos registos ca por ordem inversa Salvaguarda registos

125

(9.2)

Neste caso, so usadas as instrues rec a co procas push e depois pop pela ordem inversa, naturalmente, uma vez que a pilha uma estrutura LIFO. e Como se viu na seco 4.8 tambm poss guardar e repor todos os registos ca e e vel com um unico par de instrues pusha/popa. co

9.7

Variveis Locais a

Para armazenarem os seus prprios dados locais as funes necessitam tambm o co e das suas prprias variveis, designadas habitualmente de variveis locais. O o a a armazenamento de variveis locais pode ser feito de trs formas diferentes: a e nos registos; na memria; o na pilha. A utilizao de registos como variveis locais a uma funo tem como ca a ca vantagem a simplicidade e a rapidez. A desvantagem evidente que na e

126

CAP ITULO 9. FUNCOES

fam 80x86 at ao Pentium o nmero de registos de utilizao geral lia e u ca e muito limitado, pelo que todos os registos fazem diferena. No cdigo 9.1 c o em que a soma dos registos ebx, ecx e edx armazenado no registo eax este e ultimo desempenha o papel de varivel local. a A utilizao de memria no to imediata como a utilizao de registos, ca o a e a ca mas , ainda assim, bastante simples, tambm. Alm disso no conta com e e e a a desvantagem de ser um recurso extremamente limitado. No dif a a e cil uma funo guardar, por exemplo, vrios inteiros em memria. Porm, esta ca a o e soluo tambm apresenta desvantagens. Em particular, uma desvantagem ca e ser a falta de isolamento das variveis que, em geral, sero vis a a a veis a partir do exterior da funo. Esta situao pode propiciar duas situaes desvanca ca co tajosas: conitos de nomes entre variveis supostamente locais de funes a co diferentes; incentivo de prticas de programao desajustadas. Com efeito, a ca pode haver a tentao de usar as variveis para passar parmetros para o inca a a terior da funo estar ca amos, neste caso, perante variveis globais. Posto de a outra forma, a fronteira entre variveis locais a uma funo e globais a todo a ca o programa pode passar a ser uma linha demasiado tnue com preju para e zo a clareza da programao. A programao com variveis globais vivamente ca ca a e desaconselhada porque limita a independncia entre as partes constituintes e dum programa. Isto o mesmo que dizer que o programa ser mais dif e a cil de ler, corrigir e modicar. A outra desvantagem de usar variveis locais a em memria mais subtil. Ocorre nos casos em que uma funo possa ser o e ca chamada uma segunda vez antes de ter terminado a execuo anterior. Isto ca ocorre nas funes recursivas, por exemplo 9 . Com a segunda execuo, o co ca contedo das variveis necessrio ` primeira execuo estar corrompido. A u a a a ca a
Mas no s. Caso um processo tenha mltiplos os de execuo, i.e., seja multitarefa, a o u ca pode acontecer que dois desses os de execuo se encontrem na mesma funo em sica ca multneo. a
9

9.7. VARIAVEIS LOCAIS

127

salvaguarda dos valores das variveis para a pilha e posterior recuperao a ca no m da execuo no resolve todos os casos em que h problemas de conca a a corrncia e
10

Voltando ao exemplo da adio dos registos ebx, ecx e edx, o cdigo 9.3 ca o representa uma situao em que a varivel soma armazenada em memria ca a o serve para guardar as somas parciais da operao. O resultado novamente ca e devolvido no registo eax. No se pode falar propriamente de varivel local, a a uma vez que, em geral, a varivel soma ser vis tambm do exterior da a a vel e funo. ca .lcomm soma, 4 ... soma regs: movl %ebx, soma addl %ecx, soma addl %edx, soma movl soma, %eax ret (9.3) O terceiro mtodo faz recurso ` pilha. Este o mtodo mais elegante para e a e e situaes em que o nmero de variveis locais no permita a utilizao de regco u a a ca istos. O grande inconveniente a sua relativa complexidade. A programao e ca segundo este mtodo dif e e cil, sobretudo para programadores pouco experientes. No entanto, uma vez compreendido o mecanismo, a sua utilizao ca e sempre igual. Atente-se novamente no exemplo da adio, ilustrado no cdigo 9.1. Agora, ca o em vez de se usar o registo eax como varivel local, vai ser usada a pilha. O a
10

M[soma] ebx
32

M[soma] M[soma] + ecx


32

M[soma] M[soma] + edx


32

eax M[soma]
32

Precisamente nos casos em que h mltiplos os de execuo. a u ca

128

CAP ITULO 9. FUNCOES

espao para a varivel local inteira criado pela instruo subl $4, %esp c a e ca (que deixa quatro bytes livres na pilha). O acesso a essa varivel feito com a e endereamento relativo ` base ebp, o que pressupe a inicializao adequada c a o ca deste registo. A reserva do espao e inicializao do registo ebp ser ento feita da forma c ca a a representada no cdigo 9.4. Note-se que suposto que a funo no altere o o e ca a registo ebp, razo pela qual o valor desse registo salvaguardado na pilha. a e

soma regs: pushl %ebp movl %esp, %ebp subl $4, %esp
Salvaguarda registos

(9.4)
ebp esp
32

esp esp - 4
32

eip velho ebp velho variveis locais ebp esp

Figura 9.2: Utilizao de variveis locais na pilha ca a

A situao resultante representada na gura 9.2 mostra que a varivel ca a local est armazenada 4 bytes abaixo do ponteiro base ebp, pelo que o acesso a a essa varivel se faz com a expresso -4(%ebp). Esta varivel vai desempenhar a a a o papel que o registo eax tinha no cdigo 9.1. A concluso da funo soma o a ca est representada no cdigo 9.5. a o

9.7. VARIAVEIS LOCAIS soma regs: pushl %ebp movl %esp, %ebp subl $4, %esp movl %ebx, -4(%ebp) addl %ecx, -4(%ebp) addl %edx, -4(%ebp) movl -4(%ebp), %eax ret (9.5)
Salvaguarda registos ebp esp
32

129

esp esp - 4
32

M[ebp - 4] ebx
32

M[ebp - 4] M[ebp - 4] + ecx


32

M[ebp - 4] M[ebp - 4] + edx


32

eax M[ebp - 4]
32

Neste exemplo, que muito simples, a vantagem de usar a pilha para e armazenar uma varivel local no muito evidente. Na verdade, esta soluo a a e ca ser muito mais lenta do que a apresentada no cdigo 9.1, porque inclui vrios a o a acessos ` memria. No cdigo 9.1 no existe qualquer acesso, visto que o valor a o o a da soma armazenado em eax. e A vantagem de ter variveis locais na pilha s ser evidente quando o a o a nmero de variveis locais necessrio e/ou a complexidade do cdigo for u a a o maior. Facilmente se percebe que se forem necessrias 10 variveis locais no a a a ser poss armazen-las nos registos. a vel a Neste caso, o acesso a essas variveis seria feito segundo a correspondncia a e apresentada na gura 9.1, para as variveis identicadas na gura 9.3. a var1 var2 var10 -4(%ebp) -8(%ebp) -40(%ebp)

Tabela 9.1: Tipos de nmeros inteiros u

130

CAP ITULO 9. FUNCOES

eip velho ebp velho var1 var2 var3 ... var10 esp ebp

Figura 9.3: Funo com muitas variveis locais ca a

Note-se que quando a programao feita numa linguagem de alto n ca e vel, digamos em Pascal ou em C, no interior das funes so usados nomes para co a as variveis locais, tais como i, j ou var1, por exemplo. Caber depois ao a a compilador substituir esses nomes segundo uma correspondncia idntica a e e esta. Se a funo for escrita directamente em assembly caber ao prograca a mador manter, para sua prpria orientao, uma tabela como esta, o que o ca representa um trabalho bastante fastidioso.

9.8

Passagem de Parmetros para uma Funo a ca

Uma funo que produzisse sempre o mesmo resultado seria talvez pouco ca interessante. Por exemplo, a utilidade duma funo que imprima a frase ca Ol Mundo! no monitor ser, em princ a a pio, muito reduzida. Tem que ser poss a uma funo alterar o seu comportamento de forma controlada a vel ca partir do exterior. Uma forma de controlar o comportamento duma funo ca

9.8. PASSAGEM DE PARAMETROS PARA UMA FUNCAO ser a partir dos seus parmetros a a
11

131

. Por exemplo, uma funo matemtica ca a

pode receber um ou mais parmetros. Para calcular o seno necessrio um a e a parmetro, que o ngulo. a e a Muitas vezes (mas nem sempre, veja-se a funo getchar apresentada na ca ` seco 10.4) uma funo necessita de receber parmetros. A semelhana do ca ca a c que sucede com o armazenamento de variveis locais, os parmetros podem a a ser recebidos de trs formas diferentes: por registo, por memria ou pela e o pilha. Os argumentos a favor duma ou de outra opo assemelham-se muito ca aos que foram usados aquando da mesma explicao para as variveis locais. ca a Justica-se a utilizao de registos em casos onde h poucos parmetros a ca a a passar e os registos no fazem falta para construir a funo. A utilizao a ca ca de memria, por sua vez, ultrapassa o problema de haver poucos registos, o mas traz novos potenciais problemas que j foram descritos. Finalmente, a a utilizao de pilha , em simultneo, a soluo mais ex e mais complexa. ca e a ca vel Este ultimo mecanismo merece um olhar mais atento. Na gura 9.4 est a representado o estado duma pilha no interior duma funo que recebe dois ca parmetros nome1 e nome2 e usa duas variveis locais chamadas vogais e a a consoantes onde armazenar, respectivamente, o nmero de vogais e de a u consoantes existentes nos dois nomes. Esta pilha no mais que uma exa e tenso ao tipo de pilha que foi apresentada na gura 9.3, mas agora so a a considerados parmetros, para alm de variveis locais. E de referir o papel a e a fundamental que o ponteiro base ebp desempenha nesta situao, servindo de ca in de contagem para aceder quer `s variveis locais, quer aos parmetros. cio a a a O acesso a estes elementos feito segundo a correspondncia da tabela 9.2. e e So ainda de notar dois aspectos: em primeiro lugar, a posio do pona ca teiro base ebp no tem que ser exactamente a posio que est representada a ca a
Outra forma de alterar o comportamento duma funo seria atravs de operaes de ca e co E/S, como sejam leitura duma tecla ou do disco, etc.
11

132

CAP ITULO 9. FUNCOES

nome2 nome1 eip velho ebp velho vogais consoantes esp ebp

Figura 9.4: Passagem de parmetros pela pilha a nome2 nome1 vogais consoantes 12(%ebp) 8(%ebp) -4(%ebp) -8(%ebp)

Tabela 9.2: Acesso `s variveis locais e aos parmetros a a a

na gura 9.4. No entanto, se o ponteiro base ebp estiver num s ligeiratio mente diferente (quatro bytes mais abaixo, por exemplo), a forma de aceder a `s variveis e aos parmetros tem que variar de forma correspondente. Em a a segundo lugar, o registo ebp usado para estas funes por razes histrias, e co o o anteriores ao aparecimento do 80386. A partir deste microprocessador, qualquer registo de utilizao geral poderia desempenhar o mesmo papel. ca Para melhor comparar os trs mecanismos de passagem de parmetros e a apresentados registo, memria e pilha considere-se como exemplo uma o funo que dever determinar o maior de dois nmeros e armazenar o resulca a u tado no registo eax. As solues para o problema esto representadas nos co a fragmentos de cdigo 9.6, 9.7 e 9.8, respectivamente sobre este ultimo o

9.8. PASSAGEM DE PARAMETROS PARA UMA FUNCAO

133

caso veja-se a gura 9.5, que ilustra o estado da pilha durante a execuo da ca funo. ca

Note-se que nos fragmentos de cdigo 9.7 e 9.8 utilizada uma varivel o e a local armazenada no registo ebx. No caso da passagem por registos, os nmeros so enviados nos registos ebx e ecx; quando a passagem por u a e memria, em num1 e num2; na passagem por pilha primeiro pe-se na pilha o o o ultimo nmero. u

maior regs: cmpl %ecx, %ebx jge maior1 jmp maior2 maior1: movl %ebx, %eax jmp fim maior2: movl %ecx, %eax fim: ret (9.6)
ecx >= ebx ?

134 maior mem: movl num1, %ebx cmpl num2, %ebx jge maior1 jmp maior2 maior1: movl %ebx, %eax jmp fim maior2: movl num2, %eax fim: ret maior pilha: pushl %ebp movl %esp, %ebp movl 12(%ebp), %ebx cmpl 8(%ebp), %ebx jge maior1 jmp maior2 maior1: movl %ebx, %eax jmp fim maior2: movl 8(%ebp), %eax fim: popl %ebp ret

CAP ITULO 9. FUNCOES

num2 >= ebx ?

(9.7)

num2 >= ebx ?

(9.8)

9.8. PASSAGEM DE PARAMETROS PARA UMA FUNCAO

135

num2 num1 eip velho ebp velho esp ebp

Figura 9.5: Parmetros passados pela pilha a E bastante evidente, que o cdigo 9.8 mais complexo que o cdigo 9.7 o e o que, por sua vez, mais complexo que o cdigo 9.6. e o No tocante ` passagem de parmetros, resta ainda ver como que as a a e funes devero ser invocadas para cada um dos trs mecanismos. Para se co a e codicar a chamada `s funes necessrio saber onde que inicialmente a co e a e esto armazenados os valores a passar nos parmetros. No exemplo que tem a a vindo a ser tratado consideremos que o que est a ser comparado so duas a a idades armazenadas nas variveis idade1 e idade2. A chamada para os trs a e casos est representada nos fragmentos de cdigo 9.9, 9.10 e 9.11. a o movl idade1, %ebx movl idade2, %ecx call maior regs movl idade1, %eax movl %eax, num1 movl idade2, %eax movl %eax, num2 call maior mem
resultado volta em eax resultado volta em eax

(9.9)

(9.10)

136 pushl idade2 pushl idade1 call maior pilha addl $8, %esp (9.11)

CAP ITULO 9. FUNCOES

resultado volta em eax retirar parmetros da pilha a

Uma hiptese alternativa ao que se encontra no cdigo 9.8 seria ter ret o o 8 no m do procedimento maior pilha em vez de apenas ret. Nesse caso, no seria mais necessria a instruo addl $8, %esp no nal da chamada a a ca ao procedimento, tal como se encontra em 9.11.

9.9

Retorno de Valores duma Funo ca

No que concerne ao retorno de resultados do interior para o exterior duma funo, h tambm mltiplas alternativas, entre elas as mesmas que temos ca a e u vindo a ver: registos, memria e pilha. A utilizao de registos at j foi o ca e a exemplicada atrs, quando o registo eax foi usado para devolver o maior a dos nmeros. u A tabela 9.3, apresentada em (Hyde, 2003) representa a conveno que ca determina quais os registos que devem ser usados primeiro para devolver resultados. Usar Bytes: Palavras: Inteiros: Antes Depois al, ah, dl, dh, cl, ch, bl, bh ax, dx, cx, si, di, bx eax, edx, ecx, esi, edi, ebx

Tabela 9.3: Registos a utilizar na devoluo de resultados ca

A utilizao de memria tambm muito simples, no merecendo mais ca o e e a explicaes. co

9.9. RETORNO DE VALORES DUMA FUNCAO

137

A utilizao da pilha , como sempre, mais complexa, mas uma forma de ca e o fazer deixando os resultados no topo da pilha aps o trmino da funo, e o e ca como ilustrado na gura 9.6. A funo chamante dever retirar os resultados ca a da pilha com uma ou mais instrues pop (duas neste caso). No entanto, para co que esta tcnica seja poss e vel necessrio que a funo chamante reserve e a ca o espao necessrio para a devoluo dos resultados, antes de efectuar a c a ca chamada ` funo. Em certas ocasies poss tambm reutilizar o espao a ca o e vel e c dos parmetros para esse efeito. a

resultado1 resultado2 eip esp esp

Figura 9.6: Devoluo de resultados pela pilha ca

Caso tambm houvesse lugar ` passagem de parmetros pela pilha a e a a situao seria ligeiramente mais complexa. Considere-se a existncia duma ca e funo capaz de calcular o resultado da expresso i (num1 + num2). No ca a cdigo 9.12 encontra-se o cdigo desta funo. No cdigo 9.13 encontra-se o o ca o o cdigo a utilizar para efectuar a chamada ` funo e imprimir o resultado o a ca retornado. Na gura 9.7 est representado o estado da pilha. A cinzento a esto todas as palavras que devero desaparecer para aceder aos resultados. a a Entre parntesis esto os nomes dos parmetros a passar ` funo e, no caso e a a a ca dos valores devolvidos, os registos onde o resultado nal foi armazenado inicialmente.

138 calcula: pushl %ebp movl %esp, %ebp movl 12(%ebp), %eax addl 16(%ebp), %eax imull 8(%ebp) movl %edx, 24(%ebp) movl %eax, 20(%ebp) popl %ebp ret $12 (9.12)

CAP ITULO 9. FUNCOES

Prepara enquadramento da pilha eax num1 eax eax + num2 edx:eax eax i Guarda resultado na pilha

Retorna e retira parmetros a da pilha

9.9. RETORNO DE VALORES DUMA FUNCAO .section .rodata num1: num2: i: .int 20 .int 25
Dene variveis a

139

.int 4 .string "edx = %d, eax = %d\n"

formato:

.text

.globl main

main: pushl %ebp subl $8, %esp pushl num2 pushl num1 pushl i call calcula popl %eax popl %edx pushl %eax pushl %edx pushl $formato call printf addl $12, %esp popl %ebp xorl %eax, %eax ret
Retorna o cdigo de sucesso 0 o Termina programa Chama funo printf ca Passa parmetros para printf a Chama funo calcula ca Obtm resultados e Salvaguarda ebp Guarda espao para os resultados c Passa parmetros para calcula a

140 (9.13)

CAP ITULO 9. FUNCOES

resultado1 (edx) resultado2 (eax) parmtro 3 (num2) parmetro 2 (num1) parmetro 1 (i) eip

esp

esp

Figura 9.7: Devoluo de resultados pela pilha com existncia de parmetros ca e a

Uma diferena relevante no problema do retorno de resultados, relativac mente aos problemas apresentados anteriormente, de utilizao de variveis ca a locais e de passagem de parmetros que na devoluo de resultados ser a e ca a mais frequente a utilizao de registos. Isto deve-se ao facto de haver muitas ca funes que devolvem resultados muito simples, do tipo 0 em caso de sucesso, co -1 em caso de erro. A estas funes basta um registo, nomeadamente o eax, co para o efeito. No cap tulo 10 podem encontrar-se um conjunto de funes co que o fazem. H, porm, muitas funes que devolvem resultados usando um mecana e co ismo diferente de qualquer um dos que se descreveram (por exemplo a funo ca scanf ver seco 10.4.2). Neste caso, a funo chamante tem que reservar ca ca um espao em memria, que se destina a armazenar o resultado produzido c o pela funo chamada. Para que esta saiba onde se encontra esse espao, ca c aquela dever indicar a sua localizao. Para isso utiliza um dos parmetros, a ca a

9.10. INSTRUCAO ENTER

141

que funciona como um ponteiro para a zona de memria em causa. No o a raras vezes tambm necessrio acrescentar um outro parmetro, que ine e a a dica o espao dispon nessa zona de memria. Este parmetro adicional c vel o a e dispensvel, caso o resultado pretendido seja de tamanho xo (como ser o a a caso de um inteiro). Ser no entanto necessrio se o tamanho no tiver um a a a limite impl cito ou conhecido, como acontece com as cadeia de caracteres, por exemplo. No cdigo 9.14 apresenta-se um exemplo do cdigo a usar pela o o funo chamante, estando ilustrada na gura 9.8 a situao vista pela funo ca ca ca chamada. Aps o retorno da funo chamada o contedo da pilha pode ser o ca u destru sem problemas, visto que o resultado ter sido convenientemente do a armazenado numa zona segura de memria. Apesar do exemplo utilizar a o pilha para a passagem por referncia, tambm poderia ter sido usado outro e e mecanismo de passagem de parmetros. a .EQU tamanho, 20 pushl tamanho pushl $seunome call perguntanome addl $8, %esp
retira parmetros da pilha a tamanho 20 passa tamanho passa ponteiro

(9.14)

9.10

Instruo enter ca
enter literal1, literal2
esp esp - 4
32

M[esp] ebp
32

ebp esp
32

esp esp - literal1


32

142

CAP ITULO 9. FUNCOES

Seco da Pilha

Seco de Bss

20 seunome 0x80494f4 eip velho esp

Figura 9.8: Passagem de parmetros por referncia a e

Existem trs variantes da funo enter. Numa delas o valor literal2 e ca assume o valor 0, noutra assume o valor 1 e na ultima o valor literal2 pode ser qualquer nmero inteiro com 8 bits. O operando literal1 tem sempre u 16 bits. A instruo enter prepara a pilha para a execuo duma funo. A ca ca ca preparao da pilha consiste em salvaguardar o ponteiro de base ebp, atribuir ca ao ponteiro ebp o valor de esp e subtrair o literal1 a esp. O valor literal2 usado para indicar o n de nesting da funo. Para simplicar vamos e vel ca sempre considerar que este n igual a 0. Para mais detalhes sobre esta vel e instruo poder consultar-se (IA-32 developers manual-II, 2001). ca a Aps a realizao da instruo enter $4, $0, por exemplo (que por o ca ca norma ser invocada no interior duma nova funo), dentro duma funo a ca ca sero reservados 4 bytes para variveis locais enquanto os ponteiros esp e a a

9.11. INSTRUCAO LEAVE

143

ebp so preparados para aceder a essas variveis e a eventuais parmetros. a a a A situao que se obtm aps esta instruo a mesma que foi representada ca e o ca e na gura 9.2.

9.11

Instruo leave ca
leave
esp ebp
32

ebp M[esp]
32

esp esp + 4
32

A instruo leave a instruo complementar da instruo enter. A ca e ca ca instruo leave dever ser executada no m da funo, imediatamente antes ca a ca da instruo ret. Independentemente do estado em que se encontra a pilha, ca a instruo leave atribui o valor do ponteiro ebp ao ponteiro esp, o que ca liberta todo o espao ocupado na pilha, incluindo as variveis locais. Em c a seguida, a instruo leave faz o popl do registo ebp antigo, o que efecca tua imediatamente a mudana de enquadramento de volta para a funo c ca chamante. Finalmente, aps a instruo leave, dever existir uma funo o ca a ca ret, opcionalmente ret literal, se se quiser libertar o espao reservado c para os parmetros da funo que termina. a ca

144

CAP ITULO 9. FUNCOES

Bibliotecas de funcoes
10.1 Introduo ca

10

As instrues mais importantes dos processadores x86 foram apresentadas co nos cap tulos 4, 5, 6 e 7. No cap tulo 8 o tema foi a denio e declarao ca ca de variveis para utilizao nos programas; nalmente, no cap a ca tulo anterior foram postas em conjunto as partes que devem constituir um programa. Se verdade que com esta informao (e com a adio de alguma experincia, e ca ca e talvez) j poss escrever um programa completo, com princ e a vel pio, meio e m, a verdade que continua a faltar um elo essencial: as entradas e sa e das (E/S) do programa. Para efectuar operaes de E/S existem as instrues dedicadas in e co co out. Estas instrues permitem ler (in) e escrever (out) de e para portos co do sistema. Para simplicar, pode pensar-se nos portos como sendo a viso a que o microprocessador tem dos perifricos do sistema. Cada porto tem um e endereo prprio c o
1

e a cada perifrico atribu um conjunto de portos. e e do

Por exemplo, ` primeira porta srie (COM 1), usada muitas vezes pelo rato a e ou por modems, podero estar atribu a dos os portos com endereos 0x03f8 a c 0x3, sendo que, no entanto, estes endereos so congurveis no caso das c a a portas srie. Isto signica que lendo desses portos que o processador pode e e
1

Normalmente usado o sistema de numerao hexadecimal para referir esses endereos. e ca c

145

146

CAP ITULO 10. BIBLIOTECAS DE FUNCOES

saber qual a direco do movimento do rato, no caso de ser um rato que est ca a ligado na primeira porta srie 2 que dever ser programado pelos gestores e a destes perifricos (device drivers). e Nalgumas plataformas rudimentares poss a programas no privilee vel a giados (em rigor, nesses sistemas nem sequer havia hierarquias de privilgios, e como no caso do MS-DOS, da Microsoft) aceder directamente aos portos do sistema. No entanto, nos sistemas operativos modernos multitarefa e multiutilizador isso j no poss a a e vel, pois o privilgio requerido para ler ou escrever e de portos est para alm do privilgio possu por um programa de um utia e e do lizador normal. Esta deciso justica-se em pleno, porque no admiss a a e vel que um programa qualquer possa controlar os perifricos, fazendo-se assim e substituir ao sistema operativo. No dif imaginar que consequncias a e cil e traria o facto de ser poss a um programa de utilizador manipular direcvel tamente o controlador do disco. H ainda outra razo para que no seja desejvel efectuar operaes de a a a a co E/S desta forma. Esta razo tem a ver com a falta de transparncia destes a e processos, que requerem um conhecimento muito detalhado do funcionamento do hardware e uma complexidade considervel na sua programao, a ca que no poderia ser evitada. a Dadas estas questes, a soluo para o problema do privilgio resolve-se o ca e colocando todas as funcionalidades relativas `s E/S no sistema operativo. a Competir depois ao sistema operativo em nome dos processos, efectuar esa sas operaes. Cabe-lhe tambm vericar quando que um determinado co e e
E de referir que as operaes de E/S no se processam sempre desta forma. Alguns co a perifricos mais inteligentes e sobretudo mais rpidos, que requerem larguras de banda e a elevadas na comunicao com a memria central, conseguem retirar o microprocessador ca o do caminho dos dados, deixando que este ultimo se dedique a outras tarefas. Isto poss e vel graas a um outro microprocessador, chamado controlador de DMA Acesso Directo ` c a Memria, Direct Memory Access, em ingls o e
2

10.1. INTRODUCAO

147

processo deve ou no poder efectuar a operao em questo. Esta vericao a ca a ca fundamental, uma vez que o sistema operativo tem sempre o privilgio sue e ciente para isso. O facto de ser o sistema operativo a encarregar-se das E/S resolve tambm a questo da simplicidade que se deseja para estas operaes. e a co Com efeito, as funes para realizar operaes de E/S que o sistema operativo co co disponibiliza chamadas ao sistema tm j uma interface e utilizao e a ca relativamente simples, quando comparadas com a programao directa de ca portos. No entanto, alm das chamadas ao sistema, existem muitas vezes e funes (alm de constantes e variveis) com capacidades ainda mais elaboco e a radas e que so postas ` disposio do programador. a a ca Estas funes esto reunidas em conjuntos designados de bibliotecas. co a Note-se que estas bibliotecas podem tambm incluir muitas funes que no e co a realizam operaes de E/S. Uma biblioteca, tem algumas semelhanas com co c um programa executvel, nomeadamente o facto de tambm conter cdigo, a e o variveis, e alguns s a mbolos pblicos, que permitem fazer o acesso a essas u funes e variveis. A principal diferena reside no facto de a biblioteca co a c no ter uma funo main(), que lhe permita ser executada autonomamente. a ca Ao contrrio, as funes existentes numa biblioteca tm de ser ligadas (pelo a co e editor de ligaes veja-se gura 1.1) com outras funes. Entre o conjunto co co das funes que constituem o programa, apenas uma delas poder ser a co a funo main(). Isto implica que entre todos os cheiros objecto existe apenas ca uma funo main(). ca Note-se que, muitas vezes, a biblioteca j tem uma existncia anterior a e e no sequer programada pela(s) mesma(s) pessoa(s) que escreve(m) a a e funo main(). E o caso da biblioteca da linguagem de programao C, que ca ca oferece uma mir ade de capacidades para controlar o acesso `s E/S, para a manipular cadeias de caracteres, etc.; da biblioteca ncurses, que oferece

148

CAP ITULO 10. BIBLIOTECAS DE FUNCOES

funes, constantes e variveis, que facilitam a programao de aplicaes co a ca co visuais em modo texto; da biblioteca pthreads, que permite fazer programao ca multitarefa, etc. no h limites. Pode-se admitir sem hesitaes, que o a a co esforo de escrever um programa muito signicativamente reduzido pela c e existncia de bibliotecas. e

10.2

Bibliotecas Dinmicas a

A situao descrita na seco anterior, em que funes de biblioteca(s) so ligca ca co a adas com o resto do programa para construir o executvel acontece quando a so utilizadas bibliotecas estticas. Admita-se, por exemplo, a existncia a a e duma funo seno() numa destas bibliotecas. Se forem escritos e armazenaca dos no disco dum computador vinte programas que faam o clculo de senos c a e todos forem ligados com a biblioteca que contm os senos, isso signica que e todos os bytes do cdigo da funo seno() se encontram repetidos no disco o ca vinte vezes, em cada um desses programas. Uma alternativa melhor seria no incluir toda a funo seno() no cdigo a ca o dos programas, mas incluir apenas o cdigo necessrio ` sua invocao, o a a ca cando a funo seno() armazenada num unico local. Depois, de alguma ca forma, o cdigo da funo seno() teria de ser trazido para o espao de eno ca c dereamento do processo que corre o programa a forma exacta de o fazer c extravasa o mbito deste texto. Este mesmo racioc a nio estende-se naturalmente a qualquer outra funo armazenada numa biblioteca. ca Este tipo de bibliotecas, onde as funes no so ligadas com o programa, co a a sendo carregadas apenas quando o programa comea so designadas de bibc a liotecas dinmicas. a As gura 10.1 e 10.2 procuram ilustrar a relao entre cheiros objecto, ca

10.2. BIBLIOTECAS DINAMICAS executvel, bibliotecas estticas e dinmicas. a a a


Biblioteca esttica com a funo seno Ficheiro Objecto (.o) Outro(s) Ficheiro(s) Objecto (opcional)

149

Editor de Ligaes (ld)

Ficheiro Executvel

Figura 10.1: Construo e execuo dum programa que utiliza uma biblioteca ca ca esttica a

Ficheiro Objecto (.o)

Outro(s) Ficheiro(s) Objecto (opcional)

Editor de Ligaes (ld)

Ficheiro Executvel

Biblioteca dinmica com a funo seno

Figura 10.2: Construo e execuo dum programa que utiliza uma biblioteca ca ca dinmica a

H ainda duas vantagens adicionais a apontar `s bibliotecas dinmicas. A a a a primeira, e talvez mais importante, que permitem salvaguardar a memria e o f sica do sistema, uma vez que so carregadas para uma zona de memria a o pass de ser partilhada por vrios programas. A segunda prende-se com o vel a facto de ser poss actualizar as bibliotecas sem ser necessrio recompilar vel a os programas que as utilizam.

150

CAP ITULO 10. BIBLIOTECAS DE FUNCOES

10.3

Ferramentas de Manipulao de Biblioteca cas

No Linux os cheiros das bibliotecas so armazenados no formato elf Exea cutable and Linking Format tambm conhecido por Extended Linker Format e , que tambm o formato dos cheiros objecto e dos cheiros executveis e e a (o formato utilizado antes da existncia do elf era conhecido por a.out). e Uma especicao detalhada do formato elf tambm est fora do mbito ca e a a deste texto, embora seja interessante perceber como se faz a distino entre ca um cheiro executvel e uma biblioteca. Essa distino faz-se no cabealho a ca c ELF do cheiro onde, entre outras coisas, se encontra o tipo de cheiro em questo. Para uma abordagem mais extensiva do assunto veja-se (Card et al., a 1998). No que diz respeito a ferramentas para construir e manipular bibliotecas referenciam-se aqui as seguintes: ar constri arquivos. Mais exactamente, o ar permite juntar cheiros o objecto a uma biblioteca previamente existente ou construir uma biblioteca de raiz; objdump mostra informao de cheiros objecto; ca nm inspecciona s mbolos de cheiros objecto (incluindo executveis a e bibliotecas). O nm indica o nome e a localizao ou tamanho de todos ca os s mbolos existentes no cheiro. Indica tambm se os s e mbolos so a locais, i.e., apenas vis veis dentro do cheiro objecto, ou se so globais, a i.e., se a biblioteca exporta os s mbolos para outros programas, por exemplo. Note-se que no caso das bibliotecas (tal como nos cheiros objecto, naturalmente) a localizao dos s ca mbolos no nal, sendo a e

10.3. FERRAMENTAS DE MANIPULACAO DE BIBLIOTECAS portanto relativa ao in da biblioteca (posio 0); cio ca

151

ldd mostra todas as bibliotecas partilhadas de que o programa depende. Esta funcionalidade pode ser particularmente relevante numa situao em que seja necessrio saber de que bibliotecas partilhadas ca a uma mquina precisa para se poder executar um programa; a strace assinala todas as chamadas ao sistema programa em execuo. ca A compreenso de alguns detalhes relativos `s bibliotecas pode ser melhoa a rada, experimentando o comando nm. Para ilustrar esse facto uma pequena amostra do resultado de executar o comando nm /lib/libc.so.6 est repa resentado na tabela 10.1. Para descobrir qual e onde est a biblioteca do e a C basta executar o comando ldd sobre um executvel vulgar escrito em C, a para que esta biblioteca aparea na lista das dependncias. Na verdade, o c e Endereo Tipo c 000eefe0 B 00052ef0 T 0004cf4c T 000506f4 T Nome errno getchar printf scanf
3

efectuadas por um

Tabela 10.1: Execuo do comando nm /lib/libc.so.6 ca

resultado da execuo do comando ultrapassou as 40.000 linhas de texto, das ca quais s so apresentadas quatro, que dizem respeito a trs funes muito o a e co conhecidas e a uma varivel (errno). Os tipo dos s a mbolos so, neste caso, a representados por letras maisculas porque todos eles so globais, i.e., utiu a lizados fora do contexto do cheiro da biblioteca. Caso fossem locais a este cheiro seriam utilizadas letras minsculas. O B no caso da varivel errno u a
3

Na verdade, tambm assinala a recepo de sinais. e ca

152

CAP ITULO 10. BIBLIOTECAS DE FUNCOES

indica que esta varivel se encontra na seco de s a ca mbolos no incializados a (bss). O T no caso das trs funes indica que as funes se encontram e co co denidas na seco de texto da biblioteca. Na primeira coluna da tabela ca encontram-se os endereos de cada um dos s c mbolos, relativamente ao in cio da biblioteca.

10.4

Biblioteca do C

Entre as bibliotecas referidas neste texto interessa-nos em particular a biblioteca do C. Ser importante o conhecimento das seguintes funes, a descra co ever de seguida, pois permitem efectuar um conjunto de operaes de E/S co de forma relativamente simples: printf() scanf() getchar()

10.4.1

Funo printf() ca

Esta funo permite imprimir texto na sa padro (que normalmente ser ca da a a o monitor). A sua utilizao faz-se atravs de, pelo menos, um parmetro ca e a sendo todos os outros opcionais, segundo o seguinte prottipo: o int printf(formato, valor1, valor2, ...); Esta representao, que foi simplicada relativamente ` verdadeira repreca a sentao em C, indica que a funo devolve um inteiro e recebe um nmero ca ca u arbitrrio de parmetros. O primeiro dos parmetros chama-se formato e a a a os que se lhe seguem so valores. No parmetro formato indicado um a a e endereo de memria com uma string, que indica no s o contedo dos c o a o u

10.4. BIBLIOTECA DO C

153

restantes parmetros, como tambm o aspecto com que os dados devero ser a e a impressos. De seguida do-se alguns exemplos de utilizao do formato, mas a ca para uma referncia completa veja-se a pgina de manual do printf() (info e a printf) ou o livro (Kernighan & Ritchie, 1988). uma frase, terminada com um 0 (caracter \0 = 0, que diferente de e 0 = 48 no cdigo ASCII). Por exemplo, printf("Ol") 4 ; o a "%s" (caracter %, caracter s, caracter \0) para indicar que nos argumentos seguintes dado um endereo de memria onde se encontra e c o uma frase que tem de terminar com \0. Por exemplo, printf("%s", ptrfrase); "%d" para indicar que se segue um nmero inteiro de 32 bits. Por u exemplo, printf("%d", idade); O caracter \n permite efectuar mudanas de linha. Por exemplo, c printf("Ol!\nTenho %d anos", idade); a No caso destas funes os parmetros so colocados na pilha pela ordem co a a inversa em que aparecem no prottipo, i.e., o ultimo parmetro colocado o a e na pilha primeiro e o formato o ultimo parmetro a entrar. e a

10.4.2

Funo scanf() ca

Esta funo permite fazer a leitura de dados da entrada padro (teclado, ca a normalmente). A sua utilizao, bem como o seu prottipo so semelhantes ca o a a ` funo printf(): ca int scanf(formato, endereo do valor1, endereo do valor2, ...); c c
Normalmente o valor de retorno do printf() ignorado, porque a probabilidade de e ocorrncia de algum problema se assume como inexistente. e
4

154

CAP ITULO 10. BIBLIOTECAS DE FUNCOES

H, no entanto, algumas diferenas a considerar. Em primeiro lugar, no a c parmetro formato, no faz sentido indicar uma frase de texto para imprimir a a na sa padro (este princ da a pio inclui naturalmente o caracter de mudana c de linha - \n - que no deve ser usado). Depois, quando se pretende ler um a inteiro
5

(formato "%d"), tem de se passar no segundo parmetro da funo, a ca

o endereo de memria onde o inteiro dever ser armazenado e no o inteiro c o a a propriamente dito, como ser mais ou menos intuitivo, uma vez que esse o a e valor que se deseja obter, no sendo, portanto, conhecido de antemo. No a a a seria portanto adequado efectuar uma passagem de parmetro por valor. No a caso de se efectuar a leitura de uma frase (string "%s") a partir da entrada padro para uma zona de memria, a funo scanf() garante que a frase a o ca termina sempre com um \0.

10.4.3

Funo getchar() ca

O prottipo da funo getchar(), em termos de linguagem C, o seguinte: o ca e int getchar(void); Esta funo l o prximo caracter da entrada padro e devolve-o como ca e o a um inteiro ou devolve o cdigo EOF (-1) em caso de erro ou de no existirem o a mais dados dispon veis a partir da entrada padro. a

10.4.4

Exemplo de Utilizao das Funes da Biblioteca ca co do C

.EQU TAMNOME, 1024 .EQU TAMINTEIRO, 4

O mesmo se aplica a outro tipo de dados qualquer.

10.4. BIBLIOTECA DO C .lcomm nome, TAMNOME .lcomm idade, TAMINTEIRO

155

.section .rodata

perguntaNome: perguntaIdade: perguntaFinal:

.string "Como se chama? " .string "Quantos anos tem? " .string "Quer continuar (s em caso afirmativo)? "

formatoNome: formatoIdade: resposta: limpabarran:

.string " %s" .string " %d" .string "%s tem %d anos de idade.\n" .string "%*[\n]"

.text

.globl main

main: pushl %ebp inicio: pushl $perguntaNome call printf addl $4, %esp pushl $nome pushl $formatoNome call scanf

156 addl $8, %esp

CAP ITULO 10. BIBLIOTECAS DE FUNCOES

pushl $perguntaIdade call printf addl $4, %esp pushl $idade pushl $formatoIdade call scanf addl $8, %esp

pushl idade pushl $nome pushl $resposta call printf addl $12, %esp

pushl $perguntaFinal call printf addl $4, %esp pushl $limpabarran call scanf addl $4, %esp call getchar cmpl $s, %eax je inicio #sen~o n~o permite resposta a a

popl %ebp

10.4. BIBLIOTECA DO C xorl %eax, %eax ret

157

158

CAP ITULO 10. BIBLIOTECAS DE FUNCOES

Interrupcoes e Chamadas ao Sistema


11.1 Interrupes co

11

Suponhamos que estamos a desenvolver uma rotina para fazer a leitura de valores introduzidos pelo teclado. Uma soluo ingnua para este problema ca e consistiria em consultar o teclado periodicamente para saber se o utilizador tinha premido ou no uma tecla. Nesta abordagem, o processador teria pea riodicamente de pr de lado outras tarefas para ir controlando o teclado. A o esta aco de, repetidamente, se ir vericar se um dispositivo est pronto ca a chama-se, ` falta de melhor termo em portugus, polling. Embora o cona e ceito de polling seja simples, na prtica este tipo de programao no muito a ca a e eciente ser mais interessante ocupar o processador com tarefas melhores a do que vericar periodicamente uma dzia de perifricos, que em geral no u e a tero dados novos. a Felizmente existe uma outra abordagem mais ecaz: em vez de ser o processador a vericar periodicamente o teclado, este que avisa o processador e de que h uma nova tecla dispon a vel. Nesta segunda soluo poder ca amos ter uma rotina que permaneceria adormecida durante a maior parte do tempo, sendo depois acordada a pedido do perifrico apenas quando necessrio. e a Desta forma, logo que termine a rotina, o processador car dispon para a vel 159

160

CAP ITULO 11. INTERRUPCOES E CHAMADAS AO SISTEMA

outras tarefas. Esta soluo baseia-se no no conceito de interrupo, cuja ca ca ideia fundamental consiste em permitir a um perifrico indicar um determie nado evento ao processador. Este evento poder ser a presso duma tecla, o a a movimento do rato ou a leitura de dados provenientes duma placa de rede. E de salientar, no entanto, que esta alternativa requer suporte especial por parte do hardware. Posto de um modo mais formal, e de acordo com (IA-32 developers manual-III, 2001), uma interrupo um evento que transfere ca e a execuo de um programa ou tarefa para uma rotina especial, chamada ca handler (que poderemos designar por rotina de tratamento). Um conceito que est relacionado com o de interrupo e que tambm a ca e e abrangido pela denio anterior o de excepo. Tal como uma interca e ca rupo, uma excepo tambm transfere o controlo para uma rotina de trataca ca e mento. A diferena entre interrupo e excepo encontra-se na natureza do c ca ca evento que gerado. Numa interrupo este evento ass e ca e ncrono, isto , e trata-se de um acontecimento no previs a vel, por no estar relacionado com a o cdigo que est a ser executado (por exemplo devido a um erro de paridade o a na memria). Pelo contrrio, uma excepo um acontecimento s o a ca e ncrono, que ocorre de forma previs vel num determinado local do cdigo. H trs o a e tipos de excepes: faltas1 , traps e aborts2 . co Uma falta uma excepo que pode ser corrigida e que, caso o seja, pere ca mite ao programa continuar a sua execuo normal. Isto poder suceder, por ca a exemplo num erro com uma operao aritmtica tal como uma diviso por ca e a zero. Uma trap uma excepo que executa a rotina de tratamento no m e ca de apenas uma instruo do processador (chamada trapping instruction). ca
Outra traduo poss para a palavra inglesa fault seria falha. Embora diferentes ca vel autores utilizem as palavras falta e falha como sinnimos, quando utilizadas no mesmo o texto estas palavras tm geralmente um signicado bem diferente. e 2 A opo de no traduzir nenhum destes termos deliberada, uma vez que a palavra ca a e correspondente em portugus reduziria consideravelmente a legibilidade deste texto. e
1

11.1. INTERRUPCOES

161

Este tipo de excepes permite fazer a depurao de um programa. Aps a co ca o execuo de cada instruo do programa o depurador retoma o controlo, perca ca mitindo ao utilizador analisar variveis, ler zonas da memria do programa, a o alterar a prxima instruo, etc. Um abort uma excepo que no permite o ca e ca a o retorno ao programa e pode ser causado, por exemplo, por um erro de hardware (ser o caso de um erro de paridade na memria). Estes trs tipos de a o e excepes (faltas, traps e aborts) so gerados pelo prprio processador IA-32. co a o H ainda um outro tipo de excepes que so gerada pelo prprio programa, a co a o atravs das intrues int ou int 3. Este ultimo tipo de excepes tambm e co co e e designado por interrupes de software (ver (IA-32 developers manual-III, co 2001)). Uma vez que h diferentes eventos que podem causar interrupes, cada a co tipo de evento identicado por um nmero diferente, conhecido por vector e u de interrupo. Desta forma, o sistema operativo pode manter em memria ca o uma tabela que associa a cada nmero de vector de interrupo uma rotina u ca de tratamento. Isto permite determinar qual a rotina de tratamento do rato, e qual a rotina de tratamento do teclado, por exemplo. Dada esta tabela, chamada tabela de descritores de interrupes (Interrupt Descriptor Taco ble), a aco do processador em caso de interrupo sempre a mesma: ca ca e procurar a entrada que corresponda ao nmero do vector de interrupo u ca em causa e invocar a rotina de tratamento respectiva. Nesta consulta, o processador recorre a um registo chamado registo da tabela de descritores de interrupes (Interrupt Descriptor Table Register ). Este registo aponta co para a tabela de descritores de interrupes, sendo que, em simultneo, inco a dica tambm o seu limite que poder ir at aos 256 elementos. O registo usa e a e 32 bits para a localizao em memria da tabela mais 16 bits para o nmero ca o u de elementos da tabela. Cada elemento da tabela consiste num porta

162

CAP ITULO 11. INTERRUPCOES E CHAMADAS AO SISTEMA


Registo da Tabela de Descritores de Interrupo (IDTR)
32 bits 16 bits

Endereo Base TDI

Limite TDI

Tabela de Descritores de Interrupo (TDI)


Porta para Interrupo n. n
(n-1)*8

...
Porta para Interrupo n. 3 Porta para Interrupo n. 2 Porta para Interrupo n. 1
32 bits 16

Figura 11.1: Acesso ` tabela de descritores de interrupo a ca

que invoca a interrupo respectiva com as permisses adequadas. Isto est ca o a representado na Figura 11.1. Por exemplo, quando o processador recebe a interrupo nmero 3, tem de procurar a porta que est na 3a posio do ca u a ca tabela de descritores de interrupes. co No passado, noutros sistemas operativos mais rudimentares, como o MSDOS, o processador no corria no modo protegido, mas sim no modo real a (endereamento real). Neste caso, a tabela de interrupes encontrava-se c co localizada no endereo 0 de memria (Hyde, 2003) e cada posio deste vector c o ca

11.1. INTERRUPCOES

163

continha directamente o endereo da rotina de tratamento. Na Tabela 11.1, c encontra-se uma lista com as intrrupes da arquitectura IA-32. Esta tabela co pode ser encontrada em (IA-32 developers manual-III, 2001). INM signica Interrupo No Mascarvel. Uma INM uma interrupo, que pode ca a a e ca interromper todas as interrupes de software e as de dispositivos de hardware co no vitais. Ao contrrio do que sucede com as interrupes que tm uma a a co e prioridade associada, uma INM nunca pode ser ignorada. De uma forma geral, num PC as interrupes no so geridas pelo proco a a cessador central, mas por um processador associado, o Intel 8259A, que e um Controlador de Interrupes Programvel (CIP). O CIP pode receber co a at 8 interrupes provenientes de perifricos diferentes, atravs de entradas e co e e chamadas de requisio de interrupo (IRQ). Por sua vez, o CIP tem uma ca ca sa que conectada ao pino INTR do processador. Neste pino, o CIP inda e dica ao processador que h um interrupo pendente, usando o bus de sistema a ca para indicar ao processador central qual o nmero do vector de interrupo e u ca em causa. Uma caracter stica interessante do CIP 8259A que a um pino e IRQ do 8259A pode ser ligado outro 8259A, sendo assim poss encadear vel at oito 8259A num nono 8259A que ser ligado ao processador. Neste caso e a poss disponibilizar at 64 requisies de interrupo diferentes (8 por e vel e co ca cada 8259A, com excepo do que faz a conexo dos restantes). Na prtica, ca a a os PCs usam dois 8259A, sendo o segundo ligado ` IRQ 2 do primeiro. Assim, a as IRQs 0-1 e 3-7 so da responsabilidade do primeiro 8259A, enquanto que a as IRQs 8-15 so da responsabilidade do segundo 8259A (ver Figura 11.2). a A IRQ 2 serve apenas para fazer o encadeamento. Como as interrupes nos co pinos IRQ com nmero mais baixo tm prioridade mais elevada, a ordem real u e das prioridades : 0-1-8-9-10-11-12-13-14-15-3-4-5-6-7. No Linux as IRQs so e a individualmente atribu das a nmeros de interrupo dispon u ca veis entre o 32

164

CAP ITULO 11. INTERRUPCOES E CHAMADAS AO SISTEMA Tabela 11.1: Tabela de interrupes e excepes em modo protegido co co

N.o vector 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20-31 32-255

Descrio ca Erro de Diviso a Depurao ca Interrupo no mascarvel ca a a Breakpoint Transbordo Violao de limites (bound ca range exceeded ) Cdigo de instruo invlido o ca a (no denido) a Co-processador matemtico a ausente Dupla falta Ultrapassagem do segmento do co-processador Selector de Segmento Tarefa (TSS) invlido a Segmento ausente Falta no segmento da pilha Proteco geral ca Falta de pgina a Reservado Erro na unidade de v rgula utuante x87 (Erro matemtico) a Erro de alinhamento Vericao da mquina (maca a chine check ) Excepo de v ca rgula utuante numa instruo Single Inca struction Multiple Data Reservadas pela Intel Interrupes denidas pelo co utilizador de

Tipo falta falta/trap interrupo ca trap trap falta falta falta abort falta falta falta falta falta falta falta falta abort falta

Causa Instrues div e idiv co Qualquer referncia a cdigo ao a e o dados ou a instruo int 1 ca Origem exterior no mascarvel a a Instruo int 3 ca Instruo into ca Instruo bound ca Instruo UD2 ou cdigo de inca o struo reservado ca Instruo de v ca rgula utuante ou instrues wait/fwait co Qualquer instruo que gere uma ca excepo, uma INM ou uma INTR. ca Instruo de v ca rgula utuante (os processadores IA-32 aps o 386 no o a geram esta falta) mudano de tarefa ou acesso a um ca TSS Carregamento de registos de segmento ou acesso a segmentos do sistema Operaes na pilha e carregamentos co do registo SS Qualquer referncia a memria ou e o outras vericaes co Qualquer referncia a memria e o Erro de v rgula utuante no x87 ou instrues wait/fwait co Qualquer referncia a dados em e memria (s a partir do proceso o sador 486) Depende do modelo Instrues de v co rgula utuante SSE e SSE2 Interrupo externa ou instruo ca ca int n

interrupo ca

11.1. INTERRUPCOES

165

Tabela 11.2: Correspondncia entre IRQs e nmeros vector de interrupo e u ca IRQ 0 1 2 3 4 6 8 11 12 13 14 15 Interrupo ca 32 33 34 35 36 37 40 43 44 45 46 47 Perifrico e Temporizador Teclado encadeamento do CIP Porta srie n.o dois e Porta srie n.o um e Drive de disquetes Relgio do Sistema o Placa de rede Rato PS/2 Co-processador matemtico a Primeiro controlador de disco EIDE Segundo controlador de disco EIDE Fixa/Varivel a Fixa Fixa Fixa Varivel a Varivel a Fixa Fixa Varivel a Varivel a Fixa Varivel a Varivel a

e 47. Esta correspondncia mostrada na Tabela 11.2. Algumas das IRQs e e so xas, outras podem ser alteradas. a
IRQ 9 10 11 12 13 14 15 8

1 2 3 4 5 6 7

CIP Intel 8259A

Figura 11.2: Encadeamento de controladores de interrupes co

Para fazer a gesto das interrupes, incluindo a invocao de interrupes a co ca co de software, existe um conjunto de instrues, das quais apresentamos de co seguida as mais importantes.

INT (para o processador)

CIP Intel 8259A

INT

IRQ 0

166

CAP ITULO 11. INTERRUPCOES E CHAMADAS AO SISTEMA

11.2

Instruo int ca
int literal

Gera uma interrupo de software. ca Esta instruo gera uma interrupo de software, que resulta numa chamada ca ca a ` rotina de tratamento do nmero de vector de interrupo indicado pelo litu ca eral (como se encontra descrito na Seco 11.1). A instruo int muito ca ca e semelhante ` instruo call, visto que na verdade, ambas as instrues a ca co provocam uma alterao ao registo eip. Mais precisamente a semelhana ca c com a instruo call d-se no caso de chamadas a funes remotas, isto ca a co e que esto (ou podero estar) num segmento diferente. Neste caso, o registo a a de segmento cs tambm guardado na pilha e depois alterado, ` semelhana e e a c do que sucede com o eip. Por outro lado, as instrues diferem em dois co aspectos. Em primeiro lugar, no caso da instruo int, o programador no ca a tem alternativa quanto ao endereo da funo que vai executar: este est prec ca a determinado na porta que corresponde ao nmero do vector de interrupo u ca (ver Figura 11.1). Alm disto, a instruo int salvaguarda o registo eflags e ca na pilha antes de invocar a rotina de tratamento. A instruo int salvaca guarda primeiro o registo eflags, s depois salvaguardando os registos cs e o eip. Isto signica que a pilha ca num estado diferente daquele em que uma instruo call a deixa (mesmo que no caso de chamadas remotas). Por esta ca razo, uma rotina de tratamento de uma interrupo no pode terminar com a ca a a instruo ret, uma vez que esta deixaria car o registo eflags na pilha. ca

11.3

Instruo iret ca
iret

11.4. INSTRUCAO CLI Retorna de uma rotina de tratamento.

167

Esta instruo termina uma rotina de tratamento e devolve o controlo ca ao programa que foi interrompido. Retira os valores para os registos eip, cs e eflags da pilha e devolve o controlo ao programa ou procedimento interrompido. A diferena relativamente ` instruo ret reside no facto de c a ca o retorno duma interrupo retirar tambm o registo eflags da pilha. ca e

11.4

Instruo cli ca
cli
IF 0
1

Limpa a ag de interrupes IF. co Esta instruo faz com que o processador ignore interrupes externas ca co mascarveis. Esta instruo no afecta as interrupes no mascarveis e as a ca a co a a excepes geradas pela execuo de software. O objectivo desta instruo co ca ca e o de permitir que no interior duma rotina de tratamento no seja poss a vel iniciar uma nova rotina de tratamento de uma outra interrupo. Assim, ca uma determinada interrupo pode ser tratada at ao seu nal antes da ca e prxima. Naturalmente que isto implica que uma boa rotina de tratamento o de interrupes demore a menor quantidade de tempo poss co vel, uma vez que todas as outras interrupes caro pendentes durante o espao de tempo co a c em que esta ag se encontra desactivada.

11.5

Instruo sti ca
sti
IF 1
1

Activa a ag de interrupes IF. co

168

CAP ITULO 11. INTERRUPCOES E CHAMADAS AO SISTEMA

Tipicamente, esta instruo executada antes do iret que termina uma ca e rotina de tratamento duma interrupo. Esta instruo no tem efeito imeca ca a diato, sendo ainda executada mais uma instruo antes da ag ser activada. ca Isto permite que a rotina de tratamento termine aps a instruo iret, antes o ca de ser servida a prxima interrupo. o ca As instrues sti e cli s podem ser executadas em determinados n co o veis de privilgio 3 , i.e., um programa a correr em modo de utilizador normal num e sistema operativo como o Linux no as pode executar, uma vez que inibir ou a permitir interrupes so decises que podem comprometer toda a mquina co a o a e no apenas um processo. a

11.6

Chamadas ao Sistema

De forma a utilizar os recursos da mquina, o sistema operativo disponibia liza um conjunto de funes, habitualmente designadas por chamadas ao co sistema. Sendo o sistema operativo que controla os recursos dispon veis na mquina e sendo, por norma, necessrio utilizar o sistema operativo a a para aceder a esses recursos, facilmente se compreender que o conjunto a de chamadas ao sistema existente tem que ser bastante completo. Por exemplo, o sistema operativo oferece uma chamada ao sistema que permite escrever num cheiro, outra que permite ler, um outra que permite ler o valor do relgio, uma para obter informao sobre o processo que executa o ca o programa, entre muitas outras. Por exemplo, na verso 2.2 do Kernel do a Linux havia cerca de 190 funes destas. co Para acederem a estas funes, os programas tm de usar a interrupo co e ca 0x80. Para o Linux a interrupo 0x80 est, como estava para o MS-DOS a ca a
Mais exactamente, quando o privilgio do processo em execuo for igual ou superior e ca ao privilgio indicado na ag IOPL - Input/Output Privilege Level. e
3

11.6. CHAMADAS AO SISTEMA

169

famosa interrupo 0x21. O sistema operativo guarda uma tabela com a lista ca completa das suas chamadas e quando o programa executa uma instruo int ca $0x80 indica ao sistema operativo qual a chamada ao sistema que pretende invocar. Para isso utiliza o registo eax. Por exemplo, para invocar a 1a chamda ao sistema (de nome exit()), o programa coloca o valor do registo eax a 1 e invoca a interrupo 80h. Na prtica, o registo eax utilizado para ca a e indexar uma tabela onde se encontram todas as chamadas ao sistema. Os parmetros da chamada ao sistema so passados nos registos ebx, ecx, edx, a a esi e edi, num mximo de cinco. A funo nmero 117 (sys ipc) necessita a ca u de seis parmetros. Neste caso, o registo ebx aponta para um vector em a memria com os seis parmetros. Todas as chamadas ao sistema devolvem o a um resultado atravs do registo eax. e

No fundo, a utilizao da interrupo 0x80 resolve o problema de fornecer ca ca funes do sistema operativo aos programas do utilizador. O programa tem co de invocar estas funes atravs do mecanismo de interrupes porque as co e co portas existentes na tabela de descritores de interrupo (ver Figura 11.1) ca permitem alterar o n de privilgio do programa utilizador, unica e excluvel e sivamente para o m com que o utilizador invoca uma funo do sistema, ca por exemplo, para aceder a dados que esto no disco. Por outras palavras, a quando entra em modo privilegiado atravs da porta correspondente ao vece tor de interrupo 0x80, o processo do utilizador apenas pode efectuar um ca conjunto de operaes muito restrito, que esto previstas numa das mais co a de 190 funes oferecidas pelo sistema operativo. Repare-se que isto no co a poderia ser feito atravs de bibliotecas de funes como aquelas que foram e co apresentadas no Cap tulo 10. As funes destas bibliotecas so executadas co a no mesmo n de privilgio do programa do utilizador. No permitiriam, vel e a

170

CAP ITULO 11. INTERRUPCOES E CHAMADAS AO SISTEMA

por exemplo, aceder ao disco4 . Os seguinte programas exemplicam a utilizao de chamadas ao sistema. ca O primeiro programa escreve uma frase na sa padro do processo (em geral da a o monitor). Para isso, utiliza a chamada ao sistema nmero 4, chamada u write(), que recebe trs parmetros. O primeiro o descritor do cheiro e a e onde o sistema operativo deve escrever. No caso deste programa esse descritor tem o nmero 1, que corresponde ` sa padro (stdout, geralmente u a da a o monitor). O segundo parmetro um ponteiro para a zona de memria a e o onde se encontram os dados a escrever, que neste caso a frase strteste. e Finalmente, o ultimo parmetro o nmero de bytes que a funo dever a e u ca a escrever no cheiro (e que, portanto, devem corresponder a algum contedo u que se encontra presentemente na zona de memria indicada). Este valor o e calculado como a diferena entre a posio actual do assemblador e a posio c ca ca inicial da frase strteste. Note-se que esta frase no necessita de ser tera minada (nem sequer deveria) com um \0, graas a este terceiro parmetro c a que indica inequivocamente o nal da frase. Preenchidos estes parmetros a e invocada a chamada ao sistema atravs da instruo int $0x80. Para simplie ca car o programa ignora o valor retornado pela chamada ao sistema write(). Chama-se, no entanto, a ateno do leitor para o facto de ser um boa prtica ca a de programao fazer o tratamento do valor de retorno. Em particular, a ca funo write() retorna -1 em caso de erro, que poder ocorrer por muitas ca a razes diferentes. Por exemplo, se o descritor de cheiro passado no primeiro o parmetro no corresponder, de facto, a qualquer descritor vlido. a a a

.section .rodata

Naturalmente que o podero fazer, mas apenas porque elas prprias utilizam internaa o mente chamadas ao sistema.

11.6. CHAMADAS AO SISTEMA

171

# irrelevante a string terminar ou n~o com um \0 E a strteste: .ascii "Este programa usa a chamada ao sistema write!\n"

# Comprimento da string em bytes comprstr: .long . - strteste

.text

.globl main

main: movl $4, %eax movl $1, %ebx leal strteste, %ecx movl comprstr, %edx int $0x80 ;# fun~o write ca ;# descritor stdout ;# ecx aponta para o texto ;# nmero de bytes a passar ao stdout u ;# executa a chamda ao sist. write ;# por simplicidade ignoramos o valor ;# de retorno

xorl %eax, %eax ret E de referir que a chamada ao sistema write() se encontra em termos de funcionalidade abaixo da funo printf() oferecida pela biblioteca do C. Em ca particular, seria relativamente complicado escrever o valor dum nmero, de u forma intelig vel, na sa padro, a menos que este fosse inclu na prpria da a do o frase strteste. Por exemplo, seria necessrio algum esforo de codicao a c ca para imprimir o valor do registo eax. O problema advm do facto de a repree

172

CAP ITULO 11. INTERRUPCOES E CHAMADAS AO SISTEMA

sentao de um inteiro em memria no corresponder ` representao desse ca o a a ca mesmo inteiro em caracteres ASCII no monitor (sendo esta a representao ca de interpretao mais simples para um ser humano). Assim, enquanto a ca funo printf() permite fazer essa converso de forma transparente para o ca a programador, a funo write() escreve os dados em bruto, tal e qual eles ca se encontram em memria. Para exemplicar, consideremos que se pretende o escrever o contedo de uma posio de memria com quatro bytes que no u ca o momento esto todos a 0. Enquanto que a funo write() tentaria escrever a ca quatro zeros na sa padro, a funo printf() escreveria o caracter ASCII da a ca 0 (o valor 48). Para isso, a funo printf() tem internamente de fazer as ca converses necessrias, de forma a invocar a funo write(), passando-lhe o a ca uma localizao de memria onde se encontra o nmero 48 e indicando que ca o u apenas deve ser escrito um byte a partir daquela posio de memria. ca o O exemplo seguinte utiliza a primeira de todas as chamada ao sistema, chamada exit(), para terminar o programa. Note-se que, neste caso o programa no termina com um ret nal, uma vez que o registo eip j no a a a ` retorna a esse ponto. A semelhana do programa anterior, este programa esc creve uma frase na sa padro utilizando a chamada ao sistema write(), da a invocando depois a chamada exit(). O unico parmetro que esta funo a ca recebe o cdigo de erro com que o programa deve terminar, sendo 0 uma e o indicaao de sucesso. Assim sendo, neste caso, o registo ebx deve ser posto c a zero. Desempenha, portanto, um papel idntico ao registo eax quando , e e tambm, colocado a 0 antes da instruo ret nal, como, por exemplo, no e ca programa anterior. E interessante referir, que no caso da funo exit() no ca a necessrio vericar o valor de retorno, pela simples razo de que nunca h e a a a retorno. .section .rodata

11.6. CHAMADAS AO SISTEMA

173

despedida:

.ascii "Sada pela syscall exit...\n"

comprfrase: .long . - despedida

.text

.globl main

main: movl $4, %eax movl $1, %ebx leal despedida, %ecx movl comprfrase, %edx int $0x80

movl $1, %eax xorl %ebx, %ebx int $0x80

;# fun~o exit ca ;# cdigo de retorno 0 = sucesso o

#nunca se chega aqui...

Finalmente, o ultimo deste exemplos utiliza a funo getpid(), que tem o ca nmero 20 para obter o nmero do processo que est a executar o programa. u u a Pelas razes apontadas anteriormente, utilizamos a funo printf() para o ca fazer a impresso do nmero do processo. a u .section .rodata

174

CAP ITULO 11. INTERRUPCOES E CHAMADAS AO SISTEMA

formato: .string "O identificador do processo (pid) : %d\n" e

.text

.globl main

main: movl $20, %eax int $0x80 ;# fun~o sys_getpid ca ;# execute write system call

#n~o tente escrever %eax com a syscall write a #porque %eax tem a represent~o *binria* do a a #pid

pushl %eax pushl $formato call printf popl %eax popl %eax

xorl %eax, %eax ret

Exemplos de Programas
12.1 Programa Ol Mundo a

12

.section .rodata

strOlaMundo: .string

"Ola Mundo!\n"

.text

.globl main

main: pushl %ebp pushl $strOlaMundo call printf addl $4, %esp pop %ebp xorl %eax, %eax ret 175

176

CAP ITULO 12. EXEMPLOS DE PROGRAMAS

12.2

Programa Soma 100 primeiros

.section .rodata

strResult: .string "1 + 2 + 3 ... + 100 = %d\n"

.text

.globl main

main:

pushl %ebp movl $100, %ecx xorl %eax, %eax ciclo: addl %ecx, %eax loop ciclo pushl %eax pushl $strResult call printf addl $8, %esp popl %ebp xorl %eax, %eax ret #100 + 99 + ... + 1

12.3. PROGRAMA OPERA DOIS NUMEROS

177

12.3

Programa Opera dois nmeros u

.lcomm num1, 4 .lcomm num2, 4 .lcomm result, 4 .lcomm operacao, 4

.section .rodata

pergunta:

.string "Introduza dois numeros inteiros:\n"

formatoPerg: .string " %d %d" perguntaOp: .string "Introduza a operacao (+, -, *, /): "

formatoPergOp: .string " %c" fraseErro: .string "A operacao que introduziu nao e valida\n"

.text

#Os parametros encontram-se na pilha por esta ordem: #num1, op, num2, result fraseResult: .string "%d %c %d = %d\n" escreveResult: pushl %ebp movl %esp, %ebp pushl 20(%ebp) pushl 16(%ebp) pushl 12(%ebp)

178 pushl 8(%ebp)

CAP ITULO 12. EXEMPLOS DE PROGRAMAS

pushl $fraseResult call printf addl $20, %esp popl %ebp ret

.globl main

main: pushl %ebp

pushl $pergunta call printf addl $4, %esp pushl $num2 pushl $num1 pushl $formatoPerg call scanf addl $12, %esp pushl $perguntaOp call printf addl $4, %esp pushl $operacao pushl $formatoPergOp call scanf addl $8, %esp

12.3. PROGRAMA OPERA DOIS NUMEROS movl operacao, %eax

179

cmpl $+, %eax je mais cmpl $-, %eax je menos cmpl $*, %eax je vezes cmpl $/, %eax je dividir jmp erro

mais: movl num1, %eax addl num2, %eax pushl %eax pushl num2 pushl $+ pushl num1 call escreveResult addl $16, %esp jmp fimcase

menos: movl num1, %eax subl num2, %eax pushl %eax

180 pushl num2 pushl $- pushl num1

CAP ITULO 12. EXEMPLOS DE PROGRAMAS

call escreveResult addl $16, %esp jmp fimcase

vezes: movl num1, %eax imull num2 pushl %eax pushl num2 pushl $* pushl num1 call escreveResult addl $16, %esp jmp fimcase #facil haver transbordo...

dividir: movl num1, %eax cltd idivl num2 pushl %eax pushl num2 pushl $/ pushl num1 call escreveResult

12.3. PROGRAMA OPERA DOIS NUMEROS addl $16, %esp jmp fimcase

181

erro: pushl $fraseErro call printf addl $4, %esp

fimcase: popl %ebp xorl %eax, %eax ret

182

CAP ITULO 12. EXEMPLOS DE PROGRAMAS

References
Card, Remy, Dumas, Eric, & Mevel, Franck. 1998. the Linux Kernel book. John Wiley & Sons. Hahn, Harley. 1992. Assembler Inside-Out. Osborne McGraw-Hill. Hyde, Randall. 2003. The Art of Assembly Language. No Starch Press. IA-32 developers manual-I. 2001. The IA-32 Intel Architecture Basic Architecture. In-

Software Developers Manual, Volume 1:

tel Corporation, P.O. Box 7641, Mt. Prospect IL 60056-7641. http://developer.intel.com/design/Pentium4/manuals/245470.htm. IA-32 developers manual-II. 2001. The IA-32 Intel Architecture

Software Developers Manual, Volume 2: Instruction Set Reference. Intel Corporation, P.O. Box 7641, Mt. Prospect IL 60056-7641. http://developer.intel.com/design/Pentium4/manuals/245471.htm. IA-32 developers manual-III. 2001. The IA-32 Intel Architec-

ture Software Developers Manual, Volume 3: System Programming Guide. Intel Corporation, P.O. Box 7641, Mt. Prospect IL 60056-7641. http://developer.intel.com/design/Pentium4/manuals/245472.htm. Kernighan, Brian W., & Ritchie, Dinnis M. 1988. The C Programming Language. Prentice Hall. 183

184

REFERENCES

Murray, William H., & Pappas, Chris H. 1986. 80386/80286 Assembly Language Programming. Berkeley, California: Osborne McGraw-Hill. Silbertschatz, Abraham, & Galvin, Peter Baer. 1998. Operating System Concepts. Addison-Wesley Publishing Company. Stevens, W. Richard. 1990. Unix Network Programming. Prentice Hall.