使用汇编语言反转一个字节

时间:2011-02-07 17:00:41

标签: assembly bit-manipulation reverse codewarrior 68hc12

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

10 个答案:

答案 0 :(得分:8)

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

我敢肯定25年前我可以在没有汇编程序的Z80机器代码中执行此操作:)

答案 1 :(得分:7)

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

答案 2 :(得分:6)

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

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

答案 3 :(得分:3)

首先解决算法以完成您需要做的事情。将其表示为伪代码或C或普通英语或图表或您喜欢的任何内容。一旦你清除了这个概念上的障碍,实际的实现应该非常简单。

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

答案 4 :(得分:3)

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

当你进行旋转时,进位标志用于填充结果的空位(ROL为LSB,ROR为MSB)。

答案 5 :(得分:3)

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

mov al, 10101110
mov ecx, 8

我们在ecx for loop中放了8个

mov ebx, 0 

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

loop1:
sal al, 1;           

在进位标志中,你现在有了左边的最后一位

rcr bl, 1;           

现在你添加了你携带的内容

loop loop1

这就是

答案 6 :(得分:1)

这是评论,但我想WTH!

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

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

如果我是一名教授,我当然喜欢这两个部分,其中一个班次在索引中,另一个在外部。

答案 7 :(得分: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获得010010000之类的内容时,您必须将其移至右侧才能获得01。 然后,将其放入BH并移至所需位置,7表示字节06表示字节1,依此类推。然后OR到我们的最终结果,INCDEC必要的。不要忘记条件跳转并为下一个循环弹出AX:)

结果将在CH。

答案 8 :(得分: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 over sub来进行优化。

edit:还请注意,rcl ax(3个字节),而与adc ax, 0(2个字节)后跟shl ax(2个字节)等效。 请参阅下面的评论,非常感谢Peter Cordes的见解。

答案 9 :(得分:-1)

您所说的第一件事,就是将1000变成0001与不叫它是另一回事。 (应该只是一个周期。)