
		paulo1205
		
		(usa Ubuntu)
		
		Enviado em 15/05/2016 - 06:26h 
		Assembly não é muito a minha praia, mas vamos lá.
joaovitor02 escreveu:
Boa noite, estou começando a estudar assembly e tenho dúvidas sobre o exercício que estou resolvendo. O primeiro estou tentando criar uma seção de variáveis nao inicializadas, e as inicializadas e fazer as seguintes cópias
n1 = v1
n2 = v2
n3 = v3
fiz este código, gostaria de ver se está realmente certo o que eu fiz ou se tem possível melhoras, usar algum outro registrador 
Você está usando sintaxe Intel.  Está usando NASM, gas com opção “-msyntax=intel”, ou algum outro assembler?  Algumas das coisas que eu vou dizer podem depender dos defaults do seu assembler.
section .data
   v1: db 10d 
   v2: dd -20d
   v3: dq -30d 
  
Cuidado com o alinhamento de variáveis.  
v1, 
v2 e 
v3 têm tamanhos, respectivamente, de 1, 2 e 4 bytes.  Quando eu testei seu programa aqui (depois de adaptá-lo para sintaxe AT&T, usando gas, antes de descobrir que o gas aceita também sintaxe Intel), essa ordem de declaração deixou 
v2 e 
v3 em endereços ímpares, o que pode prejudicar o desempenho de acesso.
Se o seu assembler fornecer alinhamento otimizado automaticamente, um efeito colateral pode ser um aumento no tamanho do código (nesse caso, de apenas um byte, ao empurrar 
v2 um byte para frente, para alinhá-lo num endereço múltiplo de 2; 
v3 vai de carona, e acaba alinhado num múltiplo de 4, como deveria mesmo ser).
Curiosamente (ou nem tanto), se você inverter a ordem das variáveis (nesse caso) e já começar alinhado em múltiplo de 4, não terá nenhum problema de alinhamento.
section .bss
   n1: resb 1
   n2: resw 2
   n3: resd 4 
  
Mesmos comentários a respeito de alinhamento.
section .text
   global _start
_start:
   mov al   , [v1]
   mov [n1] , al
   mov ebx  , [v2] 
   mov [n2] , ebx 
  
Na cópia de 
v2 para 
n2, você usou um registrador de 4 bytes (
EBX) para copiar um dado de apenas 2 (que caberia perfeitamente bem em apenas 
BX).  Na leitura, isso pode significar perda de desempenho por possíveis problemas de alinhamento (
BX supostamente usaria alinhamento 2 para não perder desempenho; para 
EBX, esse alinhamento teria de ser 4).  Na escrita, além do alinhamento, existe a possibilidade de você acabar sobrescrevendo dois bytes adjacentes a 
n2 e que talvez pertençam a outro dado (isso de fato ocorreu na versão que eu testei aqui).
Se você 
garantir que os dados (particularmente o de destino) estão alinhados em endereços múltiplos de 4, não haverá maiores problemas com as transferências feitas com um registrador de 4 bytes (aliás, pode até ser uma otimização, pois as instruções que movimentam 2 bytes são ocupam um byte a mais na memória do que as que manipulam 1, 4 ou 8 bytes).  Entretanto, se você eventualmente for fazer contas com tais dados, terá de se lembrar de usar apenas os bytes relevantes, e o leitor do seu código eventualmente poderá estranhar se você fizer transferências com 
EBX mas operar apenas com 
BX.
   mov al   , [v3] 
   mov [n3] , al 
  
Aqui você fez meio que o oposto: de um dado declarado como tendo 4 bytes de comprimento, está transferindo apenas um byte.  Não é um erro, mas certifique-se de que é isso mesmo que você quer.
fim:
   mov rax, 1
   mov rbx, 0 
  
Cada uma dessas instruções gera 7 bytes depois de montadas, num total de 14.  Se você as substituir por
   xor rax, rax
   inc rax
   xor rbx, rbx 
terá os mesmos resultados, mas com um total de apenas 9 bytes (3 de cada instrução; no caso da atribuição de 
RAX, fica um byte mais curta, na de 
RBX, diminui 4 bytes).  Entretanto, note que essa alternativa altera os valores dos flags.  Se os valores dos flags forem importantes para a operação que você fizer em seguida, a forma original, com 
MOV, pode ser preferível.
Outra coisa, de que quase esqueci (e aqui vou usar a sintaxe AT&T porque não sei como é o equivalente com sintaxe Intel): em todas as operações com 
mov de/para endereço fixo, as formas “mov v1(%rip), %al” e “mov %al, n1(%rip)” produzem, cada uma, um byte a menos do que as respectivas e equivalentes versões “mov v1, %al” e “mov %al, n1”, que foi o que você usou originalmente.