好吧,首先,我知道如果我有一台 8 位计算机,它只能处理 8 位数字,不能高于 8,但我知道仍然可以表示 16 位数字,甚至是 32 位数字,64,128位数字通过在RAM中分配更多内存。 但为了简单起见,我们仅使用 16 位数字作为示例。
假设我们在 ram 中有一个 16 位数字,如下所示:
12 34 <-- That's Hexadecimal btw
我们也将其写成二进制,以防万一你们更喜欢二进制形式:
00010010 00110100 <-- Binary
&
4660 in decimal
现在,我们知道计算机无法将这个大数字(4660)理解为一个数字,因为计算机只能理解最多 255 的 8 位数字。因此右侧的字节将保持原样是:
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
所以我的问题是,如果计算机只能理解低于 255 的数字,那么它如何将第二个字节读取为 4608,然后它如何将这两个字节解释为单个数字(4660)?
谢谢,如果您感到困惑,请随时在评论中询问我。我已经说得尽可能清楚了。
最佳答案
这与硬件架构相比是更多的编程问题,因为CPU在您的测试用例中仅执行8位操作,并且不了解16位。您的示例是:8 位ALU 上的 16 位算术,通常通过拆分为数字的高半部分和低半部分(然后加入后者)来完成。这可以通过更多方式完成,例如这里的几种方式(使用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;
您需要从 8 位/16 位“寄存器”副本进行复制,这很慢,但有时可以缓解问题。
指针
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相同,但形式更易于管理
CPU 8/16 位寄存器
即使是 8 位 CPU,通常也有 16 位寄存器,可以通过其半寄存器甚至全寄存器进行访问。例如,在Z80上,您有
AF、BC、DE、HL、PC、SP
,其中大部分也可以通过其半寄存器直接访问。因此,有使用hl
的指令,也有单独使用h,l
的指令。 例如,在 x86 上是相同的:mov AX,1234h
与以下相同(除了时间和可能的代码长度之外):
mov AH,12h mov AL,34h
简而言之,这就是 8/16 位之间的转换,但我假设您更多地询问如何完成操作。这是通过使用进位标志来完成的(遗憾的是,大多数高级语言都没有使用该标志,然后是汇编语言)。例如,8 位 ALU(x86 架构)上的 16 位加法是这样完成的:
// ax=ax+bx
add al,bl
adc ah,bh
因此,首先添加最低的BYTE,然后添加最高的+进位。欲了解更多信息,请参阅:
有关如何实现其他操作的更多信息,请参阅 bignum 算术的任何实现。
[编辑1]
这里是C++的小示例,说明如何仅使用 8 位算术打印 16 位数字。您可以使用 8 位 ALU 作为构建 block 来进行 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;
}
//---------------------------------------------------------------------------
我使用VCL AnsiString
进行文本存储,您可以将其更改为任何字符串,甚至char[]
。
您需要将整个数字分开,而不仅仅是单独的字节。了解 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 ...
关于algorithm - 多个 8 位字 block 如何转换为单个数字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41367781/