Buffer Address (rsi)
CoddyのAssemblyジャーニー「基礎」セクションの一部 — レッスン 37/45。
writeシステムコールでは、出力の送信先(rdi内のファイル記述子)をOSに伝えた後、何をプリントするかを伝える必要があります。これは、メモリ内の文字列のアドレスを渡すことで行います。
バッファアドレス用のレジスタは rsi です。
バッファとは何ですか?
バッファとは、単にデータを保持するメモリのブロックのことです。今回のケースでは、バッファは出力したい文字列を指します。
なぜ値そのものではなく、アドレスなのですか?
writeシステムコールは、文字列がメモリのどこから始まるかを知る必要があります。rdxで指定した長さに達するまで、そのアドレスからバイトを読み取ります。システムコールに実際の文字を送信するのではなく、その場所(アドレス)を送信します。
例:
section .data
msg db 'Hello', 0x0a
section .text
mov rsi, msg ; rsiはmsgのアドレスを保持しますmsg の正体:
msg はラベルです。アセンブラはこれを数値、つまり文字列 'Hello' が格納されているメモリ番地(アドレス)に置き換えます。mov rsi, msg と記述すると、そのアドレスの数値を rsi に格納していることになります。
アドレスを忘れるとどうなりますか?
rsiを設定しない場合、レジスタには以前そこにあった何らかのデータ(ゴミ)が含まれたままになります。OSはランダムなメモリアドレスから読み取ろうとし、その結果、おそらくセグメンテーション違反(クラッシュ)が発生します。
writeシステムコールを使用した完全な例:
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チャレンジ
greeting という名前の文字列が与えられており、その値は 'Hi' とそれに続く改行文字です。greeting のアドレスを rsi にロードするコードを1行記述してください。
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このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。