|
主题 : : 实验四第三个上机试验根本行不通,我用我自己的方法来解决 [待解决] |
回复[ 41次 ]
点击[ 3372次 ] | |
|
|
|
|
[帖 主]
[ 发表时间:2007-10-26 00:30 ]
[引用]
[回复]
[ top ] | |
荣誉值:10
信誉值:6
注册日期:2007-10-20 14:34 |
mov ax, (这里很多人说填cx,但我根本就不懂填cx有什么意义)
这个代码的整体原理,从下面可以看清ES和[BX]用来指向00200H的地址了,也就是说现在的问题只是要代码可以将自己运行时,所使用的那个内存单元段保存起来,然后向这个单元段里逐个逐个字节的取出来,循环放到ES:[BX]上面
根据第四章来提到过的,一个EXE运行时必定要先载入到内存里,而DS寄存器里存放的就是当前EXE的文件头,前256个字节是用于DOS系统保留来干正事的,所以DS里存放的段地址,再往后偏移0010H就是指向EXE文件的第一条指令的内存地址,这样第一个问题“从哪里复制”就可以解决了,然后第二个问题是复制多少,第四章也说过CX存放的就是整个EXE文件里所有汇编指令的长度,所以循环的次数就是CX中的值,我修改后的代码长度为001FH,转成十进制就是31,就是循环31次。
我修改后的代码如下
assume cs:mycode
mycode segment
mov ax,ds
add ax,0010H
mov ds,ax
mov ax,0020h
mov es,ax
mov bx,0
mov cx,28
s:mov al,[bx]
mov es:[bx],al
inc bx
loop s
mov ax,4c00h
int 21h
mycode ends
end
用T逐条运行之后,再拿00200H处的内存来比较,刚好修改到mov ax.4c00h的前一个单元,就跟问题的要求符合了! | | |
|
|
|
|
[第1楼]
[ 回复时间:2007-10-26 00:37 ]
[引用]
[回复]
[ top ] | |
荣誉值:10
信誉值:6
注册日期:2007-10-20 14:34 |
mov cx,28 这里改一下 改31 我修改后忘了改了
下面是我调试后将两段内存做的对比
AX=4C00 BX=001F CX=0000 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0B8C ES=0020 SS=0B8C CS=0B8C IP=001D NV UP EI PL NZ NA PO NC
0B8C:001D CD21 INT 21
-p
Program terminated normally
-d 0b8c:0 1f
0B8C:0000 8C D8 83 C0 10 8E D8 B8-20 00 8E C0 BB 00 00 B9 ........ .......
0B8C:0010 1F 00 8A 07 26 88 07 43-E2 F8 B8 00 4C CD 21 CC ....&..C....L.!.
-d 0:0200 1f
^ Error
-d 0:0200 021f
0000:0200 8C D8 83 C0 10 8E D8 B8-20 00 8E C0 BB 00 00 B9 ........ .......
0000:0210 1F 00 8A 07 26 88 07 43-E2 F8 CC 00 4C CD 21 00 ....&..C....L.!.
-q
D:\ASMCOD~1> | | |
|
|
|
|
[第2楼]
[ 回复时间:2007-10-26 00:39 ]
[引用]
[回复]
[ top ] | |
荣誉值:10
信誉值:6
注册日期:2007-10-20 14:34 |
int 21H 那几条也复制过去了 但F8后面不知道怎么变成CC了 而最后本来是CC的反倒变成00了
这个可能是我多次覆盖搞出来的偏差,你们试试看 | | |
|
|
|
|
[第3楼]
[ 回复时间:2007-10-26 09:48 ]
[引用]
[回复]
[ top ] | |
荣誉值:283
信誉值:0
注册日期:2007-06-26 11:42 |
mov ax, (这里很多人说填cx,但我根本就不懂填cx有什么意义)
=======
cx在程序一加载的时候,记录的是程序的长度。这个楼主自己不是也说出来了。 | | |
|
|
|
|
[第4楼]
[ 回复时间:2007-10-26 09:49 ]
[引用]
[回复]
[ top ] | |
荣誉值:283
信誉值:0
注册日期:2007-06-26 11:42 |
to 2楼:
你的程序出了Program terminated normally ,非正常终止。不知道影响没影响你的结果呢。 | | |
|
|
|
|
[第5楼]
[ 回复时间:2007-10-26 10:49 ]
[引用]
[回复]
[ top ] | |
荣誉值:10
信誉值:6
注册日期:2007-10-20 14:34 |
那么再看看书上的例子
mov ax,cx
mov ds,ax
这里将代码的长度赋值给DS,用代码的长度作为段地址有何意义?
我编译后用debug来调试,EXE被载入内存的0B8C段,而CX的值是01FC,当程序执行到循环那一段时:
S: mov al,[bx]
将DS:[bx]内存单元的数据送到al,而这些ds的值是什么?就是你们认为的CX了,这条指令对应的内存地址应该是0B8C,当然你们在调试的时候可能会用了某段不同的空闲地址,并不一 '定是0B8C,但无论地址是什么,绝对不可能这么巧合刚好就是CX的值 | | |
|
|
|
|
[第6楼]
[ 回复时间:2007-10-26 10:51 ]
[引用]
[回复]
[ top ] | |
荣誉值:10
信誉值:6
注册日期:2007-10-20 14:34 |
反正我用mov ax,cx
mov ds,ax
这两条指令开头,后面的照抄书上的,复制到00200H内存的数据根本就和EXE的机器码不一样 | | |
|
|
|
|
[第7楼]
[ 回复时间:2007-10-26 23:32 ]
[引用]
[回复]
[ top ] | |
荣誉值:32
信誉值:0
注册日期:2007-07-14 19:06 |
楼主是不是看错了,
mov ax,cx
mov ds,ax确实是不对吧,是不是应该是
mov ax,cs
mov ds,ax就对了? | | |
|
|
|
|
[第8楼]
[ 回复时间:2007-11-01 12:05 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2007-09-29 20:49 |
我认为开头指令应该是:MOV AX,CS
MOV DS,AX
就是第二个问题,有多少个字节?如何知道要复制的字节的数量? | | |
|
|
|
|
[第9楼]
[ 回复时间:2007-11-01 12:25 ]
[引用]
[回复]
[ top ] | |
荣誉值:283
信誉值:0
注册日期:2007-06-26 11:42 |
|
|
|
|
|
[第10楼]
[ 回复时间:2007-11-05 17:32 ]
[引用]
[回复]
[ top ] | |
荣誉值:7
信誉值:9
注册日期:2007-11-01 20:06 |
|
|
|
|
|
[第11楼]
[ 回复时间:2007-11-05 17:33 ]
[引用]
[回复]
[ top ] | |
荣誉值:7
信誉值:9
注册日期:2007-11-01 20:06 |
|
|
|
|
|
[第12楼]
[ 回复时间:2007-11-05 17:41 ]
[引用]
[回复]
[ top ] | |
荣誉值:7
信誉值:9
注册日期:2007-11-01 20:06 |
|
|
|
|
|
[第13楼]
[ 回复时间:2007-11-06 08:10 ]
[引用]
[回复]
[ top ] | |
荣誉值:19
信誉值:0
注册日期:2007-10-31 16:24 |
这道题其实很有意思。复制的代码段其实也就是CS:IP所指向的内存中的数据,也就是说一段内存中的数据复制到另一段内存中去。因此,首先要解决的是所要复制的数据的起始地址,其次呢,就是数据的长度。尤其是数据的长度,可能很多人都有疑问。其实只要把代码反汇编就可以弄清楚,mov用在寄存器之间传送数据的指令是2个字节,用在寄存器和立即数之间是3个字节,用在寄存器和ES:[BX]这之间是3个字节。inc指令占用一个字节,loop s占用两个字节。题目所要求的数据长度加起来应该是23个字节,也就是0017H。 | | |
|
|
|
|
[第14楼]
[ 回复时间:2007-11-06 10:46 ]
[引用]
[回复]
[ top ] | |
荣誉值:43
信誉值:3
注册日期:2007-07-05 19:53 |
|
|
|
|
|
[第15楼]
[ 回复时间:2008-02-04 13:50 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-01-05 13:50 |
我还是不懂,怎办呢?
因为疑问多多!!
尽管楼主,得出来的结果是符合要求,但如果前面再加个数据段,怎办呢?你要怎样确定其位置呢?
所以我感觉这个方法有点不可取! | | |
|
|
|
|
[第16楼]
[ 回复时间:2008-02-25 16:25 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-02-24 19:41 |
|
|
|
|
|
[第17楼]
[ 回复时间:2008-02-29 07:03 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-02-27 05:17 |
呵呵,其实不用算前面程序的长度的
程序启动时,CX里的初始值就是程序全部指令的长度
我们不想复制的只有
mov ax,4c00h
int 21h
这两行,这两行的机器码字节数应该很好确认,5个单位
只要能让(cx)=(cx)-5,CX的值就是我们要复制的字节总数了,也就是循环的次数(循环就是1次复制1字节)
mov cx,_____
我怀疑这里是印刷错误?也有可能是王老师故意设障让我们对机器指令的字节长度有所了解
这里如果改写成 sub cx,_____
就一点问题都没了
网上那个答案说服力也不是很够,虽然确实可以实现,但是那可真是笨办法啊
没填好之前不能上机,不能上机就没法用DEBUG看到程序长度
全靠人工算,结果还出错 | | |
|
|
|
|
[第18楼]
[ 回复时间:2008-04-24 18:07 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:1
注册日期:2008-04-17 11:21 |
我用的是mov ax,code,因为那个前面再没代码了,所以就这么写了,不过也谢谢楼主说的这种思维 | | |
|
|
|
|
[第19楼]
[ 回复时间:2008-05-06 17:48 ]
[引用]
[回复]
[ top ] | |
荣誉值:2
信誉值:0
注册日期:2008-04-19 14:53 |
程序调试出来了,通过实验,我的做法:
assume cs:coderat
coderat segment
mov ax,cs
mov ds,ax
mov ax,0020h
mov es,ax
mov bx,0
mov cx,24
s:mov al,[bx]
mov es:[bx],al
inc bx
loop s
mov ax,4c00h
int 21h
coderat ends
end
其中第一步肯定是
mov ax,cs
当然,楼主这么写
mov ax,ds
add ax,0010H
其实就等同于我的mov ax,cs
( 因为(cs)=(ds)+0010h )
而至于问题:“如何知道复制的字节数量”
我参考shanguianti 的意见:“mov用在寄存器之间传送数据的指令是2个字节,用在寄存器和立即数之间是3个字节,用在寄存器和ES:[BX]这之间是3个字节。inc指令占用一个字节,loop s占用两个字节”
同时我也很赞同nasaga 的意见:“如果改写成 sub cx,_____ "
那么我们就会更少的计算复制的字节数量 | | |
|
|
|
|
[第20楼]
[ 回复时间:2008-05-06 18:34 ]
[引用]
[回复]
[ top ] | |
荣誉值:2
信誉值:0
注册日期:2008-04-19 14:53 |
我晕
实验发现
mov al,[bx]
指令只是2个字节,我多数了一个进去
上面的代码应该改为
assume cs:coderat
coderat segment
mov ax,cs
mov ds,ax
mov ax,0020h
mov es,ax
mov bx,0
mov cx,23
s:mov al,[bx]
mov es:[bx],al
inc bx
loop s
mov ax,4c00h
int 21h
coderat ends
end | | |
|
|
|
|
[第21楼]
[ 回复时间:2008-05-15 15:34 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-02-26 16:41 |
回复:[第14楼]
[helloworld]
int 21H 那几条也复制过去了 但F8后面不知道怎么变成CC了 而最后本来是CC的反倒变成00了
这个可能是我多次覆盖搞出来的偏差,你们试试看
-------------------------------------------------------------------------------
研究了吗?为什么变成“CC”这个数据? 继续讨论
------------------
这个CC好像和DEBUG里的T命令有关,如果程序被一次执行的话,就没会出现这种情况,应该还是中断的问题吧?推测是,不敢确定,我还没看到中断.... | | |
|
|
|
|
[第22楼]
[ 回复时间:2008-05-15 15:43 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-02-26 16:41 |
assume cs:codesg
codesg segment
mov ax,cs
mov ds,ax
mov ax,0020h
mov es,ax
mov bx,0
mov cx,cx
s: mov al,[bx]
mov es:[bx],al
inc bx
loop s
mov ax,4c00h
int 21h
codesg ends
end
我的程序如上,完全按书上敲下来的.
C:\ASM>debug lab43.exe
-r
AX=0000 BX=0000 CX=001B DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=14FD ES=14FD SS=150D CS=150D IP=0000 NV UP EI PL NZ NA PO NC
150D:0000 8CC8 MOV AX,CS
-u
150D:0000 8CC8 MOV AX,CS
150D:0002 8ED8 MOV DS,AX
150D:0004 B82000 MOV AX,0020
150D:0007 8EC0 MOV ES,AX
150D:0009 BB0000 MOV BX,0000
150D:000C 8BC9 MOV CX,CX
150D:000E 8A07 MOV AL,[BX]
150D:0010 26 ES:
150D:0011 8807 MOV [BX],AL
150D:0013 43 INC BX
150D:0014 E2F8 LOOP 000E
150D:0016 B8004C MOV AX,4C00
150D:0019 CD21 INT 21
150D:001B 92 XCHG DX,AX
150D:001C 3E DS:
150D:001D 2B2EC706 SUB BP,[06C7]
-
可是DEBUG载入后CX=1B,即程序总长度为1B字节,减去mov ax,4c00h和int 21h两句话的5字节,应该是16H字节,为什么大家都得17H或18H字节呢?我得16H字节和大家的结果差了1字节,请问那区别在哪呢? | | |
|
|
|
|
[第23楼]
[ 回复时间:2008-05-23 11:37 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-04-14 12:38 |
我的程序是这样的:
assume cs:code
code segment
mov ax, cs
mov ds, ax
mov ax, 0020h
mov es, ax
mov bx, 0
mov cx, 17h ;这里先随便填一个数,debug后u一下看看,再改为正确的,我改后是17h,即23次
s: mov al, [bx]
mov es:[bx], al
inc bx
loop s
mov ax, 4c00h
int 21h
code ends
end
大家看看这个程序对不对。我觉得这道题应该有多个不同答案,因为第一句可以多种答案,有一个参考答案是mov ax,code,我觉得这也对。 | | |
|
|
|
|
[第24楼]
[ 回复时间:2008-05-25 09:40 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-01-21 11:43 |
此题有多个答案,但最终解答离不开shanguianti 的意见:“mov用在寄存器之间传送数据的指令是2个字节,用在寄存器和立即数之间是3个字节,用在寄存器和ES:[BX]这之间是3个字节。inc指令占用一个字节,loop s占用两个字节”
答案1:mov ax,cs (占2个字节)
mov cx,17
答案2:mov ax,code (占3个字节)
mov cx,18
答案3:mov ax,cs 或mov ax,code
把mov cx, 改成 sub cx,5(因为在载入程序时,cx保存程序的长度,减去5是为减去mov ax,4c00h和
int 21h的长度)
总结:
此题王爽老师的目的是:
1、理解CS和CODE的关联
2、CS保存程序的代码段,即“复制的是什么,从哪里到哪里”
3、熟记某些指令的长度,即“复制的是什么,有多少个字节”,具体参考shanguianti 的意见。
4、理解CX在载入程序后保存程序的长度。
5、理解数据和代码对CPU来说是没区别的,只要CS:IP指向的就是代码 | | |
|
|
|
|
[第25楼]
[ 回复时间:2008-07-15 16:05 ]
[引用]
[回复]
[ top ] | |
荣誉值:337
信誉值:0
注册日期:2008-01-01 17:48 |
|
|
|
|
|
[第26楼]
[ 回复时间:2008-08-29 17:22 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-08-29 16:35 |
|
|
|
|
|
[第27楼]
[ 回复时间:2008-10-07 21:24 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2008-08-26 19:04 |
我是这样理解的,根据试验4的前两个试验
mov ax,0h
……
mov cx,64
这样就是把00000-00040h处的数据放到00200-0023f处
我已经吧图片截屏了,可惜不会发 | | |
|
|
|
|
[第28楼]
[ 回复时间:2008-11-06 16:06 ]
[引用]
[回复]
[ top ] | |
荣誉值:4
信誉值:0
注册日期:2008-10-30 16:26 |
我想问个问题mov ax,code ;这里的CODE什么意思,是assume cs:code吗?如果是那code和CS中内容是一样的吗
请大侠解释下 | | |
|
|
|
|
[第29楼]
[ 回复时间:2008-12-22 04:08 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:4
注册日期:2008-12-12 00:18 |
我想问个问题mov ax,code ;这里的CODE什么意思,是assume cs:code吗?如果是那code和CS中内容是一样的吗
请大侠解释下
------------------
回复:
你说的code 就是第一条指令assume cs:code 中与cs代码段关联的code,既然关联了,code就代表的是cs代码段,两都含义是一样的,没有区别,区别就是code是编译器帮你翻译成cs,而cs就是cs,不用编译帮你转换了,应该也可以换句话说,cs是有对应机器代码的汇编指令,而code是伪指令,没有对应机器码,由编译器执行.也不知道我的科不科学,这是我的理解!!! | | |
|
|
|
|
[第30楼]
[ 回复时间:2008-12-24 11:17 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:2
注册日期:2008-12-15 16:17 |
楼主的是正确的,我看过题目没有看代码只是自己尝试下了下代码,debug后我验证了是代码是正确的代码如下:
assume cs:code
code segment
mov ax,20h
mov ds,ax
mov bx,0h
sub cx,5h //cx开始存储了代码的长度,去掉后面的5个长度就符合题目要求
s: mov dl,cs:[bx]
mov [bx],dl
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end
我想这个程序更好理解! | | |
|
|
|
|
[第31楼]
[ 回复时间:2009-04-14 23:07 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-03-31 10:39 |
mov 语句不同的寻址方式该指令需要的字节不一样 有的是3个有的是2个~~~
am i right? | | |
|
|
|
|
[第32楼]
[ 回复时间:2009-05-04 12:58 ]
[引用]
[回复]
[ top ] | |
荣誉值:30
信誉值:0
注册日期:2009-04-09 10:05 |
|
|
|
|
|
[第33楼]
[ 回复时间:2009-07-13 15:00 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:2
注册日期:2009-06-29 14:39 |
支持sub cx,5!!!
当然20楼的也可以。
但我觉得王爽老师并不是让我们去背指令长度吧?前面根本没有类似的语句要求我们或告诉我们啊,突然出现在试验题里也不太正常吧? | | |
|
|
|
|
[第34楼]
[ 回复时间:2009-08-01 00:11 ]
[引用]
[回复]
[ top ] | |
荣誉值:9
信誉值:1
注册日期:2009-05-09 14:55 |
to 2L:
Program terminated normally 的意思不是正常终止么?- - | | |
|
|
|
|
[第35楼]
[ 回复时间:2009-08-28 02:32 ]
[引用]
[回复]
[ top ] | |
荣誉值:15
信誉值:0
注册日期:2009-07-08 20:35 |
回复:[贴 主]
------------------
楼主的那个结论是个错的,MOV CX ,“” 后面应是1A=26才对 | | |
|
|
|
|
[第36楼]
[ 回复时间:2009-09-17 10:26 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-09-16 04:17 |
|
|
|
|
|
[第37楼]
[ 回复时间:2009-09-21 17:19 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2009-09-21 16:51 |
前几天看到了有人发了一篇帖子,提到训练营的教程有很多错误,而且又涉嫌抄袭,那位网友应该是为了引起汇编网的注意吧,发了很多帖子,不过全都被管理员删掉了。
训练营的教程到底是怎么回事呢?
据我所知,确实有不少人对此有意见了,汇编网的回答又让人不满意。
我也发很多帖子,看看会怎么样 | | |
|
|
|
|
[第38楼]
[ 回复时间:2009-12-20 12:56 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:4
注册日期:2009-12-18 19:17 |
回复:[第14楼]
------------------
网只连接到的文章被删除了。。。。
继续思考 | | |
|
|
|
|
[第39楼]
[ 回复时间:2010-04-04 13:58 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2010-04-03 22:07 |
应该是这样的:
assume cs:code(注意这里!)
code(这里!) segment
mov ax,code(还有这里!) -->这里其实就是让代码段和数据段重合
mov ds,ax
mov ax,0020H
mov es,ax
mov bx,0
mov cx,0018H ;-->0018H=24,怎么来的?请看分析:
s: mov al,[bx] ;形如mov 寄存器,数字 这样的,占3个字节;形如mov 寄存器,寄存器 占2个字节
mov es:[bx],al ;这个比较特殊,因为多一个段es引用,所以加1字节,占3字节
inc bx ;占1字节
loops ;占2字节
mov ax,4c00h
int 21h
code ends
所以,楼主自己算一下就可以了。这个规律是通用的,每个指令占几个字节,在设计指令集的时候就确定了。
end | | |
|
|
|
|
[第40楼]
[ 回复时间:2011-08-16 00:33 ]
[引用]
[回复]
[ top ] | |
荣誉值:3
信誉值:0
注册日期:2011-07-19 22:32 |
|
|
|
|
|
[第41楼]
[ 回复时间:2018-01-22 13:10 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2018-01-22 12:51 |
回复:[第14楼]
------------------
10年过去了,学习汇编的 人还多么,14楼说法 是对的,我是直接查看 指令占用字节数,在来确定cx的次数,虽然复制过程 loop 指令对应的值不一样,但是指向的地址和原来一样就行。 | | |