bom cara, eu também tenho as mesmas dúvidas... to começando com NASM aqui, e até hoje eu não entendo o que o LEA faz, com uma função de "load effective address", não faço a mínima idéia XD
Posso estar perdido no mundo mas acho que a sua relação está meio incorreta. NASM é o Compilador não? De qualquer modo, ao menos ao meu ponto de vista, você está tratando o NASM como uma linguagem a parte. ???
É verdade vuln, NASM é um compilador.
Mas alguns compiladores mudam um pouco a forma de escrever em assembly, não a linguagem em si, mas o jeito de usa-la.
É meio estranho de explicar mesmo, procure no Google exemplos de como fazer um hello world com o NASM e compare com o FASM.
Hi,
Tentarei explicar de acordo com minhas concepções e nível de conhecimento atuais. Leve em conta que eu sou iniciante em Assembly e o que eu passar pode não estar correto ;)
1. Tem como mover o registrador de 8 bits al para o de 32 bits eax ?
Os registradores AL, AH, AX e EAX, podem ser considerados como apenas um: o Acumulador.
Na verdade, esses registradores têm tamanhos diferentes:
AL - 8 bits;
AH - 8 bits;
AX - 16 bits;
EAX - 32 bits;
Os dois primeiros (AL e AH) são subdivisões do registrador AX: AL é o byte baixo (bits: 0 a 7) e AH o byte alto (bits: 8 a 15). O registrador EAX é uma extensão para 32 bits (bits: 0 a 31).
Lolz, já vou avisar que eu não sei desenhar, então nem pode zuar meu esquema:
_____________________________ EAX
AL AH
_______|_______|
AX
O registrador EAX começa no bit 0 e termina no bit 31;
O regitrador AX começa no bit 0 e termina no bit 15;
Temos ainda dentro do registrador AX: AL = 0 até 7 e AH = 8 até 15;
Vamos supor que temos:
mov al,11b
Estamos movendo o valor binário 11 para o byte baixo de AX, que é AL.
Considerando que EAX é 0, seu valor seria:
0x0000011b
|
AL
Sabendo-se que o bit mais significativo é 1, o valor de EAX seria 0x11b, o mesmo valor de AL.
Portanto, para que EAX tenha o valor de AL, basta zerá-lo antes de mover para AL o respectivo valor:
xor eax,eax ; Zera EAX
mov al,valor
Com o trecho acima, o valor de EAX seria o mesmo movido para AL.
Este processo se faz necessário pois AL possui 8 bits e se os bits superiores (8 a 31) de EAX não forem 0, ou seja, forem significativos, o registrador EAX como um todo terá outro valor.
Exemplo:
mov eax,2048 ; EAX = 2048 = 100000000000b
Em binário, o valor de EAX seria:
0x100000000000b
Se não zerarmos EAX e fizermos:
mov al,4 ; AL = 4 = 100b
O registrador EAX teria agora o seguinte valor (binário):
0x100000000100b
|
100b -> AL
O valor de EAX portanto, seria 2052 em decimal e não 4.
A página abaixo explica mais sobre registradores:
http://www.powerbasic.com/support/help/ ... isters.htm (http://www.powerbasic.com/support/help/pbcc/registers.htm)
-----------------------------------------------------------------------
2. Como gravar em um arquivo um registrador de 8 bits sem usar funções API ?
Pode-se utilizar em conjunto as interrupções: "21,3C", "21,40" e "21,3E".
Exemplo no FASM:
org 100h ; Origem -> endereço 256
;Cria o arquivo: lol.txt
mov ah,3ch ; AH = 3CH
mov cx,0 ; CX = 0;
mov dx,arq ; DX = ponteiro para o buffer que contém o nome do arquivo
int 21h ; 21,3C
; Move para bx o ponteiro para o arquivo criado
mov bx,ax
; Escrever no arquivo o caractere em AL
mov ah, 40h ; AH = 40h
mov cx,1 ; Bytes a serem escritos -> 1 caractere = 1 byte
mov al,'S' ; Move para AL -> 'X' -> caractere a ser escrito
mov [char],al ; Move para o primeiro caractere do buffer o valor de AL
mov dx,char ; Move para DX o ponteiro para o buffer
int 21h ;21,40
; Fecha o arquivo
mov ah,3eh-> AH = 3Eh
int 21h ;21,3E
mov ax,0x4C00 ; AH = 4C, AL = 0
int 21h ; 21,4C ; Encerra
char db 0,0 ; Buffer que a escrever no arquivo
arq db "lol.txt",0 ; Nome do arquivo a ser criado
Note que a interrupção 21,40 é utilizada para escrever uma string em um arquivo. Utilizamos o buffer "char" como string. Movemos para o primeiro byte do buffer "char" o caractere em AL, para que só assim possa ser escrito posteriormente.
-----------------------------------------------------------------------
3. Quais as diferenças do comando lea e mov ?
Geralmente, a instrução MOV é utilizada para mover valores para registradores, exemplo:
mov cx,1000 ;cx = 1000
A instrução LEA é utilizada para mover endereços de variáveis, ou seja, um ponteiro. Exemplo:
lea dx,buffer ; Move para DX o endereço de "buffer
buffer db "Buffer!",0
Dependendo do assembler, as instruções LEA e MOV podem assumir papeis diferentes, em alguns casos, a instrução LEA nem mesmo é reconhecida como instrução válida, no FASM por exemplo:
mov dx,buffer ; Move para DX o endereço de "buffer"
buffer db "Buffer!",0
Ainda no FASM:
; O FASM considera a instrução LEA como inválida
lea dx,buffer
buffer db "Buffer!",0
A instrução MOV assume o papel da instrução LEA, movendo para DX o endereço de "buffer".
-----------------------------------------------------------------------
4. É diferente fazer lea ax,bx e mov ax,bx ?
Seria diferente sim. Enquanto a instrução LEA move endereços, a instrução MOV, geralmente, move valores.
Pode-se no entanto, fazer com que MOV mova endereços:
mov dx,OFFSET buffer ; Move para DX o endereço de buffer
buffer db "Buffer!",0
Equivale a:
lea dx,buffer ; Move para DX o endereço de buffer
buffer db "Buffer!",0
O uso de LEA e MOV pode ser diferente dependendo do compilador em questão.
-----------------------------------------------------------------------
Aproveitando o post acima, um Hello World feito no NASM, seria basicamente o seguinte:
[ORG 0x100] ; endereço de memória 256
mov ah,9 ; ah = 9 (escrever string na tela
mov dx,msg ; move para DX o ponteiro para a string
int 21h ; chama interrupção 21,9
mov ax,0X4C00 ; AH = 4C; AL = 0
int 21h; interrupção 21,4C -> sair do programa
msg db "Hello World!$" ; Buffer a ser escrito na tela
Lolz... eu acho que é isso.
Bye
Em um Hello World, é preciso colocar org 0x100 (256 em decimal né?) se colocarmos por exemplo 0x101 não iria funcionar?