-40- | PC机汇编语言实战精解 | ![]() |
|||||||||||||||||||
我们继续使用"T"命令跟踪RET指令: | |||||||||||||||||||||
-t | 注意堆栈指针SP寄存器恢复成FFFEH | ||||||||||||||||||||
AX=0161 | BX=0001 | CX=0000 | DX=6131 | SP=FFFE | BP=0000 | SI=0000 | DI=0000 | ||||||||||||||
DS=0A3E | ES=0A3E | SS=0A3E | CS=0A3E | IP=0107 | NV UP EI PL ZR NA PE CY | ||||||||||||||||
0A3E:0107 | 3C1B | CMP AL,1B | |||||||||||||||||||
可以看到CPU确实返回到0107处执行CMP指令 | |||||||||||||||||||||
前面我们编写过一些程序用RET指令返回DOS,RET为什么会有这样的功能呢? 如果在启动DEBUG之后注意观察SP寄存器的初值,就会发现DOS将程序调入内存执行时已事先在堆栈中放入了数据,这个数据就是: |
|||||||||||||||||||||
-dfffe | DOS预先存于堆栈中的返回地址 | ||||||||||||||||||||
0A3E:FFF0 | 00 00 | .. | |||||||||||||||||||
当CPU执行RET指令时,这个"0"将被弹到IP寄存器中,也就是说CPU将从CS:0处继续执行指令。那么在CS:0处有没有指令呢?我们可以把CS:0处的指令"反汇编"出来。在"-"后打入"U0"并回车: | |||||||||||||||||||||
-u0[Enter] | |||||||||||||||||||||
0A3E:0000 | CD20 | INT | 20 | ||||||||||||||||||
0A3E:0002 | FF9F009A | CALL | FAR [BX+9A00] | ||||||||||||||||||
0A3E:0006 | F0 | LOCK | |||||||||||||||||||
0A3E:0007 | FE1D | CALL | FAR [DI] | ||||||||||||||||||
0A3E:0009 | F0 | LOCK | |||||||||||||||||||
0A3E:000A | 4F | DEC | DI | ||||||||||||||||||
0A3E:000B | 038D048A | ADD | CX,[DI+8A04] | ||||||||||||||||||
. | |||||||||||||||||||||
. | |||||||||||||||||||||
. | |||||||||||||||||||||
![]() |
当我们用A命令输入指令时,这些指令都被DEBUG编译成机器码。我们要想通过机器码重新获得指令,就必须"Unassembled"(反汇编),这就是命令码"U"的来历。 此命令可以将内存中任意位置开始的机器码反汇编成指令,若打入"U100[Enter]",那么DEBUG将把CS:100处开始的指令显示在屏幕上。 "反"出来的指令和我们当初输入的指令应该是相同的。那些紧挨着逻辑地址后面的16进制数就是指令编译后的机器码。我们可以大概了解一些常用指令对应的机器码是什么,比如"INT"和"CD"之间的关系。 |
||||||||||||||||||||
反汇编的结果真是不可思意,CS:0处竟然有一条"INT 20"指令。为什么会有这样的一条指令呢? 前面已经提到过,在我们的程序之前,DOS保留了256字节的内存空间安排了一些重要的数据,这个"CD 20"就是DOS打的小埋伏。这是因为在DOS正式成为PC机的标准操作系统之前,已有人编写了一个称为"CP/M-86"的操作系统,遗憾的是这个可怜的软件没能竞争DOS。不过 |
|||||||||||||||||||||
Copyright © 2004-2015 Reanimator | www.cookmoon.org |