【发布时间】:2019-04-02 04:55:07
【问题描述】:
编辑:
我没想到这个问题会如此迅速地引起关注。根据我已经收到的答案,我似乎遗漏了一条重要信息。该模式不是固定数量的位。有些字母可能有更多或更少的位。即,B 有 5 位,但 C 可能使用多达 6 位,但没有使用超过一个字节。我在我的问题中包含了一个“A”位模式的示例,每行使用 7 位。另请参阅问题底部的编辑。
我是组装新手。我有对应于字母的文本表示的位模式。每个 1 代表一个 $(或任何符号),每个 0 代表一个空格。即:
$$$$ 11110
$ $ 10001
$ $ 10001
$$$$ 11110
$ $ 10001
$ $ 10001
$$$$ 11110
$ 0001000
$ $ 0010100
$$$$$ 0111110
$ $ 1000001
我编写了一个汇编语言程序,它读取每个模式并根据它读取的是 1 还是 0 打印正确的符号。要确定它是 1 还是 0,我将寄存器与 1 然后将位右移等于每行中位数的次数,然后比较结果:
请注意,每行的位存储在单独的 2 字节字的底部,我将其加载到 8 位寄存器中。
patternb: dw 011110b,010001b,010001b,011110b,010001b,010001b,011110b
rowloop:
mov bl,[patternb+si] ;iterate through each element in binary array
patternloop:
mov bh,bl ;move bit pattern into register so that we can change it
and bh,1 ;AND register to find set bits and store back in register
shr bl,1 ;SHIFT original bit pettern right
cmp bh,1 ;check if bit is set or not (1=set, else 0)
je writesym ;if set, write symbol
jne writeblank ;if not set, write space
问题在于 AND 的工作方式。显然,它从最低有效位开始并在位右移时打印,但这会导致它以“反向”顺序打印字母的问题。即:
####
# #
# #
####
# #
# #
####
我尝试了一些操作,但似乎都没有。我还尝试移动和旋转位模式以对应正确的打印,但这不适用于每一行,因为并非每一行都需要以这种方式进行操作。 (例如,第 2 行将正确打印,无需先进行操作)。对于 A-E 中的每个字母,我都有相同的位模式技术。
理想情况下,我希望它以某种方式从最高有效位开始比较,然后以正确的顺序打印它,但我不确定如何处理为了实现这一目标。
编辑:
按照 Peter Duniho 的回答,我想发布一些我尝试过的东西:
我尝试使用 10000b 对模式进行与运算,然后对结果进行 ROL 以获得00001b 的答案,然后将位左移。然后比较结果以查看应该打印哪个符号。这也不起作用,但因为位模式并不总是固定的,所以无论如何它都不是解决方案。
mov bh,bl ;move bit pattern into register so that we can change it
and bh,10000b ;AND register to find set bits and store back in register
rol bh,1 ;rol result to obtain 00001b
shl bl,1 ;SHIFT original bit pettern right
cmp bh,1 ;check if bit is set or not (1=set, else 0)
je writesym ;if set, write symbol
jne writeblank ;if not set, write space
我现在最接近解决这个问题(在 Peter Duniho 的回答作为指导的帮助下)是将我的位数组存储为完整的 8 位形式(即 011110000b 等而不是 011110b 否则汇编器将其存储为 00011101 隐式存储,如 Martin Rosenau 的回答中所述,我们不想要)以及完整的 10000000b (因为我们最多使用 8 位,这让我们可以检查 MSB) 1 个(000000001b),就像我之前尝试做的那样,然后使用上面的 ROL 和比较方法(或者只是将它与10000000b 进行比较)。循环总共运行了 7 次(由于每个字母有 7 行/位模式,除了 A 有 4 所以 A 打印不正确,但这是我可以在某些条件下自己解决的问题。程序工作并打印现在正确。这是我使用的代码:
mov bh,bl ;move bit pattern into register so that we can change it
and bh,10000000b ;AND register to find set bits and store back in register
rol bh,1 ;shift MSB to LSB to compare (or could just compare with 10000000b instead)
shl bl,1 ;SHIFT original bit pettern left
cmp bh,1 ;check if bit is set or not (or use cmp bh,10000000b and omit rol above)
je writesym ;if set, write symbol
jne writeblank ;if not set, write space
我已将 Peter 的解决方案标记为答案,因为它为我指明了解决此问题的正确方向。但正如他所提到的,有很多方法可以解决这个问题(如发布的不同解决方案所示),但他恰好是我为我自己的代码实现的最简单的方法,这正是他想要的。
Martin Rosenau 的回答也很有见地,尤其是优化。当我有更多时间时,我会尝试实现这些,然后更新上面的解决方案。
【问题讨论】:
-
左移一点,从顶部移到 CF 中。例如
add bl,bl / jc writesym/ 否则失败或jmp写空白。 -
re:编辑:如果它实际上是可变宽度,您的代码如何知道位模式的开始位置?即使前几列全为零,将每个块视为始终为 8x7 似乎要容易得多。然后你可以按照我在第一条评论中建议的方式简单地解码它,一次将一位移动到 CF 中。
标签: assembly x86 bit-manipulation nasm