Oracle字母移位,汇编总结:左移,右移指令

1.左移指令和右称指令的种类及作用:

左移指令作用:左移指令将操作数的bit位向左移动n位,空出来的位用0填充。

左移指令包含sal和shl,这两条指令的作用是相同的,空出来的位用0填充。

其中左移sal的指令用法:

.section .text

.global _start

_start:

movb $0b11111111, %al  #8字节

salb $3, %al

movw $0b11111111, %ax  #16字节

salw $3, %ax

movl $0b11111111, %eax #32字节

sall $3, %eax

movq $0b11111111, %rax #64字节

salq $3, %rax

其中左移shl的指令用法:

.section .text

.global _start

_start:

movb $0b11111111, %al #1个字节

shlb $3, %al

movw $0b11111111, %ax #2个字节

shlw $3, %ax

movl $0b11111111, %eax #4个字节

shll $3, %eax

movq $0b11111111, %rax #8个字节

shlq $3, %rax

右移指令作用:右移指令将操作数的bit位向右移动n位,sar执行算术移位(填上符号位),而shr执行逻辑移位(填上0).移位操作的目的操作数可以是一个寄存器或是一个存储器位置。

右移指令sar和shr

其中右移sar的指令用法,sar右移会用符号位填充,如果符号位是1,就填充1,如果是0就填充0。

.section .text

.global _start

_start:

movb $0b01111111, %al #符号位是0

sarb $3, %al

movb $0b11111111, %al #符号位是1

sarb $3, %al

movw $0x7FFF, %ax

sarw $3, %ax

movw $0xFFFF, %ax

sarw $3, %ax

movl $0x7FFFFFFF, %eax

sarl $3, %eax

movl $0xFFFFFFFF, %eax

sarl $3, %eax

movq $0x7FFFFFFFFFFFFFFF, %rax

sarq $3, %rax

movq $0xFFFFFFFFFFFFFFFF, %rax

sarq $3, %rax

其中右移sar的指令用法,shr始终填充0

.section .text

.global _start

_start:

movb $0b01111111, %al #符号位是0

shrb $3, %al

movb $0b11111111, %al #符号位是1

shrb $3, %al

movw $0x7FFF, %ax

shrw $3, %ax

movw $0xFFFF, %ax

shrw $3, %ax

movl $0x7FFFFFFF, %eax

shrl $3, %eax

movl $0xFFFFFFFF, %eax

shrl $3, %eax

movq $0x7FFFFFFFFFFFFFFF, %rax

shrq $3, %rax

movq $0xFFFFFFFFFFFFFFFF, %rax

shrq $3, %rax

2.C语言中的同类操作符:

左移操作符是>>  用法value >> 1

右移操作符是<<  用法value << 1

注意:

在c标准里说明无符号值执行的所有移位操作都是逻辑移位,但对于有符号值,到底是采用逻辑移位还是算术移位取决于编译器。

3.练习:

练习题摘自《c和指针》第5章操作符和表达式

3.1.请编写函数

unsigned int reverse_bits(unsigned int value);

这个函数的返回值是把value的二进制位模式从左到右变换一下后的值。例如,在32位机器上,25这个值包含了下列各个位:

00000000000000000000000000011001

10011000000000000000000000000000

汇编code:

.section .text

.global reverse_bits

.type reverse_bits, @function

reverse_bits:

xorl %eax, %eax

movl $32, %ecx

reverse_bits_start:

cmpl $0, %ecx

je reverse_bits_end

shll $1, %eax

movl %edi, %esi

andl $1, %esi

orl  %esi, %eax

shrl $1, %edi

decl %ecx

jmp reverse_bits_start

reverse_bits_end:

ret

c测试代码

#include 

#include 

extern int reverse_bits(unsigned int ui);

int main() {

unsigned u;

u = reverse_bits(0x7fffffff);

assert(u == 0xfffffffe);

printf("u(%x)\n", u);

u = reverse_bits(0x00ffffff);

assert(u == 0xffffff00);

printf("u(%x)\n", u);

u = reverse_bits(0xffff00ff);

assert(u == 0xff00ffff);

printf("u(%x)\n", u);

u = reverse_bits(0xffffff00);

assert(u == 0x00ffffff);

printf("u(%x)\n", u);

u = reverse_bits(0xff00ffff);

assert(u == 0xffff00ff);

printf("u(%x)\n", u);

return 0;

}

3.2.编写一组函数,实现位数组。函数的原型应该如下:

void set_bit(char bit_array[], unsigned bit_number);

void clear_bit(char bit_array[], unsigned bit_number);

void assign_bit(char bit_array[], unsigned bit_number, int value);

int test_bit(char bit_array[], unsigned bit_number);

每个函数的第1个参数是个字符数组,用于实际存储所有的位。第2个参数用于标识需要访问的位。函数的调用者必须确保这个值不要太大,以至于超出数组的边界。

第1个函数把指定的位设置为1。

第2个函数则把指定的位清零。

如果value的值为0,第3函数把指定的位清0,否则设置为1.

至于最后一个函数,如果参数中指定的位不是0,函数就返回真,否则就返回假。

汇编code:

.section .text

.global set_bit

.type set_bit, @function

set_bit:

movl %esi, %edx

shrl $3, %edx

movb (%rdi, %rdx, 1), %r8b

movb $1, %r9b

movb %sil, %cl

andb $7, %cl

shlb %cl, %r9b

orb %r8b, %r9b

movb %r9b, (%rdi, %rdx, 1)

ret

.global clear_bit

.type clear_bit, @function

clear_bit:

movl %esi, %edx

shrl $3, %edx

movb (%rdi, %rdx, 1), %r8b

movb $1, %r9b

movb %sil, %cl

andb $7, %cl

shlb %cl, %r9b

notb %r9b

andb %r8b, %r9b

movb %r9b, (%rdi, %rdx, 1)

ret

.global test_bit

.type test_bit, @function

test_bit:

movl %esi, %edx

shrl $3, %edx

movb (%rdi, %rdx, 1), %r8b

movb $1, %r9b

movb %sil, %cl

andb $7, %cl

shlb %cl, %r9b

andb %r8b, %r9b

movl $0, %eax #返回假

cmpb $0, %r9b

je test_bit_false

movl $1, %eax #返回真

test_bit_false:

ret

.global assign_bit

.type assign_bit, @function

assign_bit:

cmpl $0, %edx

je call_clear_bit

call set_bit

jmp assign_bit_end

call_clear_bit:

call clear_bit

assign_bit_end:

ret

c测试代码:

#include 

#include 

extern void set_bit(char arr[], unsigned int bit_number);

extern void clear_bit(char arr[], unsigned int bit_number);

extern int  test_bit(char arr[], unsigned int bit_number);

extern void assign_bit(char arr[], unsigned int bit_number, int value);

void test_one_bit() {

printf("test one bit start...\n");

unsigned char c = 0;

set_bit(&c, 1);

assert(test_bit(&c, 1) == 1);

clear_bit(&c, 1);

assert(test_bit(&c, 1) == 0);

assign_bit(&c, 1, 1);

assert(test_bit(&c, 1) == 1);

assert(c == 2);

assign_bit(&c, 1, 0);

assert(test_bit(&c, 1) == 0);

assert(c == 0);

}

void test_byte() {

printf("test one byte start...\n");

unsigned char c = 0;

int i;

for (i = 0; i 

set_bit(&c, i);

}

assert(c == 0xff);

for (i = 0; i 

assert(test_bit(&c, i) == 1);

}

for (i = 0; i 

clear_bit(&c, i);

}

assert(c == 0);

for (i = 0; i 

assign_bit(&c, i, 1);

}

assert(c == 0xff);

for (i = 0; i 

assign_bit(&c, i, 0);

}

assert(c == 0);

}

void test_two_byte() {

printf("test two byte start...\n");

unsigned short s = 0;

int i;

for (i = 0; i 

set_bit((char *)&s, i);

}

assert(s == 0xffff);

for (i = 0; i 

assert(test_bit((char *)&s, i) == 1);

}

for (i = 0; i 

clear_bit((char *)&s, i);

}

assert(s == 0);

for (i = 0; i 

assign_bit((char *)&s, i, 1);

}

assert(s == 0xffff);

for (i = 0; i 

assign_bit((char *)&s, i, 0);

}

assert(s == 0);

}

int main() {

test_one_bit();

test_byte();

test_two_byte();

//test_xxoo();

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值