<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>zlfn.space</title>
      <link>https://zlfn.space</link>
      <description></description>
      <generator>Zola</generator>
      <language>ja</language>
      <atom:link href="https://zlfn.space/ja/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Fri, 10 Apr 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>コンピュータアーキテクチャとRISC-V</title>
          <pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://zlfn.space/ja/blog/computer-architecture-riscv/</link>
          <guid>https://zlfn.space/ja/blog/computer-architecture-riscv/</guid>
          <description xml:base="https://zlfn.space/ja/blog/computer-architecture-riscv/">&lt;p&gt;コンピュータアーキテクチャとRISC-V CPUの構造について見ていきましょう。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;本記事の内容は浦項工科大学校のCSED311の内容を基に、
授業で扱われなかったいくつかの内容を追加して構成しました。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;akitekutiyatoha&quot;&gt;アーキテクチャとは？&lt;&#x2F;h1&gt;
&lt;p&gt;コンピュータアーキテクチャは、ハードウェアとソフトウェアの間のインターフェース規約です。
具体的にはCPUが理解する命令セット（ISA、Instruction Set Architecture）を
中心に、以下の内容を定義します。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;命令（インストラクション）：どのような演算（加算、分岐、メモリアクセスなど）をサポートし、どのような形式で
表現するか&lt;&#x2F;li&gt;
&lt;li&gt;レジスタ：レジスタがいくつあり、それぞれ何ビットか、それぞれの用途は何か&lt;&#x2F;li&gt;
&lt;li&gt;メモリモデル：アドレス空間のサイズ、バイト順序（エンディアン）&lt;&#x2F;li&gt;
&lt;li&gt;例外&#x2F;割り込み処理：エラーや外部イベントをどのように処理するか&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;アーキテクチャ&lt;&#x2F;strong&gt;は実際のハードウェア的な実装とは無関係に同一に維持される&lt;strong&gt;抽象層&lt;&#x2F;strong&gt;
です。コンパイラがこの規約だけを見て当該アーキテクチャに合うコードを生成すれば、その
アーキテクチャを実装したどのチップでも動作します。そのため、製造元が異なっても
アーキテクチャが同じであればユーザーは同一のOSとアプリケーションを実行できます。（AMDと
Intelのx86-64 CPUを想像できます）&lt;&#x2F;p&gt;
&lt;p&gt;一方、&lt;strong&gt;マイクロアーキテクチャ&lt;&#x2F;strong&gt;はアーキテクチャという「約束」を実際のハードウェアで実現する内部
設計です。パイプライン、アウトオブオーダー実行、分岐予測などの最適化や詳細な実装が
マイクロアーキテクチャに該当します。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;akitekutiyanozhong-lei&quot;&gt;アーキテクチャの種類&lt;&#x2F;h2&gt;
&lt;p&gt;コンピュータアーキテクチャの主な種類には、フォン・ノイマンアーキテクチャ、ハーバードアーキテクチャ、
データフローアーキテクチャなどがあります。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;huon-noimanakitekutiya&quot;&gt;フォン・ノイマンアーキテクチャ&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;フォン・ノイマンアーキテクチャ&lt;&#x2F;strong&gt;はジョン・フォン・ノイマンが提案したコンピュータの基本構造で、今日ほぼ
すべての汎用コンピュータの基盤となっています。フォン・ノイマンアーキテクチャ以前のコンピュータ（ENIACなど）は
プログラムを変更するには物理的に配線を変更する必要がありました。&lt;&#x2F;p&gt;
&lt;p&gt;当時ENIACを開発したモークリーとエッカートは後続コンピュータEDVACを設計しながら、プログラムと
データを同じメモリに格納する方法を構想します。こうすることで、プログラムをメモリに
ロードするだけで一つの配線で異なる作業を実行できるという利点があります。
（その後フォン・ノイマンがこのアイデアをまとめた報告書を単独著者として配布したことで、
この構造の名前がフォン・ノイマンアーキテクチャとなりました。）&lt;&#x2F;p&gt;
&lt;p&gt;フォン・ノイマンアーキテクチャはCPUがメモリから命令を取得し、解釈し、実行する
過程を繰り返してプログラムを実行します。この時、命令とデータが同じメモリ、同じ
データバスを共有するため、CPUがいくら高速であってもメモリ帯域幅によって
性能が制限されるフォン・ノイマンボトルネック（Von Neumann Bottleneck）が発生します。この
理由から、現代のCPUはフォン・ノイマンアーキテクチャを基盤としていますが、伝統的なフォン・ノイマン
アーキテクチャの構造をそのまま使用せず、以下のハーバードアーキテクチャの構造と適切に
組み合わせて使用しています。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;habadoakitekutiya&quot;&gt;ハーバードアーキテクチャ&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;ハーバードアーキテクチャ&lt;&#x2F;strong&gt;はフォン・ノイマンアーキテクチャと同時期にハーバード大学のMark Iコンピュータに由来する
アーキテクチャです。Mark Iは命令をパンチテープから、データを機械式カウンタから
別々に読み取っていたため、フォン・ノイマンアーキテクチャとは異なり命令メモリとデータメモリを
物理的に完全に分離した構造を持ちます。&lt;&#x2F;p&gt;
&lt;p&gt;ハーバードアーキテクチャは命令とデータのバスを区別して命令と
データを同時に読み取ることができるため、スループットが高いという利点があります。
しかし二つのメモリ間の容量を柔軟に分割できず、プログラムを命令メモリに移す
別のメカニズムが必要です。現代ではマイクロコントローラ（Arduinoに搭載されるAVRなど）や
DSP（デジタル信号処理器）のような一部の分野でハーバードアーキテクチャが利用されています。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;xiu-zheng-habadoakitekutiya&quot;&gt;修正ハーバードアーキテクチャ&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;修正ハーバードアーキテクチャ&lt;&#x2F;strong&gt;は現代のCPUの大部分が採用している、フォン・ノイマンアーキテクチャと
ハーバードアーキテクチャの間の折衷案です。L1キャッシュレベルでI-cacheとD-cacheを分離して
ハーバードアーキテクチャの高い帯域幅という利点を取り、それ以下のメモリは統合して
フォン・ノイマンアーキテクチャの柔軟性を維持します。CPU側からはL1キャッシュのメモリが
命令とデータに分離されているためハーバードアーキテクチャのように動作しますが、キャッシュを直接
扱わないコンパイラやプログラマの観点からは一つのアドレス空間としてコンピュータを扱うことが
できます。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;detahuroakitekutiya&quot;&gt;データフローアーキテクチャ&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;データフローアーキテクチャ&lt;&#x2F;strong&gt;は上記のハーバードアーキテクチャやフォン・ノイマンアーキテクチャとは根本的に
異なるアーキテクチャパラダイムです。フォン・ノイマン方式はプログラムカウンタが「次に実行する
命令」を順次指定します。データフローアーキテクチャはこの
フォン・ノイマン方式の順次的な演算実行という限界を脱却するために設計された
アーキテクチャで、プログラムカウンタがありません。
データフローアーキテクチャではプログラムカウンタが順次的にどの命令を実行するか
指定しなくても、必要なデータがすべて準備されると命令が即座に実行されます。プログラムの実行
順序をプログラマやハードウェアが決めるのではなく、データ自体が実行
フローを決定するのです。&lt;&#x2F;p&gt;
&lt;p&gt;データフローアーキテクチャではプログラムは順次的な命令リストではなく、有向
グラフで表現されます。&lt;code&gt;(a + b) * (c - d)&lt;&#x2F;code&gt;のような演算を実行する時、加算ノードと
減算ノードは互いに依存関係がないため同時に実行されます。二つの演算の結果がどちらも乗算
ノードに到着すると乗算演算が発火（fire）します。明示的にプログラマが並列
演算を指定しなくても、自動的にすべての演算が並列的に実行されるのです。&lt;&#x2F;p&gt;
&lt;p&gt;1970年代に初めて登場したデータフローアーキテクチャは1980-1990年代に次世代コンピュータとして
活発に研究されましたが、様々な限界により商用化には失敗しました。データフロー
アーキテクチャに必要な演算がハードウェア的に非常にコストが高かったこと、大規模データ
構造を扱う際の困難さ、既存のすべてのソフトウェアインフラが順次実行モデルを
前提として作成されているという複合的な問題のためでした。&lt;&#x2F;p&gt;
&lt;p&gt;純粋なデータフローコンピュータは現在は姿を消しましたが、アイデアは現代まで残り
受け継がれています。フォン・ノイマンモデル内でのアウトオブオーダー実行（OoO）構造、FPGAでの
回路設計などでデータフローアーキテクチャの設計思想が受け継がれており、最近ではAI
アクセラレータプロセッサがデータフロー原理をハードウェアに再び適用しており、汎用
コンピューティングマシンとしては商用化されませんでしたが、様々な特殊目的ハードウェアで
データフローアーキテクチャを利用しようとする研究が続いています。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;isa&quot;&gt;ISA&lt;&#x2F;h2&gt;
&lt;p&gt;ISAは&lt;strong&gt;Instruction Set Architecture&lt;&#x2F;strong&gt;の略で、ソフトウェアとハードウェアの間の
インターフェースと言えます。ISAは以下のような事項を決定します。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;命令セットにどのような演算が存在するか、各命令のエンコーディング形式はどうか&lt;&#x2F;li&gt;
&lt;li&gt;ハードウェアが直接サポートするデータ型にはどのようなものがあるか、バイト
順序はどうか（リトルエンディアン、ビッグエンディアン）&lt;&#x2F;li&gt;
&lt;li&gt;レジスタ構成とレジスタの数、ビット幅と用途&lt;&#x2F;li&gt;
&lt;li&gt;アドレッシングモード（Addressing Mode）と命令がオペランドの位置をどのように
指定するか&lt;&#x2F;li&gt;
&lt;li&gt;メモリモデルのアドレス空間サイズ&lt;&#x2F;li&gt;
&lt;li&gt;どのような状況（ゼロ除算、ページフォールト、不正な命令）で例外が発生するか、
割り込みはどのように処理されるか&lt;&#x2F;li&gt;
&lt;li&gt;権限レベルと保護モード&#x2F;カーネルモードの区分、各モードでアクセス可能なレジスタと
命令の範囲、仮想メモリ関連部分&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;一方、ISAの下に位置するマイクロアーキテクチャに関連する部分（クロック速度、パイプライン
段数、キャッシュ構造など）とソフトウェア層の規約（ABI、メモリマップ、ファームウェア
インターフェース）はISAが指定しません。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Programmer Visible State&lt;&#x2F;strong&gt;はISAでプログラマ（コンパイラ）が命令を通じて直接
読み書きできるすべてのハードウェア状態です。プログラムの意味（semantics）はこの
状態の変化で定義されます。具体的には汎用レジスタ、プログラムカウンタ、スタック
ポインタ、フラグレジスタ、メモリアドレス空間全体などが該当します。&lt;&#x2F;p&gt;
&lt;p&gt;これとは反対に見えない状態（microarchitectural state）はキャッシュ内容、分岐
予測器のヒストリ、リオーダーバッファ、リザベーションステーション、物理レジスタファイル、TLBエントリ
などがあります。これらは性能にのみ影響を与え、プログラムの論理的な結果を変えることは
ありません。&lt;&#x2F;p&gt;
&lt;p&gt;同じISAを実装したどのチップでも&lt;strong&gt;Programmer Visible State&lt;&#x2F;strong&gt;の変化が同一であれば
正確な実装であり、その他の内部状態は自由に異なることができます。&lt;&#x2F;p&gt;
&lt;p&gt;ISAが提供する命令を機能別に分類すると以下のように分けることができます。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;算術&#x2F;論理演算（Arithmetic&#x2F;Logical）&lt;&#x2F;strong&gt;：レジスタや即値に対して演算を
実行します。結果は通常レジスタに格納され、副次的にフラグが更新されます。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;データ移動（Data Transfer&#x2F;Memory）&lt;&#x2F;strong&gt;：レジスタとメモリ間、またはレジスタ間で
データを移動します。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;制御フロー（Control Flow）&lt;&#x2F;strong&gt;：プログラムカウンタを変更して実行フローを変えます。
無条件分岐（Jump）、条件分岐（Branch）、関数呼び出し&#x2F;復帰などがあります。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;システム命令（System&#x2F;Privileged）&lt;&#x2F;strong&gt;：OSやハードウェアの制御のための
命令です。ユーザーモードからカーネルへの移行、割り込み制御などがあります。現代の
マイクロプロセッサではこのような命令の大部分はカーネルモードでのみ実行可能で、
ユーザーモードで実行すると例外が発生します。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;これらの命令は必ず**アトミックに（Atomicity）**実行されなければなりません。一つの
命令はProgrammer Visible Stateを複数変更できますが、このような中間変更
過程はプログラマに公開されてはなりません。実際のハードウェアではパイプラインで
レジスタを先に書き込み、PCを後で更新するといった形で命令を段階的に処理することが
ありますが、これはMicroarchitectural Stateであり、Programmer Visible Stateではありません。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;isanoli-shi&quot;&gt;ISAの歴史&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;edsac&quot;&gt;EDSAC&lt;&#x2F;h3&gt;
&lt;p&gt;EDSACは最初のストアドプログラムコンピュータの一つで、非常に単純なISAを持って
います。&lt;&#x2F;p&gt;
&lt;p&gt;命令は5ビットopcode + 予約ビット + 10ビットメモリアドレス（n）で構成され、単一アキュムレータ
（Accumulator）構造です。レジスタはAcc一つだけで、すべての演算はこのAcc
レジスタを中心に行われます。命令の例は以下の通りです。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A n：&lt;code&gt;M[n]&lt;&#x2F;code&gt;を&lt;code&gt;ACC&lt;&#x2F;code&gt;に加算します&lt;&#x2F;li&gt;
&lt;li&gt;T n：&lt;code&gt;ACC&lt;&#x2F;code&gt;の内容を&lt;code&gt;M[n]&lt;&#x2F;code&gt;に移し、ACCをクリアします&lt;&#x2F;li&gt;
&lt;li&gt;E n：&lt;code&gt;ACC&amp;gt;=0&lt;&#x2F;code&gt;ならば、&lt;code&gt;M[n]&lt;&#x2F;code&gt;にジャンプします&lt;&#x2F;li&gt;
&lt;li&gt;I n：テープから次の文字を読み取り、&lt;code&gt;M[n]&lt;&#x2F;code&gt;が指すアドレスに格納します。&lt;&#x2F;li&gt;
&lt;li&gt;Z  ：プログラムを停止してベルを鳴らします。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;すべてのメモリアドレスが命令にハードコーディングされている点が特徴です。しかしこれでは
以下のような問題が発生します。&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;コードで関数を実行する場合、関数は呼び出し元に復帰しなければなりません。
しかしEDSACは復帰アドレスが命令にハードコーディングされているため、
同じ関数を複数箇所から呼び出す場合、復帰アドレスの指定が困難でした。&lt;&#x2F;li&gt;
&lt;li&gt;配列要素にアクセスする際、配列のアドレスが命令にハードコーディングされているため、ループを
回しながら配列にアクセスするには毎回命令自体を修正してアドレスを変更する必要がありました。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;isanofa-zhan&quot;&gt;ISAの発展&lt;&#x2F;h3&gt;
&lt;p&gt;このような問題を解決するため、後代のCPUは様々な方式で進化してきました。&lt;&#x2F;p&gt;
&lt;p&gt;一つ目に、レジスタはアキュムレータレジスタ一つだけを使用する構造から、プログラムのアドレス
指定のためのレジスタが追加され、現代では汎用レジスタ（GPR、General Purpose
Register）が多数追加されてすべてのレジスタをどのような用途でも使用できるように
なりました。&lt;&#x2F;p&gt;
&lt;p&gt;二つ目に、命令に様々なオペランドを指定できるようになりました。EDSACのように
命令が暗黙的なオペランド（ACC）を持ち、明示的オペランドは一つだけの構造を
&lt;strong&gt;Monadic&lt;&#x2F;strong&gt;、&lt;code&gt;OP inout, in2&lt;&#x2F;code&gt;のようにオペランドが2つで入力の一つが結果で
上書きされる構造を&lt;strong&gt;Dyadic&lt;&#x2F;strong&gt;、&lt;code&gt;OP out, in1, in2&lt;&#x2F;code&gt;のように出力と入力2つをすべて
明示する構造を&lt;strong&gt;Triadic&lt;&#x2F;strong&gt;と呼びます。&lt;&#x2F;p&gt;
&lt;p&gt;後述するCISCアーキテクチャでは&lt;code&gt;ADD [mem], reg&lt;&#x2F;code&gt;のように命令一つでメモリアクセスと演算を
同時に実行できる一方、RISCアーキテクチャではメモリアクセスはload&#x2F;storeのみで
行います。（load-store architecture）&lt;&#x2F;p&gt;
&lt;p&gt;三つ目に、命令に様々なメモリアドレスを指定できるようになりました。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Absoulte&lt;&#x2F;strong&gt; - &lt;code&gt;LD rt, 100&lt;&#x2F;code&gt;：EDSACと同様にアドレスが命令に定数として指定される方式です。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Register Indirect&lt;&#x2F;strong&gt; - &lt;code&gt;LD rt, (r_base)&lt;&#x2F;code&gt;：レジスタに格納されている値をアドレスとして
使用します。ポインタのデリファレンスがこの方式です。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Displaced&lt;&#x2F;strong&gt; - &lt;code&gt;LD rt, offset(r_base)&lt;&#x2F;code&gt;：レジスタの値に定数オフセットを加えて
アドレスを作ります。構造体アクセスに有用です。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Indexed&lt;&#x2F;strong&gt; - &lt;code&gt;LD rt, (r_base, r_index)&lt;&#x2F;code&gt;：二つのレジスタの値を加えてアドレスを
作ります。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Memory Indirect&lt;&#x2F;strong&gt; - &lt;code&gt;LD rt, ((r_base))&lt;&#x2F;code&gt;：メモリアドレスから値を読み取り、その値を
再びアドレスとして使用します。二重ポインタのデリファレンスに該当します。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Auto increment&#x2F;decrement&lt;&#x2F;strong&gt; - &lt;code&gt;LDR rt, (r_base)&lt;&#x2F;code&gt;：レジスタの値をアドレスとして
使用しつつ、アクセス前後にレジスタの値を自動的に増加&#x2F;減少させます。配列を
順次走査する時に有用です。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;riscnodeng-chang&quot;&gt;RISCの登場&lt;&#x2F;h3&gt;
&lt;p&gt;初期のCPUの発展は、単純だったISAを徐々に複雑にし、命令セットに様々な
機能を追加する形で進められました。当時はアセンブリで直接プログラミングすることが
一般的であり、多様な命令を追加することでプログラマのコーディングを簡便にすることが
できました。また、メモリのサイズや性能が限られていたため、頻繁に使用される複雑な
演算を一度に処理することが有用でした。&lt;&#x2F;p&gt;
&lt;p&gt;しかし、その後コンパイラ技術が発展し、プログラマが直接複雑なアセンブリ命令を
使用してプログラミングするケースはほとんどなくなりました。人が直接使用することを
想定して作られた複雑な命令はコンパイラが最適化しにくく、命令ごとに
実行時間やメモリアクセス回数が大きく異なるためパイプラインを効率的に設計することも
困難でした。&lt;&#x2F;p&gt;
&lt;p&gt;このような背景でRISC（Reduced Instruction Set Computer）が登場します。すべての
命令のサイズは同じ大きさで、メモリアクセスは必ず指定された命令で、各命令は
単純にしつつレジスタを十分に提供するなど、命令セットを単純化するという
思想で作られたRISC CPUは、複雑さをハードウェアからコンパイラに移し、ハードウェアを
単純にする代わりに、最適化の負担は発展したコンパイラに委ねます。&lt;&#x2F;p&gt;
&lt;p&gt;RISCはパイプラインを容易に構築でき、クロックを上げるにも有利でした。
ハードウェアが単純なのでトランジスタをキャッシュ、分岐予測器など性能に貢献する箇所に
投資でき、検証とデバッグが容易で設計サイクルも短かったです。&lt;&#x2F;p&gt;
&lt;p&gt;RISCと対比して、RISC以前のアーキテクチャ（x86、M68K、Z80など）を
CISC（Complex Instruction Set Computer）と呼びますが、
M68K、Z80など多くのCISCアーキテクチャは消滅しましたが、x86は巨大なソフトウェアエコシステムのため
消滅せず、代わりに外部ISAはCISC、内部的にはRISCという折衷案を採用して、
複雑な命令をCPU内部でRISCに分解して処理する設計を導入しました。&lt;&#x2F;p&gt;
&lt;p&gt;現代のRISCアーキテクチャの代表格としてはARMがありますが、ARMは初期に簡単な
設計による高い電力効率（消費電力あたりの性能比）を武器に新しい分野であるモバイル市場に
素早く参入し、2020年代以前まではRISCアーキテクチャはモバイル、組み込みなどの低消費電力
設計で、CISCアーキテクチャは高消費電力を費やす代わりに高い性能を必要とする
ワークステーションやデスクトップ、サーバー環境で利用されてきました。&lt;&#x2F;p&gt;
&lt;p&gt;しかし2020年代以降、Apple SiliconでM1チップを発売したことでこの状況が大きく
逆転しました。AppleのM1等のARM CPUはRISCアーキテクチャベースのCPUが高い性能とCISC
CPUより改善された電力効率で急速に市場シェアを伸ばしており、Apple以外にもARM
Windows&#x2F;Linuxノートパソコンが販売されるなど、モバイル市場以外でもRISCアーキテクチャが
シェアを少しずつ伸ばしています。&lt;&#x2F;p&gt;
&lt;h1 id=&quot;risc-v&quot;&gt;RISC-V&lt;&#x2F;h1&gt;
&lt;p&gt;RISC-Vは2010年にUC Berkeleyで始まったオープンソースISAです。1981年に設計された
最初のRISCプロセッサであるRISC-I、RISC-IIに過去30年間の教訓を反映してレガシーなしに
クリーンなRISC ISAをゼロから設計しました。（Vは Berkeleyで開発された5番目のRISC
設計という意味です。RISC-I、RISC-II、SOAR、SPUR、RISC-V）&lt;&#x2F;p&gt;
&lt;p&gt;RISC-Vは特定企業に依存するARMやx86とは異なり、誰でも無料でRISC-V ISAを
実装したプロセッサを製造でき、スタートアップ、大学、大企業すべてが自由にチップを設計
できます。また、モジュール式設計を利用して一つの巨大なISAではなく、最小限の
命令を持つ小さなISAに必要な拡張を付加する構造で開発されました。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;risc-vnoprogrammer-visible-state&quot;&gt;RISC-VのProgrammer Visible State&lt;&#x2F;h2&gt;
&lt;p&gt;RISC-Vには基本的にx0からx31まで32個の整数汎用レジスタがあります。
x0は常に0に固定された状態ですが、これはx0を0に固定することで様々な
動作を既存の命令で表現でき、命令の種類数を減らせるためです。
（例えば、NOPを&lt;code&gt;ADDI x0, x0, 0&lt;&#x2F;code&gt;で、即値ロードを&lt;code&gt;ADDI x1, x0, 42&lt;&#x2F;code&gt;で表現
できます。）&lt;&#x2F;p&gt;
&lt;p&gt;また、汎用レジスタに含まれないPCレジスタと浮動小数点演算を提供するF&#x2F;D
拡張に含まれる浮動小数点レジスタなどが存在します。&lt;&#x2F;p&gt;
&lt;p&gt;メモリはバイトアドレッシング方式で、基本的にリトルエンディアン方式です。メモリの
すべてのバイトはProgrammer Visible Stateであり、基本的にリトルエンディアンアラインメントを
使用します。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;risc-vnokuo-zhang-ti-xi&quot;&gt;RISC-Vの拡張体系&lt;&#x2F;h2&gt;
&lt;p&gt;RISC-Vは小さな基本ISAに必要な拡張を組み合わせて使用する構造です。&lt;&#x2F;p&gt;
&lt;p&gt;基本となるISAは以下の通りです。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RV32I&lt;&#x2F;strong&gt;：32ビット整数基本。整数算術&#x2F;論理、load&#x2F;storeなど最小限の
命令のみを持ちます。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RV64I&lt;&#x2F;strong&gt;：64ビット整数基本。RV32Iに64ビット演算とダブルワード命令が
追加されます。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RV128I&lt;&#x2F;strong&gt;：128ビット整数基本。ただし64ビットより大きなアドレス空間がいつ必要になるかは
まだ不明確なため、仕様が完全に確定（frozen）されていない状態です。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RV32E&lt;&#x2F;strong&gt;、&lt;strong&gt;RV64E&lt;&#x2F;strong&gt;：組み込み用縮小ISA。レジスタを32個から16個に削減して超小型
マイクロコントローラのコストを下げます。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;ここに以下のような標準Extensionが存在します。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;M&lt;&#x2F;strong&gt;：整数乗算、除算：&lt;code&gt;MUL&lt;&#x2F;code&gt;、&lt;code&gt;MULH&lt;&#x2F;code&gt;などハードウェア乗算器のネイティブ整数
乗算演算命令を追加します。超小型組み込み機器ではハードウェア乗算なしに
乗算と除算をビット演算など他の演算で代替できるため、乗算と
除算が別の拡張として分離されています。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;A&lt;&#x2F;strong&gt;：アトミック演算：マルチコア環境でコア間メモリ共有のための
命令です。メモリへの書き込みや読み取りをアトミックに実行したり、メモリを
予約する機能などが定義されています。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;F&lt;&#x2F;strong&gt;：32ビット浮動小数点演算：FPUによるハードウェア浮動小数点演算を
追加します。32個の浮動小数点レジスタf0-f31と浮動小数点演算の結果を
記録するフラグであるfcsrが追加されます。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;D&lt;&#x2F;strong&gt;、&lt;strong&gt;Q&lt;&#x2F;strong&gt;：それぞれ64ビット倍精度浮動小数点演算と128ビット4倍精度
浮動小数点演算命令を追加します。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;C&lt;&#x2F;strong&gt;：よく使う命令を16ビットでエンコードできるようにします。コードサイズを
削減できるため、フラッシュメモリのサイズが大きく制限される組み込み環境で使用
できます。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;V&lt;&#x2F;strong&gt;：ベクトル拡張。SIMDと類似した様々なベクトル演算をサポートします。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;H&lt;&#x2F;strong&gt;：ハイパーバイザー拡張。ハイパーバイザーがサポートする仮想化層をサポートします。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;これ以外に単一アルファベットの代わりに、拡張名の前にZを付けた細分化された拡張もあります。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Zicsr&lt;&#x2F;strong&gt;：CSRアクセス命令&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Zifencei&lt;&#x2F;strong&gt;：命令キャッシュ同期、自己修正コード、JITコンパイル時のI-Cacheと
D-Cacheの一貫性保証&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Zba&lt;&#x2F;strong&gt;、&lt;strong&gt;Zbb&lt;&#x2F;strong&gt;、&lt;strong&gt;Zbc&lt;&#x2F;strong&gt;、&lt;strong&gt;Zbs&lt;&#x2F;strong&gt;：アドレス計算高速化、基本ビット演算、キャリーレス
乗算などの詳細ビット操作命令&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Zfinx&lt;&#x2F;strong&gt;：浮動小数点演算を整数レジスタで実行&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ztso&lt;&#x2F;strong&gt;：Total Store Orderingメモリモデル保証。x86バイナリ変換時に有用&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Zicond&lt;&#x2F;strong&gt;：条件付き演算。分岐なしに条件付きで値を選択&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;非常に多様な拡張が存在するため、ソフトウェア互換性のためによく使用される
拡張をまとめて定義する&lt;strong&gt;RISC-Vプロファイル&lt;&#x2F;strong&gt;が存在します。
例えば&lt;strong&gt;RVA20U64&lt;&#x2F;strong&gt;はI、M、A、F、D、C、Zicsr、Zifencei拡張を
必須として持つように定義されています。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;risc-vming-ling-huomatuto&quot;&gt;RISC-V命令フォーマット&lt;&#x2F;h2&gt;
&lt;p&gt;RISC-Vは6種類の基本命令フォーマットを定義します。RV32Iですべて32ビット固定
長であり、opcode、rd、rs1、rs2の位置がフォーマット間で最大限一貫して配置され、
デコーディングを単純にします。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;r-type&quot;&gt;R-Type&lt;&#x2F;h3&gt;
&lt;p&gt;レジスタ間演算に使用されます。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[31:25]  [24:20]  [19:15]  [14:12]  [11:7]  [6:0]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;funct7   rs2      rs1      funct3   rd      opcode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7ビット    5ビット    5ビット    3ビット    5ビット   7ビット&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;rs1、rs2の二つのソースレジスタで演算し、結果をrdに格納します。&lt;code&gt;funct7&lt;&#x2F;code&gt;と
&lt;code&gt;funct3&lt;&#x2F;code&gt;が具体的な演算の種類を区別します。&lt;&#x2F;p&gt;
&lt;p&gt;例：&lt;code&gt;ADD x1, x2, x3&lt;&#x2F;code&gt;：x1 &amp;lt;- x2 + x3&lt;&#x2F;p&gt;
&lt;h3 id=&quot;i-type&quot;&gt;I-Type&lt;&#x2F;h3&gt;
&lt;p&gt;即値演算、load、JALRなどに使用されます。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[31:20]     [19:15]  [14:12]  [11:7]  [6:0]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;imm[11:0]   rs1      funct3   rd      opcode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;12ビット      5ビット    3ビット    5ビット   7ビット&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;12ビット即値が符号拡張（sign-extend）されて使用されます。R-typeから&lt;code&gt;funct7&lt;&#x2F;code&gt;と
&lt;code&gt;rs2&lt;&#x2F;code&gt;の位置が即値に置き換わった形式です。&lt;&#x2F;p&gt;
&lt;p&gt;例：&lt;code&gt;ADDI x1, x2, 10&lt;&#x2F;code&gt;：x1 &amp;lt;- x2 + 10&lt;&#x2F;p&gt;
&lt;p&gt;R-typeから&lt;code&gt;funct7&lt;&#x2F;code&gt;がなくなったため、若干の命令の違いが存在します。例えば
R-typeで&lt;code&gt;funct7&lt;&#x2F;code&gt;で区別されるADD&#x2F;SUBの場合、I-typeでは負の即値を
使えばよいので命令自体が不要となり省かれています。また、Immediate fieldを分割して細分
命令を区別するケースもあります。
（RV32I基準で即値が最大5ビットまでしか必要ないSLLI、SRLI、SRAIなどのシフト
命令は、先頭7ビットを命令指定子として、残り5ビットをシフト即値として
使用します。）&lt;&#x2F;p&gt;
&lt;p&gt;メモリから値を取得するLoad命令もI-Typeですが、&lt;code&gt;opcode&lt;&#x2F;code&gt;の位置にLoadを
意味する&lt;code&gt;0000011&lt;&#x2F;code&gt;を入れ、&lt;code&gt;rs1&lt;&#x2F;code&gt;をベースに、12ビット&lt;code&gt;imm&lt;&#x2F;code&gt;はオフセットとして
使用します。&lt;code&gt;funct3&lt;&#x2F;code&gt;に応じて32ビットを読む&lt;code&gt;LW&lt;&#x2F;code&gt;、16ビットを読んで符号拡張する&lt;code&gt;LH&lt;&#x2F;code&gt;、
16ビットを読んでゼロ拡張する&lt;code&gt;LHU&lt;&#x2F;code&gt;、8ビットを読む&lt;code&gt;LB&lt;&#x2F;code&gt;、&lt;code&gt;LBU&lt;&#x2F;code&gt;などが区別されます。&lt;&#x2F;p&gt;
&lt;p&gt;また、即値は常に12ビットに制限されます。プログラムで使用する即値は
通常小さな値であり、大きな定数が必要なケースは通常まれであるため、
最適化のための意図的な設計です。どうしても大きな定数が
必要な場合は後述するU-type命令やAUIPCなどを使用して値を生成します。
これは一つの命令ですべてを行おうとせず、簡単な複数の命令の組み合わせで
解決しようというRISCの思想に従ったものです。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;s-type&quot;&gt;S-Type&lt;&#x2F;h3&gt;
&lt;p&gt;メモリに値を格納するのに使用されます。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[31:25]   [24:20]  [19:15]  [14:12]  [11:7]   [6:0]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;imm[11:5] rs2      rs1      funct3   imm[4:0] opcode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7ビット     5ビット    5ビット    3ビット    5ビット    7ビット&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;結果をレジスタに書き込まないため&lt;code&gt;rd&lt;&#x2F;code&gt;がなく、代わりに&lt;code&gt;rd&lt;&#x2F;code&gt;の位置に即値の下位
ビットを、&lt;code&gt;funct7&lt;&#x2F;code&gt;の位置に即値の上位ビットを入れます。&lt;&#x2F;p&gt;
&lt;p&gt;例：&lt;code&gt;SW x3, 12(x2)&lt;&#x2F;code&gt;：&lt;code&gt;MEM[x2 + 12]&lt;&#x2F;code&gt; &amp;lt;- x3&lt;&#x2F;p&gt;
&lt;h3 id=&quot;b-type-sb-type&quot;&gt;B-Type（SB-Type）&lt;&#x2F;h3&gt;
&lt;p&gt;条件分岐に使用されます。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[31]     [30:25]    [24:20]  [19:15]  [14:12]  [11:8]   [7]     [6:0]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;imm[12]  imm[10:5]  rs2      rs1      funct3   imm[4:1] imm[11] opcode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1ビット    6ビット      5ビット    5ビット    3ビット    4ビット    1ビット   7ビット&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;S-Typeと類似していますが、即値のビット配置が異なります。即値が分岐オフセットとして
使用され、RISC-V命令は最小16ビット単位でアラインされるため、分岐オフセットの最下位
ビットは常に0であるためエンコードしません。したがって13ビット範囲の分岐が可能です。&lt;&#x2F;p&gt;
&lt;p&gt;例：&lt;code&gt;BEQ x1, x2, offset&lt;&#x2F;code&gt;：&lt;code&gt;x1 == x2&lt;&#x2F;code&gt;ならPC &amp;lt;- PC + offset&lt;&#x2F;p&gt;
&lt;p&gt;ビット配置が独特にねじれている理由は、S-typeと最大限多くのビット位置を共有して
ハードウェアを単純化するためです。このようなS-Typeとの類似性からB-Typeを
SB-Typeと呼ぶこともあります。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;u-type&quot;&gt;U-Type&lt;&#x2F;h3&gt;
&lt;p&gt;上位20ビット即値を使用する命令です。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[31:12]     [11:7]  [6:0]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;imm[31:12]  rd      opcode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;20ビット      5ビット   7ビット&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;20ビット即値が上位20ビットに配置され、下位12ビットは0で埋められます。I-Type
命令で最大12ビットまでの即値を使用できるため、これを補完するために
作られた命令です。&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LUI&lt;&#x2F;strong&gt;（Load Upper Immediate）：rd &amp;lt;- imm &amp;lt;&amp;lt; 12、大きな定数を作る時にADDIと
組み合わせて使用します。&lt;code&gt;0x12345678&lt;&#x2F;code&gt;を作る時、&lt;code&gt;LUI x1, 0x12345&lt;&#x2F;code&gt;で上位20ビットを
埋め、&lt;code&gt;ADDI x1, x1, 0x678&lt;&#x2F;code&gt;で下位12ビットを埋めます。&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;AUIPC&lt;&#x2F;strong&gt;（Add Upper Immediate to PC）：rd &amp;lt;- PC + (imm &amp;lt;&amp;lt; 12)、PC相対アドレス
計算に使用され、JALとloadと組み合わせて現在位置から±2GB範囲のアドレスを作ることが
できます。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;j-type-uj-type&quot;&gt;J-Type（UJ-Type）&lt;&#x2F;h3&gt;
&lt;p&gt;無条件ジャンプに使用されます。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[31]     [30:21]    [20]     [19:12]    [11:7]  [6:0]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;imm[20]  imm[10:1]  imm[11]  imm[19:12] rd      opcode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1ビット    10ビット     1ビット    8ビット      5ビット   7ビット&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;20ビット即値をジャンプオフセットとして使用し、B-Typeと同様にbit0は常に0であるため
エンコードしません。したがって21ビット範囲（±1MB）のジャンプが可能です。&lt;&#x2F;p&gt;
&lt;p&gt;B-Typeと類似して、U-Typeとビット位置を最大限共有するように設計されています。
そのためUJ-Typeと呼ばれることもあります。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rv32iming-ling-setuto&quot;&gt;RV32I命令セット&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;zheng-shu-suan-shu-lun-li-r-type&quot;&gt;整数算術&#x2F;論理（R-type）&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;命令&lt;&#x2F;th&gt;&lt;th&gt;動作&lt;&#x2F;th&gt;&lt;th&gt;説明&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;ADD rd, rs1, rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 + rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;加算&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SUB rd, rs1, rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 - rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;減算&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;AND rd, rs1, rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 &amp;amp; rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;ビットAND&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;OR rd, rs1, rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 | rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;ビットOR&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;XOR rd, rs1, rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 ^ rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;ビットXOR&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SLL rd, rs1, rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 &amp;lt;&amp;lt; rs2[4:0]&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;論理左シフト&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SRL rd, rs1, rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 &amp;gt;&amp;gt; rs2[4:0]&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;論理右シフト（0埋め）&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SRA rd, rs1, rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 &amp;gt;&amp;gt;&amp;gt; rs2[4:0]&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;算術右シフト（符号維持）&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SLT rd, rs1, rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← (rs1 &amp;lt; rs2) ? 1 : 0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;符号あり比較&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SLTU rd, rs1, rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← (rs1 &amp;lt; rs2) ? 1 : 0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;符号なし比較&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;ji-zhi-suan-shu-lun-li-i-type&quot;&gt;即値算術&#x2F;論理（I-type）&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;命令&lt;&#x2F;th&gt;&lt;th&gt;動作&lt;&#x2F;th&gt;&lt;th&gt;説明&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;ADDI rd, rs1, imm&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 + sext(imm)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;即値加算&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;ANDI rd, rs1, imm&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 &amp;amp; sext(imm)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;即値AND&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;ORI rd, rs1, imm&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 | sext(imm)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;即値OR&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;XORI rd, rs1, imm&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 ^ sext(imm)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;即値XOR&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SLLI rd, rs1, shamt&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 &amp;lt;&amp;lt; shamt&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;即値論理左シフト&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SRLI rd, rs1, shamt&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 &amp;gt;&amp;gt; shamt&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;即値論理右シフト&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SRAI rd, rs1, shamt&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← rs1 &amp;gt;&amp;gt;&amp;gt; shamt&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;即値算術右シフト&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SLTI rd, rs1, imm&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← (rs1 &amp;lt; sext(imm)) ? 1 : 0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;即値符号あり比較&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SLTIU rd, rs1, imm&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← (rs1 &amp;lt; sext(imm)) ? 1 : 0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;即値符号なし比較&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;shang-wei-ji-zhi-u-type&quot;&gt;上位即値（U-type）&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;命令&lt;&#x2F;th&gt;&lt;th&gt;動作&lt;&#x2F;th&gt;&lt;th&gt;説明&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;LUI rd, imm&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← imm &amp;lt;&amp;lt; 12&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;上位20ビットロード&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;AUIPC rd, imm&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← PC + (imm &amp;lt;&amp;lt; 12)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;PC基準上位20ビット加算&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;load-i-type&quot;&gt;Load（I-type）&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;命令&lt;&#x2F;th&gt;&lt;th&gt;funct3&lt;&#x2F;th&gt;&lt;th&gt;動作&lt;&#x2F;th&gt;&lt;th&gt;説明&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;LB rd, imm(rs1)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;000&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← sext(MEM8[rs1 + sext(imm)])&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;バイトロード（符号拡張）&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;LH rd, imm(rs1)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;001&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← sext(MEM16[rs1 + sext(imm)])&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;ハーフワードロード（符号拡張）&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;LW rd, imm(rs1)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;010&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← MEM32[rs1 + sext(imm)]&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;ワードロード&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;LBU rd, imm(rs1)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;100&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← zext(MEM8[rs1 + sext(imm)])&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;バイトロード（ゼロ拡張）&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;LHU rd, imm(rs1)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;101&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← zext(MEM16[rs1 + sext(imm)])&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;ハーフワードロード（ゼロ拡張）&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;store-s-type&quot;&gt;Store（S-type）&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;命令&lt;&#x2F;th&gt;&lt;th&gt;funct3&lt;&#x2F;th&gt;&lt;th&gt;動作&lt;&#x2F;th&gt;&lt;th&gt;説明&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SB rs2, imm(rs1)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;000&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;MEM8[rs1 + sext(imm)] ← rs2[7:0]&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;バイト格納&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SH rs2, imm(rs1)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;001&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;MEM16[rs1 + sext(imm)] ← rs2[15:0]&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;ハーフワード格納&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;SW rs2, imm(rs1)&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;010&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;MEM32[rs1 + sext(imm)] ← rs2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;ワード格納&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;tiao-jian-fen-qi-b-type&quot;&gt;条件分岐（B-type）&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;命令&lt;&#x2F;th&gt;&lt;th&gt;funct3&lt;&#x2F;th&gt;&lt;th&gt;動作&lt;&#x2F;th&gt;&lt;th&gt;説明&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;BEQ rs1, rs2, offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;000&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;if (rs1 == rs2) PC ← PC + offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;等しければ分岐&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;BNE rs1, rs2, offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;001&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;if (rs1 != rs2) PC ← PC + offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;異なれば分岐&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;BLT rs1, rs2, offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;100&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;if (rs1 &amp;lt; rs2) PC ← PC + offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;符号あり未満&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;BGE rs1, rs2, offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;101&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;if (rs1 &amp;gt;= rs2) PC ← PC + offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;符号あり以上&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;BLTU rs1, rs2, offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;110&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;if (rs1 &amp;lt; rs2) PC ← PC + offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;符号なし未満&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;BGEU rs1, rs2, offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;111&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;if (rs1 &amp;gt;= rs2) PC ← PC + offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;符号なし以上&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;ziyanpu&quot;&gt;ジャンプ&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;命令&lt;&#x2F;th&gt;&lt;th&gt;タイプ&lt;&#x2F;th&gt;&lt;th&gt;動作&lt;&#x2F;th&gt;&lt;th&gt;説明&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;JAL rd, offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;J-type&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← PC+4, PC ← PC + offset&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;直接ジャンプ（関数呼び出し）&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;JALR rd, rs1, imm&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;I-type&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;rd ← PC+4, PC ← (rs1 + sext(imm)) &amp;amp; ~1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;間接ジャンプ（関数復帰等）&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;memorishun-xu&quot;&gt;メモリ順序&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;命令&lt;&#x2F;th&gt;&lt;th&gt;説明&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;FENCE pred, succ&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;メモリアクセス順序保証（pred&#x2F;succ：I、O、R、Wの組み合わせ）&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;sisutemuming-ling&quot;&gt;システム命令&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;命令&lt;&#x2F;th&gt;&lt;th&gt;動作&lt;&#x2F;th&gt;&lt;th&gt;説明&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;ECALL&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;環境呼び出しトラップ発生&lt;&#x2F;td&gt;&lt;td&gt;システムコール（OS移行）&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;EBREAK&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;デバッグトラップ発生&lt;&#x2F;td&gt;&lt;td&gt;ブレークポイント&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;以前は&lt;code&gt;Zicsr&lt;&#x2F;code&gt;、&lt;code&gt;Zifencei&lt;&#x2F;code&gt;拡張がRV32Iに含まれていましたが、2.1で別の
拡張として分離されたため、現在は合計40個の命令がRV32Iを構成しています。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;risc-v-abikonbensiyon&quot;&gt;RISC-V ABIコンベンション&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;rezisutakonbensiyon&quot;&gt;レジスタコンベンション&lt;&#x2F;h3&gt;
&lt;p&gt;ISAレベルでは強制されませんが、すべてのシステムで推奨されるレジスタの使用
コンベンションです。&lt;code&gt;x0 = 0&lt;&#x2F;code&gt;だけが唯一ISAで強制されるものであり、それ以外はハードウェア
の観点では同等です。実際にこのようなコンベンションを遵守するのはABI、Calling
Conventionの役割です。&lt;&#x2F;p&gt;
&lt;p&gt;しかし、ほとんどのコンパイラ、OS、デバッガがこのようなコンベンションを遵守しているため、
特殊なベアメタル組み込みで外部ライブラリすら使用しない非常に特殊な
場合を除いては、このコンベンションを遵守する必要があります。&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;レジスタ&lt;&#x2F;th&gt;&lt;th&gt;ABI名&lt;&#x2F;th&gt;&lt;th&gt;用途&lt;&#x2F;th&gt;&lt;th&gt;Caller&#x2F;Callee saved&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;zero&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;常に0（ISAレベルで固定）&lt;&#x2F;td&gt;&lt;td&gt;—&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;ra&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;復帰アドレス（Return Address）&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;sp&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;スタックポインタ（Stack Pointer）&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;gp&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;グローバルポインタ（Global Pointer）&lt;&#x2F;td&gt;&lt;td&gt;—&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x4&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;tp&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;スレッドポインタ（Thread Pointer）&lt;&#x2F;td&gt;&lt;td&gt;—&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x5&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;t0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;一時レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x6&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;t1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;一時レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x7&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;t2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;一時レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x8&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;s0&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;fp&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;保存レジスタ &#x2F; フレームポインタ&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x9&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;s1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;保存レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x10&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;a0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;関数引数1 &#x2F; 戻り値1&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x11&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;a1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;関数引数2 &#x2F; 戻り値2&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x12&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;a2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;関数引数3&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x13&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;a3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;関数引数4&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x14&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;a4&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;関数引数5&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x15&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;a5&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;関数引数6&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x16&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;a6&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;関数引数7&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x17&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;a7&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;関数引数8&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x18&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;s2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;保存レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x19&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;s3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;保存レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x20&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;s4&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;保存レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x21&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;s5&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;保存レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x22&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;s6&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;保存レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x23&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;s7&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;保存レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x24&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;s8&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;保存レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x25&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;s9&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;保存レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x26&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;s10&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;保存レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x27&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;s11&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;保存レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Callee&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x28&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;t3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;一時レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x29&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;t4&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;一時レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x30&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;t5&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;一時レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;x31&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;t6&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;一時レジスタ&lt;&#x2F;td&gt;&lt;td&gt;Caller&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
</description>
      </item>
      <item>
          <title>木のリルーティング（全方位木DP）</title>
          <pubDate>Fri, 12 Apr 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://zlfn.space/ja/blog/rerooting/</link>
          <guid>https://zlfn.space/ja/blog/rerooting/</guid>
          <description xml:base="https://zlfn.space/ja/blog/rerooting/">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atcoder.jp&#x2F;contests&#x2F;abc348&quot;&gt;AtCoder ABC #348&lt;&#x2F;a&gt;の&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atcoder.jp&#x2F;contests&#x2F;abc348&#x2F;tasks&#x2F;abc348_e&quot;&gt;E - Minimize Sum of Distance&lt;&#x2F;a&gt;で木DP、その中でも全方位木（&lt;ruby&gt;全方位木&lt;rp&gt;（&lt;&#x2F;rp&gt;&lt;rt&gt;ぜんほういき&lt;&#x2F;rt&gt;&lt;rp&gt;）&lt;&#x2F;rp&gt;&lt;&#x2F;ruby&gt;）DPを使うということで調べてみました。&lt;&#x2F;p&gt;
&lt;p&gt;このアルゴリズムは日本国外では&lt;strong&gt;Rerooting&lt;&#x2F;strong&gt;と呼ばれ、根が定まっていない木で条件に合う根を求める際に便利に使えるテクニックです。韓国では木でのダイナミックプログラミングの一種として扱われますが、海外では名前を付けるほど競技プログラミングで意外と頻出するアルゴリズムのようです。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gai-nian&quot;&gt;概念&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;mu-dfs&quot;&gt;木DFS&lt;&#x2F;h3&gt;
&lt;p&gt;まず特定のノードについて&lt;strong&gt;他のノードまでの辺コストの総和&lt;&#x2F;strong&gt;を求める方法を考えましょう。これはDFS+DPで$O(n)$で実装できます。
&lt;img src=&quot;https:&#x2F;&#x2F;zlfn.space&#x2F;ja&#x2F;blog&#x2F;rerooting&#x2F;IMG_0140.png&quot; alt=&quot;IMG_0140&quot; title=&quot;IMG_0140&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;riruteingu&quot;&gt;リルーティング&lt;&#x2F;h3&gt;
&lt;p&gt;では&lt;strong&gt;他のノードまでの辺コストの総和が最も小さい&lt;&#x2F;strong&gt;ノードはどう求められるでしょうか？上で説明した木DFSをノード数だけ使えばいいですが、それでは$O(n^2)$かかり、頂点が$10^5$個を超えるとTLEになります。&lt;br &#x2F;&gt;
まさにこの時&lt;strong&gt;リルーティングテクニック&lt;&#x2F;strong&gt;を使います。DFS+DP木の根を移すことが$O(1)$で可能であることを利用するテクニックです。&lt;&#x2F;p&gt;
&lt;p&gt;上の図で、Aノードの総距離和30を使ってBノードの総距離和を求めてみましょう。Aノードとその向こうにあるA(0), C(3), F(7)ノードの距離はA-B辺のコスト5だけ増加してA(5), C(8), F(12)になり、Bノードとその下にあるB(5), D(8), E(7)ノードの距離はA-B辺のコスト5だけ減少してB(0), D(3), E(2)になります。Aノードの増加分とBノードの減少分は相殺されるので、&lt;br &#x2F;&gt;
つまり&lt;code&gt;(Aの総距離和) - {(Aノードの向こうのノード数) - (Bノードの下のノード数)} * (A-B辺のコスト)}&lt;&#x2F;code&gt;がBノードの総距離和になるわけです。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;zlfn.space&#x2F;ja&#x2F;blog&#x2F;rerooting&#x2F;IMG_0141.png&quot; alt=&quot;IMG_0141&quot; title=&quot;IMG_0141&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;この方法でAノードの総距離和を知っている時、Bノードの総距離和を$O(1)$で求められます。&lt;br &#x2F;&gt;
このテクニックを根を移すと考えるとリルーティングテクニック、双方向に探索しながらDFSを回すと考えると全方位木DPという名前になります。アルゴリズムは大体そうですが、名前はあまり重要ではありません。&lt;&#x2F;p&gt;
&lt;p&gt;ここでAノードの向こうのノード数とBノードの下のノード数は、Aの総距離和を求める最初のDFSの時に&lt;strong&gt;サブノードの個数を一緒に保存&lt;&#x2F;strong&gt;しておけば求められます。上の例で言えば、&lt;code&gt;Aのサブノード数&lt;&#x2F;code&gt; - &lt;code&gt;Bのサブノード数&lt;&#x2F;code&gt;がAの向こうのノード数、&lt;code&gt;Bのサブノード数&lt;&#x2F;code&gt;がそのままBノードの下のノード数になりますね。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;li-ti&quot;&gt;例題&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;boj-27730-qian-niu-tozhi-nu&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.acmicpc.net&#x2F;problem&#x2F;27730&quot;&gt;BOJ 27730 : 牽牛と織女&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;上の例をそのまま適用できる問題です。木2つに対して実行し、両側で距離和が最も小さいノードを出力すればOKです。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;boj-7812-zhong-yang-mu&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.acmicpc.net&#x2F;problem&#x2F;7812&quot;&gt;BOJ 7812 : 中央木&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;中央ノードをリルーティングで求めた後、再度DFSを回して全ノードからの距離を出力すればOKです。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;abc-348-e&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atcoder.jp&#x2F;contests&#x2F;abc348&#x2F;tasks&#x2F;abc348_e&quot;&gt;ABC#348 E&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;リルーティングテクニックという名前を初めて知った問題で、辺のコストではなく&lt;strong&gt;頂点のコスト&lt;&#x2F;strong&gt;が与えられます。
つまり&lt;code&gt;(該当頂点に行くのに必要な辺数) * (頂点のコスト)&lt;&#x2F;code&gt;が辺のコストになります。&lt;br &#x2F;&gt;
この問題は頂点のコスト和&lt;code&gt;c[x]&lt;&#x2F;code&gt;と距離和&lt;code&gt;c[x]*d&lt;&#x2F;code&gt;を両方記憶しながら解けばOKです。
整理した正解コードは以下の通りで、解説は&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;atcoder.jp&#x2F;contests&#x2F;abc348&#x2F;editorial&#x2F;9774&quot;&gt;エディトリアル&lt;&#x2F;a&gt;を参照してください。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;cpp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F9E2AF;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &amp;lt;bits&#x2F;stdc++.h&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;using namespace&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F9E2AF;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F9E2AF;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; llint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; long long int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cin &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    vector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    vector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;vector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; tree&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; n &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cin &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; -=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; -=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        tree&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]].&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;push_back&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        tree&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]].&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;push_back&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    vector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;llint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        cin &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;    &#x2F;&#x2F;sum_c[i]はiを根とする木に対して頂点c[x]の和&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;    &#x2F;&#x2F;sum_d[i]はiを根とする木に対してc[x] * d(i, x)の和&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    vector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;llint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; sub_sum_c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; sub_sum_d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;    auto&lt;&#x2F;span&gt;&lt;span&gt; dfs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt; par&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; pair&amp;lt;llint, llint&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;        &#x2F;&#x2F;v: 現在のノード、par: 親ノード&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; tree&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]) {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;全ての下方向ノードに対して&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;t &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span&gt; par&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; continue&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;親方向には行かない&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;            auto&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; [&lt;&#x2F;span&gt;&lt;span&gt;child_sum_c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; child_sum_d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            sub_sum_c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; child_sum_c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;下方向cを累積&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            sub_sum_d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; child_sum_d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;下方向dを累積&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        sub_sum_d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; sub_sum_c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;];&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;再帰的にc[x]がd(i, x)回合計される&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        sub_sum_c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span&gt;sub_sum_c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sub_sum_d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;    };&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; dfs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;dfs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;根からdfs、0(1)番ノードを根として扱う&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;    &#x2F;&#x2F;dfsで全ノードに対してf(n)を求める&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    vector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;llint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;    auto&lt;&#x2F;span&gt;&lt;span&gt; reroot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;](&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;auto&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt; par&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F9E2AF;font-style: italic;&quot;&gt; llint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt; par_sum_c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F9E2AF;font-style: italic;&quot;&gt; llint&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EBA0AC;font-style: italic;&quot;&gt; par_sum_d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;) -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;        &#x2F;&#x2F;v: 現在のノード、par: 親ノード、par_sum_c: 上方向へのc和、par_sum_d: 上方向へのd和&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; sub_sum_d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; par_sum_d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; t &lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; tree&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]) {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;全ての下方向ノードに対して&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;t &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span&gt; par&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt; continue&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;親方向には行かない&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            llint nc &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; par_sum_c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;vの上方向へのc和&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;                    +&lt;&#x2F;span&gt;&lt;span&gt; sub_sum_c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;vの下方向へのc和&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;                    &#x2F;&#x2F;ここまで全ノードのc和&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;                    -&lt;&#x2F;span&gt;&lt;span&gt; sub_sum_c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;];&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;tの下方向へのc和を引く&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;                    &#x2F;&#x2F;nc : tの上方向へのc和&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            llint nd &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; par_sum_d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;vの上方向へのd和&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;                    +&lt;&#x2F;span&gt;&lt;span&gt; sub_sum_d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;vの下方向へのd和&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;                    -&lt;&#x2F;span&gt;&lt;span&gt; sub_sum_d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt; sub_sum_c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;tの両方向d和を引く&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;                    &#x2F;&#x2F;ここまでtがvの位置にいた時のsum_d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;                    +&lt;&#x2F;span&gt;&lt;span&gt; nc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt; &#x2F;&#x2F;tの上方向へのc和&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;                    &#x2F;&#x2F;nd : tの上方向へのd和&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;            self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; nc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; nd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;    };&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt; reroot&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;reroot&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #FAB387;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    cout &lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt;&amp;lt;&amp;lt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;min_element&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;begin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;(),&lt;&#x2F;span&gt;&lt;span&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; endl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;can-zhao&quot;&gt;参照&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;codeforces.com&#x2F;topic&#x2F;76681&#x2F;en17&quot;&gt;Codeforces - Rerooting Technique&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nicotina04.tistory.com&#x2F;169&quot;&gt;nicotina04 - Rerooting Technique on Tree&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;codeforces.com&#x2F;blog&#x2F;entry&#x2F;76150&quot;&gt;Codeforces - Online Query Based Rerooting Technique&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>Dockerを使ったLinux実習環境の構築</title>
          <pubDate>Tue, 29 Aug 2023 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://zlfn.space/ja/blog/linux-demo-docker/</link>
          <guid>https://zlfn.space/ja/blog/linux-demo-docker/</guid>
          <description xml:base="https://zlfn.space/ja/blog/linux-demo-docker/">&lt;p&gt;サークルで後輩たちにLinuxセミナーをすることになりました。となると、実習環境の構築が必要ですよね。&lt;&#x2F;p&gt;
&lt;p&gt;一昨年は先輩たちがVirtualBoxをインストールしてこいと言い、去年は同じく自分がセミナーを担当して、後輩たちに自分のLinuxサーバーのアカウントを一つずつ渡す方式で実習をしました。&lt;&#x2F;p&gt;
&lt;p&gt;今年はLinuxと仮想化の知識がかなり増えたし、&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zlfn.space&#x2F;blog&#x2F;rocky-linux&quot;&gt;サーバーもきれいに再構築した&lt;&#x2F;a&gt;ので、仮想化を通じて一人一サーバーを提供することにしました。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;guguru&quot;&gt;ググる&lt;&#x2F;h3&gt;
&lt;p&gt;元々はコンテナを複数開いてSSHリバースプロキシやジャンプフォワードで構築しようとしていたのですが、思ったより難しくて苦戦していたところ、以下の記事を見つけました。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;questions&#x2F;126426&#x2F;replicate-and-isolating-user-environments-on-the-fly&quot;&gt;Replicate and Isolating user environments on the fly&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;まさに求めていたものだったので、この内容をベースに環境に合わせて修正して構築することにしました。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;imezinozuo-cheng&quot;&gt;イメージの作成&lt;&#x2F;h3&gt;
&lt;p&gt;上の記事ではコンテナを修正してそれを再びイメージにする過程を経ていますが、それは面倒すぎるのでDockerfileで構成することにしました。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# Dockerfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; ubuntu:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; apt-get update&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; apt-get install -y vim sudo man-db gcc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; yes | unminimize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; useradd -ms &#x2F;bin&#x2F;bash guest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; echo &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;&amp;#39;guest:password&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; | chpasswd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; usermod -a -G sudo guest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;USER&lt;&#x2F;span&gt;&lt;span&gt; guest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #CBA6F7;&quot;&gt;WORKDIR&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;home&#x2F;guest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;実習に必要なパッケージである&lt;code&gt;vim&lt;&#x2F;code&gt;、&lt;code&gt;sudo&lt;&#x2F;code&gt;、&lt;code&gt;man-db&lt;&#x2F;code&gt;、&lt;code&gt;gcc&lt;&#x2F;code&gt;をインストールし、&lt;code&gt;unminimize&lt;&#x2F;code&gt;を実行して&lt;code&gt;man&lt;&#x2F;code&gt;が動作するようにします。&lt;&#x2F;p&gt;
&lt;p&gt;そしてguestというユーザーを作成して、コンテナに接続するとrootではなくユーザーとして接続するようにします。これならSSHで直接接続するのとより似た感覚を与えられますよね。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; build --tag sandbox .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;でイメージをビルドします。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;yuzanozuo-cheng&quot;&gt;ユーザーの作成&lt;&#x2F;h3&gt;
&lt;p&gt;次にユーザーを作成して、SSHで接続すると偽のシェルに接続するようにします。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &#x2F;home&#x2F;guest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; &#x2F;home&#x2F;guest&#x2F;sandbox&lt;&#x2F;span&gt;&lt;span style=&quot;color: #94E2D5;&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;EOF&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;#!&#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;exec docker run -t -i --rm=true sandbox &#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt;EOF&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;chmod&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; +x &#x2F;home&#x2F;guest&#x2F;sandbox&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #9399B2;font-style: italic;&quot;&gt;# useradd guest -g docker -s &#x2F;home&#x2F;guest&#x2F;sandbox &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;useradd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; guest -s &#x2F;home&#x2F;guest&#x2F;sandbox&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;chown&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; guest &#x2F;home&#x2F;guest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #89B4FA;font-style: italic;&quot;&gt;passwd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6E3A1;&quot;&gt; guest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;私はDockerではなくPodman環境なので、ユーザーに&lt;code&gt;docker&lt;&#x2F;code&gt;グループを付与しなくても&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;access.redhat.com&#x2F;documentation&#x2F;ko-kr&#x2F;red_hat_enterprise_linux&#x2F;8&#x2F;html&#x2F;building_running_and_managing_containers&#x2F;proc_setting-up-rootless-containers_assembly_starting-with-containers&quot;&gt;Rootless Podman&lt;&#x2F;a&gt;を実行できました。Dockerで構成する場合は&lt;code&gt;docker&lt;&#x2F;code&gt;グループの付与が必要ですね。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;docker&lt;&#x2F;code&gt;コマンドには&lt;code&gt;--rm=true&lt;&#x2F;code&gt;引数を付けて、Dockerコンテナから出た場合にすぐコンテナが削除されるようにし、ユーザーが入ってくると偽のシェルを実行してDockerを開くようにします。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;wan-cheng&quot;&gt;完成&lt;&#x2F;h3&gt;
&lt;p&gt;上記の設定通りに構築し、&lt;code&gt;guest&lt;&#x2F;code&gt;ユーザーでSSH接続すると、一時的に生成されたコンテナに閉じ込められます。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;zlfn.space&#x2F;ja&#x2F;blog&#x2F;linux-demo-docker&#x2F;Screenshot_20230829_113449.png&quot; alt=&quot;Screenshot_20230829_113449&quot; title=&quot;Screenshot_20230829_113449&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;（ブログに書いたものとユーザー名は異なります。）&lt;&#x2F;p&gt;
&lt;p&gt;この環境では好きなだけパッケージをインストールしたり（カーネルに関連するもの以外なら）システムを変更でき、&lt;code&gt;sudo rm -rf &#x2F;&lt;&#x2F;code&gt;を実行してもコンテナを実行しているシステムには何の影響もありません。&lt;&#x2F;p&gt;
&lt;p&gt;ログアウトして再接続すると全ての内容が初期化され、新しいコンテナが生成されるので、実習に良い環境ですよね。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sudo rm -rf --no-preserve-root &#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;を実行してシステムが壊れないか確認してみましょう。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2024-07-15-zhui-ji&quot;&gt;2024.07.15 追記&lt;&#x2F;h3&gt;
&lt;p&gt;上記のようにコンテナを構築すると、ログアウト時にたまにコンテナが正しく削除されない問題、ログイン時にRefreshing Errorが発生する問題があります。&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CDD6F4; background-color: #1E1E2E;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ERRO[0001] Refreshing container 2e3d121a75ec00add6a35694cdc26e6442bb98a7e993b918569dd7584597bca6: acquiring lock 0 for container 2e3d121a75ec00add6a35694cdc26e6442bb98a7e993b918569dd7584597bca6: file exists&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ログアウト時にコンテナが削除されない問題は、&lt;code&gt;guest&lt;&#x2F;code&gt;アカウントの&lt;code&gt;.bash_logout&lt;&#x2F;code&gt;ファイルに&lt;code&gt;docker stop sandbox&lt;&#x2F;code&gt;を記述しました。確実ではありませんが解決したようです。
エラーは&lt;code&gt;loginctl enable-linger guest&lt;&#x2F;code&gt;でアカウントのlingering modeを許可すると解決するようです。&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
