有人可以像我五岁一样向我解释ARM的移位吗?我对涉及非十进制数系统的任何事物的理解都很差,因此对我来说,很难理解移位和按位运算符的概念。下列每种情况会做什么,为什么?(在R3中会发生什么,在位级别上幕后会发生什么)?/** LSL **/mov r0, #1mov r3, r0, LSL#10/** LSR **/mov r0, #1mov r3, r0, LSR#10/** ORR **/mov r0, #1mov r1, #4orr r3, r1, r0/** AND **/mov r0, #1mov r1, #4and r3, r1, r0/** BIC **/mov r0, #1mov r1, #4bic r3, r1, r0PS。不要用C位运算符来解释它。我也不知道他们在做什么(>>,<<,|,&)。 最佳答案 真值表,两个输入,左边两个数字,一个输出,右边数字:要么a b c0 0 00 1 11 0 11 1 1左侧的两个输入a和b代表输入的四种可能的组合,但也不少于列表。考虑1表示真,0表示假。并且在这种情况下,单词OR表示如果OR b为true,则c为true。从表中可以看出,如果a或b为true,则水平为c。和a b c0 0 00 1 01 0 01 1 1并且意味着如果a和b都为真,则c和true都必须为真。上面只有一种情况。现在取两个字节0x12和0x34,十进制分别是18和52,但我们并不十分在意十进制。我们关心二进制0x12是0b00010010,而0x34是0b00110100。汇编语言中的AND和OR和XOR之类的按位运算符意味着您从每个操作数中取一位,并在相同的位位置给出结果。它不像加在您有类似这样的东西的地方,等等。所以我们排位0b00010010 0x120b00110100 0x34因此,将头向侧面倾斜,就像您要从左手握着的炸玉米饼中咬一口,然后可视化上面的真相表。如果我们看一下右边的两位,分别是0和0,接下来的两位是1和0,依此类推。因此,如果我们要执行“或”运算,则规则是a或b为真,则结果c为真 0b00010010 0b00110100OR ========== 0b00110110头向右倾斜,最低有效位(数字中“ one”列中的位)为0或0 = 0,均未设置。下一列(二进制列)1或0 = 1至少一个为true。依此类推0x12或0x34 = 0x36在手臂组装中mov r0,#0x12mov r1,#0x34orr r2,r0,r1在or运算r2之后,其值将保持为0x36。现在让我们和那些数字 0b00010010 0b00110100AND ========== 0b00010000记住我们的真值表和规则a和b都必须为真(a 1),我们将头向右倾斜,0和0为0,两者都不为真。通过检查,只有一列的两个输入都带有1,即16s列。这给我们留下了0x12 AND 0x34 = 0x10在手臂组装中mov r0,#0x12mov r1,#0x34and r2,r0,r1现在我们进入BIC指令。哪个代表逐位清除,希望一点点有意义。手臂上的Bic是a,而不是b。不是另一个真值表,而是只有一个输入和一个输出不a c0 11 0仅使用一个输入,我们只有两个选择0和1,1为true,0为false。 NOT表示如果不是a,则c为真。当a不为真时c为真,当a为真时c不成立。基本上它会反转。bic所做的是有两个输入a和b,运算为c = a AND(不是b),因此该值的真值表为:a AND(非b)a b c0 1 00 0 01 1 01 0 1我先从AND真值表开始,然后注意b位,其中AND真值表中的b为0,我将其设为1,而AND真值表中的b为1,我将其设为0。所以在0x12和0x34上的bic操作是 0b00010010 0b00110100BIC ========== 0b00000010为什么叫位清除?了解这一点将使其更容易使用。如果您查看真值表并考虑第一和第二输入。如果第二个输入b为1,则输出为0。第二个输入b为0,则输出本身未经修改。因此,真值表或操作所执行的操作是说将b的任何位置清零或将A中的那些位清零。因此,如果我将数字0x1234设为零并且希望将低8位清零,则将BIC设为0x00FF。您的下一个问题是,为什么不与0xFF00相加呢? (分析AND真值表,可以看到b等于1时,将a值保持不变,b等于0时,则将输出归零)。至少在传统上,ARM使用32位寄存器和固定的32位指令集。立即指示mov r0,#0x12在手臂中,将8个非零位限制在数字内的任何位置,将移入一位。因此,如果我的值为0x12345678,并且想将低8位清零,则可以这样做; assume r0 already has 0x12345678bic r0,r0,#0xFF要么; assume r0 already has 0x12345678mov r1,#0xFF000000orr r1,r1,#0x00FF0000orr r1,r1,#0x0000FF00;r1 now contains the value 0xFFFFFF00and r0,r0,r1要么; assume r0 already contains 0x12345678ldr r1,my_byte_maskand r0,r0,r1my_byte_mask: .word 0xFFFFFF00与使用移动和两个orr相比,这并不可怕,但是与bic解决方案相比,它仍然消耗更多的时钟周期,因为您消耗了从ram读取my_byte_mask的额外内存周期,这可能需要一段时间。要么; assume r0 already contains 0x12345678mvn r1,#0xFFand r0,r0,r1这最后一个可以妥协。请注意,arm文档中的mvn不是按位的,即rx = NOT(immediate)。立即数为0xFF。 NOT(0xFF)意味着将所有位取反,这是我们要使用的32位寄存器,因此意味着0xFFFFFF00是NOT(0xFF)的结果,这是在执行and之前寄存器r1得到的结果。这就是为什么bic在ARM指令集中占有一席之地的原因,因为有时使用bic指令而不是and指令进行屏蔽(mask = AND用于使某些位为零)时需要较少的指令或时钟周期。我使用“掩码”一词作为一个概念,使数字中的零为零,而其他零星则为零。可以将orring视为在第一个数字中创建位,而其他数字则保持不变,如果您在b等于1的任何时候查看OR真值表,那么c就是1。因此0x12345678 OR 0x000000FF导致第二个位为0x123456FF设置了操作数。是的,每当在OR真值表中设置a然后设置输出,这也是正确的,但是在很多时候,当您使用这些按位运算时,您就有一个操作数想要设置,设置一定数量的位设置为1而不修改其余部分,或将某个位数设置为零而不修改其余部分,或者您想将除一定位数之外的所有位清零。当以这种方式使用时,您将要在其中操作一个操作数,然后根据您想要的整体效果创建第二个操作数,例如在C中,如果我们只想保留较低的字节,则可以具有一个参数输入,一个参数输出功能:unsigned int keep_lower_byte ( unsigned int a ){ return(a&(~0xFF));}〜表示不是〜0xFF,因为32位数字表示0xFFFFFF00,然后&表示AND,所以我们返回&0xFFFFFF00。一个是唯一出现的实际操作数,我们根据想要执行的操作发明了第二个操作数...大多数按位操作都可以在指令中交换操作数,一切都可以,就像ARM的bic这样的指令,尽管操作数是按照一定的顺序,就像减法一样,您必须使用正确的操作数顺序。移位...有两种,逻辑的和算术的。逻辑最简单,这就是在C语言中使用>>或以0x12开头,即0b00010010。向左移动三个位置(0x12 00010010 < our original number 0x120010010x < shift left one bit location010010xx < shift left another bit location10010xxx < shift left a third bit location哪些位“移入”到空位(上面的x)取决于操作。对于C编程,它始终为零:00010010 < our original number 0x1200100100 < shift left one bit location01001000 < shift left another bit location10010000 < shift left a third bit location但是有时(通常每个指令集都支持轮换和移位)还有其他移位方式,差异与您移入空白处的位有关,有时移至末尾的位并不总是只是消失了,有时您将其保存在特殊的刀柄位置。有些指令集只有一个位移位,这意味着对于您编写的每条指令,您只能位移一位,因此上述指令将是3条指令,一次一位。其他指令集(例如arm)允许您使用一条指令,并在指令中指定要在该方向上移动多少位。所以左移三mov r0,#0x12mov r3,r0,lsl#3 ; shift the contents of r0 3 bits to the left and store in r3在lsr和asr,逻辑右移和算术右移之间演示了这种移入方式的变化(您会看到没有asl,算术左移,因为这没有任何意义,某些汇编程序将允许您使用asl指令但将其编码为lsl)。逻辑右移:00010010 - our original number 0x12x0001001 - shifted right one bitxx000100 - shifted right another bitxxx00010 - shifted right another bit与C一样,有一个版本会向右移零,即逻辑右移,即向右移零00010010 - our original number 0x1200001001 - shifted right one bit00000100 - shifted right another bit00000010 - shifted right another bit算术右移意味着保留“符号位”是什么符号位?变成二进制补码,如果没有,您还需要学习。基本上,如果您认为位模式/值是二进制补码,那么最高有效位(左边的一位)就是符号位。如果为0,则数字为正数;如果为1,则数字为负数。您可能已经注意到,左移一位等于乘以2,右移等于除以2。0x12 >> 1 = 0x9,18 >> 1 = 9但是如果我们移位右边的负2,负2是使用字节的0xFE或0b11111110。使用C样式的逻辑右移0xFE >> 1 = 0x7F,或十进制-2 >> 1 = 0x127。不幸的是,我们无法在C中通过一次操作解决该问题,但是在汇编中,我们可以使用算术移位,假设您的指令集有一个,而机械臂则算术右移s1100100 - our starting value s is the sign bit whatever that is 0 or 1ss110010 - one shift rightsss11001 - another shift rightssss1100 - another shift right因此,如果在开始时符号位s为0,则数字为01100100,则01100100 - our starting value00110010 - one shift right00011001 - another shift right00001100 - another shift right但是如果那个符号位是一个11100100 - our starting value11110010 - one shift right11111001 - another shift right11111100 - another shift right我们可以解决右移0xFE的问题:11111110 - 0xFE a minus 2 in twos complement for a byte11111111 - shifted right one因此在伪代码0xFE ASR 1 = 0xFF中,-2 ASR 1 = -1。 -2除以2 = -1您需要自己阅读的最后一件事与旋转和/或移位到末端的钻头发生了什么有关。右移lsbit移到数字的“末尾”,例如滑动表的块,而掉落的那个可能只是进入“位桶”(以太,天堂或地狱,其中一些位当他们从这个世界消失时去死)。但是某些指令集中的某些指令会将该位移开并将其放入进位标志(在加法和减法中读取),不是因为它一定是进位,而是因为alu和进位位中有状态位是有点道理的现在轮换是,假设您有一个8位处理器,并旋转了一位,从末端掉落的位落入了进位位,而另一侧的位移位就是进位前的进位位操作。基本上是音乐椅,剩下的一个人站着,钻头在椅子上走来走去,站着的人是进位钻头,椅子上的人是寄存器中的钻头。为什么这很有用?假设我们有一个8位处理器,例如Atmel AVR,但想进行64位转换。 64位需要8个,8位寄存器,比如说我在这8个寄存器中有我的64位数字,我想左移64位。我将从最低有效字节开始,然后执行一个lsl,它将一个零移入,但移出的位进入进位位。然后下一个最高有效字节我进行滚动操作,向左旋转一位,进入的位是前一个字节的出位,而出去的位进入进位位。我对其他字节重复rol指令,看一下16位移位:00100010 z0001000 - our original number00100010 z 0001000 - lsl the least significant byte, the ms bit z is in carry0100010z 00010000 - rotate left the most significant byte pulling the z bit from carry00100010z0001000 - if it had been a 16 bit register0100010z00010000 - a logical shift left on a 16 bit with a zero coming in on the left这就是旋转的目的,这就是为什么汇编手册费心地告诉您在执行逻辑操作时修改了哪些标志。关于arm - 有人可以向我解释ARM按位操作吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9044803/
10-12 23:13