Assembly NumaBoa - Capítulo 4

LAYOUT E ACESSO À MEMÓRIA III

Modos de endereçamento com registradores no 80386

O processador 80386 (e posteriores) possuem registradores de 32 bits. Os oito registradores de propósito geral possuem equivalentes com 32 bits. São eles eax, ebx, ecx, edx, esi, edi, ebp e esp. Estes registradores podem ser utilizados como operandos de muitas instruções 80386.

Modos de endereçamento à memória do 80386

O processador 80386 generalizou os modos de endereçamento à memória. Enquanto o 8086 só permitia usar bx ou bp como registradores de base e si ou di como registradores de índice, o 80386 permite que praticamente todos os registradores de propósito geral de 32 bits seja usado como um registrador de base ou de índice. Além do mais, o 80386 novos modos de endereçamento indexado em escala que simplificam o acesso a elementos de arrays. Além do aumento para 32 bits, os novos modos de endereçamento são, provavelmente, o maior progresso do chip em relação a processadores anteriores.

Modos de endereçamento indireto com registradores

No 80386 é possível especificar qualquer registrador de 32 bits de propósito geral quando se usa o modo de endereçamento indireto com registradores. Tanto [eax], [ebx], [ecx], [edx], [esi] como [edi] fornecem deslocamentos, como padrão, para o segmento de dados. Os modos de endereçamento [ebp] e [esp] usam o segmento da pilha como padrão.

Note que, rodando em modo real de 16 bits no 80386, os deslocamentos nestes registradores de 32 bits precisam continuar dentro do limite de 0 a 0FFFFh. Não é possível usar valores maiores que isto para acessar mais do que 64K num segmento. Note também que é preciso usar o nome de 32 bits dos registradores (eax ao invés de ax, por exemplo). As instruções seguintes mostram todas as formas válidas:

	mov	al, [eax]		mov	al, [ebx]
	mov	al, [ecx]		mov	al, [edx]
	mov	al, [esi]		mov	al, [edi]
	mov	al, [ebp]		;Usa SS como padrão
	mov	al, [esp]		;Usa SS como padrão
Modos de endereçamento indexado, base com índice, base com índice com deslocamento no 80386

Os modos de endereçamento indexado (registrador indireto mais um deslocamento) permitem misturar um registrador de 32 bits com uma constante. Os modos de endereçamento base/indexado permitem associar dois registradores de 32 bits. Finalmente, os modos de endereçamento base/indexado/deslocamento permitem combinar uma constante e dois registradores para formar o endereço efetivo. Lembre-se de que o deslocamento produzido pelo cálculo do endereço efetivo precisa ser de 16 bits quando se opera no modo real.

No 80386 os termos registrador base e registrador índice ampliam o sentido. QUando se combina dois registradores de 32 bits num modo de endereçamento, o primeiro registrador é o registrador base e o segundo o registrador índice. Isto é verdadeiro, independentemente dos nomes dos registradores. Note que o 80386 permite usar o mesmo registrador como base e como índice, o que pode ser útil em várias ocasiões. As instruções seguintes fornecem exemplos representativos dos vários modos de endereçamento base e indexado, junto com suas variações sintáticas:

	mov	al, disp[eax]	; Modos de endereçamento
	mov	al, [ebx+disp]	; indexado.
	mov	al, [ecx][disp]
	mov	al, disp[edx]
	mov	al, disp[esi]
	mov	al, disp[edi]
	mov	al, disp[ebp]	; Usa SS como padrão.
	mov	al, disp[esp]	; Usa SS como padrão.

As instruções seguintes usam o modo de endereçamento base+indexado. O primeiro registrador no segundo operando é o registrador base, o segundo é o registrador de índice. Se o registrador base for esp ou ebp, o endereço efetivo é relativo ao segmento de pilha. Nos outros casos, o endereço efetivo é relativo ao segmento de dados. Note que a escolha do registrador índice não afeta a escolha do segmento padrão.

	mov	al, [eax][ebx]	; Modos de endereçamento Base+indexed
	mov	al, [ebx+ebx]	; base + indexado.
	mov	al, [ecx][edx]
	mov	al, [edx][ebp]	; Usa DS como padrão.
	mov	al, [esi][edi]
	mov	al, [edi][esi]
	mov	al, [ebp+ebx]	; Usa SS como padrão.
	mov	al, [esp][ecx]	; Usa SS como padrão.

É claro que podemos adicionar um deslocamento aos modos de endereçamento acima citados para produzir o modo de endereçamento base+indexado+deslocamento. As instruções seguintes são uma amostra representativa dos modos de endereçamento possíveis:

	mov	al, disp[eax][ebx]		; Modos de endereçamento
	mov	al, disp[ebx+ebx]		; base+indexado.
	mov	al, [ecx+edx+desloc]
	mov	al, disp[edx+ebp]		; Usa DS como padrão.
	mov	al, [esi][edi][disp]
	mov	al, [edi][disp][esi]
	mov	al, disp[ebp+ebx]		; Usa SS como padrão.
	mov	al, [esp+ecx][disp]	; Usa SS como padrão.

Existe uma restrição em relação ao uso do registrador índice no 80386: não se pode usar o registrador esp como um registrador índice. Ele pode ser usado como registrador base, mas não como registrador índice.

Modos de endereçamento indexado em escala no 80386

Os modos de endereçamento indexado, bas/indexado e base/indexado/deslocamento descritos acima, na realidade são instâncias especiais dos modos de endereçamento indexado em escala do 80386. Estes modos de endereçamento são particularmente úteis para acessar elementos de arrays, apesar de não estarem limitados a este propósito. Estes modos permitem multiplicar o registrador índice por um, dois, quatro ou oito. A sintaxe geral é:

	desloc[índice*n]
	[base][índice*n]
ou
	desloc[base][índice*n]

onde "base" e "índice" representam qualquer registrador de propósito geral de 32 bits do 80386 e "n" é o valor de um, dois, quatro ou oito.

O 80386 calcula o endereço efetivo somando desloc, base e índice*n. Por exemplo, se ebx contiver 1000h e esi contiver 4, então

	mov al,8[ebx][esi*4]	; Carrega AL com o valor da posição 1018h
	mov al,1000h[ebx][ebx*2]	; Carrega AL com o valor da posição 4000h
	mov al,1000h[esi*8]	; Carrega AL com o valor da posição 1020h

Note que os modos de endereçamento ampliados indexado, base/indexado e base/indexado/deslocamento do 80386 na realidade são casos especiais deste modo de endereçamento indexado em escala com "n" igual a um. Isto é, os pares de instruções seguintes são absolutamente idênticos:

	mov al, 2[ebx][esi*1]	mov al, 2[ebx][esi]
	mov al, [ebx][esi*1]	mov al, [ebx][esi]
	mov al, 2[esi*1]		mov al, 2[esi]

É claro que o MASM permite uma porção de variações destes modos de endereçamento. A seguir uma pequena amostra destas possibilidades:

desloc[bx][si*2]		[bx+desloc][si*2]		[bx+si*2+desloc]
[si*2+bx][desloc]		desloc[si*2][bx]		[si*2+desloc][bx]
[desloc+bx][si*2]
Algumas observações finais sobre os modos de endereçamento à memória do 80386

Como os modos de endereçamento do 80386 são mais ortogonais, eles são mais fáceis de memorizar do que os modos de endereçamento do 8086. Para programadores trabalhando com o processador 80386 sempre existe a tentação de deixar os modos de endereçamento do 8086 de lado e usar unicamento o conjunto do 80386. Entretanto, veremos no próximo módulo que os modos de endereçamento do 8086 são mais eficientes que os comparáveis do 80386. Portanto, é importante conhecer todos os modos de endereçamento e escolher o modo apropriado para cada situação.

Quando se usa os modos de endereçamento base/indexado e base/indexado/deslocamento no 80386, sem a opção de escala (isto é, deixando a escala padrão em "*1"), o primeiro registrador que aparece no modo de endereçamento é o registrdor base e, o segundo registrador, é o registrador índice. Este é um aspecto importante porque a escolha do segmento padrão é determinada pela escolha do registrador base. Se o registrador base for ebp ou esp, o 80386 usa como padrão o segmento de dados, mesmo se o registrador índice for ebp. Se usarmos o operador índice de escala ("*n") com um registrdor, este registrador sempre será o registrador índice, independentemente de onde aparecer no modo de endereçamento:

	[ebx][ebp]	; Usa DS como padrão.
	[ebp][ebx]	; Usa SS como padrão.
	[ebp*1][ebx]	; Usa DS como padrão.
	[ebx][ebp*1]	; Usa DS como padrão.
	[ebp][ebx*1]	; Usa SS como padrão.
	[ebx*1][ebp]	; Usa SS como padrão.
	es:[ebx][ebp*1]	; Usa ES.

A instrução MOV 80x86

Os exemplos do texto usarão com muita frequência a instrução mov 80x86. Além disso, a instrução mov é a instrução de máquina mais comum do 80x86. Portanto, compensa gastar um pouco de tempo discutindo o funcionamento desta instrução. A instrução mov é muito simples e tem a seguinte forma:

mov destino, fonte

mov faz uma cópia da fonte e armazena este valor no destino. Esta instrução não afeta o conteúdo original da fonte. Ela sobrepõe o valor anterior do destino. A operação desta instrução pode descrita pela seguinte declaração Pascal:

destino := fonte;

Esta instrução tem muitas limitações. Seremos confrontados com ela no nosso estudo da linguagem Assembly 80x86. Para entender porque estas limitações existem, é preciso dar uma olhada no código de máquina das várias formas desta instrução. Um alerta: eles nunca chamam o CISC (Complex Instruction Set Computer) do 80386. A codificação da instrução mov provavelmente é a mais complexa do conjunto de instruções. Isto significa que, se não estudarmos o código de máquina desta instrução, não seremos capazes de avaliá-la e não seremos capazes de escrever código otimizado usando esta instrução. Agora você vai entender porque trabalhamos com os processadores x86 (os "de mentira") nos módulos anteriores ao invés de usar as instruções 80x86.

MOV

Fig.13 - A instrução MOV

Existem diversas versões da instrução mov. O menumônico mov descreve mais de uma dúzia de instruções diferentes no 80386. A forma mais usada tem a seguinte codificação binária (veja a Fig.13).

Os oito primeiros bits da instrução são o opcode. Os bits zero e um definem a largura da instrução (8, 16 ou 32 bits) e a direção da transferência. Quando forem analisadas instruções específicas neste texto, os valores de d e w estarão sempre preenchidos. Outros textos, com frequência, costumam pedir que estes valores sejam preenchidos pelo leitor.

O opcode seguinte é o byte do modo de endereçamento, carinhosamente chamado de byte "mod-reg-r/m" pela maioria dos programadores. Este byte escolhe qual das 256 combinações possíveis de operandos a instrução genérica mov permite. A instrução mov genérica assume três formas diferentes na linguagem Assembly:

mov reg, memoria
mov memoria, reg
mov reg, reg

Observe que pelo menos um dos operandos é sempre um registrador de propósito geral. O campo reg no byte mod/reg/rm especifica este registrador (ou um dos registradores se usarmos a terceira forma). O bit d (de direção) do opcode decide se a instrução deve armazenar dados nos registradores (d=1) ou na memória (d=0).

regw = 0w = 1 16 bitsw = 1 32 bits
000ALAXEAX
001CLCXECX
010DLDXEDX
011BLBXEBX
100AHSPESP
101CHBPEBP
110DHSIESI
111BHDIEDI

Os bits do campo reg permitem selecionar um de oito registradores diferentes. O 8086 permite oito registradores de 8 bits e oito registradores de propósito geral de 16 bits. O 80386 também permite oito registradores de propósito geral de 32 bits. A CPU decodifica o significado do campo reg da seguinte maneira:

Para diferenciar registradores de 16 e de 32 bits, o processador 80386 e posteriores usam um byte especial de prefixo no opcode das instruções com registradores de 32 bits. No restante, as codificações das instruções são as mesmas para os dois tipos de instrução.

O campo r/m, juntamente com o campo mod, escolhe o modo de endereçamento. A codificação do campo mod é a seguinte:

MODSignificado
00O campo r/m indica um modo de endereçamento de memória indireta por registrador ou de base/indexado (veja a codificação para r/m) a não ser que o campo r/m contenha 110. Se MOD=00 e r/m=110, os campos mod e r/m indicam endereçamento apenas por deslocamento (direto).
01O campo r/m indica um modo de endereçamento indexado ou base/indexado/deslocamento. Há um deslocamento de 8 bits com sinal seguindo o byte mod/reg/rm.
10O campo r/m indica um modo de endereçamento indexado ou base/indexado/deslocamento. Há um deslocamento de 16 bits com sinal (no modo 16 bits) ou um deslocamento de 32 bits com sinal (no modo 32 bits) seguindo o byte mod/reg/rm.
11O campo r/m indica um registrador e usa a mesma codificação do campo reg.

O campo mod escolhe entre mover de registrador para registrador e mover da memória para registrador. Também escolhe o tamanho do deslocamento (zero, um, dois ou quatro bytes) que segue a instrução dos modos de endereçamento de memória. Se MOD=00, significa que se trata de um dos modos de endereçamento sem deslocamento (indireto via registrador ou base/indexado). Note o caso especial onde MOD=00 e r/m=110. Normalmente corresponderia ao modo de endereçamento [bp]. O 8086 usa esta codificação para o modo de endereçamento apenas por deslocamento. Isto mostra que não existe um modo de endereçamento por [bp] verdadeiro no 8086.

Para entender porque é possível usar o modo de endereçamento por [bp], analise os MOD=01 e MOD=02 da tabela acima. Estes padrões de bits ativam os modos de endereçamento desloc[reg] e desloc[reg][reg]. Aparentemente não correspondem a um modo de endereçamento [bp], mas considere as seguintes instruções:

	mov	al, 0[bx]
	mov	ah, 0[bp]
	mov	0[si], al
	mov	0[di], ah

Estas declarações, que usam os modos de endereçamento indexado, realizam as mesmas operações que as correspondentes indiretas por registradores (obtidas removendo-se o deslocamento das instruções acima). A única diferença real entre as duas formas é que o modo de endereçamento indexado é um byte mais longo (se MOD=01 e dois bytes mais longo se MOD=10), o qual contém o deslocamento zero. Por serem maiores, estas instruções também são um pouco mais lentas.

Esta característica do 8086 - de permitir duas ou mais maneiras de realizar a mesma coisa - ocorre em todo o conjunto de isntruções. Na verdade, veremos vários outros exemplos antes de terminarmos a análise da instrução mov. O MASM geralmente escolhe a melhor forma automaticamente. Se escrevêssemos o código acima e o submetêssemos ao MASM, ele geraria o modo de endereçamento indireto por registradores para todas as instruções, exceto para mov ah,0[bp]. Mesmo neste caso, emitiria apenas um byte para um deslocamento zero. Note que o MASM não exige que se indique 0[bp]. Podemos usar apenas [bp] que o MASM automaticamente supre o byte zero.

Se MOD for diferente de 11b, o campo r/m codifica o modo de endereçamento à memória da seguinte forma:

R/MModo de endereçamento (MOD=00, 01 ou 10)
000[BX+SI] ou DESLOC[BX][SI] (depende de MOD)
001[BX+DI] ou DESLOC[BX+DI] (depende de MOD)
010[BP+SI] ou DESLOC[BP+SI] (depende de MOD)
011[BP+DI] ou DESLOC[BP+DI] (depende de MOD)
100[SI] ou DESLOC[SI] (depende de MOD)
101[DI] ou DESLOC[DI] (depende de MOD)
110Apenas deslocamento ou DESLOC[BP] (depende de MOD)
111[BX] ou DESLOC[BX] (depende de MOD)

Não se esqueça de que os modos de endereçamento envolvendo bp usam o segmento da pilha (ss) como padrão. Todos os outros usam o segmento de dados (ds) como padrão.

Se você já ficou perdido com esta explicação, ainda não sabe do pior. Lembre-se de que estes são apenas alguns dos modos de edereçamento 8086 e ainda é preciso conhecer todos os modos de endereçamento do 80386. Agora começa a ficar claro o que o pessoal quiz dizer com computador de instruções complexas. Entretanto, o conceito importante que deve ser notado é que é possível construir instruções 80x86 da mesma forma como foram construídas as instruções do x86 no capítulo 3 - criando as instruções bit a bit.

Algumas observações finais sobre as instruções MOV

Existem vários fatos importantes, relacionados à instrução mov, que devem ser lembrados. Antes de mais nada, não existem movimentos da memória para a memória. Por alguma razão, os iniciantes da linguagem Assembly têm uma certa dificuldade de lembrar deste aspecto. Apesar de existirem algumas instruções que realizam movimentos da memória para a memória, carregar um registrador e depois armazenar este valor na memória é quase sempre mais eficiente. Outro fato importante é que existem muitas instruções mov diferentes que realizam a mesma coisa. Também existem vários modos de endereçamento diferentes que podem ser usados para a mesma posição na memória. Se você tiver interesse em escrever programas mais curtos e mais rápidos possíveis na linguagem Assembly, será preciso observar constantemente as vantagens e desvantagens de instruções equivalentes.

A análise deste capítulo refere-se principalmente às instruções mov genéricas para realçar a maneira como os processadores 80x86 codificam os modos de endereçamento de memória e de registradores numa instrução mov. Outras formas da instrução mov permitem transferir dados entre os registradores de 16 bits de propósito geral e os registradores de segmento. Outras ainda permitem carregar registradores ou posições de memória com uma constante. Estas variações da instrução mov usam opcodes diferentes. Para maiores detalhes veja a codificação de instruções no Apêndice D (em formato pdf).

Na tabela abaixo estão as principais instruções MOV e suas respectivas codificações em binário:

InstruçãoBinárioObservação
mov reg8, reg81000 1000 [11-reg-r/m]r/m especifica o reg destino
mov reg8, reg81000 1010 [11-reg-r/m]Modo alternativo. r/m especifica o reg destino
mov reg16, reg161000 1001 [11-reg-r/m]r/m especifica o reg destino
mov reg16, reg161000 1011 [11-reg-r/m]Modo alternativo. r/m especifica o reg destino
mov reg32, reg320110 0110 1000 1001 [11-reg-r/m]r/m especifica o reg destino
mov reg32, reg320110 0110 1000 1011 [11-reg-r/m]Modo alternativo. r/m especifica o reg destino
mov mem, reg81000 1000 [mod-reg-r/m]
mov reg8, mem1000 1010 [mod-reg-r/m]
mov mem, reg161000 1001 [mod-reg-r/m]
mov reg16, mem1000 1011 [mod-reg-r/m]
mov mem, reg320110 0110 1000 1001 [mod-reg-r/m]
mov reg32, mem0110 0110 1000 1011 [mod-reg-r/m]
mov reg8, imed1011 0rrr [imed8]
mov reg8, imed1100 0110 [11-000-r/m] [imed8]Modo alternativo.
mov reg16, imed1011 1rrr [imed16]
mov reg16, imed1100 0111 [11-000-r/m] [imed16]Modo alternativo.
mov reg32, imed0110 0110 1011 1rrr [imed32]
mov reg32, imed0110 0110 1100 0111 [11-000-r/m] [imed32]Modo alternativo.
mov mem8, imed1100 0110 [mod-000-r/m] [imed8]
mov mem16, imed1100 0111 [mod-000-r/m] [imed16]
mov mem32, imed1100 0111 [mod-000-r/m] [imed32]
mov al, desloc1010 0000 [desloc]
mov ax, desloc1010 0001 [desloc]
mov eax, desloc0110 0110 1010 0001 [desloc]
mov desloc, al1010 0010 [desloc]
mov desloc, ax1010 0011 [desloc]
mov desloc, eax0110 0110 1010 0011 [desloc]
mov sreg, reg161000 1110 [11-sreg-r/m]
mov sreg, mem1000 1110 [mod-reg-r/m]
mov reg16, sreg1000 1100 [11-sreg-r/m]
mov mem, sreg1000 1100 [mod-reg-r/m]

Existem várias instruções mov adicionais no 80386 que permitem carregar os registradores de propósito especial do 80386. Eles não serão analisados neste texto. No 80x86 também existem algumas instruções para strings, as quais realizam operações da memória para a memória. Estas instruções aparecem no próximo capítulo, mas não são boas substituitas da instrução mov.

Comentários

Gostou do conjunto complexo de instruções? Bota complexo nisso, compadre! Como tudo, a complexidade tem suas vantagens e suas dificuldades. Se, por um lado, entender tudo fica meio embolado, por outro, as possibilidades e formas de atuação são ampliadas. O importante é entender o mecanismo da coisa.

Volto a reforçar um argumento: conhecer os processadores mais antigos e seus conjuntos de instruções é o caminho certo e confiável para dominar os processadores atuais. De instrução mov, que faz o empurra-empurra de dados, já temos know-how. Agora chegou a hora de dar uma olhada em variáveis e estruturas de dados.



| AAAA | Página Inicial | Mapa do Site | Novidades | Busca | Indique esta página | Mestre da Teia | Voltar |
| Localizador || @ Info NumaBoa > Assembly NumaBoa > Memória II > Memória III > Laboratório cap.4
Autoria: Randall Hyde - Art of Assembly Language Programming. Tradução: vovó Vicki

webdesign sobMedida by vickiSoft - /informatica/assembly/cap4_3.php (26.01.04) versão 1.0 de 12.02.04
Licença Creative Commons 1998-2006 Aldeia NumaBoa
Exceto onde especificamente declarado, todo material deste site é disponibilizado de acordo com a Licença Creative Commons.