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 構文) のようにである。