assembly 带extend的循环移位有什么用?

1wnzp6jl  于 2023-01-17  发布在  其他
关注(0)|答案(4)|浏览(130)

我记得在一堂汇编课上,我们学习了m68k处理器,有3种移位可以做,线性移位,循环移位,带扩展的循环移位。
最后一种是循环移位扩展,基本上是将所有位向左或向右旋转,但它将最外面的位放入扩展位,然后再将其移到开头(如果您再次移位1)。
我画了一张小照片:

基本上,第33位用于循环移位,但不会出现在32位字中。第33位是处理器的X标志,代表扩展。您可以很容易地使用任何状态标志,如进位标志,但我猜摩托罗拉的人希望保留该标志,这样它就不会被覆盖。以防你需要进位标志来完成它的正常任务,在一些算法的中间,也需要用扩展来旋转。
不管怎样,rotate with extend的目的是什么?它有什么用?它有什么用?它看起来很奇怪。你到底为什么需要第33位?
我读过thisthis,两个相关的问题,但是他们没有讨论循环移位和extend
我知道正规移位的一些用途,基本上是除以2,或者测试可分性,以及置换随机位,诸如此类的东西,但是我想不出为什么你需要在循环中插入一些扩展位,但是在结果中却没有出来。

**编辑:**我对它的任何用途都感兴趣,无论是现代的还是古老的,不管它是否在m68k上。m68k只是我第一次遇到它(我甚至从来没有在那里用过它)。

emeijp43

emeijp431#

假设您想将一个32位字向右移位,但您只有16位寄存器,为此,您必须将32位字的两个16位部分向右移位,并将从高位字移出的位转移到低位字。
如果你只有逻辑移位,这是很麻烦的,因为你必须手动修复那个位。循环进位指令允许你把需要转移的位保留在进位标志中,然后一次把它移进去。循环进位指令把移出的位放在进位标志中,这样你就可以很容易地把它们链接在一起,右移任意大小的数据。

izj3ouym

izj3ouym2#

在x86(以及大多数有此指令的架构)上,多出来的位是进位标志,很多东西都可以设置这个标志。左循环进位或右循环进位让你可以将进位位移回其他寄存器。有趣的是,m68 k为扩展循环使用了不同的标志。
我对m68 k已经不是很熟悉了,所以我主要会谈论其他的拱门。(但显然这就是你想要的:)
类似这样的指令通常可以在功能远低于x86或m68 k的微控制器上使用。或者在操作码空间有限(以及解码复杂度有限)的情况下,一些CPU * 只有 * 一个循环进位1指令,而没有常规移位指令。如果你想移入零,请首先确保标志被清除。
8051是这样的:仅左/右旋转1,带进位左/右旋转1,不移位。请参阅伊萨参考手册中的rlc。如果可能,请避免使用clr指令,将rlc放在使进位清零的其他内容之后,以便移入零。
我认为扩展循环移位使用进位标志是很典型的,而不是像m68 k那样使用自己的X位。
无论如何,扩展精度旋转是一种传统的/预期的CPU,但有更多的使用更有限的CPU。
对于寄存器,rcl reg, 1adc reg,reg的运算相同:将旧内容左移1,并将低位设置为CF。由循环移位或ADC移出的位成为CF的新值。因此,如果RCL可用于内存操作数,或者(在某些奇怪的情况下)计数大于1,则RCL只是指令集的非冗余部分。(不过,右循环移位版本不是冗余的)
IDK为什么要使用count〉1。在现代x86上,循环进位在count=1时相当快,但在变量计数或固定计数〉1时肯定很慢。IDK鸡/蛋问题的方向是什么:CPU设计师没有让它变快,因为无论如何都没有人使用它,或者人们停止使用它是因为它太慢,但可能是前者,因为我不记得曾经看到过循环进位的使用超过1位。
对于扩展精度移位,x86具有双移位指令(shld/shrd dst, src, count),用于移位dst,从src移入位,而不是零或符号位的副本。它不适用于2个内存操作数,因此扩展精度移位循环必须使用单独的指令来加载和存储寄存器。这比使用rcr dword [edi], 1/的循环的代码大小要大。sub edi, 4,但在现代的x86上,代码大小几乎不是问题,而且使用单独的指令执行加载/存储也不会变慢。)更重要的是,shrd一次移位多个位,因此您可以在数组上循环一次,以实现2位或更多位的多精度移位。
扩展循环每次只能在寄存器之间移位一位,因为它使用1位的存储空间(在标志中)。我认为在m68 k上,如果你确实想在寄存器之间移位多位,你可能会复制一个寄存器,并使用常规的移位+或来合并。(或者循环和AND/OR来分割位。)
在AMD处理器上,shld/shrdrcl/rcr慢1倍,但在英特尔处理器上则相反(http://agner.org/optimize/)。
除了在寄存器之间移位之外,我实在想不出其他任何用例。也许如果你移出一个位,然后分支到可能设置或清除X位的某个位置,然后再移入位,你可以使用扩展的循环来对低位或高位做一些事情。但是你通常可以更容易地用AND、OR或XOR与一个常数做同样的事情。

ej83mcc0

ej83mcc03#

ROXL对于非破坏性测试位非常有用,与BTST.x指令(仅适用于8位和32位)相比,可以保存相当多的指令。一旦你这样做了,循环不止一个位置也可以使像跳过位这样的事情成为可能。

ROXL.W #4,D0      ; shift bit 12 into carry and X
  BCC.S isNotSet    ; branch if bit is not set
  BSR isSet         ; do whatever you want
isNotSet:
  ROXL.W #11,D0     ; rotate around to reset to previous value
z31licg0

z31licg04#

它也被用于扩展精度的乘法和除法运算,因为这些运算基本上是加法(或减法)和移位,这也意味着我们可以做一些很酷的事情,比如:

ADD eax, ebx
RCR eax, 1

来计算2个整数的平均值。
有一个用256字节编写的汇编演示程序,它使用RCL寄存器CL作为工具,仅用2字节计算随机数。

相关问题