アドレスを指定したデータの転送についても、少しはわかってきた気がするので、まとめる。
動作確認のための数値
前提として、アセンブラの動作確認のため、1073606947825の値を用いた。
この数値を16進数に直すと0xF9F7F5F3F1であり、各バイト毎の値を順に変えている。
こうしておくと、一部のバイトのみ転送する場合に、どのバイトが転送されたのか確認しやすい。
また、この数では、8byte, 4byte 2byteを切り出したときに最上位bitが1になるので、
ゼロ拡張されるのか、符号拡張されるのかを確認しやすい。
レジスタからアドレスへの転送の基本
レジスタraxの指す値へbyte数を指定して転送する。
ちなみにbyte ptrは1byteのみ転送、word ptrは2byteのみ転送、dword ptrは4byteのみ転送、qword ptrは8byteすべて転送する(指定しないのと同様)。
数値によって、即値で転送できる場合とできない場合(0xF9F7F5F3F1はqword ptrには即値で転送できなかったが、qword ptrにも0などの即値なら転送できた。)があったので、rdiに即値を転送してから、rdiから[rax]へ転送するようにした。
mov rdi, 1073606947825
mov byte ptr [rax], dil
mov word ptr [rax], di
mov dword ptr [rax], edi
mov qword ptr [rax], rdi
アドレスの確認
転送先のoffsetを変えて、アドレスの起点を確認してみた。
rax+1すると、raxに格納される値は左に1byte分シフトした。
mov rdi, 1073606947825
mov byte ptr [rax-1], dil
mov word ptr [rax-1], di
mov dword ptr [rax-1], edi
mov qword ptr [rax-1], rdi
rax-1すると、raxに格納される値は右に1byte分シフトした。
mov rdi, 1073606947825
mov byte ptr [rax+1], dil
mov word ptr [rax+1], di
mov dword ptr [rax+1], edi
mov qword ptr [rax+1], rdi
ちなみに、sourceに指定したレジスタのサイズと転送先のレジスタのサイズは同じにする必要がある。
dword ptr [rax]なら、8byteレジスタのrdiではなく4byteレジスタのediにする必要がある。
そのため、転送先のサイズを指定せずに即値をアドレスに転送することもできない。
例えば以下はだめ。
mov [rax], 0x000000F7F5F3F100
アドレスからレジスタへの転送
とりあえず転送の範囲などを確認するため、[rax]の値と、rsiの値を初期化しておく。
mov rdi, 1073606947825
mov [rax], rdi
mov rsi, 12297829382473034410
12297829382473034410は16進数に直すと0xAAAAAAAAAAAAAAAAである。
1byteの転送を以下のコードで確認すると、
rsiの値は0xAAAAAAAAAAAAAAF1となった。
レジスタへの転送のときはptrを指定しなくても転送先のレジスタサイズのみ転送される。
mov sil, [rax]
2byteの転送を以下のコードで確認すると、
rsiの値は0xAAAAAAAAAAAAF3F1となった。
mov si, [rax]
4byteの転送を以下のコードで確認すると、
rsiの値は0x00000000F7F5F3F1となった。
mov esi, [rax]
4byteの転送のみ、レジスタの上位ビットがゼロ拡張されている。
これはeaxにデータ転送したとき、上位4byteはゼロ拡張されるためである。
ちなみに、上位ビットを符号拡張したい場合はmovsxまたはmovsxd命令を使って、rsiまたはesiに転送すればよい。
rsiに転送すれば、8byteの範囲全体に符号拡張し、esiに転送すれば4byteの範囲のみ符号拡張する。
符号拡張する場合は、movによる転送と異なり、転送先のサイズは符号拡張後サイズになるので、転送するサイズはptrで指定する必要がある。
8byteに転送して符号拡張するときは以下
movsx rsi, byte ptr [rax]
movsx rsi, word ptr [rax]
movsx rsi, dword ptr [rax]
4byteに転送して符号拡張するときは以下
movsx esi, byte ptr [rax]
movsx esi, word ptr [rax]
8byteに転送してゼロ拡張するときは以下。転送先をrsiにしても1byteと2byteは動作した。
4byteをゼロ拡張するときは、movでesiに転送すれば勝手に上位4byteはゼロ拡張というかゼロに初期化される。
4byteだけゼロ拡張というのは試した範囲ではできなかったが、、、
movzx esi, byte ptr [rax]
movzx esi, word ptr [rax]
mov esi, [rax]