Профессор, который научил меня системному программированию, использовал то, что он назвал «атомарно-С» в качестве ступеньки между С и сборкой. Правила для атомно-C являются (насколько я помню):
- только простые выражения допускаются, т.е.
a = b + c;
допускается a = b + c + d;
не допускается, потому что есть два оператора там.
- Разрешены только простые булевы выражения в инструкции if, то есть
if (a < b)
разрешен, но if ((a < b) && (c < d))
не разрешен.
- только в том случае, если утверждения, нет блоков.
- не для/время или делать-то время разрешено, только Гото и лейбла
Итак, выше программа будет переводить в;
label1:
if (a == b)
goto label2;
if (a < b)
goto label4;
a = a - b;
goto label3;
label4:
b = b - a;
label3:
goto label1;
label2:
return a;
Надеюсь, я понял это правильно ... Прошло почти двадцать лет с тех пор, как я в последний раз должен был написать атом-С. Теперь, полагая, что это правильно, давайте начнем преобразовывать некоторые из операторов атома-С в MIPS (при условии, что это то, что вы используете). По этой ссылке, предоставленной Elliott Фриша, мы можем почти сразу перевести шаги вычитания:
a = a - b becomes R0 = R0 - R1 which is: SUBU R0, R0, R1
b = b - a becomes R1 = R1 - R0 which is: SUBU R1, R1, R0
Я без знака вычитания из-за одновременно и б быть положительными целыми числами.
Сравнения можно сделать таким образом:
if(a == b) goto label2 becomes if(R0 == R1) goto label2 which is: beq R0, R1, L2?
Проблема здесь состоит в том, что третий параметр Beq оп-кода является смещение, что движется ПК. Мы не будем знать эту ценность до тех пор, пока мы не выполним сборку рук здесь.
Неравенство - это больше работы. Если мы оставим инструкции псевдокода, нам сначала нужно будет использовать op-код set on less than
, который помещает один в регистр назначения, если первый регистр меньше второго. Как только мы это сделаем, мы можем использовать branch on equal
, как описано выше.
if(a < b) becomes slt R2, R0, R1
goto label4 beq R2, 1, L4?
Скачки просты, они просто j, а затем ярлык для перехода на. Таким образом,
goto label1 becomes j label1
Последнее, что нам нужно для обработки - это возврат. Возврат осуществляется путем перемещения значения, которое мы хотим присвоить специальному регистру V0, а затем перейти к следующей команде после вызова этой функции. Проблема заключается в том, что MIPS не имеет регистра для регистрации команды перемещения (или, если она ее забыла), поэтому мы переходим из регистра в оперативную память, а затем обратно. Наконец, мы используем специальный регистр R31, который содержит обратный адрес.
return a becomes var = a which is SW R0, var
ret = var which is LW var, V0
jump RA which is JR R31
С этой информацией программа становится. И мы можем также регулировать скачки, которые мы не знали раньше:
L1:
0x0100 BEQ R0, R1, 8
0x0104 SLT R2, R0, R1 ; temp = (a < b) temp = 1 if true, 0 otherwise
0x0108 LUI R3, 0x01 ; load immediate 1 into register R3
0x010C BEQ R2, 1, 2 ; goto label4
0x0110 SUBU R0, R0, R1 ; a = a - b
0x0114 J L3 ; goto label3
L4:
0x0118 SUBU R1, R1, R0 ; b = b - a;
L3:
0x011C J L1 ; goto lable1
L2:
0x0120 SW R0, ret ; move return value from register to a RAM location
0xLW ret, V0 ; move return value from RAM to the return register.
0x0124 JR R31 ; return to caller
Прошло почти двадцать лет, так как я должен был делать такие вещи, как это (теперь дни, если мне нужна сборка я просто что предложили другие, и пусть компилятор сделает весь тяжелый подъем). Я уверен, что я сделал несколько ошибок на этом пути и буду рад за любые исправления или предложения. Я только вошел в эту длинную дискуссию, потому что я интерпретировал вопрос ОП как письменный перевод - то, что кто-то мог делать, когда они изучали сборку.
ура.
Используйте параметр компилятора C для создания кода сборки. –
Прочтите следующие ответы: http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem –
Держу пари, что курс, который вы принимаете, использует сборку MIPS. Вы не найдете много профессионалов, знакомых с MIPS. Просто изучите это. – OregonTrail