对 68HC12 上的一个字节进行位反转

问题描述 投票:0回答:10

我正在上微处理器课,我们正在使用 Freescale CodeWarrior 中的汇编语言对 68HCS12 微控制器进行编程。本周我们的作业是反转一个字节,因此如果该字节是 00000001,则输出将为 10000000,或 00101011 到 11010100。我们必须使用汇编语言,并被告知我们可以使用旋转和移位(但不限于! )来完成这个任务。我真的不知道该从哪里开始。

assembly bit-manipulation reverse codewarrior 68hc12
10个回答
8
投票

提示:如果进行移位,一位会被移出,而零(可能)会被移入。移出的位会去哪里?您需要将其移入目标寄存器或内存地址的另一端。

我确信 25 年前我可以在 Z80 机器代码中做到这一点,无需汇编器:)


6
投票

如果您可以节省 256 字节的额外代码大小,查找表可能是在 68HCS12 上反转字节的最有效方法。但我很确定这不是你的老师所期望的。

对于“正常”解决方案,单独考虑数据位。旋转和移位允许您移动位。对于第一个解决方案,隔离八个位(使用按位“与”运算),将它们移动到目标位置(移位、旋转...),然后再次将它们组合在一起(使用按位“或”运算)。这不是最有效或最简单的实现,但您应该首先集中精力获得正确的结果——优化可以等待。


6
投票

将两个寄存器视为位堆栈。如果一次一点地从一个移动到另一个会发生什么?


4
投票

当您进行右移时,最低有效位将进入进位标志。

进行循环时,进位标志用于填充结果的空出位(ROL 为 LSB,ROR 为 MSB)。


3
投票

首先制定出算法来完成你需要做的事情。将其表达为伪代码、C 语言、简单英语、图表或任何您喜欢的形式。一旦清除了这个概念障碍,实际的实施应该非常简单。

您的 CPU 可能具有可让您移位和/或旋转寄存器的指令,可能包括进位标志作为附加位。这些说明将非常有用。


3
投票

例如,如果您有所有字节数,最简单的方法是

mov al, 10101110
mov ecx, 8

我们将 8 放入 ecx for 循环中

mov ebx, 0 

在 bl 中我们将得到结果,我们将制作 ebx,只是为了看看会发生什么更好

loop1:
sal al, 1;           

在进位标志中,现在您拥有左起最后一位

rcr bl, 1;           

现在你在 BL 中添加你携带的东西

loop loop1

仅此而已


1
投票

这是一条评论,但我想WTH!

为了节省 256 字节表的空间,您可以使用一个 16 字节表,一次包含四位(半字节)的值。那么算法就是

revval=(revdigit[inval&0x0f]<<4)|
        revdigit[inval>>4];

如果我是一名教授,我肯定会喜欢这两个部分,其中一个轮班在索引中,另一个轮班在索引之外。


0
投票

我还必须为大学编写这个位反向(8 位)。这是我的做法:

MOV AL, 10001011B ;set the value to test
MOV CL, 7
MOV DH, 1
MOV DL, 0

loop1: PUSH AX
AND AL, DH 
PUSH CX
MOV CL, DL
SHR AL, CL
POP CX
MOV BH, AL
SHL BH,CL
OR CH,BH
DEC CL
INC DL
SHL DH, 1
POP AX
CMP DL, 8
JE END
JMP LOOP1

END:

我没有评论它,所以它是如何工作的: DH 是一个

1
,像第一次一样以字节形式传输:
00000001
;第二次
00000010
等等。当你用 AL 制作
AND
时,你会得到
0
或类似
100
10000
的东西,你必须将其向右移动才能得到
0
1
。 然后,将其放入 BH 并移动到所需的位置,即
7
表示字节
0
6
表示字节
1
,依此类推。然后
OR
我们的最终结果以及
INC
DEC
什么是必要的。不要忘记条件跳转并弹出
AX
进行下一个循环:)

结果将在 CH 中。


0
投票

以下代码利用了旋转和移位。我使用Intel x86语法,请参阅右侧说明:

    mov cx, 8           ; we will reverse the 8 bits contained in one byte
loop:                   ; while loop
    ror di              ; rotate `di` (containing value of the first argument of callee function) to the Right in a non-destructive manner
    adc ax, ax          ; shift `ax` left and add the carry, the carry is equal to 1 if one bit was rotated from 0b1 to MSB from previous operation
    dec cx              ; Decrement cx
    jnz short loop      ; Jump if cx register Not equal to Zero else end loop and return ax

我使用 dec 指令而不是 sub,因为它只占用 1 个字节,而 sub 占用 3 个字节。最重要的是,编译器似乎总是通过选择 dec 而不是 sub 来优化。

编辑:另请注意,

rcl ax
(3 个字节),而相当于
adc ax, 0
(2 个字节)后跟
shl ax
(2 个字节)效率较低。 请参阅下面的评论,非常感谢 Peter Cordes 的见解。


0
投票

一个可能的通用解决方案(不在任何特定的汇编器中,可能很快但很大 - 我注意到这可以放入带有移位的循环中,但会更慢) 用 0 加载字节 reg a 用测试值加载字节reg b

位测试 128 与 a 如果为 0 则跳过下一个 一个<- a+1

位测试 64 与 a 如果为 0 则跳过下一个 一个<- a+2

位测试 32 与 a 如果为 0 则跳过下一个 一个<- a+2

位测试 16 与 a 如果为 0 则跳过下一个 一个<- a+4

最后一个存在

位测试 1 与 a 如果为 0 则跳过下一个 一个<- a+128 result in a

© www.soinside.com 2019 - 2024. All rights reserved.