次に実行される命令は、次のメモリ アドレスにある命令です。
16 * CS + IP
これにより、レジスタが 16 ビット幅しかないにもかかわらず、20 ビットのメモリをアドレス指定できます (また、ほとんどのアドレスをエンコードする 2 つの異なる方法が作成されます)。
CS の効果は、他のセグメント レジスタの効果と類似しています。たとえば、DS
データ アクセス (別のセグメント レジスタを指定しない) を だけインクリメントします16 * DS
。
CS
CS を変更する命令は次のとおりです。
- ljmp (ファージャンプ)
- ipとcs をスタックにプッシュしてから far jump する lcall (far call)
- lref (far return)、far 呼び出しを逆にします
- 割り込みベクタ テーブルから IP / CS を読み取る int
- int を反転する iret
mov
CS は、他のセグメント レジスタのように変更することはできません。CSの標準識別子でエンコードしようとしています.GNU GAS 2.24は、次のように書いても文句を言わずに行います:
mov %ax, %cs
実行時に無効なコード例外が発生します。
CS の効果を観察するには、ここで説明されているように、ブート セクターに以下を追加して QEMU で実行してみてください https://stackoverflow.com/a/32483545/895245
/* $1 is the new CS, $1f the new IP. */
ljmp $1, $after1
after1:
/* Skip 16 bytes to make up for the CS == 1. */
.skip 0x10
mov %cs, %ax
/* cs == 1 */
ljmp $2, $after2
after2:
.skip 0x20
mov %cs, %ax
/* cs == 2 */
知財
命令が実行されるたびに、その命令のエンコードの長さだけ IP が自動的に増加します。これが、プログラムが前進する理由です。
IP は、CS を変更するのと同じ命令によって変更され、それらの命令の非 far バージョンによっても変更されます (より一般的なケース)。
IP を直接観察することはできないため、それを操作するのは困難です。代替案については、この質問を確認してください:
プログラムカウンターを直接読み取る