Buffer Address (rsi)
CoddyのAssemblyジャーニー「基礎」セクションの一部。レッスン 37/45。
write syscallでは、出力の送信先(rdi内のファイルディスクリプタ)をOSに伝えた後、何を出力するかを伝える必要があります。これは、メモリ内の文字列のaddressを渡すことで行います。
バッファのアドレス用のレジスタはrsiです。
バッファとは何ですか?
バッファとは、データを保持するメモリの単純なブロックです。今回の場合、バッファは印刷したい文字列です。
なぜ値そのものではなく、address なのか?
write syscall は、メモリ内で string がどこから始まるかを知る必要があります。write syscall は、その address から、rdx で指定した長さに達するまで bytes を読み取ります。実際の文字を write syscall に送るのではありません。それらの場所を送ります。
例:
section .data
msg db 'Hello', 0x0a
section .text
mov rsi, msg ; rsi は msg のアドレスを保持しますmsg の正体:
msg はラベルです。アセンブラはこれを数値、つまり 'Hello' という string が格納されているメモリのアドレスに置き換えます。mov rsi, msg と記述すると、そのアドレスの数値を rsi に入れることになります。
アドレスを忘れるとどうなりますか?
rsiを設定しない場合、レジスタには以前そこにあった無関係な値が入っています。OSはランダムなメモリアドレスから読み取ろうとするため、セグメンテーションフォールト(クラッシュ)が発生する可能性が高くなります。
write syscall を使った完全な例:
section .data
msg db 'Hello', 0x0a
len equ $ - msg
section .text
mov rax, 1 ; writeシステムコール
mov rdi, 1 ; stdout
mov rsi, msg ; 文字列のアドレス
mov rdx, len ; バイト数
syscallチャレンジ
改行に続く値 'Hi' を持つ greeting という文字列が与えられています。greeting のアドレスを rsi に読み込むコード行を書いてください。
rsi の mov 命令だけを書いてください。
自分で試してみよう
section .text
global _start
_start:
%include "solution.asm"
mov rax, 1
mov rdi, 1
; rsi にはすでにアドレスが入っています(生徒のコードから)
mov rdx, greetingLen
syscall
mov rax, 60
mov rdi, 0
syscallこのレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
基礎のすべてのレッスン
自分で練習してみよう: Assemblyプレイグラウンド