分类:
2008-03-11 18:51:32
windows是如何执行一个程序的!
首先你双击一个程序图标,这个图标实际上是系统加载程序的一个按钮,当双击事件发生的时候,系统加载进程(也就是加载程序的运行时状态),读取,这 个文件头分析,看是什么东西,(if(dongxi=.gif) ) drwn(a picturr), else (dongxi=.exe) then read .exe的说明,根据PE格式开始分析,分析好了后,在内存中给他开个地方,把他的代码段,数据段,堆栈段都,还有一些没初始化但程序运行的时候需要的 段!弄好,然后分别把他的数据放进去,然后修改ip寄存器的值指向该程序的代码段,就是我们说的程序入口,然后我们的加载程序变成一个监视程序,如果程序 正常就什么都不管了,不正常就给用户说明怎么个不正常法!
上面要注意一点,有时候我们的程序很大,不能全部都读到内存中,还有按需加载什么的,这个是我们的程序可以自己完成,也可以由加载程序帮忙。
例如我们的自己完成,我们就把程序分成好几个小程序,一个小程序运行的时候既完成我们交给的任务,也把后面需要加载的东西根据自己的爱好要求自助! 说的还是比较明白了,现在我在把系统到底分给了程序几个堆栈他隐藏了那些(平常给我们说的对程序员透明什么的,透明,这个词用的不好啊!给个我们不可用, 计算机直接给我们那么个功能,你直接在他提供的服务上用或装作不知道就可以了)。
我是因为知道了PE格式的所以在这里就不复习了!
9FFF:01BB 7000 JO 01BD
9FFF:01BD 0000 ADD [BX+SI],AL
9FFF:01BF 0000 ADD [BX+SI],AL
9FFF:01C1 0000 ADD [BX+SI],AL
9FFF:01C3 0000 ADD [BX+SI],AL
-u
9FFF:01C5 0000 ADD [BX+SI],AL
9FFF:01C7 0000 ADD [BX+SI],AL
9FFF:01C9 0000 ADD [BX+SI],AL
9FFF:01CB 0000 ADD [BX+SI],AL
9FFF:01CD 0000 ADD [BX+SI],AL
9FFF:01CF 0018 ADD [BX+SI],BL
9FFF:01D1 141A ADC AL,1A
9FFF:01D3 16 PUSH SS
9FFF:01D4 72E2 JB 01B8
9FFF:01D6 0E PUSH CS
9FFF:01D7 1C72 SBB AL,72
9FFF:01D9 F2 REPNZ
9FFF:01DA 62 DB 62
9FFF:01DB 0E PUSH CS
9FFF:01DC 1E PUSH DS
9FFF:01DD 1C00 SBB AL,00
9FFF:01DF 0000 ADD [BX+SI],AL
9FFF:01E1 0000 ADD [BX+SI],AL
9FFF:01E3 0000 ADD [BX+SI],AL
-u
9FFF:01E5 0000 ADD [BX+SI],AL
9FFF:01E7 0000 ADD [BX+SI],AL
9FFF:01E9 0000 ADD [BX+SI],AL
9FFF:01EB 0000 ADD [BX+SI],AL
9FFF:01ED 0000 ADD [BX+SI],AL
9FFF:01EF 0010 ADD [BX+SI],DL
9FFF:01F1 54 PUSH SP
9FFF:01F2 38EE CMP DH,CH
9FFF:01F4 385410 CMP [SI+10],DL
9FFF:01F7 006C7C ADD [SI+7C],CH
9FFF:01FA 92 XCHG DX,AX
9FFF:01FB 1000 ADC [BX+SI],AL
9FFF:01FD 0000 ADD [BX+SI],AL
9FFF:01FF 0000 ADD [BX+SI],AL
9FFF:0201 0000 ADD [BX+SI],AL
9FFF:0203 0000 ADD [BX+SI],AL
看到了吧!你的程序写好后,由编译器编译成这样的汇编代码!然后这些汇编代码,就操作地址把你的内容分别放到不同的地方。
这本来就是在写汇编程序,如,你开辟个01200f-012400f的地址段专门放变量和常数,如
mov .02140 'fdfd'
这样你把数据fdfd放到了地址02140内,然后你把一些规定一个指令 我要把地址02140内的数据读出来。
然后就 in 02140就可以了!接着你就执行别的指令,这些指令中的地址都都是规定好了的!在编译器编译的时候就把数据段,代码段都给你弄好了,一个指令也是全部写好的。如 把那2个地址的数据相加。
我们一般了解的是指令的形式,这好比是类,而我们在程序里使用的指令都是具体指令的一个对象。
如指令:mov opre1,opre2 .这就是我们平时看到的指令。但你要明白,你要用的指令必须是实实在在的你可以定义类的很多对象,当然你页可以定义很多个mov指令的实际对象。
现在我们在来好好的回顾下!
其实解决问题必须是一步一步的来,例如,我们要计算 18+20
我们用汇编语言实现,首先
必须要把代表18的二进制码输入到内存里。这个由加载程序完成。也就是我们的run程序
假设把18加载到了1101101里了,20加载到了11010101101
mov ax 11011101
mov bx 11010101101
add ax bx
ax里的数据就是我们算得数据。
9FFF:0219 C0 DB C0
9FFF:021A 800000 ADD BYTE PTR [BX+SI],00
虽然你要记得代码段 数据段、栈段都是分开的,但指令都是包含了栈段和数据段地址的。
至此,我终于明白了,什么是一步一步的执行,就是把所有的事情都弄得好好的,程序写之前你怎么写都可以,只要实现功能就可以了,但程序写完后(此时 还没确定)——编译完之后(不同编译器结果不一样)肯定唯一的确定了。根据该硬件上的操作系统,如果你符合操作系统的规定,操作系统就让你运行,否则不能 运行。一条指令一条指令,这里的指令是唯一确定了的。是平时说的指令的对象,这点一定要深记在心啊!!
系统的中断是别的程序强行修改了程序的计数器。如果中断事件发生,就跳转到具体中断程序入口,cpu开始执行中断程序,有系统中断和程序自己中断。 呵呵,现在你可以用系统提供的指令和操作系统提供的方便的交互接口完全的把玩你的计算机了。要切记的是:抽象与具体(指令与程序中的具体指令),还要记得 有多个堆栈段,全局与局部,从宏观与微观理解计算机。不要放掉任何一个步骤。最后深入到具体电流和物理逻辑电路深处。
又有个问题,原来cpu根据不同的电路指定不同的指令,这样,当1001111111111111-101011011110- 110001101100011011010110这样的序列到达时,这些序列发送前先声明自己是数据还是代码。听说有cpu把数据当指令执行的情况,不 过我暂时觉得不可能,因为这些里面是有严格规定的!例如取16个数字开头2个与结尾2个高电平则为指令。这样规定好。
10110000 01011100 ;“MOV AL,5CH”对应的机器指令
00000100 00101110 ;“ADD AL,2EH”对应的机器指令