存儲程序式計算機以二進制來表示數據和指令。所以,我們可以對二進制位進行一些操作。
這些操作包括了與(&),或(|),異或(^),取反(~),算術左移(<<),邏輯左移(<<),算術右移(>>),邏輯右移(>>)。
與
與運算 | 0 | 1 |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
可以用與操作來屏蔽某些位。
#include <stdio.h>
int main(void)
{
int a=100;
int b=0xfffffff0;
int c=a&b; //相當於a減去a%16的值
printf("value=%d\n",c);
c=a&0xfffffff0;
printf("value=%d\n",c);
return 0;
}
彙編代碼
.section .rodata
.LC0:.string "value=%d\n"
.text
.global main
main:
pushl %ebp
movl %esp,%ebp
subl $12,%esp
movl $100,-4(%ebp);a
movl $0xfffffff0,-8(%ebp);b
movl -4(%ebp),%eax
andl -8(%ebp),%eax
movl %eax,-12(%ebp);c
pushl -12(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl -4(%ebp),%eax
andl $0xfffffff0,%eax
movl %eax,-12(%ebp)
pushl -12(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl $0,%eax
leave
ret
movl $100,-4(%ebp) 將a賦值爲100,movl $0xfffffff0,-8(%ebp) 將b賦值爲0xfffffff0,movl -4(%ebp),%eax 賦值a爲%eax,andl -8(%ebp),%eax b與%eax(a)的值相與,並將結果放入%eax中,movl %eax,-12(%ebp) 將與的結果放入c中。
andl $0xfffffff0,%eax 將0xfffffff0與%eax相與,並將結果放入%eax中。
用到的指令有
指令 | 效果 | 描述 |
---|---|---|
AND S,D | D<-D&S | 與 |
或
或運算 | 0 | 1 |
---|---|---|
0 | 0 | 1 |
1 | 1 | 1 |
可以用於設置某些位。
#include <stdio.h>
int main(void)
{
int a=0xfffffff0;
int b=0xe;
int c=a|b; //相當於a減去a%16的值
printf("value=%d\n",c);
c=a|0xe;
printf("value=%d\n",c);
return 0;
}
彙編代碼
.section .rodata
.LC0:.string "value=%d\n"
.text
.global main
main:
pushl %ebp
movl %esp,%ebp
subl $12,%esp
movl $0xfffffff0,-4(%ebp);a
movl $0xe,-8(%ebp);b
movl -4(%ebp),%eax
orl -8(%ebp),%eax
movl %eax,-12(%ebp);c
pushl -12(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl -4(%ebp),%eax
orl $0xe,%eax
movl %eax,-12(%ebp)
pushl -12(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl $0,%eax
leave
ret
movl $0xfffffff0,-4(%ebp) 賦值a爲0xfffffff0,movl $0xe,-8(%ebp) 賦值b爲0xe,movl -4(%ebp),%eax 將a放入%eax中。orl -8(%ebp),%eax a與b相或,結果放入%eax中。movl %eax,-12(%ebp) 結果放入c中。
orl $0xe,%eax 將%eax與0xe相或,結果放入%eax中。
用到的指令有
指令 | 效果 | 描述 |
---|---|---|
OR S,D | D<-D | S |
異或
異或運算 | 0 | 1 |
---|---|---|
0 | 0 | 1 |
1 | 1 | 0 |
可以用異或操作來翻轉某些位。
#include <stdio.h>
int main(void)
{
int a=100;
int b=100;
int c=a^b; //相當於a減去a%16的值
printf("value=%d\n",c);
c=a^100;
printf("value=%d\n",c);
return 0;
}
彙編代碼
.section .rodata
.LC0:.string "value=%d\n"
.text
.global main
main:
pushl %ebp
movl %esp,%ebp
subl $12,%esp
movl $100,-4(%ebp);a
movl $100,-8(%ebp);b
movl -4(%ebp),%eax
xorl -8(%ebp),%eax
movl %eax,-12(%ebp);c
pushl -12(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl -4(%ebp),%eax
xorl $100,%eax
movl %eax,-12(%ebp)
pushl -12(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl $0,%eax
leave
ret
movl $100,-4(%ebp) 賦值a爲100,movl $100,-8(%ebp) 賦值b爲100,movl -4(%ebp),%eax 將a放入%eax中。xorl -8(%ebp),%eax a與b相異或,結果放入%eax中。movl %eax,-12(%ebp) 結果放入c中。
xorl $100,%eax 將%eax與100相異或,結果放入%eax中。
用到的指令有
指令 | 效果 | 描述 |
---|---|---|
XOR S,D | D<-D^S | 異或 |
取反
取反運算 | 0 | 1 |
---|---|---|
1 | 0 |
可以用取反獲取原值各位取反的結果,例如0x1的取反結果爲0xfffffffe。
#include <stdio.h>
int main(void)
{
int a=0x55555555;
int b=~a; //相當於a減去a%16的值
printf("value=%d\n",b);
return 0;
}
彙編代碼
.section .rodata
.LC0:.string "value=%d\n"
.text
.global main
main:
pushl %ebp
movl %esp,%ebp
subl $8,%esp
movl $0x55555555,-4(%ebp);a
movl -4(%ebp),%eax
notl %eax
movl %eax,-8(%ebp);b
pushl -8(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl $0,%eax
leave
ret
subl $8,%esp 申請了8個字節,用於存放a,b。movl $0x55555555,-4(%ebp) 將0x55555555賦值給a,movl -4(%ebp),%eax 將a的值賦值給%eax,notl %eax 取反%eax,movl %eax,-8(%ebp) 將取反的結果放入b中。
用到的指令有
指令 | 效果 | 描述 |
---|---|---|
NOT D | D<-~D | 取反 |
算術左移和邏輯左移
向左移動二進制位。如 0xf << 4=0xf0。算術左移和邏輯左移的效果是相同的,可以相互替換。
#include <stdio.h>
int main(void)
{
int a=0xf;
int b=4;
int c=a<<b;
printf("value=%d\n",c);
c=a<<4;
printf("value=%d\n",c);
}
彙編代碼
.section .rodata
.LC0:.string "value=%d\n"
.text
.global main
main:
pushl %ebp
movl %esp,%ebp
subl $12,%esp
movl $0xf,-4(%ebp);a
movl $4,-8(%ebp);b
movl -4(%ebp),%eax
movl -8(%ebp),%ecx
shll %lc,%eax
movl %eax,-12(%ebp);c
pushl -12(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl -4(%ebp),%eax
shll $4,%eax
movl %eax,-12(%ebp)
pushl -12(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl $0,%eax
leave
ret
movl $0xf,-4(%ebp) 將0xf賦值給a,movl $4,-8(%ebp) 4放入b中,movl -4(%ebp),%eax a放入%eax中,movl -8(%ebp),%ecx b放入%ecx中,shll %lc,%eax左移%cl位,這裏是4位,將左移結果放入%eax中,movl %eax,-12(%ebp) 將%eax結果放入c中。
shll $4,%eax 將%eax中的值左移4位並放入%eax中。
指令有
指令 | 效果 | 描述 |
---|---|---|
SAL k,D | D<-D<<k | 算術左移 |
SHL k,D | D<-D<<k | 邏輯左移 |
偏移量可以是立即數,或是放入%cl中的值。
算術右移
向右移動二進制位。右邊添加符號位。有符號數用算術右移,無符號數用邏輯右移。
#include <stdio.h>
int main(void)
{
int a=0xf0;
int b=4;
int c=a>>b;
printf("value=%d\n",c);
c=a>>4;
printf("value=%d\n",c);
}
彙編代碼
.section .rodata
.LC0:.string "value=%d\n"
.text
.global main
main:
pushl %ebp
movl %esp,%ebp
subl $12,%esp
movl $0xf0,-4(%ebp);a
movl $4,-8(%ebp);b
movl -4(%ebp),%eax
movl -8(%ebp),%ecx
sarl %lc,%eax
movl %eax,-12(%ebp);c
pushl -12(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl -4(%ebp),%eax
sarl $4,%eax
movl %eax,-12(%ebp)
pushl -12(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl $0,%eax
leave
ret
sarl %lc,%eax sarl $4,%eax 算術右移
指令有
指令 | 效果 | 描述 |
---|---|---|
SAR k,D | D<-D>>k | 算術右移 |
邏輯右移
向右移動二進制位。右邊添加0。
#include <stdio.h>
int main(void)
{
unsigned int a=0xf;
unsigned int b=4;
unsigned int c=a<<b;
printf("value=%d\n",c);
c=a<<4;
printf("value=%d\n",c);
}
彙編代碼
.section .rodata
.LC0:.string "value=%d\n"
.text
.global main
main:
pushl %ebp
movl %esp,%ebp
subl $12,%esp
movl $0x0,-4(%ebp);a
movl $4,-8(%ebp);b
movl -4(%ebp),%eax
movl -8(%ebp),%ecx
shrl %lc,%eax
movl %eax,-12(%ebp);c
pushl -12(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl -4(%ebp),%eax
shrl $4,%eax
movl %eax,-12(%ebp)
pushl -12(%ebp)
pushl $.LC0
call printf
addl $8,%esp
movl $0,%eax
leave
ret
shrl %lc,%eax shrl $4,%eax 算術右移
指令有
指令 | 效果 | 描述 |
---|---|---|
SHR k,D | D<-D>>k | 邏輯右移 |