7

Linux ソース ツリーでは、ファイルarch/x86/boot/header.Sに次のような x86 コードがあり、呼び出される前にBSSセクションをクリアします。main

...
# Zero the bss
    movw    $__bss_start, %di
    movw    $_end+3, %cx
    xorl    %eax, %eax
    subw    %di, %cx
    shrw    $2, %cx
    rep; stosl
...

_endアドレスに 3 が追加されているのはなぜですか? なぜmovw $_end, %cx代わりにmovw $_end+3, %cx

4

1 に答える 1

7

コードがBSSセクションを 1 バイトずつクリアしていれば、movw $_end, %cxそれで十分でした。ただし、このコードは、 STOSLを使用するSTOSBでBSSをゼロにしません。一般に、一度に 8 ビットよりも 32 ビットを格納する方が効率的です。

STOSL will store EAX (which is set to zero with xorl %eax, %eax) enough times to clear the entire range of BSS to 0. The +3 insures that if the length of the BSS section ($_end-$__bss_start) is not evenly divisible by 4, that computing the number of DWORDs needed to clear will be rounded up. If this rounding up doesn't occur then in instances where the size isn't evenly divisible by 4, the last bytes may not be cleared.

The calculation being done here assumes __bss_start is a pointer to the beginning of BSS segment and that _end is a pointer to the end of BSS. The equation to compute the number of 32-bit DWORDs to clear is effectively:

NUMDWORDS=(_end+3-__bss_start) >> 2

The shrw $2, %cx (>>2 in the calculation) is integer division by 4 where the result is always rounded down. We add +3 to the number of bytes so that when the division by 4 is done it effectively rounds up to the nearest number of DWORDs. This value is then used as the number of DWORDs STOSL will be setting to zero.

于 2016-04-26T04:41:01.230 に答える