ну это еще вопрос программирующий затем HW архитектуры как CPU только делает операции 8bit в тестовом случае и не имеет знания о 16bit. Ваш пример: 16-битная арифметика на 8 бит ALU и обычно делается путем разбиения на верхнюю и нижнюю половину номера (и объединение последних). Это может быть сделано несколькими способами, например, здесь несколько (используя C++):
передачи
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 "зарегистрировать" копии который медленный, но иногда может ослабить вещи.
указатели
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
. Инициализация указателя выполняется один раз.
объединение
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, но в более управляемой форме
процессора 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 ...
Это лучше, если вы пытаетесь не думать о компьютере как «понимание» ничего, кроме своего набора команд. 8-разрядный компьютер имеет инструкции для чтения байтов, их микширования различными способами и записи байтов. Значения этих байтов становятся только цифрами в вашей голове.То, что вы хотите задать, - «как я могу добавить/вычесть/размножить/разделить» цифры> 256, если у меня есть только однобайтовые инструкции? В школе вас научили вычислять с большими числами, даже если вы помните только таблицы для одноразрядного сложения и умножения. –
Так это же ..? – CosnotraLF
Можете ли вы привести пример с использованием двоичного и фактического кода. Псевдо в порядке. – CosnotraLF