Pergunta

preciso converter meu código do ponteiro de pilha para usar apenas o ponteiro de quadro, como posso fazer isso?eu sou muito novo no MIPS.

eu tenho esse código C de recursão e seu código MIPS abaixo.estou usando o ponteiro de pilha, como posso alterá-lo para usar o ponteiro do quadro?

aqui está meu código C

int fact(int n)
{
    if(n!=1)
     return n*factorial(n-1);
}

    int comb (int n, int k)
    {
    return fact (n) / fact (k) / fact (n - k);
    }

aqui meu código MIPS

comb:           
 sub $sp, $sp, 16
 sw $ra , 0($sp)
 sw $s0, 4($sp) 
 sw $a0, 8($sp) 
 sw $a1, 12($sp)
 jal fact       
 move $s0, $v0  
 lw $a0, 12($sp) 
 jal fact       
 div $s0, $s0, $v0 
 lw $a0, 8($sp) 
 lw $a1, 12($sp) 
 sub $a0, $a0, $a1 
 jal fact       
 div $s0, $s0, $v0 
 move $v0, $s0  
 lw  $ra, 0($sp) 
 lw  $s0, 4($sp) 
 addi $sp, $sp, 16 
 jr $ra         
Foi útil?

Solução

Achei os comentários de @markgz interessantes.Seu link para a Wikipedia inclui a citação:

O ponteiro de quadro ($30) é opcional e na prática raramente usado, exceto quando a alocação de pilha em uma função é determinada em tempo de execução, por exemplo, chamando alloca().

Eu sempre pensei isso $fp parecia supérfluo, mas sempre usei mesmo assim porque foi assim que fui ensinado a fazer.

De qualquer forma, se você ainda estiver interessado, aqui está como usei o ponteiro de quadro:

#save $ra $s0, $a0 on stack
addi $sp $sp -4
sw   $fp 0($sp)
move $fp $sp
addi $sp $sp -12
sw   $ra  -4($fp)
sw   $a0  -8($fp)
sw   $s0 -12($fp)

...

#restore and shrink stack
lw $s0 -12($fp)
lw $ra  -4($fp)
lw $fp   0($fp)
addi $sp $sp 16

jr $ra

Portanto, cada vez que a pilha é expandida, eu uso o ponteiro de pilha para salvar o valor antigo do ponteiro do quadro e, em seguida, restauro o valor antigo do ponteiro do quadro ao reduzir a pilha.

Geralmente, apenas copio e colo esse código toda vez que escrevo uma nova função.

Outras dicas

Você deve nunca converter o código MIPS para usar o Ponteiro de quadro em vez do Stack Pointer, porque isso violaria o MIPS Convenção de chamada, e seu código deixaria de funcionar com o código de outras pessoas.

O Frame Pointer normalmente não é usado em assembler MIPS codificado manualmente, porque o ponteiro de pilha não altera o valor durante a execução de uma função.Na verdade, seu próprio código é codificado corretamente para que o ponteiro da pilha nunca mude de valor.

Expandindo a resposta de Konrad Lindenbach:

#save $ra, $s0, $a0, $a1
addi $sp, $sp, -4
sw $fp, 0($sp)
move $fp, $sp
addi $sp, $sp, -16
sw $ra, -4($fp)
sw $a0, -8($fp)
sw $a1, -12($fp)
sw $s0, -16($fp)


#Your Code Here


#Restore
lw $s0, -16($fp)
lw $ra, -4($fp) #Can Be C+P'd from here down
addi $sp, $fp, 4
lw $fp, 0($fp)

ja $ra

Dessa forma, é muito mais fácil ler e escrever sem sacrificar o comprimento das instruções.Você também usaria esse método para alocação dinâmica de memória, pois o snippet de restauração não precisa saber quantos dados foram alocados para a pilha.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top