そういう前提を置くことでコンパイラが機械語を生成するときにラクできるから、ということらしいです。
まぁ、DSやES、SSをうまく扱うのは難しそう。
ここで実際の確認コードをある掲示板で見つけたので貼っておく。
#include<stdio.h> int main(void) { int i; int *p = &i; i = 1; /* コンパイラはこの代入文でSSを使うようにコンパイルする */ *p = 2; /* pにはiの番地が入っているので、iはこれで2になるはず */ /* ↑コンパイラはこの代入文でDSを使うようにコンパイルする */ if (i == 1) { printf("a\n"); } else { printf("b\n"); } return 0; }
アセンブラはこちら。
espやebpの間接アドレス指定はssを参照するが、「eax, ecx, edx, ebx, esi, edi」などのレジスタはdsを参照するのでこういった動作の違いがおきてしまうらしい。
0000056d <main>: 56d: 8d 4c 24 04 lea 0x4(%esp),%ecx 571: 83 e4 f0 and $0xfffffff0,%esp 574: ff 71 fc pushl -0x4(%ecx) 577: 55 push %ebp 578: 89 e5 mov %esp,%ebp 57a: 53 push %ebx 57b: 51 push %ecx 57c: 83 ec 10 sub $0x10,%esp 57f: e8 79 00 00 00 call 5fd <__x86.get_pc_thunk.ax> 584: 05 50 1a 00 00 add $0x1a50,%eax 589: 65 8b 0d 14 00 00 00 mov %gs:0x14,%ecx 590: 89 4d f4 mov %ecx,-0xc(%ebp) 593: 31 c9 xor %ecx,%ecx 595: 8d 55 ec lea -0x14(%ebp),%edx 598: 89 55 f0 mov %edx,-0x10(%ebp) 59b: c7 45 ec 01 00 00 00 movl $0x1,-0x14(%ebp) 5a2: 8b 55 f0 mov -0x10(%ebp),%edx 5a5: c7 02 02 00 00 00 movl $0x2,(%edx) 5ab: 8b 55 ec mov -0x14(%ebp),%edx 5ae: 83 fa 01 cmp $0x1,%edx 5b1: 75 16 jne 5c9 <main+0x5c> 5b3: 83 ec 0c sub $0xc,%esp 5b6: 8d 90 dc e6 ff ff lea -0x1924(%eax),%edx 5bc: 52 push %edx 5bd: 89 c3 mov %eax,%ebx 5bf: e8 3c fe ff ff call 400 <puts@plt> 5c4: 83 c4 10 add $0x10,%esp 5c7: eb 14 jmp 5dd <main+0x70> 5c9: 83 ec 0c sub $0xc,%esp 5cc: 8d 90 de e6 ff ff lea -0x1922(%eax),%edx 5d2: 52 push %edx 5d3: 89 c3 mov %eax,%ebx 5d5: e8 26 fe ff ff call 400 <puts@plt> 5da: 83 c4 10 add $0x10,%esp 5dd: b8 00 00 00 00 mov $0x0,%eax 5e2: 8b 4d f4 mov -0xc(%ebp),%ecx 5e5: 65 33 0d 14 00 00 00 xor %gs:0x14,%ecx 5ec: 74 05 je 5f3 <main+0x86> 5ee: e8 8d 00 00 00 call 680 <__stack_chk_fail_local> 5f3: 8d 65 f8 lea -0x8(%ebp),%esp 5f6: 59 pop %ecx 5f7: 5b pop %ebx 5f8: 5d pop %ebp 5f9: 8d 61 fc lea -0x4(%ecx),%esp 5fc: c3 ret