上記はある程度正しいですが、実際には正しい解決策ではないと思います。これを x86-64 用にコンパイルする場合は、「get current」に 64 ビット操作を使用する必要があります。((カーネル?)スタックがまだ1ページしかない場合、そうでない場合は、スタックの下部を計算するために別のマスク定数が必要になります。)
asm volatile (
" movq %1, %%rax \n"
" andq %%rsp, %%rax;" // discard the low 12 bits
" movq (%%rax), %0;"
: "=r" (current)
: "i" (0xfffffffffffff000)
: "rax" // Remember to mark any temporary registers modified in "clobber"
, "memory" // and we read memory at an address that might hold a C object
);
このメモリ位置がプレーンな C で書かれていない場合は、"memory"
クロバーを省略しても安全かもしれません。
ほとんどの命令では 64 ビットの即値を使用できないため、命令を再配置しました。(この特定の定数は符号付きの 32 ビット imm32 に適合するのでand $imm, %rax
問題ありませんでしたが、AND の前に RSP をコピーすることを回避するため、この方法で行う方が効率的である可能性があります。定数は imm8 に適合しないため、両方の方法でコードサイズは同じです。)
RAX を上書きする代わりに%0
、スタック ポインターを 4k ページの先頭に切り下げるための一時的なものとして使用できます。テンプレート文字列のすべての場所を置き換え%%rax
、クロバーを削除します。または、インライン asm を使用して を取得し、C でロード部分を実行します。%0
"rax"
uintptr_t rsp
*(volatile uinptr_t*)(rsp & -4096)