GAS_演算子

代入演算子(assignment operator)

GAS (The GNU Assembler)を含め、アセンブリ言語では基本的な代入を行う場合にはmov命令を用います。


mov [代入元], [代入先]
  • 代入によって代入元が空になったりすることはありません。
  • レジスタを利用するときは、名前の先頭に%をつけます。

算術演算子(arithmetic operator)

四則演算


add [加算する値] [加算先]
sub [減算する値] [減算先]
mul [乗算する値]
div [除算する値]
  • 乗算と除算はアキュムレータレジスタ(eaxやax)の値に対して演算を行います。
  • 除算の場合、商はeaxに格納され、余りはedxに格納されます。
  • 除算は処理に時間がかかるため、シフト演算することが一般的です。

下記は四則演算を実行して、結果をprintfで標準出力しています。

mulとdivではebxレジスタを一時的に利用してeaxに対する演算を行っています。


.file "arithmetic.s"
.data
MSG: .string "%d\n"

.text
.global main
main:
    push %ebp
    movl %esp, %ebp

    movl $2, %eax # eax = 2
    addl $2, %eax # eax = 2 + 2
    subl $2, %eax # eax = 4 - 2

    movl $3, %ebx # ebx = 3
    mull %ebx     # eax = 2 * 3

    movl $0, %edx # 余り領域の初期化
    divl %ebx     # eax = 6 / 3

    /* printfで出力する */
    pushl %eax
    pushl $MSG
    call printf
    leave
    ret

インクリメントとデクリメント

値を1つ増やす、または1つ減らす演算です。


inc [加算先]
dec [減算先]

論理演算子(logical operator)

ビット演算を行う命令は以下の通りです。


or  [演算値] [論理和の格納先]
and [演算値] [論理積の格納先]
xor [演算値] [排他的論理和の格納先]
not [演算値] [否定の格納先]

下記はビット演算を実行して、結果をprintfで標準出力しています。


.file "logical.s"
.data
MSG: .string "0x%08x\n"

.text
.global main
main:
    push %ebp
    movl %esp, %ebp

    movl $0xFFFF0000, %eax
    orl  $0x0000FFFF, %eax # eax = 0xFFFFFFFF
    andl $0x0000FFFF, %eax # eax = 0x0000FFFF
    xorl $0xF0F00F0F, %eax # eax = 0xF0F0F0F0
    notl %eax              # eax = 0x0F0F0F0F

    /* printfで出力する */
    pushl %eax
    pushl $MSG
    call printf
    leave
    ret

シフト演算

シフト演算とは論理演算と同じようにビットを操作する命令です。

シフト演算では、左右のシフト方向、符号の有無で4種類を使い分けます。


符号なし整数のシフト(論理シフト)

論理シフトでは、足りなくなる桁には無条件に0が入ります。

シフト演算の結果はみ出す1桁はEFLAGS上のキャリーフラグ(CF)に格納されます。


shr [右シフトする桁数] [論理和の格納先]
shl [左シフトする桁数] [論理積の格納先]
  • shr = shift Logical right
  • shl = shift Logical left

符号付き整数のシフト

符号付き整数のシフトは、符号(上位1bit)を壊さないようにシフトさせる演算です。


sar [右シフトする桁数] [論理和の格納先]
sal [左シフトする桁数] [論理積の格納先]
  • sar = shift Arithmetic right
  • sal = shift Arithmetic left

シフト演算サンプル

符号有無によるシフト演算の違いは下記の通りです。

shr命令は符号を無視して桁を0で埋めます。

sar命令は符号を壊さないように桁を1で埋めます。


.file "shift_calc.s"
.data
MSG: .string "%d\n"

.text
.global main
main:
    push %ebp
    movl %esp, %ebp

    movl $0xFFFFFFFF, %eax # eax = -1
    shrl $16, %eax         # eax = 65535
    shrl $8, %eax          # eax = 255

    movl $0xFFFF0000, %eax # eax = -65535
    sarl $8, %eax          # eax = -256
    sarl $4, %eax          # eax = -16

    /* printfで出力する */
    pushl %eax
    pushl $MSG
    call printf
    leave
    ret


関連ページ