|
主题 : : 分析一个奇怪的程序遇到问题? [待解决] |
回复[ 34次 ]
点击[ 2461次 ] | |
|
|
|
|
[帖 主]
[ 发表时间:2007-06-26 20:49 ]
[引用]
[回复]
[ top ] | |
荣誉值:5
信誉值:3
注册日期:2007-06-26 20:40 |
分析下面的程序,在运行前思考:这个程序可以正确返回吗?
运行后再思考:为什么是这种结果?
assume cs:codesg
codesg segment
mov ax,4c00h
int 21h
start: mov ax,0
s: nop
nop
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax
s0: jmp short s
s1: mov ax,0
int 21h
mov ax,0
s2: jmp short s1
nop
codesg ends
end start | | |
|
|
|
|
[第1楼]
[ 回复时间:2007-07-13 11:57 ]
[引用]
[回复]
[ top ] | |
荣誉值:19
信誉值:0
注册日期:2007-07-05 17:25 |
可以正确返回。
这和jmp的执行原理有关系,请看第九章的分析。
上机做实验看看就知道了。 | | |
|
|
|
|
[第2楼]
[ 回复时间:2007-08-19 12:33 ]
[引用]
[回复]
[ top ] | |
荣誉值:43
信誉值:3
注册日期:2007-07-05 19:53 |
最好反复思考得出自己的结论之后再上机实验。
很有趣,也会很有收获。 | | |
|
|
|
|
[第3楼]
[ 回复时间:2007-09-16 09:26 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2007-08-29 11:41 |
关键在 jmp short s1 这一步
这一步在 s2处执行的时候是ip向上偏移了“3行”
被
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax
复制到s:处也还是向上偏移了“3行”
所以,由s0: jmp short s ,再执行s:的时候,就会执行
mov ax,4c00h
int 21h
从而可以正常的返回。 | | |
|
|
|
|
[第4楼]
[ 回复时间:2008-02-25 18:09 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2007-12-11 10:23 |
其实这个实验有两个最关键的关键点:
1。“jmp short 标号”的原理。
2。程序是编译后才运行的。
理解清楚了这两点就什么都好办了。 | | |
|
|
|
|
[第5楼]
[ 回复时间:2008-04-10 15:02 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-03-14 16:22 |
|
|
|
|
|
[第6楼]
[ 回复时间:2008-04-14 20:58 ]
[引用]
[回复]
[ top ] | |
荣誉值:44
信誉值:0
注册日期:2008-04-11 13:33 |
嗯,明白其原理就能知道它可以正确返回了。
jmp short s 在编译时,是根据标号与JMP下一条指令的偏移量来确定的,因此偏移量不变其功能不变 | | |
|
|
|
|
[第7楼]
[ 回复时间:2008-05-28 23:40 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:2
注册日期:2008-04-02 16:04 |
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax
四条指令的作用是将标号s2处的一条指令复制到标号s处。这时我们应该关心所复制的语句"jmp short s1"对程序的影响:我们知道在段内直接短转移指令所对应的机器码中,并不包含转移的目的地址,而包含的是转移的位移量(如对此概念还不太熟悉,请查看书中第167页的内容)。也就是说,在源程序的编译过程中,编译器遇到‘段内直接短转移’[形如:jmp short 标号]时就会自动算出其要跳转的位移量,以便程序在执行‘段内直接短转移’的指令时就根据位移量进行(向前或向后)跳转。通过调试中的U命令我们可以看到指令's2:jmp short s1'所对应的机器码是EBF6,F6h(-10d的补码)就是跳转的位移量[此位移量也可由指令's2:jmp short s1'处的偏移地址18h减去指令's2:jmp short s1'后一个字节的偏移地址22h得出]。这时我们就知道了其实复制到标号s处的指令所对应的机器码就是EBF6(刚好取代两个nop所对应的机器码),它的作用就是将当前IP向前移动10个字节。当程序执行标号s0处的指令后,程序便跳到标号s处接着执行标号s处的指令。s处的指令的作用是向前跳10字节,于是便跳到了代码中的第一条指令,继续执行后便实现了程序的正常返回。 | | |
|
|
|
|
[第8楼]
[ 回复时间:2008-08-01 18:36 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-07-17 09:29 |
为什么我上机测试之下,正确返回不是应该显示 "Program terminated normally",但为什么这题不会(即已经执行完S处的EBF6指令之后,跳到了代码中的第一条指令)! | | |
|
|
|
|
[第9楼]
[ 回复时间:2008-09-27 03:41 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-09-15 15:58 |
重要的一点是jmp short的跳转地址偏移是在编译时计算出来的,所以jmp short指令被复制后,跳转的地址偏移保持不变,并不会重新计算。 | | |
|
|
|
|
[第10楼]
[ 回复时间:2008-12-02 13:55 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-09-15 21:00 |
噢噢 以前一直没有好好注意 所以也不清楚 才到这里看看 受教了
呵呵 好像这个帖挺长的一个时间差啊 | | |
|
|
|
|
[第11楼]
[ 回复时间:2008-12-19 15:02 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-12-09 16:33 |
assume cs:codesg
data segment
db 'welcome to masm!'
db 02h,24h,71h
data ends
codesg segment
start:
mov ax,data
mov ds,ax
mov bx,0
mov cx,3
mov si,0
mov di,0
mov ax,stack
mov ss,ax
mov sp,04h
mov bp,0
s1:
mov dx,cx
mov cx,16
s:
mov ax,0b872h
mov es,ax
mov al,ds:[si]
mov ah,ds:10h[bp]
mov es:[bx+di],ax
add di,2
add si,1
loop s
mov cx,dx
mov ax,0
mov si,0
mov di,0
add bp,1
add bx,0a0h
loop s1
mov ax,4c00h
int 21h
codesg ends
end start | | |
|
|
|
|
[第12楼]
[ 回复时间:2009-02-02 13:28 ]
[引用]
[回复]
[ top ] | |
荣誉值:2
信誉值:0
注册日期:2009-01-28 11:57 |
请问11楼,你定义了stack段吗? 你的第15行 mov ax,stack mov ss,ax可以吗? | | |
|
|
|
|
[第13楼]
[ 回复时间:2009-05-06 12:49 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-04-22 18:44 |
up4tree(3楼) 和thisguy (7楼)分析的正确。 | | |
|
|
|
|
[第14楼]
[ 回复时间:2009-05-25 12:27 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-05-22 19:48 |
|
|
|
|
|
[第15楼]
[ 回复时间:2009-08-26 19:51 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-08-17 01:35 |
s: nop
nop
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax
s0: jmp short s
s1: mov ax,0
int 21h
mov ax,0
s2: jmp short s1
看这里 就OK了 | | |
|
|
|
|
[第16楼]
[ 回复时间:2009-12-19 21:23 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:4
注册日期:2009-12-18 19:17 |
恩
帖子有段时间了
老师那会儿建议是:大家象计算机一样思考
大家试试吧
持之以恒应该会有很大收获
呵呵 | | |
|
|
|
|
[第17楼]
[ 回复时间:2010-01-09 03:57 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-10-07 14:18 |
assume cs:codesg
codesg segment
mov ax,4c00h
int 21h
start: mov ax,0
s: nop
nop
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax
s0: jmp short s
s1: mov ax,0
int 21h
mov ax,0
s2: jmp short s1
nop
codesg ends
end start
C:\>debug32 c:\masm\qi.exe
Debug32 - Version 1.0 - Copyright (C) Larson Computing 1994
CPU = 686, Virtual 8086 Mode, Id/Step = 067A, A20 enabled
-r
AX=0000 BX=0000 CX=0023 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=2186 ES=2186 SS=2196 CS=2196 IP=0005 NV UP DI PL NZ NA PO NC
2196:0005 B80000 MOV AX,0000h
-u
2196:0008 90 NOP
2196:0009 90 NOP
2196:000A BF0800 MOV DI,0008h
2196:000D BE2000 MOV SI,0020h
2196:0010 2E8B04 MOV AX,CS:[SI]
2196:0013 2E8905 MOV CS:[DI],AX
2196:0016 EBF0 JMP Short 0008
2196:0018 B80000 MOV AX,0000h
2196:001B CD21 INT 21h
2196:001D B80000 MOV AX,0000h
2196:0020 EBF6 JMP Short 0018
2196:0022 90 NOP | | |
|
|
|
|
[第18楼]
[ 回复时间:2010-01-09 04:02 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-10-07 14:18 |
不明白 为什么会没有了 2196:0017 和 2196:21 编译的时候通过了只是结果让我产生了很多疑问,现在还没有用t到执行,想多思考一下在去实验!!! | | |
|
|
|
|
[第19楼]
[ 回复时间:2010-01-10 01:47 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-10-07 14:18 |
今天终于把实验做了一遍实验过程如下
C:\>debug32 c:\masm\qiguai.exe
Debug32 - Version 1.0 - Copyright (C) Larson Computing 1994
CPU = 686, Virtual 8086 Mode, Id/Step = 067A, A20 enabled
-r
AX=0000 BX=0000 CX=0023 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=2186 ES=2186 SS=2196 CS=2196 IP=0005 NV UP DI PL NZ NA PO NC
2196:0005 B80000 MOV AX,0000h
-u
2196:0008 90 NOP
2196:0009 90 NOP
2196:000A BF0800 MOV DI,0008h
2196:000D BE2000 MOV SI,0020h
2196:0010 2E8B04 MOV AX,CS:[SI]
2196:0013 2E8905 MOV CS:[DI],AX
2196:0016 EBF0 JMP Short 0008
2196:0018 B80000 MOV AX,0000h
2196:001B CD21 INT 21h
2196:001D B80000 MOV AX,0000h
2196:0020 EBF6 JMP Short 0018
2196:0022 90 NOP
-r
AX=0000 BX=0000 CX=0023 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=2186 ES=2186 SS=2196 CS=2196 IP=0005 NV UP DI PL NZ NA PO NC
2196:0005 B80000 MOV AX,0000h
-t
AX=0000 BX=0000 CX=0023 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=2186 ES=2186 SS=2196 CS=2196 IP=0008 NV UP DI PL NZ NA PO NC
2196:0008 90 NOP
Trace Interrupt
-t
AX=0000 BX=0000 CX=0023 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=2186 ES=2186 SS=2196 CS=2196 IP=0009 NV UP DI PL NZ NA PO NC
2196:0009 90 NOP
Trace Interrupt
-t
AX=0000 BX=0000 CX=0023 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=2186 ES=2186 SS=2196 CS=2196 IP=000A NV UP DI PL NZ NA PO NC
2196:000A BF0800 MOV DI,0008h
Trace Interrupt
-t
AX=0000 BX=0000 CX=0023 DX=0000 SP=0000 BP=0000 SI=0000 DI=0008
DS=2186 ES=2186 SS=2196 CS=2196 IP=000D NV UP DI PL NZ NA PO NC
2196:000D BE2000 MOV SI,0020h
Trace Interrupt
-t
AX=0000 BX=0000 CX=0023 DX=0000 SP=0000 BP=0000 SI=0020 DI=0008
DS=2186 ES=2186 SS=2196 CS=2196 IP=0010 NV UP DI PL NZ NA PO NC
2196:0010 2E8B04 MOV AX,CS:[SI]
Trace Interrupt
-t
AX=F6EB BX=0000 CX=0023 DX=0000 SP=0000 BP=0000 SI=0020 DI=0008
DS=2186 ES=2186 SS=2196 CS=2196 IP=0013 NV UP DI PL NZ NA PO NC
2196:0013 2E8905 MOV CS:[DI],AX
Trace Interrupt
-u 2196:0
2196:0000 B8004C MOV AX,4C00h
2196:0003 CD21 INT 21h
2196:0005 B80000 MOV AX,0000h
2196:0008 90 NOP
2196:0009 90 NOP
2196:000A BF0800 MOV DI,0008h
2196:000D BE2000 MOV SI,0020h
2196:0010 2E8B04 MOV AX,CS:[SI]
2196:0013 2E8905 MOV CS:[DI],AX
2196:0016 EBF0 JMP Short 0008
2196:0018 B80000 MOV AX,0000h
2196:001B CD21 INT 21h
-r
AX=F6EB BX=0000 CX=0023 DX=0000 SP=0000 BP=0000 SI=0020 DI=0008
DS=2186 ES=2186 SS=2196 CS=2196 IP=0013 NV UP DI PL NZ NA PO NC
2196:0013 2E8905 MOV CS:[DI],AX
-t
AX=F6EB BX=0000 CX=0023 DX=0000 SP=0000 BP=0000 SI=0020 DI=0008
DS=2186 ES=2186 SS=2196 CS=2196 IP=0016 NV UP DI PL NZ NA PO NC
2196:0016 EBF0 JMP Short 0008
Trace Interrupt
-u 2196:0
2196:0000 B8004C MOV AX,4C00h
2196:0003 CD21 INT 21h
2196:0005 B80000 MOV AX,0000h
2196:0008 EBF6 JMP Short 0000
2196:000A BF0800 MOV DI,0008h
2196:000D BE2000 MOV SI,0020h
2196:0010 2E8B04 MOV AX,CS:[SI]
2196:0013 2E8905 MOV CS:[DI],AX
2196:0016 EBF0 JMP Short 0008
2196:0018 B80000 MOV AX,0000h
2196:001B CD21 INT 21h
2196:001D B80000 MOV AX,0000h
-u
2196:0020 EBF6 JMP Short 0018
2196:0022 90 NOP
2196:0023 0000 ADD [BX+SI],AL
2196:0025 0000 ADD [BX+SI],AL
2196:0027 0000 ADD [BX+SI],AL
2196:0029 0000 ADD [BX+SI],AL
2196:002B 0000 ADD [BX+SI],AL
2196:002D 0000 ADD [BX+SI],AL
2196:002F 0000 ADD [BX+SI],AL
2196:0031 0000 ADD [BX+SI],AL
2196:0033 0000 ADD [BX+SI],AL
2196:0035 0000 ADD [BX+SI],AL
感觉最重要的地方是对EBF6的理解,其次是编译的问题,因为程序是要先经过编译再到cpu中运行,cup 并不执行编译的过程,我用的是masm5.0编译器 | | |
|
|
|
|
[第20楼]
[ 回复时间:2010-03-03 20:46 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2010-02-27 23:38 |
|
|
|
|
|
[第21楼]
[ 回复时间:2010-04-06 17:23 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2010-03-29 16:48 |
|
|
|
|
|
[第22楼]
[ 回复时间:2010-07-18 11:33 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2010-07-12 14:54 |
大家现在都知道S2:处的机器码是EBF6,是偏移-10的意思。但大家有没注意AX的内容?AX是 F6EB。内存中的存放是这样的 EB F6 。也就是说,指令和数据的读取顺序不一样!对吗?? | | |
|
|
|
|
[第23楼]
[ 回复时间:2010-09-29 11:09 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2010-06-19 23:55 |
4、7楼太酷了。 我说一下22楼的问题吧:数据的高位字节对应高位内存地址,低位字节对应低位内存地址。这是数据的读取规则。送往AX的是数据! | | |
|
|
|
|
[第24楼]
[ 回复时间:2011-01-20 13:13 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-01-14 12:26 |
|
|
|
|
|
[第25楼]
[ 回复时间:2011-02-26 01:56 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-10-07 14:18 |
大家真的名白了吗???EBF6不是偏移-10的意思(肯定是没做实验,强烈要求做实验哈!!) | | |
|
|
|
|
[第26楼]
[ 回复时间:2011-05-01 16:31 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-04-13 10:10 |
回复:[第7楼]
------------------
七楼说的很明白,小弟受教了。不过,有点小疑问:
[此位移量也可由指令's2:jmp short s1'处的偏移地址18h减去指令's2:jmp short s1'后一个字节的偏移地址22h得出]
为什么可以这样算啊?? | | |
|
|
|
|
[第27楼]
[ 回复时间:2011-06-12 12:56 ]
[引用]
[回复]
[ top ] | |
荣誉值:3
信誉值:0
注册日期:2008-06-04 16:24 |
回复:[第26楼]
有点小疑问:
[此位移量也可由指令's2:jmp short s1'处的偏移地址18h减去指令's2:jmp short s1'后一个字节的偏移地址22h得出]
为什么可以这样算啊??
------------------
回复:jmp short 标号的功能为:(IP)=(IP)+8位位移。位移由:标号处的地址-jmp指令后的第一个字节的地址”于是就由0018h-0022h=-000ah(-00ah即十进制-10,补码表示为:F6。) | | |
|
|
|
|
[第28楼]
[ 回复时间:2011-07-01 14:06 ]
[引用]
[回复]
[ top ] | |
荣誉值:1
信誉值:0
注册日期:2011-05-30 14:33 |
|
|
|
|
|
[第29楼]
[ 回复时间:2011-11-12 21:54 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2010-02-02 22:22 |
|
|
|
|
|
[第30楼]
[ 回复时间:2011-11-14 21:30 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-08-26 16:03 |
|
|
|
|
|
[第31楼]
[ 回复时间:2013-08-13 16:49 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2013-08-09 19:11 |
|
|
|
|
|
[第32楼]
[ 回复时间:2014-08-06 10:21 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2012-08-27 13:18 |
|
|
|
|
|
[第33楼]
[ 回复时间:2016-01-20 20:34 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2016-01-08 09:56 |
我觉得楼上都解释的太复杂了。
要明白实验8,要明白2点。
1、汇编指令是机器码的表现形式。也就是,我们看到的是汇编指令,其实应该透过指令看到它所代表的机器码。
2、CPU执行指令的过程。
然后,对这个实验8,本人分析如下。
当执行到s0处的指令jmp short s,
跳转到 标号s 处的指令,这个时候,根据前面代码的效果,s处的指令应该是 jmp short s1
这个时候,如果理解为,跳转到s1就错了。
应该看到,汇编指令只是我们理解的表现形式,机器CPU真正执行的是这条汇编指令表示的
机器码。
jmp short s1 对应的机器码是 EB F6。此处指令的偏移地址(IP)=0008H。 EB代表指令jmp,F6代表位移。
F6转化为十进制是-10
根据跳转原理,(IP)=(IP)+(-10).
根据CPU执行指令的过程,读取s:jmp short s1这条指令到指令缓冲器后,IP指向mov di,offset s
,即此时IP=000AH
然后机器CPU执行EB F6,然后(IP)=000AH+(-10)=0000H。指向mov ax,4c00H | | |
|
|
|
|
[第34楼]
[ 回复时间:2016-02-02 10:20 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2016-02-02 09:48 |
33楼的解释非常经典,尤其是这句“汇编指令只是我们理解的表现形式,机器CPU真正执行的是这条汇编指令表示的机器码。” | | |