コンテンツにスキップ

X86アセンブラ/データ転送命令

出典: フリー教科書『ウィキブックス(Wikibooks)』

データ転送命令

[編集]

転送

[編集]
mov src, dest GAS文法
mov dest, src MASM文法


転送

mov命令はsrcオペランドをdestオペランドにコピーします。

語源はmove(移動)ですが、転送元のデータは一般に残ったままになります。


オペランド

src

  • 即値
  • レジスター
  • メモリー

dest

  • レジスター
  • メモリー

更新されるフラグ

  • この命令によって更新されるフラグはない。

.data

value:
        .long   2

.text
        .global _start

_start:
        movl    $6, %eax
        # %eax is now 6

        movw    %ax, value
        # value is now 6

        movl    $0, %ebx
        # %ebx is now 0

        movb    %al, %bl
        # %ebx is now 6

        movl    value, %ebx
        # %ebx is now 6

        movl    $value, %esi
        # %esi is now the address of value

        xorl    %ebx, %ebx
        # %ebx is now 0

        movw    value(, %ebx, 1), %bx
        # %ebx is now 6

# Linux sys_exit
        mov     $1, %eax
        xorl    %ebx, %ebx
        int     $0x80

データ交換

[編集]
xchg src, dest GAS文法
xchg dest, src MASM文法


交換

xchg命令は、srcオペランドとdestオペランドを交換する。

オペランドの一つがメモリーアドレスだった場合には、操作はLOCKプリフィックスが暗黙のうちに指定される。つまり、交換操作はアトミックである。 これは大きなパフォーマンスの低下を引き起こす。

注目されるべきは、一般的なNOP (no op) 命令 (0x90) は、xchgl %eax, %eax だということである。

オペランド

src

  • レジスター
  • メモリー

dest

  • レジスター
  • メモリー

しかし、片一方のオペランドのみがメモリーであることができる。つまり、少なくとも一方のオペランドはレジスターでなくてなくてはいけない。

更新されるフラグ

  • この命令により更新されるフラグはない。


.data

value:
       .long   2

.text
       .global _start

_start:
       movl    $54, %ebx

       xchgl   value, %ebx
       # %ebx is now 2
       # value is now 54

       xchgw   %ax, value
       # Value is now 0
       # %eax is now 54

       xchgb   %al, %bl
       # %ebx is now 54
       # %eax is now 2

       xchgw   value(%eax), %ax
       # value is now 0x00020000 = 131072
       # %eax is now 0

# Linux sys_exit 
       mov     $1, %eax
       xorl    %ebx, %ebx
       int     $0x80

転送と拡張

[編集]
movz src, dest GAS文法
movzx dest, src MASM文法

転送とゼロ拡張

movz命令は、srcオペランドをdestオペランドにコピーし、srcで提供されないビットをゼロ(0)で埋める。


この命令は、符号なしの小さな値を、より大きなレジスターへコピーするときに役立つ。

オペランド

src

  • レジスター
  • メモリー

dest

  • レジスター

更新されるフラグ

  • この命令によって更新されるフラグはない。

.data

byteval:
       .byte   204

.text
       .global _start

_start:
       movzbw  byteval, %ax
       # %eax is now 204

       movzwl  %ax, %ebx
       # %ebx is now 204

       movzbl  byteval, %esi
       # %esi is now 204

# Linux sys_exit 
       mov     $1, %eax
       xorl    %ebx, %ebx
       int     $0x80
movs src, dest GAS文法
movsx dest, src MASM文法

転送と符号で拡張

movs命令はsrcオペランドでdestオペランドにコピーし、srcで提供されない残りのビットをsrcの符号で埋める。

この命令は、符号なしの小さな値を、より大きなレジスターへコピーするときに役立つ。

オペランド

src

  • レジスター
  • メモリー

dest

  • レジスター

更新されるフラグ

  • この命令によって更新されるフラグはない。

.data

byteval:
       .byte   -24 # = 0xe8

.text
       .global _start

_start:
       movsbw  byteval, %ax
       # %ax is now -24 = 0xffe8

       movswl  %ax, %ebx
       # %ebx is now -24 = 0xffffffe8

       movsbl  byteval, %esi
       # %esi is now -24 = 0xffffffe8

# Linux sys_exit 
       mov     $1, %eax
       xorl    %ebx, %ebx
       int     $0x80

データサイズ毎の転送

[編集]

movsb

バイト転送

movsb命令は、esiで指定された場所から 1 バイト分を、ediで指定された場所にコピーする。 方向フラグは、esiediポインターは、操作中にインクリメントされたのを示すために、クリアされる。 しかし、方向フラグがセットされているならば、これらのポインターはデクリメントされる。 この場合、コピーは逆方向で行われる。最高位のアドレスから開始し、ecxがゼロになるまで下位のアドレスに向かって行われる。

オペランド

なし。

更新されるフラグ

  • この命令によって更新されるフラグはない。


; This code is for NASM.
section .code
; copy mystr into mystr2
mov esi, mystr    ; loads address of mystr into esi
mov edi, mystr2   ; loads address of mystr2 into edi
cld               ; clear direction flag
mov ecx,6
rep movsb

section .bss
mystr2: resb 6

section .data
mystr db "Hello", 0x0


movsw

ワード転送

movsw命令は、esiで指定された場所から 1 ワード (2 バイト) 分を、ediで指定された場所にコピーする。

オペランド

なし。

更新されるフラグ

  • この命令によって更新されるフラグはない。

section .code
; copy mystr into mystr2
mov esi, mystr
mov edi, mystr2
cld
rep movsw
; due to endianess, the resulting mystr2 would be aAbBcC\0a

section .bss
mystr2: resb 8

section .data
mystr db "AaBbCca", 0x0

アドレス計算命令

[編集]
lea src, dest GAS文法
lea dest, src MASM文法


アドレス計算

lea命令は、srcオペランドのアドレスを計算し、そのアドレスをdestオペランドにロードします。


オペランド

src

  • 即値
  • レジスター
  • メモリー

dest

  • レジスター
  • メモリー

更新されるフラグ

  • この命令によって更新されるフラグはない。

注意 LEA 命令は、src オペランドを mov 命令と同じように計算する。しかし、そのアドレスの中身dest オペランドにロードするのではない。アドレスそのものをロードするのである。

lea は、アドレスを計算するのだけに使用されるのではなく、一般的な符号なしの整数の算術計算にも使用される。注意事項として、フラグが変更されないという利点がある。 これは本当にパワフルである。というのも、srcオペランドは最大 4 つのパラメーターを取ることができるからである。つまり、ディスプレイスメント、ベースレジスター、オフセットレジスター、スカラ乗算器である。 例えば、[eax - 4 + edx * 4] (Intel 構文)、-4(%eax, %edx, 4) (GAS 構文) のようにである。