A UPF tem seu próprio conjunto de registradores. Eles são organizados como uma pilha (de 8 registradores):
-------------- | | -------------- | | | | -------------- pilha | | | cresce | -------------- \ / | | -------------- | | <- st(0) ---- top -------------- | | -------------- | | -------------- | | --------------
A cada instante, o nome st(0)
se refere ao registrador
no topo da pilha, st(1) ao anterior ("abaixo" do topo), e assim
por diante.
Cada registrados da pilha de ponto flutuante tem 80 bits, para
maior precisão nas operações.
As instruções de transferência de dados da UFP, FLD? e FSTP? (Load e Store) movimentam dados entre memória principal e pilha de registradores.Não é possível movimentar dados diretamente entre os registradores da CPU e os da UPF.
As instruções FILD? e FIST? realizam conversões entre a representação em ponto flutuante e a representação de inteiro em complemento a 2.
atenção!! Essa é uma pilha de registradores, dentro da CPU, e não tem nada a ver com a pilha de registros de execução, cujo topo é apontado por ESP!!!!
A passagem de valores float ou double para uma função deve ser feita, como sempre, através da pilha. A convenção little-endian do pentium é estendida para o caso do double, ou seja, a palavra menos significativa deve aparecer em endereços de memória menores do que a mais significativa.
Quando uma função C retorna um valor float ou double, esse valor deve ser retornado no topo da pilha de registradores da UPF.
double soma (double a, double b) { return a+b; }poderia ser escrita em assembly como:
soma: push %ebp mov %esp, %ebp fldl 8(%ebp) /* carrega para a pilha da UPF a variável a */ faddl 16(%ebp) /* adiciona b */ mov %ebp, %esp pop %ebp ret
A função C abaixo:
double dot (double a[], double b[], int tam) { int i; double res = 0.0; for (i=tam;i>0;i--) res += a[i]*b[i]; return res; }poderia ser escrita em assembly como:
dot: push %ebp mov %esp, %ebp mov 8(%ebp), %eax /* endereco de a */ mov 12(%ebp), %ebx /* endereco de b */ mov 16(%ebp), %ecx /* tam - i vai ficar em um registrador! */ mov $0, %edx fldz /* coloca zero na pilha de registradores da UPF */ fori: cmp $0, %ecx je fim fldl (%eax) fmull (%ebx) faddp %st(0), %st(1) /* soma st(0) com st(1), resultado em st(1), pop st(0) */ add $8, %eax /* atualiza endereco de a[i] */ add $8, %ebx /* atualiza endereco de b[i] */ dec %ecx /* atualiza i */ jmp fori fim: mov %ebp, %esp /* resultado ja' esta' na pilha! */ pop %ebp ret