还是那个题,这回又碰到个循环左移
,有挺多操作方法之前都没有系统的学,用到的时候再看看感觉还挺好,不耽误事
0x00 基本介绍
ROL(Rotate Left):
循环左移,它有两个操作数:
第一个操作数是目标操作数,这里为
eax
(32
位寄存器)。第二个操作数指定循环移位的次数,这里为
cl
(8
位寄存器,是ecx
的低8
位)。
指令格式:rol dest, count
该指令的功能是将 eax
中的值循环左移 cl
寄存器中指定的位数。循环左移的意思是,移出的位不仅会进入进位标志(CF
),而且还会从右侧移入。
0x01 实践
push eax,0xD7E1825A
push ecx,1
rol eax,cl
最后eax
的值是0xAFC304B5
左移1
位:bit30
-bit0
成为新值的bit31
-bit1
,而原始bit31
成为新值的bit0
,所以0xD7E1825A
循环左移1
位:
二进制:1101 0111 1110 0001 1000 0010 0101 1010
左移1
位(循环):101 0111 1110 0001 1000 0010 0101 1010 1
-> 最后补上移出的1
得到:10101111 11000011 00000100 10110101 -> 0xAFE304B5
C
实现如下:
#include <stdio.h>
#include <stdint.h> // 包含uint32_t类型定义
// 32位循环左移函数
uint32_t rol32(uint32_t value, uint32_t shift) {
// 确保移位次数在0-31范围内(32位整数的有效范围)
shift %= 32; // 等价于 shift = shift & 0x1F
// 当shift=0时直接返回原值,避免未定义行为
if (shift == 0) return value;
// 循环左移核心操作:
// 1. 将value左移shift位(高位被移出)
// 2. 将value右移(32 - shift)位(获取被移出的高位)
// 3. 使用按位或组合两部分
return (value << shift) | (value >> (32 - shift));
}
int main() {
uint32_t eax = 0xd7e1825a;
uint32_t cl = 1; // 移位次数
uint32_t result = rol32(eax, cl);
printf("原始值: 0x%X\n", eax);
printf("循环左移%x位后: 0x%X\n", cl, result);
return 0;
}
0x02 扩展
ROL(Rotate Left)
: 循环左移, 高位到低位并送 CF
ROR(Rotate Right)
: 循环右移, 低位到高位并送 CF
RCL(Rotate through Carry Left)
: 带进位循环左移,进位值(原CF
)到低位, 高位进CF
RCR(Rotate through Carry Right)
: 带进位循环右移, 进位值(原CF
)到高位, 低位进CF
以RCR举例
操作数:32位寄存器(如 EAX)
移位次数:由 CL 寄存器指定
移位过程:
1、最低位移入进位标志(CF)
2、原进位标志(CF)移入最高位(MSB)
3、中间位依次右移
移位范围:0-31 位
标志位影响:
CF:设置为最后移出的位
OF:当移位次数=1时,设置为最高两位的异或;否则无定义