push,你到底做了啥事情????
来源:互联网 发布:淘宝上的快排能买吗 编辑:程序博客网 时间:2024/04/30 05:00
事情要一件一件来说,就像吃饭要一口一口吃一样。一共有两件事情,这节就先讲push的事情。
问一句,push, what the hell are u doing?
启动bochs,开始push stack之旅。
截取一部分源码:
protect:;[7].进入到保护模式后,为了给予内核最大的访问内存能力,ds段寄存器使用4G段描述符;初始化dsmov eax, 0x00000008 mov ds, eax;初始化堆栈段mov eax, 0x00000018mov ss, eaxxor esp, esp;8.将sector1的kernel代码拷贝到0x040000处的内存中来;1)由于目前不知道kernel的代码尺寸,先拷贝一个扇区看看; 根据约定,第一个扇区的前4个字节应该就是kernel的总尺寸,可以根据这个尺寸知道后面还要加载多少扇区;@input: DI:SI 起始扇区号 DS:BX 写入的内存地址mov ebx, 0x40000 ;段内偏移mov di, 0x0000mov si, 0x0001call read_from_harddisk
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@function read_from_harddisk;@input: DI:SI 起始扇区号;@input: DS:BX 写入的内存地址;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;[bits 32]read_from_harddisk:push eaxpush ebxpush ecxpush edx
目前我所知道的就只有:push eax, 就是把当前的esp值-4,然后把[ss:esp]的内存空间写上eax内这4字节的内容。
看上去挺简单的,但是,事实上就是这么简单吗????
首先先看下整个程序gdt表项,堆栈段位于0x03号选择子,内存扩展方式是expand-down,所以栈底是高位,从0x7c00开始向下扩展
<bochs:5> info gdtGlobal Descriptor Table (base=0x0000000000007e00, limit=39):GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000GDT[0x01]=Data segment, base=0x00000000, limit=0xffffffff, Read/WriteGDT[0x02]=Code segment, base=0x00007c00, limit=0x00000200, Execute-Only, Non-Conforming, 32-bitGDT[0x03]=Data segment, base=0x00007c00, limit=0xf1000fff, Read/Write, Expand-downGDT[0x04]=Data segment, base=0x000b8000, limit=0x00008000, Read/WriteYou can list individual entries with 'info gdt [NUM]' or groups with 'info gdt [NUM] [NUM]'<bochs:6>
;[7].进入到保护模式后,为了给予内核最大的访问内存能力,ds段寄存器使用4G段描述符;初始化dsmov eax, 0x00000008 mov ds, eax;初始化堆栈段mov eax, 0x00000018mov ss, eaxxor esp, esp
<bochs:18> regrax: 0x00000000_00000018 rcx: 0x00000000_00098000rdx: 0x00000000_00000000 rbx: 0x00000000_0000000brsp: 0x00000000_00000000 rbp: 0x00000000_00000000rsi: 0x00000000_000e7e20 rdi: 0x00000000_00000092r8 : 0x00000000_00000000 r9 : 0x00000000_00000000r10: 0x00000000_00000000 r11: 0x00000000_00000000r12: 0x00000000_00000000 r13: 0x00000000_00000000r14: 0x00000000_00000000 r15: 0x00000000_00000000rip: 0x00000000_000000b3eflags 0x00000046: id vip vif ac vm rf nt IOPL=0 of df if tf sf ZF af PF cf之后调用函数后,有push动作,那么会进行相关操作的内存区域肯定是<0x7c00,先dump一段内存看看,后面可以做一个push前后比较:
<bochs:20> xp /40bx 0x7bf0[bochs]:0x0000000000007bf0 <bogus+ 0>: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x000x0000000000007bf8 <bogus+ 8>: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x000x0000000000007c00 <bogus+ 16>: 0xb8 0x00 0x00 0x8e 0xd8 0xb8 0x00 0x000x0000000000007c08 <bogus+ 24>: 0xbb 0x00 0x00 0xb9 0x00 0x00 0xba 0x000x0000000000007c10 <bogus+ 32>: 0x00 0xbf 0x00 0x00 0x8b 0x36 0xf7 0x7d<bochs:21> sNext at t=17825139(0) [0x0000000000007d5f] 0010:000000000000015f (unk. ctxt): push eax ; 50<bochs:22>Next at t=17825140(0) [0x0000000000007d60] 0010:0000000000000160 (unk. ctxt): push ebx ; 53<bochs:23>Next at t=17825141(0) [0x0000000000007d61] 0010:0000000000000161 (unk. ctxt): push ecx ; 51<bochs:24>Next at t=17825142(0) [0x0000000000007d62] 0010:0000000000000162 (unk. ctxt): push edx ; 52<bochs:25>Next at t=17825143(0) [0x0000000000007d63] 0010:0000000000000163 (unk. ctxt): mov al, 0x01 ; b001<bochs:26> xp /60bx 0x7be0[bochs]:0x0000000000007be0 <bogus+ 0>: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x000x0000000000007be8 <bogus+ 8>: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x000x0000000000007bf0 <bogus+ 0>: 0x00 0x80 0x09 0x00 0x00 0x00 0x04 0x000x0000000000007bf8 <bogus+ 8>: 0x18 0x00 0x00 0x00 0xc5 0x00 0x00 0x000x0000000000007c00 <bogus+ 16>: 0xb8 0x00 0x00 0x8e 0xd8 0xb8 0x00 0x000x0000000000007c08 <bogus+ 24>: 0xbb 0x00 0x00 0xb9 0x00 0x00 0xba 0x000x0000000000007c10 <bogus+ 32>: 0x00 0xbf 0x00 0x00 0x8b 0x36 0xf7 0x7d<bochs:27> regrax: 0x00000000_00000018 rcx: 0x00000000_00098000rdx: 0x00000000_00000000 rbx: 0x00000000_00040000rsp: 0x00000000_ffffffec rbp: 0x00000000_00000000rsi: 0x00000000_000e0001 rdi: 0x00000000_00000000r8 : 0x00000000_00000000 r9 : 0x00000000_00000000r10: 0x00000000_00000000 r11: 0x00000000_00000000r12: 0x00000000_00000000 r13: 0x00000000_00000000r14: 0x00000000_00000000 r15: 0x00000000_00000000rip: 0x00000000_00000163eflags 0x00000046: id vip vif ac vm rf nt IOPL=0 of df if tf sf ZF af PF cf<bochs:28>
没有办法的情况下,大胆的猜想是应该的,先看看这4个字节是啥内容吧,具体的值是0x000000c5。
没啥特殊。无奈之下,把编译好的代码打印出来看看吧:
<bochs:20> u /2000007cb3: ( ): mov ebx, 0x00040000 ; bb0000040000007cb8: ( ): mov di, 0x0000 ; 66bf000000007cbc: ( ): mov si, 0x0001 ; 66be010000007cc0: ( ): call .+154 ; e89a00000000007cc5: ( ): mov eax, dword ptr ds:[ebx] ; 8b0300007cc7: ( ): mov ecx, 0x00000200 ; b90002000000007ccc: ( ): div eax, ecx ; f7f100007cce: ( ): mov ecx, eax ; 89c100007cd0: ( ): cmp eax, 0x00000000 ; 83f80000007cd3: ( ): jz .+29 ; 741d00007cd5: ( ): cmp edx, 0x00000000 ; 83fa0000007cd8: ( ): jnz .+3 ; 750300007cda: ( ): sub ecx, 0x00000001 ; 83e90100007cdd: ( ): add ebx, 0x00000200 ; 81c30002000000007ce3: ( ): mov di, 0x0000 ; 66bf000000007ce7: ( ): add si, 0x0001 ; 6683c60100007ceb: ( ): call .+111 ; e86f00000000007cf0: ( ): loop .-21 ; e2eb00007cf2: ( ): mov eax, dword ptr ds:0x40004 ; a10400040000007cf7: ( ): mov ecx, dword ptr ds:0x40008 ; 8b0d08000400发现有点意思,有一个地方和c5有一点点的相似,那就是下面的最后一行指令的地址:00007cc5,会不会是和这个c5是同样的东西?如果你稍微与实模式打过一些交道,相信你肯定会有这种直觉,那就是不自然的把段基址*10+c5做一个联系。这里的c5应该是和代码段相关的。
00007cbc: ( ): mov si, 0x0001 ; 66be010000007cc0: ( ): call .+154 ; e89a00000000007cc5: ( ): mov eax, dword ptr ds:[ebx] ; 8b03而且刚好,sreg一把,发现cs的段基址起始就是0x7c00,那么显而易见,c5就应该是eip的值吧~ 看看:注意cs段的base=0x7c00
是的,那么c5其实就是等于代码段的段内偏移!
<bochs:27> sreges:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1 Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessedcs:0x0010, dh=0x00409900, dl=0x7c000200, valid=1 Code segment, base=0x00007c00, limit=0x00000200, Execute-Only, Non-Conforming, Accessed, 32-bitss:0x0018, dh=0x00cf9700, dl=0x7c001000, valid=1 Data segment, base=0x00007c00, limit=0xf1000fff, Read/Write, Expand-down, Accessedds:0x0008, dh=0x00cf9300, dl=0x0000ffff, valid=1 Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessedfs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1 Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessedgs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1 Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessedldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1tr:0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1gdtr:base=0x0000000000007e00, limit=0x27idtr:base=0x0000000000000000, limit=0x3ff
原归正状:那么从0x7bfc - 0x7bff之间还存在4个字节的空位,而且刚好就是call完后return回来继续执行的代码首地址,那么push eax,你到底还干了啥,这个答案就有了一个比较完整的解释:
push eax干了啥?
1.不用怀疑:肯定就是
sub esp, 4
mov ebx, esp
mov [ss:ebx], eax
2.经过上面验证,在做1之前,他肯定还做了下面这鸟事情:
sub esp, 4
mov ebx, esp
mov [ss:ebx], 返回地址
然后才开始做上面的1.
目前还有一个疑问没有想明白:
进入call之后,你会惊奇的发现,esp由之前的0x0变成了下面的:0xfffffffc。这个值不得了,当然你会说,这个不简单吗,就是数值翻转了嘛,0-4成了负数,变成了0xfffffffc。
<bochs:30> regrax: 0x00000000_00000018 rcx: 0x00000000_00098000rdx: 0x00000000_00000000 rbx: 0x00000000_00040000rsp: 0x00000000_fffffffc rbp: 0x00000000_00000000rsi: 0x00000000_000e0001 rdi: 0x00000000_00000000r8 : 0x00000000_00000000 r9 : 0x00000000_00000000r10: 0x00000000_00000000 r11: 0x00000000_00000000r12: 0x00000000_00000000 r13: 0x00000000_00000000r14: 0x00000000_00000000 r15: 0x00000000_00000000rip: 0x00000000_0000015feflags 0x00000046: id vip vif ac vm rf nt IOPL=0 of df if tf sf ZF af PF cf<bochs:31>
话是没错,我的疑问是,如果你后面再push一个ebx,那么执行mov [ss:ebx], eax, 这一句,它的实际地址会是啥呀?莫非也会翻转,翻转+翻转 = 正确了? 明天得继续研究下翻转的原理。基础不好,汗一个。。。什么都要从零学起。。。。。
今天就到此为止吧。困了,洗漱、睡觉。
- push,你到底做了啥事情????
- free 和delete,你到底做了些什么事情?
- free 和delete,你到底做了些什么事情?
- java compiler 到底做了什么事情
- 你到底做了什么
- 一年了你到底做了什么?
- Domino的安装程序到底做了哪儿些事情?
- 简历写好就完事了?这些事情你做了吗!
- 有些事情,做了你会后悔吗?
- 做了点事情
- 剖析new/delete、new[]/delete[]到底做了些什么事情
- 析构函数到底做什么事情!
- copy到底干了什么事情?
- DUPLICATE到底做了什么?
- 到底做了些什么
- setContentView到底做了什么
- AFNetworking到底做了什么?
- AFNetworking到底做了什么?
- Android数据存储与访问之文件数据存储
- VPS使用的Linux常用维护命令入门教程
- Android优秀开源项目大全
- shell中条件判断if中的-z到-d的意思
- Codeforce 298 A snow Footprint 思维问题
- push,你到底做了啥事情????
- 标准输出的缓存问题
- oracle 10g rman 备份与恢复 之二
- 毕业5年后的总结
- 差分及延3差分在MySQL数据库中实现
- 禅道项目管理软件介绍
- ajax---简单使用Demo
- andoid 打包短信发送到gmail邮箱
- 如何在macox下面配置集成ios和android游戏教程