9

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

4

9 回答 9

8

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

我敢肯定,25 年前我可以在没有汇编程序的情况下用 Z80 机器代码做到这一点:)

于 2011-02-07T17:11:45.203 回答
7

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

于 2011-02-07T17:08:25.683 回答
6

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

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

于 2011-02-07T17:19:26.040 回答
4

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

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

于 2011-02-07T17:10:42.857 回答
3

首先,制定出你需要做的事情的算法。将其表达为伪代码或 C 或纯英语或图表或任何你喜欢的东西。一旦你清除了这个概念上的障碍,实际的实现应该非常简单。

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

于 2011-02-07T17:08:12.003 回答
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

就这样

于 2017-11-21T07:03:58.763 回答
1

这是一条评论,但我认为 WTH!

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

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

如果我是教授,我当然会喜欢两个部分,一个转变在索引中,另一个在外部。

于 2011-02-09T07:45:16.343 回答
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等等。当你AND用 AL 做一个时,你得到或类似的0东西,100或者10000你必须把它移到右边才能得到它。然后,将其放入 BH 并移动到所需的位置,即for byte ,for byte等等。然后是我们的最终结果以及什么是必要的。不要忘记条件跳转并弹出下一个循环:)017061ORINCDECAX

结果将在 CH 中。

于 2015-04-03T14:17:26.980 回答
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,因为它只占用一个字节,而 sub 占用 3 个字节。最重要的是,编译器似乎总是通过选择 dec 而不是 sub 来进行优化。

编辑:还要注意rcl ax(3字节),而等效于 adc ax, 0(2字节)后跟shl ax(2字节)效率较低。请参阅下面的评论,非常感谢 Peter Cordes 的见解。

于 2020-04-09T23:54:45.740 回答