Переполнение / переполнение в числах без знака - PullRequest
3 голосов
/ 21 октября 2011

Таким образом, если у вас есть вынос 1 при сложении с числами без знака, вы переполнились, а если у вас был перенос 0 с вычитанием, вы потеряли. Это работает в каждом случае, хотя?

Если вы делаете 5-0: 0101 -0000

= 0101 + (1111 + 1)

= 0101 + 0000

= 0101 ... здесь выносится ноль, а не 1. Как один учитывает этот случай? Есть ли другой способ сделать это?

(с использованием архитектуры MIPS или чего-либо еще)

--- Edit

Спасибо, Амадан. Я понимаю эту часть, хотя. Моя проблема только в том, что ноль кажется особым случаем. Кажется, он не следует за обычными числами: в моем примере выше нет выполнения 1.

В настоящее время я занимаюсь проектированием схем, работая с АЛУ, и пытаюсь реализовать обнаружение переполнения, когда возник этот случай, который не соответствует тому, что делают другие.

Мы предполагаем, что при вычитании второй операнд преинвертируется (дополняется двумя) перед входом в АЛУ (затем добавляется к первому операнду). Таким образом, всякий раз, когда «invert_b» для вычитания устанавливается в 1, b инвертируется, и мы предполагаем, что проверяемый случай - вычитание, которое должно иметь вынос 1. 1. 1019 *

Ответы [ 3 ]

5 голосов
/ 22 октября 2011

Я полагаю, что бит выполнения msbit сам по себе не имеет подписи, а для подписи вы посмотрите, различаются ли перенос в msbit и выполнения.

5-0 не переполняется, потому что результатподходит по количеству доступных бит.Точно так же, как 15-1 не переполняет 4-битную систему для чисел со знаком

5 - 0 = 0101 + 1111 + 1

    1
 0101
+1111
=====

11111
 0101
+1111
=====
 0101

, поэтому 5 - 0, безусловно, выполняет 1, поскольку это вычитание, которое не является переполнением

15 - 1 = 1111 + ~ 1 с переносом в наборе

    1
 1111
 1110
 ====

11111
 1111
 1110
 ====
 1110

, вычитание с выходом 1 не является переполнением без знакакак вы указали

Аналогично -1 - 1 = 1111 + ~ 1 с установленным битом переноса

11111
 1111
 1110
 ====
 1110

перенос до последнего бита равен 1, перенос равен 1они совпадают, без переполнения со знаком.

8 + 8 = 1000 + 1000 с открытым переносом

    0
 1000
+1000
=====

10000
 1000
+1000
=====
 0000

переполнение без знака.

хммм 4 + 4

    0
 0100
+0100
=====

01000
 0100
+0100
=====
 1000

unsigned add выполнения 0, это не переполнение без знака.но это переполнение со знаком, потому что перенос на бит и выполнение различаются.+4 + +4 = +8, в 4-битной системе со знаком вы не можете представить +8, поэтому переполнение со знаком является точным.

Независимо от того, сколько битов, все странные числа равны нулям и единице иОстальные нули, 0 и 8 или -8 для 4-битной системы.

Создайте диаграмму с 2, 3 или 4-битными числами для всех комбинаций и вручную просмотрите все из них, чтобы убедиться, что они имеют смысл.все, что вы найдете, будет масштабироваться независимо от того, сколько бит в ширину, 100-битный сумматор работает как 10-битный сумматор ...

add           C V  unsigned    signed
00 + 00 = 000 0 0  0 + 0 = 0   0 +  0 =  0
00 + 01 = 001 0 0  0 + 1 = 1   0 +  1 =  1
00 + 10 = 010 0 0  0 + 2 = 2   0 + -2 = -2
00 + 11 = 011 0 0  0 + 3 = 3   0 + -1 = -1
01 + 00 = 001 0 0  1 + 0 = 1   1 +  0 =  1
01 + 01 = 010 0 1  1 + 1 = 2   1 +  1 =  2  signed cannot represent a +2
01 + 10 = 011 0 0  1 + 2 = 3   1 + -2 = -1
01 + 11 = 100 1 0  1 + 3 = 4   1 + -1 =  0  unsigned cannot represent +4
10 + 00 = 010 0 0  2 + 0 = 2  -2 +  0 = -2 
10 + 01 = 011 0 0  2 + 1 = 3  -2 +  1 = -1
10 + 10 = 100 1 1  2 + 2 = 4  -2 + -2 = -4 neither +4 nor -4 will fit in 2 bits
10 + 11 = 101 1 1  2 + 3 = 5  -2 + -1 = -3 neither +4 nor -3 will fit in 2 bits
11 + 00 = 011 0 0  3 + 0 = 3  -1 +  0 = -1 
11 + 01 = 100 1 0  3 + 1 = 4  -1 +  1 = -2 +4 does not fit in 2 bits
11 + 10 = 101 1 1  3 + 2 = 5  -1 + -2 = -3 neither +5 nor -3 fit in 2 bits
11 + 11 = 110 1 0  3 + 3 = 6  -1 + -1 = -2 6 does not fit in 2 bits
sub
00 - 00 = 100 0 0
00 - 01 = 011 1 0  0 - 1 = -1   -1 does not fit in an unsigned result
00 - 10 = 010 1 1  0 - 2 = -2  0 - -2 = +2  
00 - 11 = 001 1 0  0 - 3 = -3
01 - 00 = 101 0 0
01 - 01 = 100 0 0
01 - 10 = 011 1 1  1 - 2 = -1  1 - -2 =  3
01 - 11 = 010 1 1  1 - 3 = -2  1 - -1 =  2
10 - 00 = 110 0 0  
10 - 01 = 101 0 1             -2 -  1 = -3
10 - 10 = 100 0 0
10 - 11 = 011 1 0  2 - 3 = -1
11 - 00 = 111 0 0
11 - 01 = 110 0 0
11 - 10 = 101 0 0
11 - 11 = 100 0 0

Код, который сгенерировал выше

printf("add\n");
for(ra=0;ra<4;ra++)
{
    for(rb=0;rb<4;rb++)
    {
        rd=(ra&1)+(rb&1);
        rc=ra+rb;
        rd=(rd>>1)&1;
        re=(rc>>2)&1;
        if(re) c=1; else c=0;
        if(rd!=re) v=1; else v=0;

        if(ra&2) printf("1"); else printf("0");
        if(ra&1) printf("1"); else printf("0");
        printf(" + ");
        if(rb&2) printf("1"); else printf("0");
        if(rb&1) printf("1"); else printf("0");
        printf(" = ");
        if(rc&4) printf("1"); else printf("0");
        if(rc&2) printf("1"); else printf("0");
        if(rc&1) printf("1"); else printf("0");
        printf(" %u %u\n",c,v);
    }
}
printf("sub\n");
for(ra=0;ra<4;ra++)
{
    for(rb=0;rb<4;rb++)
    {
        rd=(ra&1)+((~rb)&1)+1;
        rc=ra+((~rb)&3)+1;
        rd=(rd>>1)&1;
        re=(rc>>2)&1;
        if(re) c=0; else c=1;
        if(rd!=re) v=1; else v=0;

        if(ra&2) printf("1"); else printf("0");
        if(ra&1) printf("1"); else printf("0");
        printf(" - ");
        if(rb&2) printf("1"); else printf("0");
        if(rb&1) printf("1"); else printf("0");
        printf(" = ");
        if(rc&4) printf("1"); else printf("0");
        if(rc&2) printf("1"); else printf("0");
        if(rc&1) printf("1"); else printf("0");
        printf(" %u %u\n",c,v);
    }
}

ТеперьВаш вопрос говорил о цифрах без знака, да?так что вы можете не заботиться ни о бите V, ни о правой половине, а о половине со знаком.

Вот некоторые HDL / RTL для небольшого 16-битного процессора, который я реализовал:

case 4b0000:
{
    //0000 add rd,rs
    op_a = bundle(1b0,reg[bundle(2b0,inst[4;8])].value);
    op_b = bundle(1b0,reg[bundle(2b0,inst[4;4])].value);
    op_res = op_a + op_b;
    reg[1].value[CBIT] <= op_res[16];
    reg[1].value[NBIT] <= op_res[15];

    if(op_res[16;0] == 16h0000)
    {
        reg[1].value[ZBIT] <= 1b1;
    }
    else
    {
        reg[1].value[ZBIT] <= 1b0;
    }
    if((op_a[15] == op_b[15]) && (op_res[15] != op_b[15] ) )
    {
        reg[1].value[VBIT] <= 1b1;
    }
    else
    {
            reg[1].value[VBIT] <= 1b0;
    }
    reg[bundle(2b0,inst[4;8])].value <= op_res[16;0];
}
case 4b0001:
{
    //0001 sub rd,rs
    op_a = bundle(1b0,reg[bundle(2b0,inst[4;8])].value);
    op_b = bundle(1b0,reg[bundle(2b0,inst[4;4])].value);
    op_res = op_a - op_b;
    reg[1].value[CBIT] <= (~op_res[16]);
    reg[1].value[NBIT] <= op_res[15];

    if(op_res[16;0] == 16h0000)
    {
        reg[1].value[ZBIT] <= 1b1;
    }
    else
    {
        reg[1].value[ZBIT] <= 1b0;
    }
    if((op_a[15] != op_b[15]) && (op_res[15] == op_b[15] ) )
    {
        reg[1].value[VBIT] <= 1b1;
    }
    else
    {
        reg[1].value[VBIT] <= 1b0;
    }
    reg[bundle(2b0,inst[4;8])].value <= op_res[16;0];
}

Я видел / видел вещь с бит-битом для переполнения со знаком в другой логике и не смог найти случай, когдаон не соответствовал методу переноса и выполнения, когда пробовал каждую возможную комбинацию в анализе «голова к голове».

Если я перешел за ответ с ответом, я не возражал бы вырезать его в начале, где он показывает, что 5 -0 имеет 1 как вынос 1, который для вычитания не является переполнением.Длинный ответ, потому что это может быть трудно обернуть голову вокруг подписанного против неподписанного и как сумматор работает в логике в целом.Сумматор не знает или не заботится о знаке или без знака, он заботится о сложении против вычитания, с вычитанием вы инвертируете второй операнд, инвертируете перенос в lsbit и перенос msbit (подумайте о сложении, сложении с переносом, саб и саб с переносом).Подписанный против неподписанного заботится о себе (красота двойки дополняет).Сокращение приведенного выше до обсуждения без знака делает его более чем вдвое более простым, поскольку переполнение со знаком не является (как) очевидным (как переполнение без знака) случайным наблюдателем.

Я очень надеюсь, что вырезал и вставил отлаженный HDL, получу много ответов / исправлений, если я этого не сделал ... Я потратил несколько дней, чтобы убедить себя во всем вышеперечисленном и сравнить с результатами другихпроцессоры, к которым у меня был доступ, и т. д. Надеюсь, это сэкономит вам несколько дней.

3 голосов
/ 21 октября 2011

Не эксперт, но все утверждение о вычитании кажется неправильным.

Вы можете реализовать вычитание двумя основными способами: непосредственно как вычитание или как дополнение к двум дополнениям.

Если выперейдите к сложению с дополнением до двух, тогда это, как вы говорите: перенос 1 - это недополнение.

5 - 6
= 0101 - 0110
= 0101 + (1001 + 1)
= 0101 + 1010
= (0)1111, carry 0 = underflow

Если вы вычесть непосредственно, то 1 перенос - это недополнение:

0101 - 0110:
0     to    1 is 1
1     to (1)0 is 1, carry 1
1 + 1 to (1)1 is 1, carry 1
0 + 1 to (1)0 is 1, carry 1 = underflow
0 голосов
/ 21 октября 2011

Могут быть и другие эквивалентные способы проектирования блоков обнаружения переполнения для сумматоров, но наиболее распространенным является Cin XOR Cout. Например, см. Конец лекции 4 http://cs.nyu.edu/~gottlieb/courses/2007-08-fall/arch/class-notes.html

Он просто проверяет, являются ли добавляемые числа (если что-то инвертировано для дополнения 2 или нет, не имеет значения, мы посмотрим на эти значения впоследствии) переносят в вычисление последней цифры, но не в цифру за пределами поддерживаемого бита. размер или наоборот.

Это имеет смысл, потому что, если они вводят, а не выводят, результат должен быть отрицательным (так как MSB должен быть равен 1), но операнды должны быть положительными (так как если бы они были отрицательными, то выполнялись бы). Это определение переполнения, поскольку два положительных значения не могут суммироваться в отрицательное значение.

Это подписанная модель, однако я не уверен, что это то, что вы ищете, так как вы упомянули без знака. Если это так, то вы правы, простая модель сложения имеет переполнение, когда выполнение равно 1 (это эквивалентно приведенному выше, если вы считаете, что добавление имеет дополнительный 0 для MSB каждого операнда, тогда выполнение будет всегда будет 0, и переполнение будет только в том случае, если перенос равен 1. В данном случае перенос является переносом в нашей модели).

Вычитание приводит к недостаточному расходу, если значение отрицательное. Мы снова можем получить эквивалентность, если считаем, что положительный операнд имеет добавленный MSB, равный 0, и отрицательный операнд, равный 1 (расширение знака). Тогда мы получим отрицательный результат, когда MSB результата равен 1. Это происходит, если выполнение в нашей исходной модели (перенос в новой модели) равно 0, поскольку только тогда MSB результата в новой модели останется 1 .

Ваш пример не является исключением: 0101 + 1111 + 1 = 0101 с выносом 1 и, следовательно, без потери, поскольку результат положительный.

...