x86.h static inline void stosb(void *addr, int data, int cnt)
トップページ
jupiteroak.hatenablog.com
x86.h
https://github.com/mit-pdos/xv6-public/blob/master/x86.h#L42
static inline void stosb(void *addr, int data, int cnt) { asm volatile( "cld; rep stosb" : "=D" (addr), "=c" (cnt) : "0" (addr), "1" (cnt), "a" (data) : "memory", "cc" ); }
stosb関数は、先頭アドレスが引数addr・サイズが引数cntのメモリ領域を、引数dataで指定された1バイトの値を使って初期化します(特定のメモリ領域を指定された値で埋めます)。
引数 void *addr
初期化の対象となるメモリ領域の先頭アドレスです。
引数 int data
初期化で使用される1バイトの値です。
引数 int cnt
初期化の対象となるメモリ領域のサイズ(バイト単位)です。
処理の内容
インラインアセンブラ
asm volatile( "cld; rep stosb" : "=D" (addr), "=c" (cnt) : "0" (addr), "1" (cnt), "a" (data) : "memory", "cc" );
関数内のインラインアセンブラを解釈すると以下のようになります。
アセンブリ言語命令
cld rep stosb
インラインアセンブラの命令を実行する前の状態
・ediレジスタ(入力レジスタのリストに0、出力レジスタのリストにDで表記されている)
引数addrの値が設定されています。
・ecxレジスタ(入力レジスタのリストに1、出力レジスタのリストにcで表記されている)
引数cntの値が設定されています。
・eaxレジスタ(入力レジスタのリストにaで表記されている)
引数dataの値が設定されています。
cld
cld命令は、EFLGSレジスタのDFフラグ(bit10)をクリアします。DFフラグが0の時にストリング命令(movs、lods、cmps、stosなど)を実行すると、ediレジスタの値がインクリメントするようになります。
rep stosb
repプレフィックス(リピートプレフィックス)を付けられた命令は、ecxレジスタに設定された値の回数分繰り返すように実行されます。
stosb命令は、eaxレジスタに設定された1バイトの値をediレジスタで指定されたメモリに格納します。
DFフラグが0の時(前のcld命令によってDFフラグが0の値になっている)、stosb命令を実行するとediレジスタがインクリメントされます。
repプレフィックスの効果により、この操作をecxレジスタに設定された値の回数分繰り返します。
参考
http://exlight.net/devel/8086/string.html
https://stackoverflow.com/questions/38410829/why-cant-find-the-insl-instruction-in-x86-document