use*_*636 7 linux x86 assembly linux-kernel bootloader
在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
...
Run Code Online (Sandbox Code Playgroud)
为什么_end
地址中添加了3个?为什么不movw $_end, %cx
代替movw $_end+3, %cx
?
如果代码逐字节清除BSS部分movw $_end, %cx
就足够了.但是,此代码不零出BSS与STOSB他们使用STOSL.通常一次存储32位而不是8位更有效.
STOSL将存储 EAX(其被设定到零xorl %eax, %eax
)足够次数以清除的整个范围 BSS为0.3确保了如果长度 BSS部分($ _end - $ __ bss_start)是不能被4整除,计算清除所需的 DWORD数量将被四舍五入.如果没有发生这种舍入,那么在大小不能被4整除的情况下,最后的字节可能不会被清除.
这里进行的计算假定__bss_start
是指向BSS段开始的指针,并且_end
是指向BSS末尾的指针.计算要清除的32位DWORD数的等式是有效的:
NUMDWORDS=(_end+3-__bss_start) >> 2
Run Code Online (Sandbox Code Playgroud)
的shrw $2, %cx
(>>2
在计算中)是由4整数除法,其中结果总是向下舍入.我们在字节数上加上+3,这样当除以4时,它有效地向上舍入到最接近的DWORD数.然后将该值用作DWORD的值,STOSL将设置为零.
归档时间: |
|
查看次数: |
236 次 |
最近记录: |