assembly 组件x86 MASM -从内存撷取5比特时发生问题

j5fpnvbx  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(172)

我有一个问题要解决,但我不知道如何去解决。我想知道如何去解决这个问题的大致想法。我有一个存储器地址,在ESI中。存储器代表某种简化的ASCII编码,其中5位,一个接一个表示一个特定字符。存储器以五位结束-00000 b。为了转换为正常的8-必须向每个5位值添加60 H位ASCII码我希望将每个5位编码字符存储为EDI地址下8位ASCII码EDI还必须以0 - 0000000 b结尾
例如:[ESI] = 00011 00010 11010 00000 b [EDI] = 01100011 01100010 01111010 00000000 b
我将如何去提取每5位,一个接一个从esi?

5lhxktic

5lhxktic1#

让我们看看一种从字节流中累积位的方法。
假设内存中有以下源字节

abcdefgh ijklmnop qrstuvwx     bits 
       +0       +1       +2        address offset

它们表示5位代码如下:

abcde fghij klmno pqrst uvwx.. 5-bit values

我们将做一个类似这样的算法,我们使用一个16位累加器,当我们没有至少5位可供使用时,再取8位。

// Initialize
    int bitcount to 0 
    unsigned accumulator16 to 0
loop:
    if bitcount < 5 then         // don't have enough bits? no, get some more
        temp8 = *sourcepointer++;// 8 bit fetch from memory, and increment pointer
        combine temp8 with accumulator16
        bitcount += 8;           // we added 8 more bits
    end if
    temp5 = accumulator16 >> 11;  // accumulator holds 5 bits of immediate interest
    *destinationpointer++ = temp5 + 0x60; // add the bias and store in memory
    if temp5 == 0 break;         // if we read a 0, then stop
    accumulator <<= 5;           // loose those 5 bits we just consumed
    bitcount -= 5;               // and update how many bits are left still
    goto loop;                   // lather, rinse, repeat

因此,第一次迭代将具有:

accumulator16 = 0000000000000000
    bitcount = 0
first iteration:
    since bitcount < 5 then we fetch:
    temp8 = abcdefgh (fetch byte from sourcepointer and increment it)
    and combine temp8 with accumulator
    accumulator = abcdefgh00000000
    and adjust bit count
    bit count += 8, (0+8=8)

    temp5 = accumulator16 >> 11, so 000abcde
    store it adding 0x60
    shift accumulator to loose the 5 bits we just consumed
    accumulator = fgh0000000000000
    adjust bitcount
    bitcount -= 5, (8-5=3)
    loop
Second iteration:
    since bitcount < 5 then we fetch:
    temp8 = ijklmnop (fetch byte from sourcepointer and increment it)
    and combine temp8 with accumulator
    accumulator = fghijklmnop00000
    and adjust bit count
    bit count += 8, (3+8=11)
        
    temp5 = accumulator16 >> 11, so 000fghij
    store it adding 0x60
    shift accumulator to loose the 5 bits we just consumed
    accumulator = klmnop0000000000
    adjust bitcount
    bitcount -=5 , (11-5=6)
    loop
Third iteration:
    since bitcount >= 5 we don't fetch any bytes this time

    temp5 = accumulator16 >> 11, so 000klmno
    store it adding 0x60
    shift accumulator to loose the 5 bits we just consumed
    accumulator = p000000000000000
    adjust bitcount
    bitcount -= 5, (6-5=1)
    loop
Fourth iteration:
    since bitcount < 5 then fetch another byte and combine

    ...

将刚刚获取的temp 8与当前累加器组合的工作需要对temp进行可变移位,以便该值的第一位与累加器中数据的最后一位对齐。

temp8       = ijklmnop

expand temp8 to 16 bits using zero extension:
temp16      = 00000000ijklmnop

next, shift temp16 such that the "ijklmnop" lines up where we need it

accumulator = fgh0000000000000 // value left after first iteration

how much do we need to shift if we want, to line up "i" to just after "h"
temp16      = 000ikjlkmnop0000

the answer here is 5, 
and it has to do with the number of bits still left in the accumulator, which is a variable amount

that formula is computed by 8-bitcount, which says, 

if there are no bits left we want to shift by 8 (8-0=8)
and for every bit sill left we shift by one smaller (8-3=5)

temp16 <<= 8-bitcount

with the new bits properly shifted, we can or them in
accumulator |= temp16;
accumulator = fghijklmnop00000 // value we want after merge

注意事项:上面假设我们想要abcdefgh中的abcde作为第一个5位代码,而不是defgh,这也是合乎逻辑的。对于读者来说,将上述方法适用于该情况是一种练习,但并不复杂--想法是从累加器的低端而不是从累加器的高端取出5位,并且合并从最后一次迭代剩余的左边的8位,而不是组合从最后一次迭代剩余的右边的8位。
(This也可以适于一次取出多于8位;但是,可能不希望对未对齐的字符串数据执行字或更大的读取操作(例如,在MIPS上不起作用,在支持它的体系结构上可能性能较低)。

相关问题