2016-12-28 5 views
0

Хорошо, я знаю, что если у меня 8-битный компьютер, он может обрабатывать только 8-битные номера, но не выше 8, но я знаю, что по-прежнему можно представить 16-битное число или даже 32, 64 128-битное число, выделяя больше памяти в памяти. Но для простоты просто используйте 16-битное число в качестве примера.Как многократные куски 8-битных слов преобразуются в один номер?

Допустим, у нас есть 16 битное число в оперативной памяти, как это:

12 34 <-- That's Hexadecimal btw 

Давайте также записать его в двоичной системе только в том случае Yall предпочитают двоичную форму:

00010010 00110100 <-- Binary 
       & 
     4660 in decimal 

Теперь мы знаем, что компьютер не может понять это большое число (4660) как одно число, поскольку компьютер может понимать только 8-битные числа, которые достигают 255. Таким образом, байт справа будет оставаться таким, как есть:

00110100 <-- 52 in decimal 

но левые байты:

00010010 <-- would be 18 if it was the byte on the right, 
      but since it is on the left, it means that its 
      4608 

Так что мой вопрос, как же компьютер читать вторые байты в 4608, если он может понять только цифры, которые ниже, чем 255, а затем после того, как это делает интерпретирует эти два байта как одно число (4660)?

Спасибо, если вы в замешательстве, не стесняйтесь спрашивать меня в комментариях. Я сделал это максимально ясно.

+6

Это лучше, если вы пытаетесь не думать о компьютере как «понимание» ничего, кроме своего набора команд. 8-разрядный компьютер имеет инструкции для чтения байтов, их микширования различными способами и записи байтов. Значения этих байтов становятся только цифрами в вашей голове.То, что вы хотите задать, - «как я могу добавить/вычесть/размножить/разделить» цифры> 256, если у меня есть только однобайтовые инструкции? В школе вас научили вычислять с большими числами, даже если вы помните только таблицы для одноразрядного сложения и умножения. –

+0

Так это же ..? – CosnotraLF

+0

Можете ли вы привести пример с использованием двоичного и фактического кода. Псевдо в порядке. – CosnotraLF

ответ

3

ну это еще вопрос программирующий затем HW архитектуры как CPU только делает операции 8bit в тестовом случае и не имеет знания о 16bit. Ваш пример: 16-битная арифметика на 8 бит ALU и обычно делается путем разбиения на верхнюю и нижнюю половину номера (и объединение последних). Это может быть сделано несколькими способами, например, здесь несколько (используя C++):

  1. передачи

    const int _h=0; // MSB location 
    const int _l=1; // LSB location 
    BYTE h,l; // 8 bit halves 
    WORD hl; // 16 bit value 
    h=((BYTE*)(&hl))[_h]; 
    l=((BYTE*)(&hl))[_l]; 
    // here do your 8bit stuff on h,l 
    ((BYTE*)(&hl))[_h]=h; 
    ((BYTE*)(&hl))[_l]=l; 
    

    Вам нужно скопировать из/в 8bit/16bit "зарегистрировать" копии который медленный, но иногда может ослабить вещи.

  2. указатели

    const int _h=0; // MSB location 
    const int _l=1; // LSB location 
    WORD hl; // 16 bit value 
    BYTE *h=((BYTE*)(&hl))+_h; 
    BYTE *l=((BYTE*)(&hl))+_l; 
    // here do your 8bit stuff on *h,*l or h[0],l[0] 
    

    вам не нужно копировать что-либо, но использовать доступ указателя *h,*l вместо h,l. Инициализация указателя выполняется один раз.

  3. объединение

    const int _h=0; // MSB location 
    const int _l=1; // LSB location 
    union reg16 
    { 
    WORD dw; // 16 bit value 
    BYTE db[2]; // 8 bit values 
    } a; 
    // here do your 8bit stuff on a.db[_h],a.db[_l] 
    

    Это то же самое, как # 2, но в более управляемой форме

  4. процессора 8/16 битовых регистров

    Даже 8 бит процессора имеют обычно 16-битные регистры, доступные по полу или даже полному регистру. Например, на Z80 у вас есть AF,BC,DE,HL,PC,SP, большинство из которых напрямую доступны его полурегистрами. Таким образом, есть инструкции, которые работают с hl, а также инструкции, работающие с h,l отдельно. На x86 это то же самое, например:

    mov AX,1234h 
    

    ли то же самое (кроме сроков и, возможно, длины кода), как:

    mov AH,12h 
    mov AL,34h 
    

Хорошо, что это преобразование между 8/16 бит в двух словах, но я предполагаю, что вы спрашиваете больше о том, как выполняются операции. Это делается с использованием Флаг Carry (который, к сожалению, отсутствует на большинстве высших языков, затем ассемблер). Для примера 16 бит дополнительно на 8-битным АЛУ (x86 архитектура) осуществляется следующим образом:

// ax=ax+bx 
add al,bl 
adc ah,bh 

Итак, сначала вы добавить низкий BYTE, а затем высокий + Carry. Для получения дополнительной информации см:

Для получения дополнительной информации о том, как осуществлять другие операции, видят реализацию на bignum арифметике.

[Edit1]

Вот небольшая С ++ пример того, как печатать 16-битное число с только 8 бит арифметике. Вы можете использовать 8 бит ALU в качестве строительного блока, чтобы сделать N*8 битовые операции таким же образом, как я сделал 16 битовые операции ...

//--------------------------------------------------------------------------- 
// unsigned 8 bit ALU in C++ 
//--------------------------------------------------------------------------- 
BYTE cy;     // carry flag cy = { 0,1 } 
void inc(BYTE &a);   // a++ 
void dec(BYTE &a);   // a-- 
BYTE add(BYTE a,BYTE b); // = a+b 
BYTE adc(BYTE a,BYTE b); // = a+b+cy 
BYTE sub(BYTE a,BYTE b); // = a-b 
BYTE sbc(BYTE a,BYTE b); // = a-b-cy 
void mul(BYTE &h,BYTE &l,BYTE a,BYTE b); // (h,l) = a/b 
void div(BYTE &h,BYTE &l,BYTE &r,BYTE ah,BYTE al,BYTE b); // (h,l) = (ah,al)/b ; r = (ah,al)%b 
//--------------------------------------------------------------------------- 
void inc(BYTE &a) { if (a==0xFF) cy=1; else cy=0; a++; } 
void dec(BYTE &a) { if (a==0x00) cy=1; else cy=0; a--; } 
BYTE add(BYTE a,BYTE b) 
    { 
    BYTE c=a+b; 
    cy=DWORD(((a &1)+(b &1) )>>1); 
    cy=DWORD(((a>>1)+(b>>1)+cy)>>7); 
    return c; 
    } 
BYTE adc(BYTE a,BYTE b) 
    { 
    BYTE c=a+b+cy; 
    cy=DWORD(((a &1)+(b &1)+cy)>>1); 
    cy=DWORD(((a>>1)+(b>>1)+cy)>>7); 
    return c; 
    } 
BYTE sub(BYTE a,BYTE b) 
    { 
    BYTE c=a-b; 
    if (a<b) cy=1; else cy=0; 
    return c; 
    } 
BYTE sbc(BYTE a,BYTE b) 
    { 
    BYTE c=a-b-cy; 
    if (cy) { if (a<=b) cy=1; else cy=0; } 
    else { if (a< b) cy=1; else cy=0; } 
    return c; 
    } 
void mul(BYTE &h,BYTE &l,BYTE a,BYTE b) 
    { 
    BYTE ah,al; 
    h=0; l=0; ah=0; al=a; 
    if ((a==0)||(b==0)) return; 
    // long binary multiplication 
    for (;b;b>>=1) 
     { 
     if (BYTE(b&1)) 
      { 
      l=add(l,al); // (h,l)+=(ah,al) 
      h=adc(h,ah); 
      } 
     al=add(al,al);  // (ah,al)<<=1 
     ah=adc(ah,ah); 
     } 
    } 
void div(BYTE &ch,BYTE &cl,BYTE &r,BYTE ah,BYTE al,BYTE b) 
    { 
    BYTE bh,bl,sh,dh,dl,h,l; 
    // init 
    bh=0; bl=b; sh=0; // (bh,bl) = b<<sh so it is >= (ah,al) without overflow 
    ch=0; cl=0; r=0; // results = 0 
    dh=0; dl=1;   // (dh,dl) = 1<<sh 
    if (!b) return;  // division by zero error 
    if ((!ah)&&(!al)) return; // division of zero 
    for (;bh<128;) 
     { 
     if ((ah)&&(bh>=ah)) break; 
     if ((!ah)&&(bl>=al)) break; 
     bl=add(bl,bl); 
     bh=adc(bh,bh); 
     dl=add(dl,dl); 
     dh=adc(dh,dh); 
     sh++; 
     } 
    // long binary division 
    for (;;) 
     { 
     l=sub(al,bl); // (h,l) = (ah,al)-(bh,bl) 
     h=sbc(ah,bh); 
     if (cy==0)  // no overflow 
      { 
      al=l; ah=h; 
      cl=add(cl,dl); // increment result by (dh,dl) 
      ch=adc(ch,dh); 
      } 
     else{   // overflow -> shoft right 
      if (sh==0) break; 
      sh--; 
      bl>>=1;  // (bh,bl) >>= 1 
      if (BYTE(bh&1)) bl|=128; 
      bh>>=1; 
      dl>>=1;  // (dh,dl) >>= 1 
      if (BYTE(dh&1)) dl|=128; 
      dh>>=1; 
      } 
     } 
    r=al;  // remainder (low 8bit) 
    } 
//--------------------------------------------------------------------------- 
// print 16bit dec with 8bit arithmetics 
//--------------------------------------------------------------------------- 
AnsiString prn16(BYTE h,BYTE l) 
    { 
    AnsiString s=""; 
    BYTE r; int i,j; char c; 
    // divide by 10 and print the remainders 
    for (;;) 
     { 
     if ((!h)&&(!l)) break; 
     div(h,l,r,h,l,10); // (h,l)=(h,l)/10; r=(h,l)%10; 
     s+=char('0'+r);   // add digit to text 
     } 
    if (s=="") s="0"; 
    // reverse order 
    i=1; j=s.Length(); 
    for (;i<j;i++,j--) { c=s[i]; s[i]=s[j]; s[j]=c; } 
    return s; 
    } 
//--------------------------------------------------------------------------- 

Я использую VCLAnsiString для текста хранения можно изменить это то, что когда-либо было строкой или даже char[]. Вам нужно разделить целое число, а не только BYTE отдельно. Посмотрите, как работает функция div. Вот пример значащей цифры 264 печатных 264%10 ...

a = 264 = 00000001 00001000 bin 
b = 10 = 00000000 00001010 bin 
d = 1 = 00000000 00000001 bin 
// apply shift sh so b>=a 
a = 00000001 00001000 bin 
b = 00000001 01000000 bin 
d = 00000000 00100000 bin 
sh = 5 
// a-=b c+=d while a>=b 
// a<b already so no change 
a = 00000001 00001000 bin b = 00000001 01000000 bin c = 00000000 00000000 bin d = 00000000 00100000 bin 
// shift right 
b = 00000000 10100000 bin d = 00000000 00010000 bin sh = 4 
// a-=b c+=d while a>=b 
a = 00000000 01101000 bin c = 00000000 00010000 bin 
// shift right 
b = 00000000 01010000 bin d = 00000000 00001000 bin sh = 3 
// a-=b c+=d while a>=b 
a = 00000000 00011000 bin c = 00000000 00011000 bin 
// shift right 
b = 00000000 00101000 bin d = 00000000 00000100 bin sh = 2 
b = 00000000 00010100 bin d = 00000000 00000010 bin sh = 1 
// a-=b c+=d while a>=b 
a = 00000000 00000100 bin c = 00000000 00011010 bin 
// shift right 
b = 00000000 00001010 bin d = 00000000 00000001 bin sh = 0 
// a<b so stop a is remainder -> digit = 4 
//now a=c and divide again from the start to get next digit ... 
+0

Thx bro этот ответ был действительно полезен +1 – CosnotraLF

+0

Но хорошо, если это 8 бит alu. Как бы напечатать это 16-битное число на экране. Я знаю, что довольно легко напечатать его как шестнадцатеричный номер, потому что ему просто нужно будет распечатать или сохранить значения ah и al в памяти, а затем распечатать их позже. Но как бы преобразовать этот большой 16-разрядный номер, который компьютер не может понять как 1 большое число, потому что он только считывает информационный байт на каждый байт, поэтому, если 16-битное число было 01 A0, что равно 416 в десятичном и максимальное число 8 разрядный компьютер может понять, что это 255. Итак, как бы компьютер распечатал этот номер, если он не знает своих возможностей? – CosnotraLF

+0

@CosnotraLF легко вы просто разделить на 10 в 16-битной арифметике, сделанной из 8-битных операций ... печать остатков в обратный порядок. Операции 'div' и' mod' могут быть преобразованы в набор '+, -' операций, которые легко реализуемы. Для более быстрых методов используется двоичное деление (с использованием сдвигов и подстрок для div и shift и добавление для подходов mul и radix ...) для получения дополнительной информации см. [Bigint hex/dec conversion in C++] (http://stackoverflow.com/a/18231860/2521214) – Spektre

0

Путем интерпретации их как базы-256.

>>> 18*256 + 52 
4660