|
主题 : : 实验8遇到的问题 [待解决] |
回复[ 16次 ]
点击[ 1110次 ] | |
|
|
|
|
[帖 主]
[ 发表时间:2009-03-26 08:31 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-03-06 09:35 |
实验8
这个程序,刚看时觉得不能正确返回。
后来上机操作后,发现能返回。但是一直不明白为什么JMP 0008后就是JMP 0000,反复操作了很多遍,还是不明白怎么回事。JMP 0008后IP等于-10,也就是F6了,然后就卡住了。
我是不是可以这样理解:
当执行完
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax这四条指令后,s2处的指令被复制到标号S处覆盖了两个nop,接着cpu读取指令jmp short s,此时ip指向mov ax,0.然后cpu执行jmp short s,此时跳转位移=8h-18=-10H,ip=18h+8位位移=18h-10h=8h,ip指向标号s处,读取被复制到此处的s2的指令,ip指向0AH。CPU执行jmp short s1时,跳转位移=18h-22h=-0Ah,ip=0Ah-0Ah=0,然后程序就正确返回了。
还有两个地方我不太明白:
1,指令在内存里是以二进制的形式储存的,所以复制指令时只要复制指令的物理地址就行了,是不是?
2,S2处的指令被复制到标号S处时,它的跳转位移也同样被复制了吗? | | |
|
|
|
|
[第1楼]
[ 回复时间:2009-03-26 12:46 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-03-16 10:57 |
看楼主上面所说,相信楼主一定没调试过这个程序,建议楼主用debug再重新调试一下仔细看看每条指令执行的顺序是不是真的跟你说的一样,还有程序复制的内容是该内存单元的数据。 | | |
|
|
|
|
[第2楼]
[ 回复时间:2009-03-26 15:31 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-03-06 09:35 |
|
|
|
|
|
[第3楼]
[ 回复时间:2009-03-26 18:01 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-03-16 10:57 |
那当s2处的指令被复制到标号s处覆盖了两个nop,接着cpu读取的指令在debug中显示出来的是jmp short s?仔细看看这里的机器码以及指令,关键就在这里! | | |
|
|
|
|
[第4楼]
[ 回复时间:2009-03-26 18:03 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-03-16 10:57 |
楼主一定要明白这条jmp指令后面跟的是什么,目的地址?还是位移呢?好好想想 | | |
|
|
|
|
[第5楼]
[ 回复时间:2009-03-28 00:03 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-01-03 23:01 |
我也是新手,看了好一阵子,后来才明白怎么回事.
正如课本开始时所说,在计算机里,指令和数据只是应用上的概念.在内存里都是二进制信息,所以楼主不要区分复制的是指令还是什么,只要把这两个字节复制过去就行了.
jmp指令编译成二进制机器指令后,都是EBxx,XX认为是一个偏移值.我们用U命令在debug环境下看到,同样的二进制机器指令EBF6,在S2这个位置是JMP 0018,而在S这个位置是JMP 0000,是因为U命令在已经做了IP-10H的计算,0000和0018已经是目的地址了。正如x_miracle 所问的那样,jmp指令在CPU执行时其实根本不需要转移的目的地址. | | |
|
|
|
|
[第6楼]
[ 回复时间:2009-04-11 21:24 ]
[引用]
[回复]
[ top ] | |
荣誉值:11
信誉值:0
注册日期:2009-03-19 18:06 |
首先要明确,EBF6中,F6是位移,而且是二进制的补码形式。转化为10进制,是-10,转化为16进制数,是-Ah,不是什么-10h
靠后的那个jmp指令位置是1454:0020,占用2个字节。因此,在执行这条指令以前(已取出,放入了缓冲器),ip自加2,指向了下一条指令的首地址1454:0022,然后执行指令EBF6,0022h-Ah=0018h(16进制减法),翻译成汇编指令是jmp 0018
靠前的那个复制过去的指令,复制的是机器码EBF6,占用了1454:0008开始的两个字节单元。因此,执行这条指令时,ip是指向1454:00a0的。00a0-a=0000.翻译成汇编指令是jmp 0000.
总结:一个exe程序中,所有的汇编代码都已经被转化为机器代码,也就是二进制的形式了。debug中的指令,是根据内存单元中的机器代码翻译过来的。因此,执行复制时复制的是二进制数据,不是指令本身。同一个数据,比如上面的EBF6,在不同的地方,可以解释为不同的汇编指令jmp 0018 和jmp 0000.当然,如果不包含位移,只包含绝对地址,那么机器指令处在内存中的任何位置,都解释为相同的汇编指令。 | | |
|
|
|
|
[第7楼]
[ 回复时间:2009-04-23 13:05 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-03-06 09:35 |
|
|
|
|
|
[第8楼]
[ 回复时间:2009-12-15 13:43 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:2
注册日期:2009-11-26 12:16 |
那么 s1:mov ax,0
int 21h
mov ax,0
中的int 21h有什么作用呢? | | |
|
|
|
|
[第9楼]
[ 回复时间:2010-11-11 22:13 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:2
注册日期:2010-10-25 16:06 |
1404:001B CD21 INT 21
1404:001D B80000 MOV AX,0000;复制jmp short s1以前,机器码为EBF6,
1404:0020 EBF6 JMP 0018;此时跳向F6+22=18H
1404:0022 90 NOP
1404:0023 0000 ADD [BX+SI],AL
1404:0000 B8004C MOV AX,4C00;复制jmp short s1后
1404:0003 CD21 INT 21; jmp short s1d 1404:8处
1404:0005 B80000 MOV AX,0000;此时跳向f6h+0ah=0处,即1404:0(start)处
1404:0008 EBF6 JMP 0000
1404:000A BF0800 MOV DI,0008 | | |
|
|
|
|
[第10楼]
[ 回复时间:2010-12-08 14:57 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2010-12-04 20:54 |
一定要记着,标号是编译器处理的,CPU不认识。CPU只知道跳转距离 | | |
|
|
|
|
[第11楼]
[ 回复时间:2011-01-20 01:49 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2010-12-24 15:57 |
11楼 的大哥解释的很详细,受教了。就是有个地方写错了吧--....ip是指向1454:00a0的。00a0-a=0000... 是 1454:000a | | |
|
|
|
|
[第12楼]
[ 回复时间:2011-02-23 23:11 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-02-07 15:40 |
|
|
|
|
|
[第13楼]
[ 回复时间:2011-05-13 15:29 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2010-06-23 00:14 |
EBF6其中的F6是指要位移多少个字节,F6要是转换成10进制的话是246。JMP的位移范围是在负的128到127之间,246显然是不对的。所以F6是以补码的形式存在的。由于这个是补码形式所以感觉有点纠结。 | | |
|
|
|
|
[第14楼]
[ 回复时间:2011-05-25 15:13 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-05-18 15:55 |
一针见血的回答:这里复制的不是/ jmp short s1/这条指令本身,而是这条指令在S2处的机器码,也就是该处内存中的两个字节数据 EB F6,执行这条指令,将IP前移10d.很多同学之所以迷惑,就是因为想当然的用/jmp short s1/来替换了S处两个NOP,实际上S处相应的汇编指令根本就不可能是/JMP SHORT S1/.而是根据EB F6 直接计算出目的地址 0000,也即 MOV AX,4C00处。
这个例子让我们深刻的记住,复制的是内存的数据,并不一定是汇编指令本身!!!切记 | | |
|
|
|
|
[第15楼]
[ 回复时间:2011-05-25 15:16 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-05-18 15:55 |
至于这个距离 EBF6是怎么算出来的,编译器在编译程序的时候,根据S1和S2的位置就算出来了,并将其保存在S2的内存处,也即EBF6.执行复制命令后,将EBF6这个字复制到S处。 | | |
|
|
|
|
[第16楼]
[ 回复时间:2012-01-26 02:27 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2012-01-10 21:29 |
|