Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 位反转68HC12上的一个字节_Assembly_Bit Manipulation_Reverse_Codewarrior_68hc12 - Fatal编程技术网

Assembly 位反转68HC12上的一个字节

Assembly 位反转68HC12上的一个字节,assembly,bit-manipulation,reverse,codewarrior,68hc12,Assembly,Bit Manipulation,Reverse,Codewarrior,68hc12,我在一个微处理器类,我们正在使用飞思卡尔CodeWarrior中的汇编语言来编程一个68HCS12微控制器。本周我们的任务是反转一个字节,因此如果字节是00000001,那么输出将是10000000,或者00101011到11010100。我们必须使用汇编语言,并且被告知我们可以使用轮换和移位(但不限于!)来完成这项任务。我真的不知道该从哪里开始。首先,制定出做你需要做的事情的算法。将其表示为伪代码、C语言、简单英语、图表或任何您熟悉的语言。一旦您清除了这个概念上的障碍,实际的实现应该非常简单

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

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


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

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

右移时,最低有效位进入进位标志


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

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


我确信25年前,我可以在没有汇编程序的情况下在Z80机器代码中实现这一点:)

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


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

这是一个注释,但我认为是正确的


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

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

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

我还必须为大学编程这个位反转(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做
时,你会得到
0
或类似
100
10000
之类的东西,你必须向右移动它才能得到
0
1
。 然后,将其置于BH并移动到所需的位置,即字节
0
7
、字节
1
6
,依此类推。然后
到我们的最终结果和
INC
DEC
所需的内容。不要忘记条件跳转,并为下一个循环弹出
AX


结果将以CH.

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

mov al, 10101110
mov ecx, 8
我们将8放入ecx循环中

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

loop1:
sal al, 1;           
在进位标志中,现在是从左开始的最后一位

rcr bl, 1;           
现在你在bl中添加你在carry中的内容

loop loop1

这就是全部

下面的代码使用旋转和移位。我使用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的见解。

有更为粗糙的方法:(在C中,但可以在汇编中完成…)实际上汇编比C更容易,因为您有旋转进位。将一位移位到进位标志中,然后执行类似于adc same,same的操作,将进位标志移位到寄存器的底部。好的,我知道了如何使用移位和旋转来实现。然而,我们可以因为拥有最高效的代码而获得额外的荣誉。他不在乎我们怎么做。我真的不知道如何查找表。我以前在研究这个问题的答案时读过一些关于它们的书,但我真的不知道如何实现它们。假设你的程序在它的生命周期中将要做无数的位反转。当您启动程序时,您只需按位旋转执行所有256种可能的操作,并将结果存储在256字节的连续内存中,例如从基开始。现在,每当需要翻转寄存器的位时,只需查看(基+值)。这是一个查找表(LUT)。如果可以预计算,甚至可以将LUT硬编码到程序集中,作为256个常量的块。那么就不需要初始化了。为了节省256字节表的空间,您可以使用一个16字节的表,一次包含四位(半字节)的值。然后,算法将是“revval=revdigit[inval&0x0f]4]”。如果我是教授,我喜欢两个部分,一个在索引中,另一个在索引外。你不需要慢的
rcl
;您可以使用adc ax,ax
。两者都是2字节(在16位模式下),在现代CPU上,
adc
更快。您在shl eax,1和adc al,0方面的细分是错误的:它将是
shl ax,1
adc ax,0<