X86アセンブラ/データ転送命令
データ転送命令
[編集]転送
[編集]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
で指定された場所にコピーする。
方向フラグは、esi
とedi
ポインターは、操作中にインクリメントされたのを示すために、クリアされる。
しかし、方向フラグがセットされているならば、これらのポインターはデクリメントされる。
この場合、コピーは逆方向で行われる。最高位のアドレスから開始し、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 構文) のようにである。