Вот как компиляторы переводят этот вид кода.
Это код C, но он строго эквивалентен вашему исходному коду и написан таким образом, что каждая инструкция C может быть сопоставлена с инструкцией asm. Я даже написал, какую инструкцию следует использовать.
int * pA=&A[0]; // mov
int * pB=&B[0]; // mov
int i=1; // addi
int n=50; // addi
do{
// body of for loop
int B_1=*(pB-1) ; // lw
int A_1=*(pA-1) ; // lw
int D=B_1/A1; // div
int A=*pA; // lw
A += D; // add
*pA = A; // sw
// increment part of the loop
i+=1; // addi
pA+=1; // addi
pb+=1; // addi
// test part of the loop
while (i<N); // blt -> do
}
Вам просто нужно выбрать регистр для всех переменных (например, выбрать скопировать pA
в $t3
(или r4
или что-то еще) и выяснить, как перевести эту инструкцию в asm. Посмотрите на Документация MIPS и перевод должны быть легкими.
Есть несколько важных вещей, которые нужно знать.
Указатели аналогичны адресам памяти, которые обрабатываются процессором, за исключением случаев, когда речь идет об увеличении (или общей арифметике указателей). Если p
является указателем на элемент типа T
в C, p++
означает, что p
будет указывать на следующий элемент типа T
. Для адресов следует учитывать размер типа. Если int
равен 4 байта, «точка к следующему целому» будет соответствовать «добавить к адресу размер целого» (то есть 4).
lw
и sw
используют адресацию на основе, то есть они могут добавить немедленный адрес. Указатель арифметики также актуален. Таким образом, если p
является указателем int
, и вы хотите реализовать x=*(p+2)
, предполагая, что x
находится в $t4
, а p
находится в $t7
, вы должны сделать lw $t4,8($t7)
, что означает чтение память по адресу $t7+8
(как 8==2*sizeof(int)
.
Не должно быть слишком сложно написать первый код. Затем вы можете попытаться оптимизировать его. Может быть, загрузка A[i-1]
на каждой итерации бесполезна, например? Может быть, вы можете уменьшить количество переменных (регистров)?