我在微处理器课上,我们在飞思卡尔 CodeWarrior 中使用汇编语言对 68HCS12 微控制器进行编程。我们本周的任务是反转一个字节,因此如果字节为 00000001,则输出将为 10000000,或 00101011 到 11010100。我们必须使用汇编语言,并被告知我们可以使用旋转和移位(但不限于! ) 来完成这项任务。我真的不知道应该从哪里开始。
9 回答
提示:如果您进行移位,一位会被移出,而零(可能)会被移入。移出的位会去哪里?您需要将其移入目标寄存器或内存地址的另一端。
我敢肯定,25 年前我可以在没有汇编程序的情况下用 Z80 机器代码做到这一点:)
将两个寄存器视为位堆栈。如果您一次将一点从一处移动到另一处,会发生什么?
如果您可以节省 256 字节的额外代码大小,查找表可能是在 68HCS12 上反转字节的最有效方法。但我很确定这不是你的导师所期望的。
对于“正常”解决方案,请单独考虑数据位。旋转和移位允许您移动位。对于第一个解决方案,隔离八位(使用按位“与”操作),将它们移动到它们的目标位置(移位、旋转......),然后再次将它们组合在一起(使用按位“或”操作)。这将不是最有效或最简单的实现,但您应该首先专注于获得正确的结果——优化可以等待。
当您进行右移时,最低有效位进入进位标志。
当您进行循环时,进位标志用于填充结果的空位(LSB 表示 ROL,MSB 表示 ROR)。
首先,制定出你需要做的事情的算法。将其表达为伪代码或 C 或纯英语或图表或任何你喜欢的东西。一旦你清除了这个概念上的障碍,实际的实现应该非常简单。
您的 CPU 可能具有可让您移位和/或旋转寄存器的指令,可能包括进位标志作为附加位。这些说明将非常有用。
例如,如果您有所有字节数,最简单的方法是
mov al, 10101110
mov ecx, 8
我们将 8 放入 ecx for 循环
mov ebx, 0
在bl中我们将得到结果,我们将制作ebx,只是为了看看会发生什么更好
loop1:
sal al, 1;
现在在进位标志中,您有左起最后一位
rcr bl, 1;
现在你在 bl 中添加你携带的东西
loop loop1
就这样
这是一条评论,但我认为 WTH!
为了节省 256 字节表的空间,您可以有一个 16 字节表,一次包含四个位(半字节)的值。那么算法将是
revval=(revdigit[inval&0x0f]<<4)|
revdigit[inval>>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
等等。当你AND
用 AL 做一个时,你得到或类似的0
东西,100
或者10000
你必须把它移到右边才能得到它。然后,将其放入 BH 并移动到所需的位置,即for byte ,for byte等等。然后是我们的最终结果以及什么是必要的。不要忘记条件跳转并弹出下一个循环:)0
1
7
0
6
1
OR
INC
DEC
AX
结果将在 CH 中。
以下代码使用旋转和移位。我使用 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 的见解。