2014-10-14 2 views
3

Я хочу, чтобы выполнить 64-битное сложение и вычитание:Как выполнить 64-битное сложение и вычитание с использованием MIPS?

v1v0(HiLo) = a1a0 + a3a2 использование MIPS ассемблера (a1a0(HiLo) является первым 64-разрядное число состоит из двух 32-битных чисел, и a3a2(HiLo) является вторым)

и у меня есть:

$a0 = 0xffffffff 
$a1 = 0x0 
$a2 = 0x1 
$a3 = 0x0 

Я новичок в MIPS, и я не знаю, как обращаться несет. Может ли кто-нибудь дать решение с объяснением?

Заранее благодарен! Это набор инструкций, которые я использую:

http://www.cs.uregina.ca/Links/class-info/201/SPIM-IO/MIPSrefCard.pdf

+0

Я понял, что добавление, но не уверен, как работает вычитание ... – Meteorite

+1

Мне было бы хорошо, если бы вы сделали явным, что вы хотите вычитать – Amadeus

+0

, почему тэг [tag: mips64] здесь? В MIPS64 добавления и вычитания по сути являются 64 бит, и вам не нужно ничего особенного для этого. –

ответ

5

Чтобы вычесть число, то есть v = a - b такое же, как и добавление с отрицательным числом, то есть v = a + (-b). Но в целочисленной арифметике отрицательное число кодируется как 2-комплимент, то же самое, что и 1-комплимент + 1 и 1-комплимент - побитовое отрицание.

Таким образом, мы можем написать, что:

v1v0 = a1a0 - b1b0 
v1v0 = a1a0 + ~b1~b0 + 1 

так, мы можем записать это в сборке, как (предполагается, что b1 = а3 и b0 = а2):

add64: addu $v0, $a0, $a2 # add least significant word 
     nor $t0, $a2, $zero # ~a2 
     sltu $t0, $a0, $t0 # set carry-in bit (capturing overflow) 
     addu $v1, $t0, $a1 # add in first most significant word 
     addu $v1, $v1, $a3 # add in second most significant word 
     jr $ra 
#PS: To capture the carry bit in a unsigned sum is equivalent to test if the sum 
# can not be contained in a 32 bit register. I.e. if a0 + a2 > 2^32 - 1 

sub64: nor $a3, $a3, $zero # ~b1 
     nor $a2, $a2, $zero # ~b0 
     jal add64 # v1v0 = a1a0 + ~b1~b0 
     # adding 1 to v1v0 
     ori $a0, $v0, 0 
     ori $a1, $v1, 0 
     ori $a2, $zero, 1 
     ori $a3, $zero, 0 
     jal add64 
     jr $ra 

используя ваши идеи, которые, я думаю, вы ответили бы на ваш вопрос:

subu $v0, $a0, $a2 # $v0 = $a0 - $a2 
sltu $v1, $a0, $a2 # $v1 = ($a0 < $a2)? 1:0(subtract 1 if there's a borrow for Lo words) 
subu $a1, $a1, $v1 # $a1 = $a1 - $v1 
subu $v1, $a1, $a3 # $v1 = $a1 - $a3 
+0

Для добавления я сделал то же самое. Но для вычитания я думаю 'sub64: subu $ v0, $ a0, $ a2 # $ v0 = $ a0 - $ a2 sltu $ v1, $ v0, $ a2 # $ v1 = ($ v0 <$ a2)? 1: 0 (вычесть 1, если есть заимствование для слов Lo) addu $ a3, $ a3, $ v1 # $ a3 = $ a3 + $ v1 subu $ v1, $ a1, $ a3 # $ v1 = $ a1 - $ a3 \t jr \t $ ra' должен работать. Как вы думаете? – Meteorite

+0

Попробуйте следующие значения и посмотрите, работает ли это: '$ a1 = 0, $ a0 = 0x8000 0001, $ a3 = 0, $ a2 = 0x8000 0000' – Amadeus

+0

Извините, была опечатка. Я действительно использовал этот код: '# ваш код здесь subu $ v0, $ a0, $ a2 # $ v0 = $ a0 - $ a2 sltu $ v1, $ a0, $ a2 # $ v1 = ($ a0 <$ a2)? 1: 0 (вычесть 1, если есть заимствование для слов Lo) addu $ a3, $ a3, $ v1 # $ a3 = $ a3 + $ v1 subu $ v1, $ a1, $ a3 # $ v1 = $ a1 - $ a3' – Meteorite

0

В общем, вы должны делать то, что вы узнали, как второй класс при добавлении многозначных чисел. Добавьте каждый столбец.

12 89 
+34 +33 
--- --- 
46 122 

Первый легко, потому что «перенос» не происходит. Во втором случае вам нужно было добавить 3 числа в десяток столбцов: 8 + 3 + 1 (переносить из одного столбца). Затем вторая колонка также переносится, чтобы сделать 100.

Вам нужно сделать то же самое, но вы будете добавлять 32 бит в каждую колонку. К счастью, поскольку вы находитесь в двоичном формате, вы можете переносить только один бит из первого столбца во второй.

+0

MIPS не имеет флага переноса. – markgz

1

Архитектура MIPS не обеспечивает флаг переноса (или любые другие флаги!). Согласно странице this переполнение, требующее переноса, происходит при добавлении двух положительных чисел, дает отрицательное число (или наоборот).

Нечто вроде bool carry = (a1[31] == a3[31]) && (v1[31] != a1[31]), переведенное на сборку MIPS, должно работать.

+0

Спасибо @markgz! Я решил, что мне нужно что-то подобное, и я пытаюсь реализовать логику с помощью 'sltu'. – Meteorite

0

Алгоритм add64 должен быть:

addu $v0, $a0, $a2 # add least significant word 
    nor $t0, $a2, $zero # ~a2 
    sltu $t0, $t0, $a0 # **~a2 < a0 to check carry generation** 
    addu $v1, $t0, $a1 # add in first most significant word 
    addu $v1, $v1, $a3 # add in second most significant word 
    jr $ra 

Мы можем проверить перенос с а0 + а2> 2^32 - 1, но помните, что в двоичной системе:

2^п - 1 = a2 + ~ a2 (например: a2 = 0110, ~ a2 = 1001, a2 + ~ a2 = 1111 = 2^4 - 1, n = 4)

Таким образом, a0 + a2> a2 + ~ a2 => a0> ~ a2

Смежные вопросы