作者charleshu (Analog Engineer)
看板ASM
标题Re: [问题] int 0x03 (IA86)
时间Thu Jul 15 21:49:13 2010
※ 引述《suhorng ( )》之铭言:
: int $3 的 op code 是 0xCC
: 但我用 0xCD 0x03 去跑的时候,在 OllyDbg 下正常,在 debug (16bit) 下就出问题了?
: 这让我很疑惑,到底是 debug 的bug,还是跟 32-bit, 16-bit 有关?
: 附上 debug 的测试结果:
: -
: Microsoft Windows [???? 6.0.6000]
: Copyright (c) 2006 Microsoft Corporation. All rights reserved.
: C:\>debug
: -e 100
: 179E:0100 00.cd 00.03 00.b8 00.00 00.4c 00.cd 00.21
: -u 100 105
: 179E:0100 CD03 INT 03
: 179E:0102 B8004C MOV AX,4C00
: 179E:0105 CD21 INT 21
: -r
: AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
: DS=179E ES=179E SS=179E CS=179E IP=0100 NV UP EI PL NZ NA PO NC
: 179E:0100 CD03 INT 03
: -p
: AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
: DS=179E ES=179E SS=179E CS=179E IP=0101 NV UP EI PL NZ NA PO NC
: 179E:0101 03B8004C ADD DI,[BX+SI+4C00]
: DS:4C00=0000
: -
: 但是我用
: int main() {
: __asm(".byte 0xCD, 0x03");
: return 0;
: }
: 在 OllyDbg 下测试就正常…
这个不是bug,而是设计上的选择.
x86在interrupt发生时,会把下一个指令的地址与flag放进stack,并将IP改为ISR的位置.
一般ISR不需要知道是哪个指令或原因呼叫它,只需执行完呼叫IRET就回覆原指令流程.
而INT 3的ISR也是一样, 当ISR执行起来时, 它也只能拿到呼叫它的那个指令的下一个指令
的位置. 而DEBUG需要知道呼叫它的那个指令位置, 而且要把从那里开始的指令反组译出来
. 而DEBUG的设计者假设, INT 3 只会由指令码CC的指令所呼叫, 所以它就直接把stack上
的地址减1之後,开始反组译. 当然遇到 CD 03 时就会从 03那个指令开始反组译, 而03开
头的指令是ADD, 这就是你例子里ADD DI,[BX+SI+4C00]的由来了.
而OllyDbg是32Bit的程式, 它认为执行它的机器应该够快, 记忆体应该够多, 所以它的设
计者决定, 在遇到 INT 3时, ISR会检查它到底是由CC触发的还是由CD 03所触发的, 所以
它能正确的处理CD 03触发的interrupt.
这跟32bit还是16bit是没有关系的,只是设计时的选择,不过别抱怨,不是DEBUG.COM的作者
不好,而是他的设计选择, 当年我还在PC XT上执行DEBUG.COM这个程式时, 我可是非常愿
意牺牲这个少见的特例来加快它的执行速度并减少记忆体消耗量的. 也许DEBUG.COM的作者
的想法也跟我一样.
--
Do not depend on others without effort...
当我年轻时,请教别人问题时常听到上面那句话. 当时心里偶而会有些小小抱怨.
当时间过去,我偶而会想到上面那句话, 心中十分感谢当初告诉我那句话的人.
当发现问题时,最有价值的不是问题的答案,
而是找到解决的方向,并在努力的过程里具备解决问题的能力.
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 221.169.217.133
1F:推 suhorng:感谢您的回答 <(_ _)> 07/16 14:03
2F:推 jeunder:我觉得你想太多了. 这就是 bug, 和 16/32 bits 或 CPU 07/21 23:34
3F:→ jeunder:速度快慢, 记忆体大小无关 ~ 07/21 23:35
4F:→ jeunder:还说到 "设计上的选择", 就真的是 "想太多了" ~ 07/21 23:35