当前位置: 技术问答>linux和unix
2.6.24内核的compressed/head_32.S的问题
来源: 互联网 发布时间:2017-04-11
本文导语: 我在看2.6.24内核,linux/arch/x86/boot/compressed/head_32.S中,既然运行时被重定位了,那么连接时的标号地址就不准确了,怎么还能直接调用call decompress_kernel呢?相关代码如下: …… call 1f 1: popl %ebp …… movl o...
我在看2.6.24内核,linux/arch/x86/boot/compressed/head_32.S中,既然运行时被重定位了,那么连接时的标号地址就不准确了,怎么还能直接调用call decompress_kernel呢?相关代码如下:
……
call 1f
1: popl %ebp
……
movl output_len(%ebx), %eax
pushl %eax
pushl %ebp # output address
movl input_len(%ebx), %eax
pushl %eax # input_len
leal input_data(%ebx), %eax
pushl %eax # input_data
leal _end(%ebx), %eax
pushl %eax # end of the image as third argument
pushl %esi # real mode pointer as second arg
call decompress_kernel
addl $20, %esp
popl %ecx
……
既然用了input_len(%ebx), 说明代码是从0地址开始链接的,并且通过寄存器进行了重定位寻址,那么decompress_kernel应该
也是相对于0始址的偏移量(head_32.S和misc_32.c是一起链接的),当压缩内核移到到0x100000+X的地址开始解压缩前夕,decompress_kernel的实际位置显然和链接位置不一致,怎么还能用call decomress_kernel呢(没有重定位)?前面的call 1f 可以看做是短调用(二进制代码中用相对位移,无需重定位),而call decomress_kernel显然不是。
……
call 1f
1: popl %ebp
……
movl output_len(%ebx), %eax
pushl %eax
pushl %ebp # output address
movl input_len(%ebx), %eax
pushl %eax # input_len
leal input_data(%ebx), %eax
pushl %eax # input_data
leal _end(%ebx), %eax
pushl %eax # end of the image as third argument
pushl %esi # real mode pointer as second arg
call decompress_kernel
addl $20, %esp
popl %ecx
……
既然用了input_len(%ebx), 说明代码是从0地址开始链接的,并且通过寄存器进行了重定位寻址,那么decompress_kernel应该
也是相对于0始址的偏移量(head_32.S和misc_32.c是一起链接的),当压缩内核移到到0x100000+X的地址开始解压缩前夕,decompress_kernel的实际位置显然和链接位置不一致,怎么还能用call decomress_kernel呢(没有重定位)?前面的call 1f 可以看做是短调用(二进制代码中用相对位移,无需重定位),而call decomress_kernel显然不是。
|
call decomress_kernel类似于执行
push IP
jmp near ptr decomress_kernel
jmp near ptr做的事情就类似于:
IP=IP+16位位移
16位位移=标号decomress_kernel处的地址-jmp指令后的第一个字节的地址
所以其实IP偏移是个相对地址
push IP
jmp near ptr decomress_kernel
jmp near ptr做的事情就类似于:
IP=IP+16位位移
16位位移=标号decomress_kernel处的地址-jmp指令后的第一个字节的地址
所以其实IP偏移是个相对地址