この記事について
「Linuxでx86アセンブラ」シリーズの4回目です.
前回は四則演算でした.数学ならば四則演算ができればおおよそのことができます.
しかし、計算機の演算は四則演算だけではありません.andやorなどの論理演算があります.
論理演算は条件分岐に欠かせない演算です.今回はアセンブラでの論理演算について説明していきます.
使用するソフトウェア
この連載ではLinux環境でnasmを使用することを想定しています.
論理演算とは?
論理演算はブール演算ともよばれ真と偽の2つの値をもつ集合に対する演算です.
2つの値しか持たいないのでbitで計算を行うコンピュータとの相性がとてもよく、10進数の計算より高速に計算を行えます.
論理演算の主なものにnot、and、or、xorがあります.
notは、論理を反転します.入力Aが真なら偽、偽なら真を返します.
A | 結果 |
---|---|
1 | 0 |
0 | 1 |
andに考えられるA,B,2つの入力を与えた結果を表にしたものを下に示します.
A | B | 結果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
andはAかつBとも言われ、AとBがともに真(1)の時に結果が真(1)になります.
orも同様に表にすると
A | B | 結果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
となります.orはAまたはBともいい、AとBのどちらかが真(1)のとき結果が真(1)になります.
xorは排他的論理和と呼ばれています.orとほとんど同じですが、A,Bがともに真(1)の時は偽(0)になります.
A | B | 結果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
コンピュータの論理演算はこれらの演算をビット列に適用します.
1010 \; {\rm and} \;0110 = 0010 \\
1010 \;\; {\rm or} \;\;0110 = 1110 \\
1010 \; {\rm xor} \;0110 = 1100
シフトとローテーション
上の論理演算の他にシフトとローテーションがあります.
シフトはビット列を左右にずらします.
左シフトの場合はこのように
0111 \rightarrow 1110
右シフトの場合は右の方にビット列がずれます.
1110 \rightarrow 0111
左シフトをするとき一番上の位が1の時に一番上のくらいの1はなくなり一番下のくらいに0がはいります.一番上のくらいのビットを再利用したいときはローテーションを使います.
ローテーションを行うとなくなってしまうはずだった一番上の位のビットが一番下の位のビットになります.
アセンブラの論理和
論理演算がどのようなものかわかっていただけたと思います.
それでは、アセンブラのプログラムでこれらの演算を表現するためのニーモニックを見て行きましょう.論理和andの演算を行うためにはand
ニーモニックを使います.
and <レジスタ>, <レジスタまたは規定値>
結果は第一オペランドに格納されます.and
の主な使い道ですが、ビット列のマスキングに使います.例えば下の命令はalレジスタの上位4ビットの値だけをそのまま切り出し、それ以外は0に設定します.
and al, 0b11110000
アセンブラの論理積
or <レジスタ>, <レジスタまたは規定値>
論理積にはor
ニーモニックを使います.and
と同様に第一オペランドに結果が格納されます.
アセンブラの排他的論理和
xor <レジスタ>, <レジスタまたは規定値>
排他的論理和にはxor
ニーモニックを使います.xor
の主な使い道はレジスタの初期化です.排他的論理和では2つのオペランドが等しい時、結果は必ず0になります.これを利用してレジスタの値を0に設定することができます.
xor eax, eax
この演算によりeaxレジスタを0に設定することができます.
アセンブラのシフト・ローテーション
shl <レジスタ>, <回数>
shr <レジスタ>, <回数>
左シフトにはshl
.右シフトにはshr
を使います.第二オペランドにシフトする回数を指定します.
ローテーションには
ror <レジスタ>, <回数>
rol <レジスタ>, <回数>
を使います.オペランドの意味はシフト命令と同じです.
サンプルコード
上記の命令のサンプルコードです.
section .bss
section .data
section .text
global main
main:
enter 0,0
nop
.not:
xor rax, rax
xor rbx, rbx
mov ax, 0b00001111
not ax
.and:
xor rax, rax
xor rbx, rbx
mov ax, 0b00001111
mov bx, 0b00001100
and ax, bx
.or:
xor rax, rax
xor rbx, rbx
mov ax, 0b00001111
mov bx, 0b10100100
or ax, bx
.xor:
xor rax, rax
xor rbx, rbx
mov ax, 0b00001111
mov bx, 0b10100100
xor ax, bx
.shl:
xor rax, rax
xor rbx, rbx
mov ax, 0b00001111
shl ax, 4
.rhl:
xor rax, rax
xor rbx, rbx
mov ax, 0b11110000
shr ax, 4
.final:
mov eax, 0
leave
ret
このコードを、logic.asmと名づけて保存してください.
nasm -g -f elf64 -o logic.o logic.asm
で、コンパイル.
gcc -o logic logic.o
で、リンクして実行ファイルlogicを生成してください.
gdb -tui logic
で、どのように処理されているかを見ることができます.
この時レジスタを2進数として表示するには
display/t <レジスタ>
というコマンドをgdb内で使用します.
参考文献
- NASM development team site:
http://www.nasm.us/ - GDB: The GNU Project Debugger site:
https://www.gnu.org/software/gdb/ - Assembly Language Step-by-Step: Programming with Linux:
http://www.amazon.co.jp/Assembly-Language-Step---Step-Programming/dp/0470497025/ref=sr_1_1?ie=UTF8&qid=1446704607&sr=8-1&keywords=assembly+language+step+by+step
↓↓過去の投稿もよろしくね↓↓
-
Linuxでx86アセンブラ(四則演算編)
http://qiita.com/MoriokaReimen/items/4853587dcb9eb96fab62 -
Linuxでx86アセンブラ(Cとの連携編)
http://qiita.com/MoriokaReimen/items/590a4ddb3de15bfacb4b -
Linuxでx86アセンブラ(道具編)
http://qiita.com/MoriokaReimen/items/b316a68d76c1eafa18f8 -
tmuxの使い方
http://qiita.com/MoriokaReimen/items/d7d5b158cb412dd65a60
↓↓コメントをいただけたら励みになります↓↓