segunda-feira, 9 de novembro de 2009

O Sistema de Organização- Arquiteturas Intel

O Sistema básico de organização de um computador é chamado arquitetura John Von Neumann um designer de arquitetura emprestou seu nome, pois a maiora dos computadores de hoje seguem essa arquitetura. A família 80x86 segue essa arquitetura. Essa arquitetura possui três componentes básicos: Unidade Central de Processamento(CPU), Memória, dispositivos de entrada e saída E/S.
Barramento de Sistema: É o dispositivo que conecta as várias partes do sistema. Existem três: Barramento de endereço, barramento de dados, e barramento de controle. Variam de processador para processador. Um típico sistema 80x86 utiliza a lógica TTL.
Barramento de dados: O tamanho é diferente para cada processador da família 80x86. Na verdade o tamanho desse barramento define o tamanho do processador. Num típico sistema 80x86, ele contém 8,16,32 ou 64 linhas. Tamanho do barramento nos processadores:




Barramento de Endereço: Na família 80x86 transfere informações entre uma memóra particular e sistema de E/S e CPU. Família 80x86 e tamanhos:
Ordenamento de Bit e Byte: Na figura abaixo, você poderá ver que as memórias mais baixas(endereços menores) estão embaixo. Os endereços aumentam em direção ao topo. Como vimos na seção de dados, os bits são da direita para esquerda. Os processadores Intel 64 e IA-32 são máquinas Little-endian. Isso quer dizer que os bytes de uma palavra (word) são enumerados, começando pelo byte menos significativo:

Bits Reservados e Compatibilidade de Software: Em muitos registradores e camadas de memórias, certos bits estão marcados como reservados. Isso é essencial para processadores futuros, para que o software trate esses bits como tendo uma finalidade futura, mas ainda desconhecida, nos processadores atuais. Como isso pode ser feito? Há algumas sugestões:
- Não dependa dos estados desses bits reservados, quando testar os valores nos registradores que contém tais bits. Mascare esses bits antes de testá-los;
- Não dependa do estado desses bits quando armazenar para a memória ou para o registrador;
- Não dependa da habilidade deles de reter informação escrita nesses bits;
- Quando rodar um registrador, sempre rode esses bits reservados com os valores escritos nos manuais do fabricante;
Obs.: Evite qualquer software dependente do estado desses bits. Isso torna eles dependentes de forma imprevisível. E correm risco de incopatibilidade futura.
Operandos de instruções: Na família 80x86 usamos esse formato:
label: mnemonic argument1, argument2, argument3
onde :
label = rótulo, identificador.
mnemonic = nome reservado para uma classe de opcode, que possuem as mesmas funções.
argument 1, 2 e 3 = são opcionais. Depende do opcode.
Quando dois operandos estão presentes, o da direita é a fonte e o da esquerda o destino. Exemplo:
LOADREG: mov eax, subtotal
Neste exemplo LOADREG é o rótulo. MOV é o mnemônico identificador do opcode. EAX é o destino do operando, e SUBTOTAL é a fonte do operando. Algumas linguagens assembly colocam isso na ordem inversa.
Endereçamento Segmentado: O processador usa endereçamento por byte. Isso quer dizer que a memória é acessada, lida e escrita, como uma sequencia de bytes. O intervalo de memória que pode ser endereççada é chamada de espaço de memória. O processador também suporta a forma segmentada. Essa é a forma onde o processador usa segmentos independentes de memórias. Por exemplo, o processador pode ter os códigos(instruções) e a pilha em segmentos separados. Códigos de endereço serão sempre referentes ao espaço de código, e a pilha ao espaço da pilha. A convenção abaixo refere-se a um byte de endereço com segmento:
REGISTRADOR DE SEGMENTO:BYTE DE ENDEREÇO
Exemplo: DS:FF79H
Significa endereço FF79H, no segmento apontado pelo registrador DS.
Outro exemplo: CS:EIP
Significa que o registrador EIP contém o endereço da instrução, e o registrador CS o segmento.
Pense na memória como uma matriz linear de bytes. O endereço do primeiro byte é 0, e o endereço do último byte é 2^n -1, onde n é o número de bits no barramento de endereços. Para um processador 8088 com 20 bits de barramento de endereço, a declaração da matriz pseudo-pascal é uma boa aproximação da memória:
Memory: matriz [0..1048575] de byte;
Para executá-la, o processador sabe que isso é equivalente a “Memory [125] := 0;” A CPU coloca o valor 0 no barramento de dados, o valor 125 no barramento de endereços, e a assertiva escrever(w) linha, já que neste exemplo é escrever(w), mas pode ser ler(R):

Para executar o equivalente a “CPU := Memory [125];” a CPU coloca o valor 125 no barramento de endereços, a assertiva ler linha(r), e lê o dado resultado disso no barramento de dados. Olhe a figura:

Isso só ocorre quando há acesso a um simples byte na memória. Mas o que ocorre, quando a CPU acessa uma WORD ou DOUBLEWORD? Como é uma matriz, como pode ter valores maiores do que oito bits?
Diferentes computadores possuem soluções diferentes para isso. A família 80x86 resolve isso armazenando o byte menos significativo da WORD no endereço especificado, e o byte mais significativo no próximo local. Mas a WORD consome dois endereços consecutivos de memória(dois bytes). Similarmente a DOUBLEWORD consome quatro endereços consecutivos de memória. O endereço da DW é o byte menos significativo. O restante dos três bytes seguem o menos significativo, com o mais significativo aparecendo no endereço da DW mais 3 bytes. Bytes, WORD e DW podem começar em qualquer endereço válido na memória. Nós veremos depois que começar com objetos mais largos que o normal não é uma boa idéia.
Repare na figura abaixo, que endereços de BYTE, WORD e DOUBLEWORD podem se sobrepôr. Quando for lido, é de baixo para cima, portanto serão sobrepostos.

Os processadores 8088 e 80188 possuem barramento de dados de oito bits. Isso significa que a CPU SÓ PODE TRANSFERIR DADOS no valor de oito bits por vez. O termo "matriz byte de memória endereçável" significa que a CPU pode endereçar memórias truncadas no valor tão pequeno quanto um simples byte. É a menor unidade de memória acessada pelo processador. Por exemplo, se ele quiser ler apenas quatro bits, terá que ler oito bits, e desprezar quatro. A CPU também não acessa qualquer oito bytes endereçáveis arbitrariamente. Se você inseriu 125, ela vai processar o byte desse valor, nem mais, nem menos. Endereços são sempre inteiros. O processador 8088 e 80188 podem manipular WORD e DW mesmo que seu barramento seja de apenas 1 byte. Isso requer outras operações de manipulações, porque eles só podem processar oito bits por vez. Para rodar uma WORD precisa de duas operações de memória. Para rodar DW(DOUBLWWORD), precisariam de quatro operações de memória. Aqui no blog, vamos inicar as programações com a família 80x86, pois é o padrão universal. Devagar, vamos ampliando nosso leque até as famílias mais atuais. Isso, claro, levará muito tempo. Paciência. Do contrário, não terá lógica. Aprendemos a andar, depois a correr.
As famílias 8086, 80186, 80286 e 80386sx têm um barramento de endereço de dados de 16 bits. Isso, permite o processador acessar duas vezes mais memória num único período de tempo, do que o de oito bits. Esses processadores organizam a memória em dois blocos: os pares e os ímpares:

A figura abaixo denota que a CPU utiliza como byte menos significativo D0-D7 no barramento de dados, o byte mais significativo D8-D15 no barramento de dados.

Lembram do que falei a respeito da família de 16 bits usar memórias consecutivas: Os oito bits menos significativos, mais os consecutivos? Isso cria uma problema sutil. O que ocorreria se olhar a figura acima, se o endereço de uma word fosse par? Ainda bem que a CPU reconhece esse problema e resolve ela mesmo. Apesar de ser 16 bits, a CPU ainda assim lerá em duas operações uma WORD na memória. O segundo problema é ainda mais obscuro. Quando as palavras de acesso, nós estamos realmente acessando dois bytes separados, cada qual tem seu próprio endereço de byte.. Quando as palavras de acesso, nós estamos realmente acessando dois bytes separados, cada qual tem seu próprio endereço de byte. Então surge a pergunta:
"Que endereço aparece no barramento de endereços?"
Os processadores de 16 bits do 80x86 sempre colocam endereços pares no barramento. Bytes pares sempre aparecem nas linhas de dados D0-D7 e os bytes ímpares sempre aparecem em linhas de dados D8-D15. Se você acessar uma word em um endereço par, a CPU pode trazer um fragmento inteiro de 16 bits em uma operação de memória. Da mesma forma, se você acessar um único byte, a CPU ativa o bloco apropriado (utilizando um byte "enable" linha de controle). Se o byte apareceu em um endereço ímpar, a CPU automaticamente move-o do byte mais significativo no barramento para o byte menos significativo. Então o que acontece quando a CPU acessa uma word em um endereço ímpar, como o exemplo dado anteriormente? Bem, a CPU não pode colocar o endereço 125 no barramento de endereços e ler os 16 bits da memória. Não há endereços ímpares resultantes de uma CPU de 16 bits do 80x86. Os endereços são sempre os mesmos. Portanto, se você tentar colocar 125 no barramento de endereços, esta vai colocar 124 para o barramento de endereços. Se você ler os 16 bits nesse endereço, você começaria a palavra no endereço 124 (byte menos significativo) e 125 (byte mais significaivo) - não é o que você esperaria. Acessando uma palavra em um endereço ímpar requer duas operações de memória em famílias 80x86. Primeiro o processador tem de ler o byte no endereço 125, então ele precisa ler o byte no endereço 126. Finalmente, ele precisa de swap as posições destes bytes internamente, uma vez que ambos entraram na CPU na metade errada do barramento de dados.
Felizmente, as CPUs de 16 bits do 80x86 ocultam esses detalhes de você. Seus programas podem acessar palavras a qualquer endereço e a CPU acessará apropriadamente e trocará (se necessário) o dados na memória. No entanto, como para acessar uma word em um endereço ímpar requer duas operações de memória (exatamente como o 8088/80188). Portanto, acessar words em endereços ímpares em um processador de 16 bits é mais lento do que acessar words em endereços pares. O uso organizando de memória, pode melhorar a velocidade do seu programa. Acessar quantidades de 32 bits sempre leva pelo menos duas operações na memória de 16 bits processadores. Se você acessar uma quantidade de 32 bits em um endereço ímpar, o processador exigirá três operações de memória para acessar os dados. Isso, na família 8088, ok?
Os processadores de 32 bits do 80x86 (o 80386, 80486 e Pentium Overdrive) utilizam quatro bancos de memória conectado ao barramento de dados de 32 bits:

O endereço colocado no barramento de endereços é sempre um múltiplo de quatro. Usando byte "permitir várias linhas", a CPU pode selecionar quais dos quatro bytes nesse endereço o software quer acessar. Tal como acontece com o Processador de 16 bits, a CPU automaticamente reorganizar bytes, se necessário. Com uma interface de memória de 32 bits, a CPU do 80x86 pode acessar qualquer byte com uma memória operação. Se (o endereço MOD 4) não é igual a três, em seguida, uma CPU de 32 bits pode acessar uma palavra usando esse endereço de uma operação única memória. No entanto, se o restante é três, então terá duas operações de memória para acessar essa palavra(acessando palavra em endereço mod 4=3):

Vamos resumir então algumas características dos processadores:
-Processadores 16 bits, segmentação(1978):
O IA-32 da família de arquitetura foi precedida por processadores de 16-bits, o 8086 e 8088. O 8086 tem registos de 16 bits e 16-bit barramento de dados externos, com 20-bit endereçamento dando um 1-MByte espaço de endereço. O 8088 é semelhante ao 8086, exceto se tem um 8-bit ônibus de barramento de dados externa.
A segmentação 8086/8088 introduziu a arquitetura IA-32. Com a segmentação, de 16-bit registrador de segmento contém um ponteiro para um segmento de memória de até 64 KBytes. Utilizando quatro registradores de segmento de cada vez, 8086/8088 processadores são capazes de endereçar até 256 KBytes sem alternar entre os segmentos. Os 20-bit endereços que podem ser formados usando um registrador de segmento e um adicional de 16 bits como ponteiro para fornecer um intervalo de endereços total de 1 MByte.
-Processador Intel ® 286 (1982):
O processador Intel 286 introduziu a operação em modo protegido para a arquitetura IA-32. Modo Protegido usa o conteúdo de registro do segmento como selectores ou ponteiros em tabelas como descritores. Descritores fornecem endereços de 24-bit com uma base física tamanho de memória de até 16 MBytes, suporte para o gerenciamento de memória virtual em uma troca de base do segmento, e uma série de mecanismos de proteção. Estes mecanismos incluem:
• verificação de limite de segmento Vol 2-2.1 Intel ® 64 e IA-32 arquiteturas
• Read-only e executar as opções único segmento
• Quatro níveis de privilégio
-Processador Intel386 ™(1985):
O processador Intel386 foi o primeiro processador de 32 bits da família IA-32. Ele introduziu os registros 32-bit para o uso tanto para conter operandos e para endereçamento. A metade inferior de cada registrador 32-bit Intel386 mantém as propriedades dos registros de 16 bits
das gerações anteriores, permitindo a compatibilidade com versões anteriores. O processador também fornece um modo virtual-8086 que permite ainda maior eficiência na execução programas criados para processadores 8086/8088.
Além disso, o processador Intel386 tem o apoio:
• A 32-bit endereço que suporta até 4 GBytes de memória física
• Um modelo de memória segmentado e um modelo de memória plana
• Paging, com 4 fixas KByte tamanho página que fornece um método para a gerenciamento de memória virtual
• Suporte para estágios em paralelo
-Processador Intel486 ™(1989):
O processador Intel486 ™ acrescentou mais capacidade de execução paralela através da expansão do decodificador do processador Intel386 de instrução e em cinco unidades de execução em estágios pipeline. Cada estágio funciona em paralelo com os outros em até cinco instruções diferentes em fases de execução.
Além disso, o processador acrescentou:
• Um 8-Kbyte de cache nível primeiro chip-que aumentou a porcentagem de instruções que possa executar a taxa de escalar de um ciclo do clock
• Uma x87 FPU integrado
• Poupar energia e recursos de gerenciamento de sistema
-O processador Intel ® Pentium ® (1993):
O lançamento do processador Pentium Intel adicionou uma segunda execução pipeline para alcançar um desempenho superescalar (duas pipeline, conhecido como u e v, juntos podem executar duas instruções por pulso). The on-chip cache de primeiro nível dobrou, com 8 KBytes dedicado para codificar e outros 8 KBytes dedicados aos dados. O cache de dados utiliza o protocolo MESI para um apoio mais eficiente cache write-back, além da WriteThrough cache anteriormente utilizada pelo processador Intel486. Ramo de previsão com uma na tabela de filial chip foi adicionado para aumentar o desempenho em construções em looping.
Além disso, o processador acrescentou:
Vol. 1 2-3 nas arquiteturas Intel ® 64 e IA-32 :
• Extensões para tornar o virtual-8086 de modo mais eficiente e permitir 4-MByte bem como 4-Kbyte páginas
• Os dados interno de 128 trajetos e 256 bits para adicionar velocidade para as transferências de dados internos
• Burstable barramento externo de dados foi aumentado para 64 bits
• Uma APIC para apoiar sistemas com múltiplos processadores
• Um processador dual mode para apoiar glueless com sistemas de dois processadores
Depois,houve um aprofundamento da família Pentium Intel quando introduziu a tecnologia MMX (o Processador Pentium com tecnologia MMX). A tecnologia Intel MMX usa o singleinstruction, múltiplos dados (SIMD modelo de execução) para realizar cálculos em paralelo inteiro embalado em dados contidos em registros de 64-bit.
-A família P6 de processadores (1995-1999):
A família de processadores P6 foi baseada em uma micro-arquitetura super escalar que estabelecem novos padrões de desempenho;
Um dos objetivos do projeto da micro arquitetura da família P6 podia exceder ao desempenho do processador Pentium significativamente enquanto estiver usando o mesmo 0,6 - micrômetro, quatro camadas, processo de fabricação BICMOS metal. Os membros desta família incluem os seguintes:
• O processador Intel Pentium Pro é de três super escalas. Usando técnicas de processamento paralelo, o processador é capaz de decodificar, em média, de expedição, e execução completa de três instruções por ciclo de clock. O Pentium Pro apresenta a análise de fluxo de execução dinâmica (micro-dados, fora de ordem de execução, previsão de desvio superior e execução especulativa) em uma implementação super escalar. O processador foi reforçado pelos seus esconderijos. Ele tem os mesmos dois on-chip 8-Kbyte caches de nível 1 como o processador Pentium e um adicional de 256 KByte cache de nível 2 no mesmo pacote do processador.
• O processador Intel Pentium II acrescentou a tecnologia Intel MMX para a família P6 de processadores, juntamente com novas embalagens e acessórios de hardware diversas. O núcleo do processador é embalado no cartucho Single Edge Contact (SECC). O Nível L de Dados e caches de instrução foram ampliados para 16 servidores cada, e cache de nível 2 com tamanhos de 256 servidores, 512 KBytes, e 1 MByte são suportados. A meia-velocidade de relógio o barramento traseiro liga o cache de nível 2 no processador. Múltiplos de baixa potência, Estados como AutoHALT, Stop-Grant, sono, sono profundo e são suportados para conservar energia quando em marcha lenta.
• O processador Pentium II Xeon combina as características premium das gerações anteriores de processadores Intel. Isto inclui: 4-way, 8-way (e acima) escalabilidade e um 2 MByte-Level 2 cache rodando em uma faixa backside em plena velocidade por detrás do barramento.
• A família de processadores Intel Celeron foca no segmento de valor de mercado do PC.
A sua introdução oferece um integrado 128 Kbytes de cache de nível 2 e um pino de plástico Grid Array (PPGA form factor) para diminuir o custo do sistema de design.
Arquiteturas Vol 2-4. 1 Intel ® 64 e IA-32 :
• O processador Intel Pentium III introduziu a Streaming SIMD Extensions (SSE) para a arquitetura IA-32. Extensões SSE expandir a execução SIMD modelo introduzido com a tecnologia Intel MMX, fornecendo um novo conjunto de 128 -- registros bits e capacidade de realizar operações SIMD em singleprecision com valores de ponto flutuante .
• O processador Pentium III Xeon estende os níveis de desempenho do IA-32 com o aumento da velocidade, on-die, e Advanced Transfer Cache.
-O processador Intel ® Pentium ® 4 Família (2000-2006):
A família de processadores Intel Pentium 4 é baseado na microarquitetura Intel NetBurst;
O processador Intel Pentium 4 introduziu Streaming SIMD Extensions 2 (SSE2)
Arquitetura Intel 64 foi introduzida no processador Intel Pentium 4 Extreme Edition Hyper-Threading e no processador Intel Pentium 4 6xx e 5xx seqüências.
Intel ® Virtualization Technology (Intel ® VT) foi introduzida no processador Intel Pentium 4 processador de 672 e 662.
-O processador Intel ® Xeon ® (2001 - 2007):
Processadores Intel Xeon (com exceção para os dual-core Intel Xeon LV, da Intel Xeon série 5100) são baseados na micro arquitetura Intel NetBurst.
O processador Intel Xeon MP introduziu o suporte para processadores Intel ® Hyper-Threading.
The 64-bit Intel ® Xeon ® 3,60 GHz (com um sistema de 800 MHz Bus) foi utilizado para introduzir Intel 64. O processador Dual-Core Intel Xeon dual inclui A tecnologia de núcleo. O processador Intel Xeon série 70xx inclui Virtualização da tecnologia Intel.
O processador Intel Xeon série 5100 apresenta potência de desempenho eficiente e de alta Micro arquitetura Intel Core. Este processador é baseado na arquitetura Intel ® 64, que inclui a Tecnologia de Virtualização da Intel e da tecnologia dual-core. O Intel Xeon série 3000 do processador também são baseados na micro arquitetura Intel Core. O Intel Xeon da série 5300 apresenta quatro núcleos de processamento em um pacote físico, eles são também baseado na micro arquitetura Intel Core.
-O processador Intel ® Pentium ® M (2003-atual):
A família de processadores Intel Pentium M é um alto desempenho, baixo consumo de energia móvel na família de processadores com melhorias na micro arquitetura com relação às gerações anteriores de IA-32, móveis da Intel. Esta família é projetada para prolongar a vida da bateria e integração perfeita com inovações de plataforma que permitem que novos modelos de uso (como a mobilidade estendida, forma ultra-fino fatores, e rede sem fio integrada).
Sua micro arquitetura Enhanced inclui:
• Suporte para arquitetura Intel com Dynamic Execution
• A alta performance, core de baixo consumo da Intel fabricados com avançada tecnologia de processo com interconexão de cobre
• On-Die, principal 32-KByte cache de instruções e 32-KByte write-back cache de dados
• On-die, cache de segundo nível (até 2 MByte) com Advanced Transfer Cache Architecture
• Advanced Branch Prediction and Data Prefetch Logic
• Suporte para a tecnologia MMX, instruções Streaming SIMD, e ao conjunto de instruções para SSE2
• A 400 ou 533 MHz, Source-Synchronous Processor System Bus
• gerenciamento avançado de energia usando a tecnologia Enhanced Intel SpeedStep ®
- O Processador Intel ® Pentium ® Extreme Edition (2005-2007):
O processador Intel Pentium Extreme Edition introduziu a tecnologia dual-core. Esta tecnologia oferece hardware avançado com multi-threading. O processador é com base na micro arquitetura Intel NetBurst e suporta SSE, SSE2, SSE3, Hyper - Threading, Intel e 64.
-O processador Intel ® Core ™ Duo e Intel ® Core ™ Solo
(2006-2007) :
O processador Intel Core Duo oferece energia eficiente, o desempenho dual-core com um design de baixo consumo, que aumenta a vida útil da bateria. Esta família e os single-core Intel Core Vol 2-6. 1 Individual oferecem melhorias na micro arquitectura sobre processador Pentium M família.
Sua micro arquitetura Enhanced inclui:
• Intel ® Smart Cache que permite o compartilhamento eficiente de dados entre dois núcleos de processador
• Melhoria da execução de decodificação e SIMD
• Intel ® Dynamic Power Coordination e Enhanced Intel ® Deeper Sleep para reduzir consumo de energia
• Intel ® Manager Advanced Thermal que apresenta sensor térmico digital com interfaces
• Suporte para poder otimizado barramento 667 MHz
O dual-core Intel Xeon LV baseia-se na mesma micro arquitetura que Intel Core Duo, e suporta a arquitetura IA-32.
- O Processador Intel ® Xeon ® 5100, 5300 e Série Intel ® Core ™ 2 Family (2006-atual) :
O processador Intel Xeon 3000, 3200, 5100, 5300 e 7300 series, Intel Pentium Dual-Core, Intel Core 2 Extreme, Intel Core 2 Quad e Intel Core 2 Duo com apoio à família do processador Intel de 64 de arquitetura, pois eles são baseados no desempenho de alta velocidade, poder e eficiência na micro arquitetura Intel ® Core construída sobre tecnologia de processo 65 nm.
A micro arquitetura Intel Core inclui as seguintes características inovadoras:
• Intel ® Wide Dynamic Execution para aumentar o desempenho e a execução
throughput
• Intel ® Intelligent Power Capability para reduzir o consumo de energia
• Intel ® Advanced Smart Cache que permite o compartilhamento eficiente de dados entre dois núcleos de processamento
• Intel ® Smart Memory Access para aumentar a largura de banda de dados e esconder a latência dos acessos à memória
• Intel ® Advanced Digital Media Boost que melhora o desempenho do aplicativo
utilizando várias gerações de Streaming SIMD Extensions

- O Processador Intel ® Xeon ® 5200, 5400, 7400 e Série Intel ® Core ™ 2 Family (2007-atual) :
O processador Intel Xeon 5200, 5400 e 7400, processador Intel Core 2 Quad
Q9000 Series, processador Intel Core 2 Duo E8000 série de suporte da Intel 64 arquitetura; eles são baseados na micro arquitetura Enhanced Intel ® Core utilizando processo de 45 nm tecnologia. O Enhanced microarquitetura Intel Core oferece os seguintes características melhoradas:
• A raiz-16 com divisor, primitivos e rápidos SO que aumenta ainda mais o desempenho do Intel ® Wide Dynamic Execution.
• Melhora Intel ® Advanced Smart Cache com até 50% maior cache de nível dois
e até 50% de aumento no caminho-set associatividade.
• Um motor de 128-bit shuffler melhora significativamente o desempenho do Intel ®
Advanced Digital Media Boost e SSE4.
Processador Intel Xeon série 5400 e Intel Core 2 Quad Série Q9000 Processador
suportam os processadores Intel quad-core. Processador Intel Xeon série 7400 oferece até seis núcleos do processador e um cache L3 de até 16 MBytes.
- O processador Intel ® Atom ™ Processor Family (2008-atual) :
Os processadores Intel ® AtomTM são construídos sobre a tecnologia de processo 45 nm. Elas são baseadas em uma nova micro arquitetura, AtomTM micro arquitetura Intel ®, que é otimizada para dispositivos de potência ultra-baixa. A micro arquitetura Intel ® AtomTM duas características em ordem de execução de condutas que minimizam o consumo de energia, aumentam a vida útil da bateria, e permite ultra-fatores de forma pequena. Ele fornece as seguintes características:
• Enhanced Intel SpeedStep ®
• Intel ® Hyper-Threading
• Deep Power Down Technology com Dynamic Cache Sizing
• Suporte para novas instruções até e inclusive Supplemental Streaming SIMD
Extensões de 3 (SSSE3).
• Suporte para processadores Intel ® Virtualization Technology
• Suporte para Arquitetura Intel ® 64 (excluindo o processador Intel Atom Z5xx Series)
- O processador Intel ® Core ™ i7 Família (2008-atual) :
O processador Intel Core i7 da Intel suporte a arquitetura 64, pois eles são baseados em Intel (Nehalem), utilizando tecnologia de processo de 45 nm. O processador Intel Core i7 processador inclui as seguintes características inovadoras:
• Intel ® Turbo Boost tecnologia converte headroom térmica em um melhor desempenho.
• Intel ® Hyper Tecnologia em conjunto com Quadcore para quatro
núcleos e oito threads.
Unidade de controlo
• Dedicado poder de reduzir o consumo de energia ativo e inativo.
• controlador de memória integrado no processador com suporte para três canais de memória DDR3 memória.
• 8 MB inclusiva Intel ® Smart Cache.
• Intel ® QuickPath Interconnect (QPI) fornecendo ponto-a-ponto link para o chipset.
• Suporte para SSE4.2 e conjuntos de instruções SSE4.1.
• Segunda geração Intel Virtualization Technology.
Bom, isso é um resumo das estruturas modernas. Nem esquenta cabeça com isso. Era apenas para se ver como evoluiu a tecnologia nos processadores. Lá na frente pretendo me aprofundar muito nisso. Muito mesmo, com detalhes. Mas, me concentrarei mais na família 80x86. Neste momento.
Barramento de controle família 80x86: É um conjunto de sinais elétricos que comandam o resto atravéns da CPU. Considere por um momento o seguinte:
Considere por um momento o barramento de dados. A CPU envia dados para a memória e recebe dados da memória no barramento de dados. Isso leva a pergunta: "está enviando ou recebendo?" Há duas linhas no barramento de controle, ler e escrever, que especificam a direção do fluxo de dados. Outros sinais incluem clocks do sistema, interromper linhas, o estado, e assim por diante. A exata composição do barramento de controle varia entre os processadores da família 80x86. No entanto, algumas linhas de controle são comuns a todos os processadores e merecem uma breve menção. A linha ler e escrever de controle controlam a direção dos dados no barramento de dados. Quando ambos contêm uma lógica de um, a CPU e memória de E / S não estão se comunicando um com o outro. Se a linha de leitura é baixa (zero lógico), a CPU está lendo dados da memória (isto é, o sistema está transferindo dados da memória para a CPU). Se a linha de escrita está baixa, o sistema de transferências de dados é da CPU para a memória. O byte de habilitar linhas são um outro conjunto de linhas de controle importante. Estas linhas de controle permitem processadores 16, 32 e 64 de lidar com pequenos pedaços de dados.
A família 80x86, ao contrário de muitos outros processadores, fornece dois espaços de endereços distintos:
-uma para a memória e um para I / O.
Enquanto o barramento de endereço de memória em vários processadores 80x86 variam em tamanho, o barramento de E / S endereço em todas as CPUs do 80x86 é de 16 bits. Isso permite que o processador possa endereçar até 65.536 diferentes localizações I / O(e/s). Como se constata, a maioria dos dispositivos (como o teclado, impressora, discos, etc) exigem mais do que um I / O local. No entanto, 65.536 locais de I / O(e/s) são mais que suficientes para a maioria das aplicações. O IBM PC original no design só é permitido o uso de 1.024 destes.
Embora a família 80x86 suporte dois espaços de endereço, ele não tem dois endereços de barramento (para I / O e memória). Em vez disso, o sistema compartilha o barramento de endereços, tanto para I / O e endereços de memória. Linhas de controle adicionais decidem se o endereço é destinado à memória ou I / O. Quando tais sinais estão ativos, os dispositivos de I / O usam o endereço do byte menos significativo de 16 bits do barramento de endereços. Quando inativos, os dispositivos de I / O ignoram os sinais no barramento de endereços (o subsistema de memória assume nesse momento).
-Sistema I/O(E/S:ENTRADA/SAÍDA):
Além dos 20, 24 ou 32 linhas de endereço que acessam a memória, a família 80x86 fornece um de 16 bits I / O para o barramento de endereços. Isto dá às CPUs do 80x86 dois espaços de endereços distintos: um para memória e um para operações de I / O. Linhas no barramento de controle diferenciam entre a memória e o endereço da E / S. Outras linhas de controle separadas e um barramento menor. O endereçamento de I / O se comporta exatamente como a memória de endereçamento. Memória e dispositivos de I / O compartilham ambos o barramento de dados e a mesma 16 linhas no barramento de endereços(byte menos significativo).
Há três limitações para o subsistema de E / S no PC da IBM: primeiro, as CPUs do 80x86 requerem instruções especiais para acessar dispositivos de I / O, em segundo lugar, os projetistas do IBM PC utilizam o "melhor" local de I / O para seus próprios fins, forçando os desenvolvedores de terceiros a utilizar os locais menos acessíveis, em terceiro lugar, os sistemas de 80x86 podem endereçar mais de 65.536 (216)Endereços de I / O. Quando você considerar que uma placa de vídeo VGA típica requer mais de 128.000 locais diferentes, você pode ver um problema com o tamanho do barramento de E / S.
Felizmente, os projetistas de hardware podem mapear seus dispositivos de I / O para o endereço de memória com espaço tão facilmente como para o espaço de endereço do I / O. Então, usando o circuito adequado, eles podem fazer seus dispositivos de I / O olhar apenas como memória. Isto é como, por exemplo, mostrar,adaptadores no trabalho IBM PC. Por enquanto você pode assumir que eles acessam a memória do mesmo jeito.
Sistema de Tempo:
Embora os computadores modernos sejam bastante rápidos e estão ficando mais rápido o tempo todo, eles ainda requerem uma quantidade finita de tempo para realizar até mesmo as menores tarefas. Nas máquinas Von Neumann, como o 80x86, a maioria das operações são serializados. Isto significa que o computador executa comandos em uma ordem prescrita. Não faria, por exemplo, para executar a instrução
I: = I * 5 +2; antes I: = J; na seguinte seqüência:
I: = J;
I: = I * 5 + 2;
É evidente que precisamos de alguma forma de controle que executa a primeira declaração e que executa a segunda. Claro que, em sistemas de computador real, as operações não ocorrem instantaneamente. Movendo uma cópia de J para I toma uma certa quantidade de. Da mesma forma, multiplicando I por cinco em seguida, adicionando dois e armazenar o resultado de volta para I leva tempo. Como você poderia esperar, a segunda afirmação Pascal acima toma um pouco mais de tempo para executar do que a primeira. Para aqueles interessados em escrever o software rápido, uma questão natural perguntar é: "Como é que o processador executa instruções, e como podemos medir quanto tempo demora para executar? "
A CPU é uma peça muito complexa de circuitos. Sem entrar em muitos detalhes, vamos apenas dizer que as operações dentro da CPU devem ser cuidadosamente coordenadas ou a CPU produzirá resultados errados. Para garantir que todas as operações ocorram no momento certo, atualmente , as CPUs do 80x86 usam um sinal alternado chamado relógio do sistema(clock).
O CLOCK:
No nível mais básico, o relógio do sistema lida com toda a sincronização dentro de um sistema de computador. O relógio do sistema é um sinal elétrico no barramento de controle que alterna entre zero e um, a uma taxa periódica (ver Figura). CPUs são um bom exemplo de um sistema de lógica complexa síncrona. O relógio do abre muitas das portas lógicas que compõem a CPU o que lhes permite operar em um modo sincronizado.

A freqüência com que o relógio do sistema alterna entre zero e um é o sistema freqüência de clock. O tempo que leva para o relógio do sistema para mudar de zero a um e volta ao zero é o período de relógio. Um período completo é chamado também um ciclo de relógio. Nos sistemas mais modernos, o relógio do sistema alterna entre zero e um a velocidades superiores a vários milhões vezes por segundo. A freqüência do relógio é simplesmente o número de ciclos de relógio que ocorrem a cada segundo. Um chip 80486 típica roda em velocidades 66 milhões de ciclos por segundo.
"Hertz" (Hz) é o termo técnico que significa um ciclo por segundo. Portanto, o chip 80486 funciona em 66 milhões hertz, ou 66 megahertz (MHz). As freqüências típicas de 80x86 escala peças de 5 MHz a 200 MHz ou mais. Note-se que um período de clock (a quantidade de tempo para completar um ciclo de relógio) é o inverso da freqüência do relógio. Por exemplo, um clock de 1 MHz teria um período de clock de um microssegundo (1 / 1, 000.000 de um anúncio segundo). Da mesma forma, um relógio de 10 MHz teria um período de clock de 100 nanossegundos (100 bilionésimos de um segundo). Uma CPU rodando a 50 MHz teria um período de clock de 20 nanossegundos.Note que nós normalmente expressamos períodos de relógio em milionésimos ou bilionésimos de segundo.Para garantir a sincronização, a maioria dos CPUs iniciam uma operação sobre a crista de queda (quando o clock vai de um a zero) ou a borda de subida (quando o relógio vai de zero a um). O relógio do sistema passa a maior parte de seu tempo em zero ou um e muito pouco tempo com comutação entre os dois. Portanto clock é o ponto de sincronização perfeita. Uma vez que todas as operações da CPU são sincronizadas em torno do relógio, a CPU não pode executar tarefas mais rapidamente do que o clock4. Entretanto, apenas porque uma CPU está funcionando em algumas frequências de relógio não significa que ele está sendo executado, em muitas operações por segundo. Muitas operações tem múltiplos ciclos de clock para completar, então a CPU geralmente executa operações em uma operação significativamente mais baixa.
Sistema de Acesso à Memória e CLOCK:
Acesso à memória é provavelmente a mais comum das atividades da CPU. Acesso à memória é definitivamente uma operação sincronizada com o relógio do sistema. Ou seja, a leitura de um valor de memória ou escrever um valor para a memória não ocorre mais frequentemente do que uma vez a cada relógio ciclo 5. De fato, em muitos processadores 80x86, leva vários ciclos de clock para acessar um local de memória.
O tempo de acesso à memória é o número de ciclos de relógio do sistema requer acesso a uma localização de memória, este é um valor importante já que o resultado da memória os tempos de acesso em desempenho inferior.
Diferentes processadores 80x86 têm tempos diferentes de memória de acesso que variam de um a quatro ciclos de relógio. Por exemplo, as CPUs 8088 e 8086 requerem quatro ciclos de clock para acessar memória; o 80486 requer apenas um. Portanto, a 80486 vai executar programas que acessam memória mais rápido que um 8086, mesmo quando rodando a mesma freqüência. Abaixo um ciclo de memória do 80486 para leitura de um dado:

Abaixo, um modelo de escrever na memória do 80486:

Tempo de acesso à memória é a quantidade de tempo entre um pedido de operação de memória (leitura ou escrita) e o tempo que a operação de memória leva para ser concluída. Em uma CPU 5 MHz a 8088/8086 o tempo de acesso à memória é de aproximadamente 800 ns (nanossegundos). Em uma de 50 MHz 80486, o tempo de acesso é um pouco menos de 20 ns. Note-se que o tempo de acesso de memória para o 80486 é de 40 vezes mais rápido do que o 8088/8086. Isso ocorre porque o 80486 da freqüência do relógio é dez vezes mais rápido e que utiliza um quarto do ciclo de clock para acessar a memória. Durante a leitura da memória, o tempo de acesso à memória é a quantidade de tempo a partir do ponto que a CPU coloca um endereço no barramento de endereços e a CPU recebe os dados off barramento de dados. Em um processador 80486 com um tempo de acesso a um ciclo de memória, uma leitura é algo como mostrado na figura . Gravação de dados em memória é similar (ver Figura).
Note-se que a CPU não esperar pela memória. O tempo de acesso é especificado pela freqüência. Se o subsistema de memória não funciona suficientemente rápido, o processador irá ler lixo sobre uma operação de leitura de memória e não armazena corretamente os dados em uma operação de memória write. Isto vai certamente causar a falha do sistema. Dispositivos de memória têm avaliações diferentes, mas as duas mais importantes são a capacidade e velocidade (tempo de acesso). RAM dinâmica típica (memória de acesso aleatório), os dispositivos têm capacidade de quatro (ou mais) Megabytes e uma velocidade de 50-100 ns. Você pode comprar dispositivos maiores ou mais rápido, mas eles são muito mais caros. Um típico 33 MHz 80486 sistema usa 70 ns nos dispositivos de memória. Aguarde só um segundo aqui! Aos 33 MHz, o relógio do período é de aproximadamente 33 ns. Como pode um programador fugir do uso de memória de 70 ns? A resposta é esperar estados.
- Estados de Espera
Um estado de espera não é nada mais do que um ciclo de clock extra para dar algum tempo ao dispositivo para concluir uma operação. Por exemplo, um sistema de 50 MHz 80486 tem um período de relógio de 20 ns. Este implica que você precisa de memória de 20 ns. Na verdade, a situação é pior do que isso. Na maioria dos computadores, nos sistemas há circuitos adicionais entre a CPU e memória: decodificação e lógica buffering. Este circuito adicional introduz atrasos adicionais no sistema :

Neste diagrama, o sistema perde 10ns em buffering e decodificação. Assim, se o CPU precisa dos dados de volta em 20 ns, a memória deve responder em menos de 10 ns. Você pode realmente comprar 10ns memória. No entanto, é muito caro, volumoso, consome uma muita energia, e gera uma grande quantidade de calor. Estes são atributos ruins. Supercomputadores usam este tipo de memória. No entanto, os upercomputadores também custam milhões de dólares, ocupam todo os quartos, requerem refrigeração especial, e fontes de alimentação gigante. Não é o tipo de coisa que você quer sentar em sua mesa. Se o custo-eficaz de memória não irá funcionar com um processador rápido, como as empresas gerem PCs para vender rápido? Uma parte da resposta é o estado de espera. Por exemplo, se você tiver um 20 MHz, com um tempo de ciclo de memória de 50 ns e você perde 10 ns para tamponamento e decodificação, você vai precisar de memória 40 ns. E se você só pode comprar uma memória de 80 ns em 20 MHz de sistema? Adicionando um estado de espera para prolongar o ciclo de memória de 100 ns (dois ciclos de relógio) resolverá este problema. Subtraindo 10ns para as folhas de decodificação e buffering 90 ns.Portanto, a memória de 80 ns responde bem antes de a CPU requerer os dados. Quase todas as CPUs de uso geral na existência fornece um sinal no barramento de controle para permitir a inserção de estados de espera. Geralmente, o circuito de decodificação afirma essa linha para demorar um período de relógio adicional, se necessário. Isto dá a memória de acesso tempo suficiente, o sistema funciona corretamente .
Às vezes nem um único estado de espera é suficiente. Considere a 80486 rodando a 50 MHz. O tempo de ciclo normal de memória é inferior a 20 ns. Portanto, menos de 10 ns estão disponíveis para depois subtrair o tempo de decodificação e buffering. Se você estiver usando 60 ns de memória no sistema, a adição de um único estado de espera não irá fazer o truque. Cada estado de espera dá-lhe 20 ns, assim com um único estado de espera você precisaria de memória de 30 ns. Para trabalhar com memória de 60 ns você seria necessário adicionar três estados de espera (zero estados de espera = 10 ns, um estado de espera = 30 ns, dois estados de espera = 50 ns, e três estados de espera = 70 ns). Desnecessário será dizer que, do ponto de vista do desempenho do sistema, estados de espera não são uma boa coisa. Enquanto a CPU está à espera de dados da memória não pode operar sobre esses dados.
Adicionando um único estado de espera para um ciclo de memória em uma CPU 80486 dobra a quantidade de tempo necessário para acessar os dados. Este, por sua vez, divide na metade da velocidade o acesso à memória. Rodando um estado de espera em cada acesso à memória é quase como cortar a freqüência do relógio do processador pela metade. Você está conseguindo metade do trabalho realizado no mesmo período de tempo. Você provavelmente já viu os anúncios. "80386DX, 33 MHz, 8 megabytes de RAM 0 estado de espera ... apenas X! "Se você olhar de perto as especificações você notará que o fabricante está utilizando memória 80ns(nas família 80x86). Como eles podem construir sistemas que funcionam em 33 MHz e tem zero estados de espera?
Fácil. Eles mentem. Não há nenhuma maneira um 80386 pode ser executado em 33 MHz, executando um programa arbitrário, sem nunca inserir um estado de espera. É claramente impossível. No entanto, é perfeitamente possível conceber um subsistema de memória que, sob certas circunstâncias excepcionais, consegue operar sem parte dos estados de espera do tempo. A maioria dos tipos de comercialização desconfigura se o seu sistema já funciona em zero estados de espera, eles podem afirmar isso em sua literatura. Na verdade, a maioria de marketing desse tipo não tem nenhuma idéia que um estado de espera é outro que não é ruim e com os estados de espera não é algo para se gabar. No entanto, nós não estamos condenados a uma execução lenta por causa da adicionou estados de espera. Há vários truques projetistas de hardware podem desempenhar para atingir zero estados de espera maior parte do tempo. O mais comum deles é o uso de cache de memória.
-Memória Cache:
Se você olhar para um programa típico (como muitos pesquisadores), você vai descobrir que ele tende a acessar os mesmos locais de memória repetidamente. Além disso, você também descobrirá que um programa geralmente acessa posições de memória adjacentes. Os nomes técnicos dados a este fenômeno são localidade temporais de referência e localidade espacial de referência. Quando exibindo localidade espacial, um programa acessa posições de memória vizinhas. Ao exibir localidade temporal de referência um programa acessa repetidamente a mesma memória local durante um curto período de tempo. Ambas as formas de localização ocorrer nos seguintes segmentos de códigos Pascal:
for i: = 0 to 10 do
A [i]: = 0;
Há duas ocorrências de cada localidade espacial e temporal de referência dentro desta loop. Vamos considerar o primeiro.
No código Pascal acima, o programa faz referência à variável i muitas vezes. O loop for compara icom 10 para ver se o ciclo está completo.Ele também incrementa i de um na parte inferior do loop. A atribuição declarada também usa i como um índice da matriz. Isto mostra a localidade temporal de referência em ação desde que a CPU acessa i em três pontos em um curto período de tempo.
Este programa também exibe localidade espacial de referência. O próprio laço zera os elementos da matriz A escrevendo um zero para o primeiro local em A, então para o segundo local em A, e assim por diante. Assumindo que Pascal armazena os elementos de A em posições de memória consecutivas de memória, cada iteração do loop acessa espaços de memória que estão lado a lado. Há um exemplo adicional de localidade temporal e espacial de referência no exemplo Pascal acima, embora não seja tão óbvio. Instruções de computador que informam o sistema para fazer a tarefa especificada também residem na memória. Essas instruções aparecem sequencialmente na memória - a localidade espacial. O computador também executa essas instruções repetidamente, uma vez para cada iteração - a localidade temporal.
Se você olhar o perfil de execução de um programa típico, você descobrirá que o programa geralmente executa menos da metade das declarações. Geralmente, um programa típico pode usar apenas 10-20% da memória destinada a ele. Em qualquer dado momento, um programa de um megabyte pode acessar apenas 4-8 kilobytes de dados e código.
A memória cache fica entre a CPU e memória principal. É uma pequena quantidade de de memória muito rápida(zero estados de espera). Diferentemente da memória normal, os bytes que aparecem dentro de um cache não têm endereços fixos. Em vez disso, a memória cache pode transferir o endereço de um objeto de dados.
Isso permite que o sistema mantenha os valores recentemente acessados em cache. Endereços que a CPU nunca acessou em algum tempo permanecem na memória principal (lenta). Como a maioria dos acessos de memória são para variáveis acessadas recentemente (ou para locais perto de um local recentemente acessados), os dados geralmente aparecem na memória cache.
A memória cache não é perfeita. Embora um programa possa gastar um tempo considerável na execução do código em um lugar, eventualmente, ele vai chamar um procedimento ou desviará para alguma seção do código fora da memória cache, como num evento em que a CPU tem que ir à memória principal para buscar os dados. Como a memória principal é lenta, isso vai requerer a inserção de estados de espera. Um acerto de cache ocorre sempre que a CPU acessa a memória e encontra os dados no cache. Em tal caso a CPU pode realmente acessar o dado com zero estados de espera. Uma falha de cache ocorre se a CPU acessa a memória e os dados não estão na cache. Em seguida, o processador tem de ler os dados da memória principal, incorrendo em um desempenho de perda. Para tirar vantagem da localidade de referência, a CPU copia dados para o cache sempre que acessa um endereço não presente no cache. Uma vez que é provável que o sistema acesse o mesmo local em breve, o sistema irá salvar os estados de espera por ter esses dados em cache.
Como descrito acima, a memória cache trata dos aspectos temporais do acesso à memória, mas não da quantidade. Pegando locais de memória, se você acessá-los não vai acelerar o programa se você constantemente acessa locais consecutivos (localidade espacial). Entraremos mais nesse tópico mais tarde, quando usarmos computadores com essa arquitetura.
Depois de escrever esses tópicos muito técnicos e complicados, não quero que o leitor fique desanimado. Isto é apenas uma apresentação contínua das arquiteturas de microprocessadores. Eu quis usar a evolução da tecnologia, como um raciocínio contínuo, para ter lógica. Na verdade, irei apenas trabalhar o assembly na arquitetura intel, por ser o que a maioria dos computadores no mundo usam. E começarei de baixo....de baixo mesmooo...precisamos primeiro aprender a soletrar, depois aprender a juntar palavras, e só depois formar textos. Começaremos a trabalhar com processores arcaicos, mas dentro deles, todo o aprendizado será feito. Primeiro, com o 8080 ou 8085, este, é de oito bits. Apesar do que alguma spessoas acham, eles são úteis e muito utilizados até hoje. A eletrônica o usa para aúdio e estúdios, e fazem qualquer coisa lá. Outros, o usam como microcontrolador, de oito bits, usados em indústrias. A linguagem muda, mas, a lógica é exatamente a mesma. Depois, iremos abordar o 8088 e 8086. De onde todas as outras são derivadas. Ele possui 16 bits, mas é a base de todos os outros, e veremos depois o porquê. E assim, por diante. Com o pouco tempo que disponho, e devido à alta complexidade do assunto, isso levará tempo.


Referências Bibliográficas:Por favor ler o tópico específico desse item...há muitas referências e gosto de lembrar de todas!

Bibliografia e Referências(textos,imagens,etc.etc.)

-VISCONTI, Eng. Antonio Carlos José Franceschini, Microprocessadores 8080 e 8085. Software. Vol. 2, 6ªEdição, Ed. Érica,São Paulo,1981.
-http://www.unit.br/efreire/sistemas_digitais.htm
-http://sdig.home.sapo.pt/Micros/8085_inicio.html
-IDOETA, Ivan V. e CAPUANO, Francisco G.. Elementos de Eletrônica Digital. 16. ed., ed. Érica, 1984;
-MALVINO, Albert Paul e LEACH, Donald P.. Eletrônica Digital: Princípios e Aplicações. São Paulo: McGraw-Hill, 1987, 684p. 2 volumes.
-MALVINO, Albert Paul. Microcomputadores e Microprocessadores. McGraw-Hill, [s.d.].
-PADILHA, António J.G.. Sistemas Digitais. Lisboa: McGraw Hill, 1993
-Circuitos Digitais e Microprocessadores Taub
-Eletrônica Digital Taub/Schilling
-Linguagem Assembler Orientada para Objeto Len Dorfman
-PCI Local Bus Specification, Revision 2.0 April 30, 1993 intel
-Standard BIOS 32-bit Service Directory Proposal, Revision 0.4 May 24, 1993
(available from Phoenix Technologies Ltd., Norwood, MA)intel
-MicrosoftPlug and Play Specification Plug and Play Design Specification for IEEE 1394
-www.ivair.com.br
-www.microcontroller.com
-www.8052.com
-www.vidal.com.br
-www.questlink.com
-www.microchip.com
-www.ti.com
-www.zilog.com
-www.asm51.eng.br
-www.digikey.com
-Designing Hardware for Microsoft® Operating Systems
(Microsoft Extensible Firmware Initiative FAT32 File System Specification FAT: General Overview of On-Disk Format Version 1.03, December 6, 2000 Microsoft Corporation)
-Microsoft Portable Executable and Common Object File Format Specification
Microsoft Corporation(Revision 6.0 - February 1999)
-Writing Drivers for the DP8390 NIC Family of Ethernet Controllers
-O Livro Negro dos Vírus de Computadores Mark Ludvig
-Princípios Digitais Tokheim
-Assembly Language Step-by-Step: Programming with DOS and Linux, Second Edition by Jeff Duntemann ISBN:0471375233
-Assembly Language The True Language of Programmers
-Professional Assembly Language Richard Blum
-http://pt.wikipedia.org/wiki/Mapa_de_Karnaugh
- http://pt.wikipedia.org/wiki/%C3%81lgebra_booleana
- http://pt.wikipedia.org/wiki/Sistema_octal
- http://pt.wikipedia.org/wiki/Sistema_bin%C3%A1rio_(matem%C3%A1tica)
-http://pt.wikipedia.org/wiki/Linguagem_de_baixo_n%C3%ADvel
-http://pt.wikipedia.org/wiki/Assembly
- Art of Assembly de Randall Hyde.
-Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 1:
Basic Architecture
-Intel® 64 and IA-32 Architectures Software Developer’s Manual
-Intel® 64 Architecture x2APIC Specification
- Intel® 64 and IA-32 Architectures Software Developer’s Manual (in five volumes)
http://developer.intel.com/products/processor/manuals/index.htm
- Intel Virtualization Technology for Directed I/O, Rev 1.1 specification
http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direc
t_IO.pdf
- Detecting Multi-Core Processor Topology in an IA-32 Platform
http://www3.intel.com/cd/ids/developer/asmo-na/eng/recent/275339.htm
-Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2A:
Instruction Set Reference, A-M
- The data sheet for a particular Intel 64 or IA-32 processor
-The specification update for a particular Intel 64 or IA-32 processor
-Intel® C++ Compiler documentation and online help
http://www.intel.com/cd/software/products/asmo-na/eng/index.htm
- Intel® Fortran Compiler documentation and online help
http://www.intel.com/cd/software/products/asmo-na/eng/index.htm
- Intel® VTune™ Performance Analyzer documentation and online help
http://www.intel.com/cd/software/products/asmo-na/eng/index.htm
- Intel® 64 and IA-32 Architectures Software Developer’s Manual (in five volumes)
http://developer.intel.com/products/processor/manuals/index.htm
- Intel® 64 and IA-32 Architectures Optimization Reference Manual
http://developer.intel.com/products/processor/manuals/index.htm
- Intel® Processor Identification with the CPUID Instruction, AP-485
http://www.intel.com/support/processors/sb/cs-009861.htm
- Intel 64 Architecture x2APIC Specification:
http://developer.intel.com/products/processor/manuals/index.htm
- Intel 64 Architecture Processor Topology Enumeration:
http://softwarecommunity.intel.com/articles/eng/3887.htm
- Intel® Trusted Execution Technology Measured Launched Environment
Programming Guide, http://www.intel.com/technology/security/index.htm
- Intel® SSE4 Programming Reference
http://developer.intel.com/products/processor/manuals/index.htm
- Developing Multi-threaded Applications: A Platform Consistent Approach
http://cachewww.intel.com/cd/00/00/05/15/51534_developing_multithreaded_applications.pdf
- Using Spin-Loops on Intel Pentium 4 Processor and Intel Xeon Processor MP
http://www3.intel.com/cd/ids/developer/asmona/
eng/dc/threading/knowledgebase/19083.htm
http://softwarecommunity.intel.com/isn/home/
http://www.intel.com/cd/ids/developer/asmo-na/eng/dc/index.htm
http://www.intel.com/support/processors/1-10 Vol. 2A
http://www.intel.com/cd/software/products/asmo-na/eng/index.htm
- Intel 64 and IA-32 processor manuals (printed or PDF downloads):
http://developer.intel.com/products/processor/manuals/index.htm
- Intel® Multi-Core Technology:
http://developer.intel.com/multi-core/index.htm
- Intel® Hyper-Threading Technology (Intel® HT Technology):
http://developer.intel.com/technology/hyperthread/
- Intel®Developing Multithreaded Applications: A Platform Consistent Approach
V. 2.0, February 2005
-The Intel® C++ Compiler User’s Guide or The Intel® Fortran Compiler User’s
Guide, see “Compiler Optimizations/Parallelization/Automatic Parallelization”
-“Efficient Exploitation of Parallelism on Pentium® III and Pentium 4 Processor-Based
Systems”, Aart Bik, Milind Girkar, Paul Grey and Xinmin Tian, Intel Technology
Journal
-http://www.intel.com/technology/itj/q12001/articles/art_6.htm
-The Intel Software College provides extensive training material on Intel software
development products.
-Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2B : Instruction Set Reference, N-Z
-http://www.numaboa.com/informatica/tutos/aoa/634-lab1

quinta-feira, 5 de novembro de 2009

Compreendendo Dados Configurados para Assembly!

Linguagem de programação de baixo nível trata-se de uma linguagem de programação que compreende as características da arquitetura do computador. Assim, utiliza somente instruções do processador, para isso é necessário conhecer os registradores da máquina. Nesse sentido, as linguagens de baixo nível estão diretamente relacionadas com a arquitetura do computador. Um exemplo é a linguagem Assembly (não Assembler) que trabalha diretamente com os registradores do processador, manipulando dados.

As linguagens de baixo nível são divididas em duas categorias: primeira geração e segunda geração.

Primeira Geração
A linguagem de primeira geração, ou 1GL, é o código de máquina. É a única linguagem que um microprocessador pode entender nativamente. O código de máquina não pode ser escrito ou lido por um editor de texto, e portanto é raramente usado por uma pessoa diretamente.

Exemplos: 1 - instrução de adição dos computadores B-200, B-300 e B-500 da Burroughs Corporation:

O=Op Code M e N variaveis que definem os campos dos endereços AAA e BBB
AAA, BBB e CCC campos com os endereços dos operandos
Campo O M N AAA BBB CCC
Código: 1 2 3 100 200 300
Interpretação:

1.O - 1 Código da instrução de adição
2.M - 2 Quantidade de dígitos da parcela 1, em AAA
3.N - 3 Quantidade de dígitos da parcela 2, em BBB
4.AAA - 100 endereço da parcela 1
5.BBB - 200 endereço da parcela 2
6.CCC - 300 endereço onde deve ser armazenado o resultado da adição da parcela 1 com a parcela 2.

2 - uma das instruções de adição do microprocessador de sinal digital (DSP) TMS-320C54x da Texas Instruments:

0000000SIAAAAAAA
Interpretação:
0000000 - Código desta instrução de adição.
S - define qual dos dois acumuladores será usado: 0 acumulador "A", 1 acumulador "B" I - indica o modo de endereçamento: 0 é endereçamento direto, 1 indireto.
AAAAAAA - Address (endereço) Esta instrução soma um valor de 16 bits da memória (cujo endereço está no apontador) ao acumulador selecionado

Segunda Geração
A linguagem de segunda geração, ou 2GL, é a linguagem Assembly. É considerada de segunda geração pois embora não seja uma linguagem nativa do microprocessador, uma linguagem Assembly ainda deve compreender as características da arquitetura do microprocessador (como registradores e instruções).
Uma linguagem de montagem ou assembly é uma notação legível por humanos para o código de máquina que uma arquitectura de computador específica usa. A linguagem de máquina, que é um mero padrão de bits, torna-se legível pela substituição dos valores em bruto por símbolos chamados mnemônicos.

Por exemplo, enquanto um computador sabe o que a instrução-máquina IA-21 (10110000 01100001) faz, para os programadores é mais fácil recordar a representação equivalente em intruções mnemônicas MOV AL, 61h. Tal instrução ordena que o valor hexadecimal 61 (97, em decimal) seja movido para o registrador 'AL'.

Arquitetura
Ao contrário do que acontece nas linguagens de alto nível, existe (até certo ponto) uma correspondência de 1 para 1 entre a linguagem de montagem simples e a linguagem de máquina. Por isso a tradução do código de montagem em código de máquina não é chamada compilação, mas montagem. Consegue-se transformar a linguagem de montagem em linguagem de máquina recorrendo a um montador (também chamado assembler, originado do termo em inglês), e a transformação inversa faz-se recorrendo a um desmontador (também chamado disassembler, originado do termo em inglês).

Cada arquitectura de computador tem a sua própria linguagem de máquina e, portanto, sua própria linguagem de montagem. Essas linguagens de montagem diferem no número e tipo de operações que suportam. Também têm diferentes tamanhos e números de registos, e diferentes representações dos tipos de dados armazenados. Enquanto todos os computadores de utilização genérica são capazes de desempenhar essencialmente as mesmas funções, o modo como o fazem é diferente.

Além disso, podem existir conjuntos múltiplos de mnemónicas, ou sintaxes de linguagem de montagem, para um único conjunto de instruções. Nestes casos, o conjunto mais popular é aquele que é utilizado pelo fabricante na sua documentação.

A maioria dos processadores só consegue manipular os dados que estão em registradores e a linguagem de montagem facilita o trabalho direto com os registradores.

No mercado de PCs, dominado por processadores Intel e AMD, atualmente existem duas arquiteturas. Primeiro a IA32, criada pela Intel em 1985 e primeiramente utilizada pelo processadores i386 e segundo a IA32-EM64T (ou IA32-AMD64 ) criada em 2002 pela AMD (Mas também utilizada pela Intel hoje). O IA32 utiliza o grupo de instruções chamado x86, e o IA32-EM64T utiliza o grupo chamado x86-64. As duas arquiteturas usam numeros diferentes de registradores gerais e tamanho. Enquanto os registradores do x86 são 32 bits os da x86-64 são 64 bits.Aqui no nosso blog será tratado apenas dessas plataformas,ou seja, Intel.São as mais utilizadas, e se você compreender bem, poderá fazer o mesmo em qualquer outra plataforma.O que mudará serão as instruções, e os registradores, e modo de endereçamento.O raciocínio é o mesmo.
Essa foi apenas uma introdução, não ligue muito para o termo, com o tempo irão se clareando cada vez mais. Considere isso como os tópicos, que com o tempo precisará assimilar.

Estamos estudando um computador, certo?Computar significa armazenar. Trabalhar com informações, dados.Hoje esse conceito foi muito ampliado, mas tudo não passa, na parte técnica, de processamento de informações. Celulares, redes 3g, rádios, objetos eletrônicos são sistemas lógicos baseados em informações, e hoje , são cada vez mais digitais, e menos analógicos. Utilizam pacotes de dados que trafegam em suas redes. O ábaco(aquela plaquinha com bolinhas utilizados por orientas como forma de cálculo) é um computador de forma diminuta. Para trabalhar com dados, precisamos acima de tudo, de transformá-los em modelos que podem ser acessados por um determinado sistema. No nosso caso, utilizaremos o sistema binário e o sistema hexadecimal. Em sua infra-estrutura, o processador e um micro-controlador só reconhecem 0 e 1, quando o sistema é digital. Queria lembrar que para nós humanos seria muito tosco e difícil raciocinar em forma binária ou hexadecimal, por uma razão bem simples: Possuímos dez dedos. Portanto, nosso sistema de contagem só faz sentido quando transformamos numa forma decimal. E por aí vai. Um Opcode, é uma tradução em hexadecimal de nossa instrução, chamada mnemônica junto com os dados, que estamos trabalhando. É uma forma mais simples de compreender quantos bytes possui uma instrução e seu dado.Mas lembre-se, o processador ou micro-controlador só compreende o 0 e 1. Nós inserimos símbolos que sejam legíveis para nós.
Alguém pode perguntar, mas peraí....existe outra forma de número que não o decimal?sim.Os maias por exemplo, utilizavam um sistema com base 20, ou seja, diferente do nosso. Isso, provavelmente, porque contavam com os dedos dos pés e das mãos ao mesmo tempo. Todo sistema em qualquer base possui as mesmas características de matemática. Só que possui uma conotação diferente. Se nós tivéssemos só um dedo, provavelmente contaríamos de forma binária. Ou tem dedo, ou não tem. Por exemplo:
0+0=0 Se não temos dedos nenhum, é zero.
0+1=1 Se um dedo se soma com nenhum?Temos um dedo.
Idêntico ao sistema decimal, porém lembre-se da regra do vai um na soma:
Em decimal teríamos: 21+9=30.Vamos enxergar isso de forma mais clara:
21
09
---
30
Repare, 1 mais nove, dá dez.Então, se deve pensar assim, 0 e vai um.Certo?dois com um, dá três. Em binário é igual:
01
01
--
10
Ou seja: 1 mais 1, é 0 e vai um.Só temos dois números...lembre-se disso.1 mais zero é um.Isso, seria o equivalente em dois em binário.
Como vamos trabalhar com computação, iremos trabalhar muito com isso. É como o ábaco. Se você dissesse 12 para alguém calcular em ábaco, ele contaria as bolinhas equivalentes ao número doze em decimal, certo? E isso varia, de ábaco para ábaco. Há uns com cinco unidades e outros com dez unidades. A representação em cada um seria diferente, particular. Como no computador. Mas diferente do ábaco, letras também são representadas por binários no processador ou micro-controlador, e binário ou hexadecimal para nós.
Já se perguntou como você sabe a noção de quantidade de 345 em decimal? Nós sabemos que equivale a trezentos e quarenta e cinco. O algoritmo para se conhecer esse valor, nós aprendemos na alfabetização, quando a professora escrevia um quadro unidade, dezena, centena, milhar, lembra? Pois é, existe uma fórmula matemática para isso. Um número em determinada base, é a somatória de todos os seus dígitos, multiplicados por sua base, elevados a potência equivalente à sua posição.
Por exemplo, 345 equivale à duas posições contadas da direita para esquerda, incluindo o zero.
5= posição zero.
4=posição 1.
3=posição 2.
Agora, peque meu enunciado e aplique aqui:
3(dígito)*10(base)^2(esse acento equivale a potência.2,ou seja,posição dois conforme acima)+ 4(dígito)*10(base)^1(esse acento equivale a potência.1,ou seja,posição um conforme acima)+ 5(dígito)*10(base)^0(esse acento equivale a potência.0,ou seja,posição zero conforme acima),ou melhor resumido:3*10^2+4*10^1+5*10^0=345. Ou seja, 3 casas da centena mais 4 casas da dezena, mais 5 casas da unidade. E assim, com qualquer número, em qualquer base. Outro exemplo:





Obs.: Qualquer número na posição de zero é um, mesmo o zero, pois se trata das casas unitárias.



Sistema binário
Se trata do 0 e 1. Pode ser simbolizado também em sistema lógicos em idéias, ou seja, ligado/desligado, aceso/apagado, ou seja, qualquer idéia que tenha apenas duas posições. No sistema binário, temos base dois. Como no sistema deciam fica mais fácil entender número grandes colocando-se o ponto, por exemplo, 1.000.456.000, mais fácil do que 1000456000, também costuma-se separar os dígitos binários de quatro em quatro, para facilitar sua compreensão, exemplo:0101 0101 do que 01010101. Outra coisa importante de se conhecer é por convenção colocar a letra b após o número, exemplo:01010101b para conhecimento de que é binário.O número mais à direita é o número menos significativo, cada número à esquerda é um bit sucessivo:
Binário de oito bits: X7 X6 X5 X4 X3 X2 X1 X0
Binário de 16 bits: X15 X14 X13 X12 X11 X10 X9 X8 X7 X6 X5 X4 X3 X2 X1 X0
O bit zero é chamado menor ordem. O bit mais à esquerda é o de maior ordem.
Bit : É a menor representação de um dado no computador, ou seja, um zero ou um 1.
NIBBLE: São quatro bits, exemplo: 0101b
Byte: São oito bits. Exemplo:





Note que isso é um byte, mas se olhar melhor, verá um byte tendo dois nibbles o de maior valor e o de menor valor:

Como um byte são oito bits, temos 2^8 tipos de valores, ou seja: 254. Estes podem ser números naturais de 0 a 255, números inteiros com sinais que pode ser de -128 a +127.Ou um caractere ASCII/IBM.
Dois bytes equivalem a uma WORD, e duas palavras(WORD) equivalem a duas palavras(DWORD):
WORD


Byte menos significativo e o mais significativo(com quatro nibbles cada um):

DWORD


O grande problema do sistema binário é sua verbosidade. Para representar o valor decimal 202, de apenas três casas decimais, precisamos de oito casas binárias. É óbvio que com um conjunto de dez dígitos possíveis, o sistema decimal pode representar números de uma forma muito mais compacta do que o sistema binário, que possui um conjunto de apenas dois dígitos. Valores grandes precisam de uma infinidade de casas binárias, tornando o número praticamente inutilizável para os mortais comuns. Além disso, as conversões entre decimal e binário são um tanto trabalhosas. Para mal dos pecados, o computador só "pensa" em binário. Resolveu-se então partir para uma solução radical, ou seja, criar um sistema cuja base fosse a mesma do tipo mais usado nos computadores. Como já vimos, os tipos mais utilizados são o byte e o word. Um byte possui oito bits - então foi criado um sistema octal. Um word possui 16 bits - então foi criado o sistema hexadecimal.
O bit menos significativo num nibble (como em qualquer outro grupo) é o bit 0.
Na prática, os números binários são muito desajeitados para serem usados. É por isso que a maioria dos programadores utiliza o sistema de numeração hexadecimal. O sistema de numeração hexadecimal (também conhecido simplesmente como hexa) fornece notações muito mais compactas que o sistema binário e a conversão entre hexa e binário é bastante simples quando se usa a seguinte tabela:
Hexadecimal Binário Hexadecimal Binário
0 0000 8 1000
1 0001 9 1001
2 0010 A 1010
3 0011 B 1011
4 0100 C 1100
5 0101 D 1101
6 0110 E 1110
7 0111 F 1111
Cada dígito hexadecimal pode representar um dos dezesseis valores entre 0 e 15. Como só existem dez dígitos decimais, foi preciso inventar seis dígitos adicionais. Optou-se pelas letras de A a F. Alguns exemplos de números hexadecimais seriam 1234, CADA, BEEF, 0FAB, FADA, FEFE, FAFA, etc. Como vamos nos referir com frequência a números em várias notações, é bom por ordem na casa desde já. Nos textos serão usadas as seguintes convenções:
- Todos os valores numéricos, independente da sua base, começam com um dígito decimal.
- Todos os valores hexadecimais terminam com a letra "h".
- Todos os valores binários terminam com a letra "b".
- Todos os valores decimais terminam com o sufixo "d".
Quando queremos transformar um número qualquer binário ou decimal, devemos utilizar aquela fórmula antiga que escrevi acima, por exemplo (10100101b)2, lê-se na base dois:

Sistema Hexadecimal
Possui 16 dígitos: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
Veremos uma tabela que a cada nibble, ou seja, a cada 4 bits poderemos ter um hexadecimal:


Exemplo:

A convenção é colocar a letra h no final do número, e o zero antes de qualquer letra,exemplo: 0E120h.
Agora, e se quiséssemos o contrário, ou seja, converter decimal em binário ou hexadecimal?Faremos assim, dividiremos o número pela base que queremos, pegando o quociente da primeira divisão e colocando como dividendo da próxima divisão e os restos serão os números dessa base.Faremos a divisão até termos zero.Exemplo:
39 (base 10) converter em hexadecimal (base 16):

Input= Divisor; Result = quociente; Remainder=Resto.
Portanto, o número 39d equivale a 27h, em hexadecimal.Outro exemplo 43868:



O resultado é 0AB5Ch.Se quisermos saber como o processador irá entender esse número basta transformá-lo em binário, utilizando a tabela de hexadecimal acima:

Então, o número 0AB5Ch hexadecimal é entendido assim pelo processador 1010101101011100b, ou seja, binário.
Operações Aritméticas com Binários e Hexadecimais
Devemos ter cuidado em não pensar nesses números como se fosse decimais, ou seja:
9h
+ 1h
----
Você pode achar que o resultado é 10h, mas não é.A resposta correta é 0Ah.Assim como 10h mais 1h não é 11h. E sim 0Fh.A melhor forma na prática é usar uma calculadora do Windows de forma fácil.rs.Se quiser ter trabalho, o jeito mais fácil é transformar o hexadecimal em binário calcular.Depois, transformar de novo usando a tabela e ver o resultado.Então, vejamos a melhor forma de calcular os binários:
Soma de Binários
0+0=0
0+1=1
1+0=1
1+1=10, ou seja 0 e vai 1* (para somar ao digito imediatamente à esquerda)
Para somar dois números binários, o procedimento é o seguinte:
Exemplo 1:
*
1100
+ 111
-----
= 10011
Explicando: Os números binários são base 2, ou seja, há apenas dois algarismos: 0 (zero) ou 1 (um). Na soma de 0 com 1 o total é 1. Quando se soma 1 com 1, o resultado é 2, mas como 2 em binário é 10, o resultado é 0 (zero) e passa-se o outro 1 para a "frente", ou seja, para ser somado com o próximo elemento, conforme assinalado pelo asterisco,como no exemplo acima.
Exemplo 2:
**
1100
+ 1111
-----
= 11011
Explicando: Nesse caso acima (exemplo 2), na quarta coluna da direita para a esquerda, nos deparamos com uma soma de 1 com 1 mais a soma do 1 ( * ) que veio da soma anterior. Quando temos esse caso (1 + 1 + 1), o resultado é 1 e passa-se o outro 1 para frente.
Obs.:É melhor memorizar esse vai um, ou vem um, pois posteriormente veremos suas funções quando estivermos programando.Mas antes, aprenda a soletrar, para depois aprender escrever.
Subtração de Binários
0-0=0
0-1=1 e vai 1* para ser subtraido no digito seguinte
1-0=1
1-1=0
Para subtrair dois números binários, o procedimento é o seguinte:
* ***
1101110
- 10111
-------
= 1010111
Explicando: Quando temos 0 menos 1, precisamos "pedir emprestado" do elemento vizinho. Esse empréstimo vem valendo 2 (dois), pelo fato de ser um número binário. Então, no caso da coluna 0 - 1 = 1, porque na verdade a operação feita foi 2 - 1 = 1. Esse processo se repete e o elemento que cedeu o "empréstimo" e valia 1 passa a valer 0. Os asteriscos marcam os elementos que "emprestaram" para seus vizinhos. Perceba, que, logicamente, quando o valor for zero, ele não pode "emprestar" para ninguém, então o "pedido" passa para o próximo elemento e esse zero recebe o valor de 1.
Multiplicação de Binários
A multiplicação entre binários é similar à realizada com números decimais. A única diferença está no momento de somar os termos resultantes da operação:
1 0 1 1
x 1 0 1 0
---------
0 0 0 0
+ 1 0 1 1
+ 0 0 0 0
+ 1 0 1 1
---------------
= 1 1 0 1 1 1 0
*
Perceba que na soma de 0 e 1 o resultado será 1, mas na soma de 1 com 1, ao invés do resultado ser 2, ele será 0 (zero) e passa-se o 1 para a próxima coluna, conforme assinalado pelo asterisco. Nota que se a soma passar de 2 dígitos, deve-se somar o número em binário correspondente ( ex. 7 = 1001, 6 = 1000, 5 = 101, 4 = 100, 3 =11).
1 1 1
x 1 1 1
---------
1 1 1
+ 1 1 1
+ 1 1 1
---------------
= 1 1 0 0 0 1
No caso, a terceira coluna a soma dá 4 (com mais um da anterior), que adiciona um "1" duas colunas depois (100).
Divisão de Binários
Essa operação também é similar àquela realizada entre números decimais:
110 __10__
- 100 11—010
- 10—00
Deve-se observar somente a regra para subtração entre binários. Nesse exemplo a divisão de 110 por 10 teve como resultado 11.
Código BCD 8421
O código BCD é um sistema de representação dos dígitos decimais desde 0 até 9 com um código binário de 4 bits. Esse código BCD usa o sistema de pesos posicionais 8421 do código binário puro. Exatamente como binário puro, pode-se converter os números BCD em seus equivalentes decimais simplesmente somando os pesos das posições de bits onde aparece 1.
somando os pesos das posições de bits onde aparece 1.


Decimal, Binário Puro e BCD
Observe, entretanto, que existem apenas dez códigos válidos. Os números binários de 4 bits representando os números decimais desde 10 até 15 são inválidos no sistema BCD. Para representar um número decimal em notação BCD substitue-se cada dígito decimal pelo código de 4 bits apropriados.
Por exemplo, o inteiro decimal 834 em BCD é 1000 0011 0100. Cada dígito decimal é representado pelo seu código BCD 8421 equivalente. Um espaço é deixado entre cada grupo de 4 bits para evitar confusão do formato BCD com o código binário puro. Este método de representação também se aplica as frações decimais.
Por exemplo, a fração decimal 0,764 é “0.0111 0110 0100” em BCD. Novamente, cada dígito decimal é representado pelo seu código equivalente 8421, com um espaço entre cada grupo.
Uma vantagem do código BCD é que as dez combinações do código BCD são fáceis de lembrar. Conforme se começa a trabalhar com números binários regularmente, os números BCD tornam-se tão fáceis e automáticos como números decimais. Por esta razão, por simples inspeção da representação BCD de um número decimal pode-se efetuar a conversão quase tão rápido como se já estivesse na forma decimal.
Como exemplo, converter o número BCD no seu equivalente decimal. 0110 0010 1000.1001 0101 0100 = 628,954
O código BCD simplifica a interface Homem-máquina, mas é menos eficiente que o código binário puro. Usam-se mais bits para representar um dado número decimal em BCD que em notação binária pura.
Por exemplo, o número decimal 83 é escrito como 1000 0011. Em código binário puro, usam-se apenas 7 bits para representar o número 83. Em BCD, usam-se 8 bits. O código BCD é ineficiente, pois, para cada bit numa palavra de dado, há usualmente alguma circuitaria digital associada. A circuitaria extra associada com o código BCD custa mais, aumenta a complexidade do equipamento e consome mais energia. Operações aritméticas com números BCD também consomem mais tempo e são mais complexas que aquelas com números binários puros. Com quatro bits de informação binária, você pode representar um total de 24 = 16 estados diferentes ou os números decimais equivalentes desde o 0 até o 15. No sistema BCD, seis destes estados (10-15) são desperdiçados.
Quando o sistema numérico BCD é usado, alguma eficiência é perdida, mas aumenta-se o entendimento entre o equipamento digital e o operador humano.
Conversão Binário para BCD
A conversão de decimal para BCD é simples e direta. Entretanto, a conversão de binário para BCD não é direta. Uma conversão intermediária deve ser realizada primeiro. Por exemplo, o número 1011.01 é convertido no seu equivalente BCD.
Primeiro o número binário é convertido para decimal. 1011.01 = (1x23)+(0x22)+(1x21)+(1x20)+(0x2-1)+(1x2-2) =8+0+2+1+0+0,25 = 11,2510
Então o resultado decimal é convertido para BCD. 11,2510 = 0001 0001.0010 0101
Para converter de BCD para binário, as operações anteriores são invertidas. Por exemplo, o número BCD 1001 0110.0110 0010 0101 é convertido no seu equivalente binário.
1. O número BCD é convertido para decimal. 1001 0110.0110 0010 0101 = 96,625
2. O resultado decimal é convertido para binário
Inteiro Resto Posição Fração Inteiro Posição
96 ÷ 2 = 48 0 -> LSB 0,625 x 2 = 1,25 = 0,25 1 <- MSB 48 ÷ 2 = 24 0 0,250 x 2 = 0,50 = 0,50 0 24 ÷ 2 = 12 0 0,500 x 2 = 1,00 = 0 0 <- LSB 12 ÷ 2 = 06 0 06 ÷ 2 = 03 0 03 ÷ 2 = 01 1 01 ÷ 2 = 00 1 <- MSB 9610 = 11000002 0,62510 = 0.101 96,62510 = 9610 + 0,62510= 1100000 + 0.101 = 1100000.101 Como o número decimal intermediário contém uma parte inteira e uma parte decimal, cada parte é convertida como visto anteriormente. A soma binária (inteiro mais fração) 1100000.101 é equivalente ao número BCD 1001 0110.0110 0010 0101. Vários códigos binários são chamados códigos alfanuméricos pois eles são usados para representar caracteres assim como números. Código ASCII O "American Standard Code for Information Interchange" comumente referido como ASCII – também chamado ASCII completo, ou ASCII estendido –, é uma forma especial de código binário que é largamente utilizado em microprocessadores e equipamentos de comunicação de dados. Um novo nome para este código que está se tornando popular é "American National Standard Code for Information" (ANSCII). Entretanto, utilizaremos o termo consagrado, ASCII. É um código binário que usado em transferência de dados entre microprocessadores e seus dispositivos periféricos, e em comunicação de dados por rádio e telefone. Com 7 bits pode-se representar um total de 27 = 128 caracteres diferentes. Estes caracteres compreendem números decimais de 0 até 9, letras maiúsculas e minúsculas do alfabeto, mais alguns outros caracteres especiais usados para pontuação e controle de dados! Sistema Octal é um sistema de numeração cuja base é 8, ou seja, utiliza 8 símbolos para a representação de quantidade. No ocidente, estes símbolos são os algarismos arábicos: 0 1 2 3 4 5 6 7 O octal foi muito utilizado em informática como uma alternativa mais compacta ao binário na programação em linguagem de máquina. Hoje, o sistema hexadecimal é mais utilizado como alternativa ao binário. Este sistema também é um sistema posicional e a posição de seus algarismos determinada em relação à vírgula decimal. Caso isso não ocorra, supõe-se implicitamente colocada à direita do número. A aritmética desse sistema é semelhante a dos sistemas decimal e binário, o motivo pelo qual não será apresentada. Exemplo: - Qual o número decimal representado pelo número octal 4701? Utilizar a forma que ensinei lá em cima. 4 x 8³ + 7 x 8² + 0 x 8¹ + 1 x 8° = = 2048 + 448 + 0 + 1 = 2497. Conversões de um sistema para outro Conversão Decimal – Octal Método de multiplicações sucessivas por 8 É utilizado para converter uma fração decimal para o sistema octal. Multiplica-se a fração decimal por 8, obtendo-se na parte inteira do resultado o primeiro dígito da fração octal resultante. O processo é repetido sucessivamente com a parte fracionária do resultado para obter os dígitos seguintes e termina quando a parte fracionária é nula ou inferior à medida de erro especificada. Exemplo: Converter a fração decimal 0.140625 em octal. 0.140625 x 8 = 1.125 0.125 x 8 = 1.0 Combinamos os dois métodos anteriores podemos converter para octal números decimais com parte inteira e fracionária Método de subtrair potências de 8 Outro método de conversão de números decimais para o sistema octal que serve para números com partes inteiras e fracionária é o de subtrair potências de 8. é semelhante ao estudado para a conversão decimal – binário e para a sua aplicação é necessária uma tabela de potências de 8. Conversão Octal – Decimal Existem vários métodos, sendo mais comumente utilizado o proveniente da maneira que sempre fazemos aqui no blog, em que se faz a conversão de forma direta através da fórmula. Exemplo: Converter o número octal 764 para o sistema decimal 764 (8) = 7 x 8² + 6 x 8¹ + 4 x 8° = 448 + 48 + 4 = 500 (10) Conversão Hexadécimal – Binário Quando existir necessidade de converter números hexadécimais em binários, deve-se separar cada dígito do número hexadécimal e substituí-lo pelo seu valor correspondente de binário. Exemplo: Converter o número hexadécimal 1572 em binário. Logo, 1 5 7 2 = 0001 0101 0111 0010 Conversão Binário – Octal Para converter um número binário em octal, executa-se o processo inverso ao anterior. Agrupam-se os dígitos binários de 3 em 3 do ponto decimal da esquerda para a direita, substituindo-se cada trio de dígitos binários pelo equivalente dígito octal. Por exemplo, a conversão do número binário 1010111100 em octal: 001 010 111 100 1 2 7 4 Assim, tem-se 1010111100bin = 1274oct Conversão Octal – Hexadecimal Para esta conversão é necessário executar um passo intermediário utilizando o sistema binário. Primeiramente converte-se o número octal em binário e depois converte-se o binário para o sistema hexadecimal, agrupando-se os dígitos de 4 em 4 e fazendo cada grupo corresponder a um dígito hexadecimal. Por, exemplo, a conversão o número octal 1057 em hexadecimal: Passagem ao binário: 1 0 5 7 001 000 101 111 Passagem ao hexadecimal: 0010 0010 1111 2 2 F Assim, tem-se 1057oct = 22Fhex Conversão Hexadecimal – Octal Esta conversão, assim com a anterior, exige um passo intermediário em que se utiliza o sistema binário. Converte-se o número hexadecimal em binário e este em octal. Exemplo: Converter o número hexadecimal 1F4 em octal. 1 F 4 0001 1111 0100 Conversão para octal 0 7 6 4 000 111 110 100 Tabela de valores
Operações Lógicas com Bits
Aqui muitos daqueles que já estudaram circuitos eletrônicos saberão do que estou falando.É a lógica Booleana.São lógicas direcionadas a decisões.Seria como verdadeiro ou falso.Sim ou não.Essa lógica é muito utilizada em algoritmo, ou seja, sequência em que se faz as coisas.Por exemplo, se fóssemos fazer um algoritmo(modo de se fazer um procedimento, com detalhes de como fazer) de tomar banho, entenderíamos muito bem essa lógica.
Entrar no banheiro-verificar chuveiro=ligado?sim ou não.Se sim, abrimos a torneira para a água sair;se não, acionamos o interruptor para energia esquentar...e por aí vai.Como você pode ver, praticamente qualquer coisa pode ser colocada em termos booleanos.Até mesmo instruções de programas, quando você não souber fazer um bom algoritmo de algo em funções avançadas, faça o básico.Planeje no papel como seria feito, e utilize lógica booleana.Dá mais tempo, mais trabalho, mas sempre nos tira de alguma fria...rs!Todo circuito integrado utiliza essa lógica.Se você olhar uma placa verá esses símbolos contornados nela.São utilizados até mesmo em sistemas analógicos.Aliás, uma boa diferença para quem ainda não distingue analógico de digital, seria no exemplo do chuveiro o seguinte, as respostas sim ou não seriam digitais ou binárias, e o quanto você abre de água para chegar na temperatura certa ou ideal seria analógico.
Na matemática e na ciência da computação, as álgebras booleanas (também conhecida como "Álgebra de Boole") são estruturas algébricas que "capturam a essência" das operações lógicas E, OU e NÃO, bem como das operações da teoria de conjuntos soma, produto e complemento. Ela também é o fundamento da matemática computacional, baseada em números binários.
Receberam o nome de George Boole, matemático inglês, que foi o primeiro a defini-las como parte de um sistema de lógica em meados do século XIX. Mais especificamente, a álgebra booleana foi uma tentativa de utilizar técnicas algébricas para lidar com expressões no cálculo proposicional. Hoje, as álgebras booleanas têm muitas aplicações na electrônica. Foram pela primeira vez aplicadas a interruptores por Claude Shannon, no século XX.
Os operadores da álgebra booleana podem ser representados de várias formas. É frequente serem simplesmente escritos como E, OU ou NÃO (são mais comuns os seus equivalentes em inglês: AND, OR e NOT). Na descrição de circuitos também podem ser utilizados NAND (NOT AND), NOR (NOT OR) e XOR (OR exclusivo). Os matemáticos usam com frequência + para OU e . para E (visto que sob alguns aspectos estas operações são análogas à adição e multiplicação noutras estruturas algébricas) e representam NÃO com uma linha traçada sobre a expressão que está a ser negada.
Combinando binários e AND:
0 and 0 = 0
0 and 1 = 0
1 and 0 = 0
1 and 1 = 1
Tabela verdade AND:

Combinando OR :
0 or 0 = 0
0 or 1 = 1
1 or 0 = 1
1 or 1 = 1

Combinando XOR(OR-exclusivo):
0 xor 0 = 0
0 xor 1 = 1
1 xor 0 = 1
1 xor 1 = 0

Combinando NOT:
NOT 0 = 1
NOT 1 = 0

AND, OR e XOR são funções diádicas (precisam de dois operandos) e NOT é monádica. Por exemplo:
1 AND 1 = 1
0 OR 0 = 0
1 XOR 0 = 1
NOT 1 = 0
A base dos sistemas de computadores digitais modernos são os circuitos lógicos. Para poder entender como estes sistemas funcionam é preciso ter algum conhecimento da lógica digital e da álgebra booleana. Estes assuntos são muito extensos, geralmente temas de livrões inteiros. Neste capítulo vamos apenas dar uma olhada no feijão com arroz, apenas o suficiente para poder trabalhar com Assembly. A lógica booleana é a base dos sistemas binários. Usando um sistema de equações booleanas é possível representar qualquer algoritmo ou qualquer circuito eletrônico do computador. Este capítulo será uma breve introdução à álgebra booleana. Analisaremos tabelas lógicas, representação canônica, funções booleanas, simplificação de funções booleanas, desenho lógico, circuitos combinados e sequenciais e equivalência de hardware e software. A seção que trata da minimização (otimização) de funções lógicas usa Diagramas Veitch ou Diagramas de Karnaugh. As técnicas de otimização utilizadas reduzem o número de termos numa função booleana. É preciso ressaltar que muitos consideram estas técnicas de otimização obsoletas porque a redução do número de termos numa equação não tem mais a importância que lhe era atribuída tempos atrás. Usaremos o método de diagramas como exemplo de otimização, não como uma técnica a ser empregada regularmente. Se você se interessa por projetos de circuitos e otimização, vai precisar consultar outros textos para encontrar técnicas melhores.
Apesar deste capítulo tratar basicamente de hardware, lembre-se de que muitos dos conceitos se referem a equações booleanas (funções lógicas). Alguns exercícios de programação, que serão apresentados em outros capítulos, vão exigir este conhecimento.
Álgebra booleana
Colocarei um tópico apenas sobre operações booleanas e lógica booleana, por se tratar de um assunto complexo,e necessitar de especial atenção para ser compreensível!
Operações lógicas com Números Binários e Strings de Bits

Como foi visto, as funções lógicas funcionam apenas com operandos de bit único. Uma vez que o 80x86 usa grupos de 8, 16, 32 ou 64 bits, é preciso ampliar a definição destas funções para poder lidar com mais de dois bits. As funções lógicas do 80x86 operam na base do bit a bit, ou seja, tratam os bits da posição 0, depois os bits da posição 1 e assim sucessivamente. É como se fosse uma cadeia de operações. Por exemplo, se quisermos realizar uma operação AND com os números binários 1011 0101 e 1110 1110, faríamos a operação coluna a coluna:
1011 0101 AND
1110 1110
-----------
1010 0100
O resultado desta operação foi "ligar" os bits onde os dois são 1. Os bits restantes foram
zerados. Se quisermos garantir que os bits de 4 a 7 do primeiro operando sejam zerados e que os bits 0 a 3 fiquem inalterados, basta fazer um AND com 0000 1111. Observe:
1011 0101 AND
0000 1111
-----------
0000 0101
Se quisermos inverter o quinto bit, basta fazer um XOR com 0010 0000. O bit (ou os bits) que quisermos inverter, mandamos ligado. Os bits zerados não alteram os bits do primeiro operando. Assim, se quisermos inverter os bits 0 a 3, basta fazer um XOR com 0000 1111.
1011 0101 XOR
0000 1111
-----------
1011 1010
E o que acontece quando usamos um OR com 0000 1111? Os bits 0 não alteram os bits do primeiro operando e os bits 1 forçam os bits para 1. É um método excelente para ligar bits na (ou nas) posições desejadas.
1011 0101 OR
0000 1111
-----------
1011 1111
Este método é conhecido como máscara. Através de uma máscara de AND é possível zerar bits. Com uma máscara XOR é possível inverter bits e, através de uma máscara OR é possível ligar bits. Basta conhecer as funções e saber lidar com os bits. Quando temos números hexadecimais, o melhor é transformá-los em binário e depois aplicar as funções lógicas.
Sinal::
Até agora tratamos os números binários como valores sem sinal. Mas como se faz para
representar números negativos no sistema binário? É aí que entra o sistema de numeração do complemento de dois. Vamos lá.
Números com e sem sinal
Os números, no computador, não podem ser infinitos pelo simples fato de que a quantidade de bits disponível para expressá-los é restrita (8, 16, 32, ou qualquer quantidade que nunca será grande demais :smile: ). Com um número fixo de bits, o valor máximo também é fixo. Por exemplo, com 8 bits podemos obter no máximo o valor 256. Se quisermos expressar números negativos, teremos que dividir estas 256 possibilidades, metade para os positivos e metade para os negativos. Isto diminui o valor máximo, porém aumenta o valor mínimo. Se a divisão for bem feita, podemos obter -128 a 0 e 0 a 127. O mesmo raciocínio pode ser usado para 16 bits, 32bits, etc. Como regra geral, com n bits podemos representar valores com sinal entre -2(n-1) e 2(n-1)-1
Muito bem, já sabemos que podemos dividir o espaço dos valores numéricos oferecido pelos bits, mas ainda não sabemos como representar os valores negativos usando os bits. O microprocessador 80x86 usa a notação de complemento de dois. Neste sistema, o bit mais significativo é que sinaliza se o número é positivo ou negativo: se for 0, o número é positivo; se for 1, o número é negativo. Veja os exemplos para 16 bits:
8000h é negativo => 1000 0000 0000 0000
100h é positivo => 0000 0001 0000 0000
7FFFh é positivo => 0111 1111 1111 1111
FFFFh é negativo => 1111 1111 1111 1111

Se o bit O.A. for zero, então o número é positivo e é armazenado como um valor binário
padrão. Se o bit O.A. for um, então o número é negativo e é armazenado na forma de
complemento de dois. Para converter um número positivo para negativo use o seguinte
algoritmo:
- 1. Inverta todos os bits do número com uma operação lógica NOT.
- 2. Adicione 1 ao resultado.
No exemplo a seguir faremos a conversão de +5 para -5 usando o complemento de dois com apenas 8 bits:

Primeira linha é cinco em binário;
Segunda linha inverter todos os bits;
Adicionar 1 para obter o resultado.
Se repetirmos a operação com o valor encontrado para -5, voltamos a obter o valor original:

Primeira linha o complemento de dois para -5;
Segunda linha inverter todos os bits;
Adicionar 1 para obter o resultado +5.
Agora observe o que acontece com o hexadecimal 8000h, o menor número negativo com sinal (-32.768):
hexa 8000h
binário 1000 0000 0000 0000
(8000h) inverter bits
0111 1111 1111 1111 (7FFFh) somar 1
1000 0000 0000 0000 (8000h) ???
Invertendo 8000h obtemos 7FFFh e, somando 1, voltamos para 8000h. Tem alguma coisa errada pois -(-32768) não pode ser igual a -32768! O que ocorre é que, com 16 bits, não é possível obter o inteiro positivo +32768. Se tentarmos realizar o complemento de dois com o menor número negativo, o processador 80x86 vai dar erro de overflow na aritmética com sinal.
Talvez você esteja pensando que usar o bit mais significativo como flag de sinal e manter o número original fosse uma solução mais lógica. Por exemplo, 0101 seria +5 e 1101 seria -5. Acontece que esta operação depende do hardware. Para o processador, a negação (ou complemento, ou inversão) dos bits é fácil e rápida de ser realizada. Para o programdor, não é preciso realizá-la bit a bit pois o 80x86 possui a instrução NEG que trata todos os bits.
As operações com números negativos não são problemas. Imagine a operação de soma com os números +5 e -5, sendo que o -5 foi obtido com o sistema de complemento de dois:
1 1111 1111 5d
0000 0101 -5d
+ 1111 1011
------------
1 0000 0000
Os dígitos em vermelho são os famosos "vai um", que acontecem quando somamos dois bits de valor 1. O bit em azul é o bit que excedeu o comprimento de oito bits, chamado de carry (excedente). Se ignorarmos o carry, o resultado está absolutamente correto, pois 5 + (-5) = 0. É exatamente assim que o processador opera. Não custa repetir que os dados representados por um conjunto de bits dependem inteiramente do contexto. Os oito bits do valor binário 11000000b podem representar um caracter ASCII, o valor decimal sem sinal 192, o valor decimal com sinal -64, etc. Como programador, é sua a responsabilidade de usar os dados de forma consistente.
Extensão com Sinal e Extensão com Zeros
Como os inteiros no formato de complemento de dois têm um comprimento fixo, surge um pequeno problema. O que acontece quando for preciso transformar um valor de complemento de dois de 8 bits num valor de 16 bits? Este problema, e seu oposto (a transformação de um valor de 16 bits num de 8 bits), pode ser resolvido através das operações de extensão e contração com sinal. O 80x86 trabalha com valores de comprimento fixo, mesmo quando estiver processando números binários sem sinal. A extensão com zeros permite converter pequenos valores sem sinal em valores maiores sem sinal. Vamos a um exemplo considerando o valor -64. O valor de complemento de dois para este número é 0C0h. O equivalente de 16 bits deste número é 0FFC0h. Agora considere o valor +64. As versões de 8 e de 16 bits deste valor são 40h e 0040h. A diferença entre os números de 8 e de 16 bits com sinal pode ser definida com a seguinte regra: "Se o número for negativo, o byte mais significativo do número de 16 bits contém 0FFh; se o número for positivo, o byte mais significativo do número de 16 bits é zero".
Para fazer a extensão com sinal de um valor com qualquer número de bits para um número maior de bits, basta copiar o bit de sinal para todos os bits adicionais. Por exemplo, para ampliar um número de 8 bits com sinal para um número de 16 bits com sinal, só é preciso copiar o bit 7 do número de oito bits para os bits de 8 a 15 do número de 16 bits. Para ampliar um número de 16 bits para um número de double word (32 bits), simplesmente copie o bit 15 para os bits de 16 a 31 do double word.
A extensão com sinal é necessária quando manipulamos valores com sinal de comprimentos diferentes. É comum precisarmos somar uma quantidade em byte com uma quantidade em word. Neste caso, antes de efetuar a operação, será preciso transformar a quantidade byte numa quantidade word. Outras operações, em particular a multiplicação e a divisão, podem necessitar uma extensão com sinal para 32 bits. É óbvio que não é necessário fazer a extensão com sinal para valores sem sinal.
São exemplos de extensão com sinal:

Para ampliar números sem sinal faz-se a extensão com zeros, um processo muito simples de zerar os bytes adicionais. Veja abaixo:

A contração com sinal, ou seja, converter um valor com determinado número de bits para um valor idêntico com um número menor de bits é um processo um pouco mais complicado. A extensão com sinal sempre é possível, já a contração com sinal nem sempre o é. Por exemplo, o valor decimal -448, representado como hexadecimal de 16 bits, é 0FE40h. Neste caso, é impossível obter este valor com apenas 8 bits, ou seja, a contração com sinal não é possível pois o valor original seria perdido. Aliás, este é um exemplo de overflow que pode ocorrer numa conversão impossível.
Para avaliar se é possível realizar uma contração com sinal é preciso analisar o(s) byte(s) mais significativos que deverão ser descartados: todos precisam conter zero ou 0FFh. Se forem encontrados quaisquer outros valores, não será possível fazer uma contração sem overflow. Além disso, o bit mais significativo do valor resultante precisa coincidir com cada bit removido do número. Veja os exemplos:

Deslocamentos e Rotação
Outro conjunto de operações lógicas que podem ser aplicadas em strings de bits são o
deslocamento (shift) e a rotação (rotate). As duas categorias ainda podem ser subdivididas em deslocamento para a esquerda (left shift), deslocamento para a direita (right shift), rotação para a esquerda (left rotate) e rotação para a direita (right rotate). Estas operações se revelaram extremamente úteis para os programadores da linguagem Assembly.
Exemplo de um deslocamento para esquerda, A operação de deslocamento para a esquerda move uma posição para a esquerda cada um dos bits de uma string de bits (veja ao lado). O bit zero é deslocado para a posição 1, o da posição 1 para a posição 2, etc. Surgem naturalmente duas perguntas: "O que vai para o bit zero?" e "Para onde vai o bit 7?" Bem, isto depende do contexto. Nós colocaremos um bit zero na posição zero e bit sete "cai fora" nesta operação.

Observe que deslocar o valor para a esquerda é o mesmo que multiplicá-lo pela sua base (ou radix). Por exemplo, deslocar um número decimal para a esquerda em uma posição
(adicionando um zero à direita do número) o multiplica por 10 (a sua base):
1234 SHL 1 = 12340 (SHL 1 = shift esquerda 1 posição)
Como a base de um número binário é dois, o deslocamento em uma posição para a esquerda multiplica-o por 2. Se deslocarmos um valor binário duas vezes para a esquerda, ele é multiplicado duas vezes por 2, ou seja, é multiplicado por 4. Se o deslocarmos três vezes, será multiplicado por 8 (2*2*2). Como regra, se deslocarmos um valor binário para a esquerda n vezes, isto o multiplicará por 2n (ou 2 elevado a n).
O deslocamento para direita funciona do mesmo jeito, só que no sentido oposto.Bit sete para o seis, o seis para o cinco, o cinco para o quatro....No deslocamento para direita movemos um zero para o bit 7, o zero será o bit carry-out. Como o deslocamento para a esquerda equivale a uma multiplicação pela base, não é de se admirar que um deslocamento para a direita equivale a uma divisão pela base. No sistema binário, se fizermos n deslocamentos para a direita, o valor será dividido por 2n.

Existe um problema relacionado à divisão efetuada por um shift para a direita: um shift para a direita equivale a uma divisão de um número sem sinal por 2. Por exemplo, se deslocarmos uma posição para a direita a representação sem sinal de 254 (0FEh), obtemos 127 (07Fh), exatamente o esperado. Entretanto, se deslocarmos uma posição para a direita a representação binária de -2 (0FEh), obtemos 127 (07Fh), o que não está correto. Este problema ocorre porque estamos introduzindo um zero no bit sete. Se o bit sete contém 1 antes do deslocamento, indicativo de número negativo nos inteiros com sinal, e depois recebe zero, estamos alterando o sinal deste número (que passa de negativo para positivo). Como este não é o propósito da divisão... dá erro.
Para usar um shift para a direita como um operador de divisão, antes é preciso definir uma terceira operação de deslocamento: o deslocamento aritmético para a direita (arithmetic shift right). Um shift aritmético para a direita funciona como o shift para a direita normal, com uma diferença: ao invés de deslocar o bit sete para a posição seis, este bit é deixado intacto, ou seja, o bit sete não é zerado.

Isto geralmente produz o resultado esperado. Por exemplo, fazendo um shift aritmético para a direita com -2 (0FEh), obtemos -1 (0FFh). Uma coisa, no entanto, não pode ser esquecida: esta operação sempre arredonda os números para o inteiro que seja menor ou igual ao resultado, ou seja, arredonda para baixo. Um shift artimético para a direita com 5 dá como resultado 2. Mas preste atenção. Um shift aritmético para a direita com -1 dá como resultado -1, e não zero! O arredondamento se faz na direção do menor valor e -1 é menor do que 0. Este não é um "bug" no shift aritmético para a direita, é apenas como a divisão de inteiros foi definida.
Outra operação muito útil é a rotação para a esquerda e para a direita. Estas operações se comportam como os deslocamentos, com uma diferença importante: o bit que sai numa extremidade entra na extremidade oposta.


Campos Bit e Dados Compactados
Apesar do 80x86 operar eficientemente com tipos de dado byte, word e double word,
ocasionalmente teremos que trabalhar com tipos de dado que usam um número de bits
diferente do habitual (8, 16, 32 ou 64). Por exemplo, imagine uma data na forma "2/4/98". São três valores numéricos que representam uma data: valores para o dia, para o mês e para o ano. Os dias variam de 1 a 31, o que consome 5 bits (valor máximo de 32) para representar a entrada dos dias. Os meses variam de 1 a 12. Portanto, 4 bits são suficientes (valor máximo de 16). O valor para o ano, imaginando que trabalhemos com valores variando de 0 a 99, precisam de 7 bits (que podem representar até o valor 128). Somando os bits necessários, chega-se a 16 bits, o mesmo que 2 bytes. Em outras palavras, podemos acomodar nossos dados de data em dois bytes ao invés de três se usássemos um byte para cada um dos campos dia, mês e ano. Isto economiza um byte de memória para cada data armazenada, que pode representar uma economia substancial se tivermos que armazenar zilhões de datas. O arranjo dos bits pode ser visto na figura acima. DDDDD representam os 5 bits reservados para o valor do dia, MMMM representam os quatro bits para armazenar o mês e YYYYYYY são os sete bits reservados para o valor do ano. Cada coleção de bits representando um item de data é denominado campo bit. 2 de Abril de 1998 seria representado, respectivamente, pelos bits 00010 0100 1100010, ou seja, 1262h.

Os MMMM representam os quatro bits do valor mês, DDDDD representam os cinco bits do valor dia, e YYYYYYY são os setes bits do ano.Cada coleção d bits representa uma data no campo bit.2 de Abril de 1988 seria representado como 4158h:

Apesar dos valores compactados serem muito eficientes para economizar espaço (isto é,
eficientes em termos de uso de memória), computacionalmente são muito ineficientes. A razão é que dependem de instruções extras para descompactar os dados dos diversos campos bit. Estas operações adicionais consomem tempo e bytes adicionais para armazenar as instruções. Portanto, o planejamento prévio e o custo/benefício precisam ser bem analisados. Existem inúmeros exemplos de tipos de dados compactados. Pode-se compactar oito valores booleanos num único byte, pode-se acomodar dois dígitos BCD num byte, etc.
conjunto de caracteres ASCII
O conjunto dos caracteres ASCII (excluindo-se os caracteres expandidos definidos pela IBM) é dividido em quatro grupos de 32 caracteres. O primeiro grupo, códigos ASCII de 0 a 1Fh (31), formam um conjunto especial de caracteres não imprimíveis chamados de caracteres de controle. Recebem este nome porque realizam várias operações de controle de impressão/display ao invés de mostrarem símbolos. Exemplos incluem o retorno de carro (carriage return), que posiciona o cursor no lado esquerdo da linha atual, avanço de linha (line feed), que move o cursor uma linha para baixo no dispositivo de saída e o retorno (backspace), que move o cursor uma posição para a esquerda. Infelizmente os caracteres de controle realizam operações diferentes dependendo do dispositivo de saída. A padronização entre os dispositivos de saída é precária. Para saber exatamente como se comporta determinado caracter de controle em relação a um determinado dispositivo de saída é preciso consultar o manual do dispositivo.
O segundo grupo de 32 códigos de caracteres ASCII inclui vários símbolos de pontuação, caracteres especiais e algarismos. Os caracteres mais conhecidos deste grupo são o espaço (código ASCII 20h) e os algarismos (códigos ASCII de 30h a 39h). Lembre-se de que os algarismos diferem dos seus valores numéricos apenas no nibble mais significativo. Se subtrairmos 30h do código ASCII de qualquer um dos dígitos, obtemos o equivalente numérico deste dígito.
O terceiro grupo de caracteres ASCII é reservado para os caracteres alfabéticos maiúsculos. Os códigos ASCII para os caracteres de A a Z ficam no intervalo 41h a 5Ah (65 a 90). Como só existem 26 caracteres alfabéticos diferentes, os seis códigos restantes são de vários símbolos especiais.
Finalmente, o quarto grupo de 32 códigos de caracteres ASCII são reservdos para os símbolos alfabéticos minúsculos, cinco símbolos adicionais especiais e outro caracter de controle (delete). Observe que os símbolos dos caracteres minúsculos usam os códigos ASCII de 61h a 7Ah. Se convertermos os códigos dos caracteres maiúsculos e minúsculos para binário, é possível verificar que os símbolos maiúsculos diferem dos seus correspondentes minúsculos em apenas um bit (veja ao lado os códigos para os caracteres "E" e "e").

A única diferença entre estes dois códigos reside no bit 5. Caracteres maiúsculos sempre
possuem 0 no bit cinco, os minúsculos sempre possuem 1 no bit cinco. Podemos usar esta característica para converter rapidamente maiúsculas em minúsculas e vice versa. Se o caracter for maiúsculo, para forçá-lo para minúsculo basta setar o bit cinco para 1. Se o caracter for minúsculo, para forçá-lo para maiúsculo basta setar o bit cinco para 0.
Na realidade, os bits cinco e seis determinam o grupo ao qual o caracter ASCII pertence:

Bit 6 Bit 5 Grupo
0 0 Caracteres de controle
0 1 Dígitos e caracteres de pontuação
1 0 Maiúsculos e especiais
1 1 Minúsculos e especiais
Podemos, por exemplo, transformar qualquer caracter maiúsculo ou minúsculo (ou especial) no seu caracter de controle equivalente apenas zerando os bits cinco e seis.
Agora observe os códigos ASCII para os caracteres dos dígitos numéricos. A representação decimal destes códigos ASCII não esclarece grande coisa, mas a representação hexadecimal revela algo muito importante - o nibble menos significativo do código ASCII é o equivalente binário do número representado. Zerando o nibble mais significativo, converte-se o código do caracter para a sua representação binária. Inversamente, é possível converter um valor binário do intervalo de 0 a 9 para a sua representação ASCII simplesmente setando o nibble mais significativo em três. Note que é possível usar a operação lógica AND para forçar os bits mais significativos para zero e usar a operação lógica OR para forçar os bits mais significativos para 0011 (três).

Lembre-se de que não é possível transformar uma string de caracteres numéricos na sua
representação binária correspondente simplesmente zerando o nibble mais significativo de cada dígito da string. Transformando 123 (31h 32h 33h) desta maneira resulta em três bytes:
010203h, e não no valor correto que é 7Bh.
Transformar uma string de dígitos requer um pouco mais de sofisticação. A transformação explicada acima só serve para dígitos únicos. O bit sete no ASCII padrão é sempre zero. Isto significa que o conjunto de caracteres ASCII utiliza apenas a metade dos códigos possíveis num byte de oito bits. A IBM usa os 128 códigos restantes para vários caracteres especiais (caracteres com acento, etc), símbolos matemáticos e caracteres de desenho de linhas. Deve ficar claro que estes caracteres extras são uma extensão não padronizada do conjunto de caracteres ASCII. É claro que o nome IBM tem peso e a maioria dos computadores baseados no 80x86 e as impressoras acabaram incorporando os caracteres adicionais da IBM.
Apesar do fato de que sejam um padrão, codificar dados usando simplesmente caracteres padrão ASCII não garante a compatibilidade entre os sistemas, se bem que, hoje em dia, dificilmente encontraremos problemas. Como usaremos com frequência os caracteres ASCII em Assembly, seria interessante guardar de cabeça alguns códigos ASCII importantes, como o do "A", do "a" e do "0".
Meus leitores devem ser perguntar para que serve tudo isso?Na prática conforme fomos programando, tudo se tornará mais óbvio.Mas as funções booleanas servem para tomar decisões e principalmente circuitos.Quando quisermos escrever drivers ou controlar robôs, é muito importante conhecer, e se quisermos estudar as relações dos componentes eletrônicos.Aqui na internet existem muitos textos excelentes sobre eletrônica, e até melhores do que este.Mas quero ajudar um pouco.Em eletrônica existem circuitos combinacionais e sequenciais.Nesses circuitos poderemos ver que existem componentes que funcionam como os operadores booleanos AND,OR e NOT.Quando estiver escrevendo driver leia os manuais do fabricante do produto e você verá símbolos como esse(existentes em eletrônica):

Na ordem exata, temos da esquerda para direita símbolo de AND, OR e NOT(também conhecido como inversor).São chamadas de portas em eletrônica.Ainda há combinações dessas portas, como a função NAND:

Um exemplo de circuito combinacional mais óbvio que tem , é um LED ou decodificador de sete segmentos.Aquela luzinha que tem no rádio relógio.

Isto é um circuito combinacional que possui quatro entradas e determina os sete segmentos de LED estejam em lógica 1(ligada) ou lógica 0(desligada).Como ele contém sete segmentos ou saídas, serão sete funcçoes lógicas associadas a isso.A figura abaixo fornece os devidos segmentos para determinados números decimais:

As quatro entradas, cada uma sendo uma função booleana,equivalem a 4 bits de um número binário no intervalo entre 0 e 9.Se D é o maior valor ou bit mais significativo, e A o menor número ou bit mais menos significativo para este número.Cada função lógica deveria produzir um segmento ligado para uma dada entrada, se um segmento particular fosse iluminado.Por exemplo,S4(segmento 4) deveria estar ligado para o valor binário 0000,0010,0110 e 1000.Para cada valor que ilumina um segmento, você deveria ter um minitermo na equação lógica:
S4 = D'C'B'A' + D'C'BA' + D'CBA' + DC'B'A'.
Vamos esclarecer mais isso daí:

Seguindo a sequencia de número de 0 a 9 em decimal, temos que os valores binários são,respectivamente:DCBA = 0000 - 1001.
E = D’C’B’A’ + D’C’BA’ + D’C’BA + D’CB’A + D’CBA’ + D’CBA + DC’B’A’ + DC’B’A
F = D’C’B’A’+ D’CB’A’ + D’CB’A + D’CBA’ + DC’B’A’ + DC’B’A
G = D’C’B’A’ + D’C’B’A + D’C’BA’ + D’C’BA + D’CB’A’ + D’CBA + DC’B’A’ + DC’B’A
H = D’C’BA’ + D’C’BA + D’CB’A’ + D’CB’A + D’CBA’ + DC’B’A’ + DC’B’A
I = D’C’B’A’ + D’C’BA’ + D’CBA’ + DC’B’A’
J = D’C’B’A’ + D’C’B’A + D’C’BA + D’CB’A’ + D’CB’A +D’CBA’ + D’CBA + DC’B’A’ + DC’B’A
K = D’C’B’A’ + D’C’BA’ + D’C’BA + D’CB’A + D’CBA’ + DC’B’A’
Portanto, acima vemos que para cada segmento temos uma função lógica que o aciona. E por aí vai. Você pode construir circuitos por adição, multiplicação, subtração, comparação usando lógica combinacional.






Referências Bibliográficas:
Por favor, consultar um tópico no blog assim denominado. Tenho muitas referências e estou sempre atualizando...!