. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->[bx]和loop指令
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  实验四第三个上机试验根本行不通,我用我自己的方法来解决  [待解决] 回复[ 41次 ]   点击[ 3372次 ]  
helloworld
[帖 主]   [ 发表时间: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的前一个单元,就跟问题的要求符合了!
helloworld
[第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>
helloworld
[第2楼]   [ 回复时间:2007-10-26 00:39 ]   [引用]   [回复]   [ top ] 
荣誉值:10
信誉值:6
注册日期:2007-10-20 14:34
int 21H 那几条也复制过去了 但F8后面不知道怎么变成CC了 而最后本来是CC的反倒变成00了
这个可能是我多次覆盖搞出来的偏差,你们试试看
fishboy
[第3楼]   [ 回复时间:2007-10-26 09:48 ]   [引用]   [回复]   [ top ] 
荣誉值:283
信誉值:0
注册日期:2007-06-26 11:42
mov ax, (这里很多人说填cx,但我根本就不懂填cx有什么意义) 
=======
cx在程序一加载的时候,记录的是程序的长度。这个楼主自己不是也说出来了。
fishboy
[第4楼]   [ 回复时间:2007-10-26 09:49 ]   [引用]   [回复]   [ top ] 
荣誉值:283
信誉值:0
注册日期:2007-06-26 11:42
to 2楼:
你的程序出了Program terminated normally ,非正常终止。不知道影响没影响你的结果呢。
helloworld
[第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的值
helloworld
[第6楼]   [ 回复时间:2007-10-26 10:51 ]   [引用]   [回复]   [ top ] 
荣誉值:10
信誉值:6
注册日期:2007-10-20 14:34
反正我用mov ax,cx
        mov ds,ax

这两条指令开头,后面的照抄书上的,复制到00200H内存的数据根本就和EXE的机器码不一样
happy
[第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就对了?
heshen75
[第8楼]   [ 回复时间:2007-11-01 12:05 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2007-09-29 20:49
我认为开头指令应该是:MOV AX,CS
                   MOV DS,AX
就是第二个问题,有多少个字节?如何知道要复制的字节的数量?
fishboy
[第9楼]   [ 回复时间:2007-11-01 12:25 ]   [引用]   [回复]   [ top ] 
荣誉值:283
信誉值:0
注册日期:2007-06-26 11:42
cx在程序一加载的时候,记录的是程序的长度。
lijangwei
[第10楼]   [ 回复时间:2007-11-05 17:32 ]   [引用]   [回复]   [ top ] 
荣誉值:7
信誉值:9
注册日期:2007-11-01 20:06
楼主太猛了,这么一点的问题都能找出来,佩服!
lijangwei
[第11楼]   [ 回复时间:2007-11-05 17:33 ]   [引用]   [回复]   [ top ] 
荣誉值:7
信誉值:9
注册日期:2007-11-01 20:06
楼主对这个问题是吃透了.真猛.
lijangwei
[第12楼]   [ 回复时间:2007-11-05 17:41 ]   [引用]   [回复]   [ top ] 
荣誉值:7
信誉值:9
注册日期:2007-11-01 20:06
我试过的,楼主的结果完全正确,支持你啊,楼主
shanguianti
[第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。
Wednesday
[第14楼]   [ 回复时间:2007-11-06 10:46 ]   [引用]   [回复]   [ top ] 
荣誉值:43
信誉值:3
注册日期:2007-07-05 19:53
[helloworld]
int 21H 那几条也复制过去了 但F8后面不知道怎么变成CC了 而最后本来是CC的反倒变成00了 
这个可能是我多次覆盖搞出来的偏差,你们试试看
-------------------------------------------------------------------------------

研究了吗?为什么变成“CC”这个数据? 继续讨论

可以参考:
http://www.asmedu.net/blog/user/postcontent.jsp?neighborId=4739&kindId=3319&postId=3649&readSg=1&vs=1
wyc520
[第15楼]   [ 回复时间:2008-02-04 13:50 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-01-05 13:50
我还是不懂,怎办呢?
因为疑问多多!!
尽管楼主,得出来的结果是符合要求,但如果前面再加个数据段,怎办呢?你要怎样确定其位置呢?
所以我感觉这个方法有点不可取!
negatlov
[第16楼]   [ 回复时间:2008-02-25 16:25 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-02-24 19:41
没必要算出28
nasaga
[第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看到程序长度
全靠人工算,结果还出错
xiaofeng176
[第18楼]   [ 回复时间:2008-04-24 18:07 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:1
注册日期:2008-04-17 11:21
我用的是mov ax,code,因为那个前面再没代码了,所以就这么写了,不过也谢谢楼主说的这种思维
ratboy
[第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,_____ "
那么我们就会更少的计算复制的字节数量
ratboy
[第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
onei
[第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命令有关,如果程序被一次执行的话,就没会出现这种情况,应该还是中断的问题吧?推测是,不敢确定,我还没看到中断....
onei
[第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字节,请问那区别在哪呢?
lnkm
[第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,我觉得这也对。
leefox
[第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指向的就是代码
mess
[第25楼]   [ 回复时间:2008-07-15 16:05 ]   [引用]   [回复]   [ top ] 
荣誉值:337
信誉值:0
注册日期:2008-01-01 17:48
楼上的兄弟好详细啊,帮顶
p4ti5
[第26楼]   [ 回复时间:2008-08-29 17:22 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2008-08-29 16:35
支持24楼!

完全正确
linfeng0521
[第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处
我已经吧图片截屏了,可惜不会发
aimy
[第28楼]   [ 回复时间:2008-11-06 16:06 ]   [引用]   [回复]   [ top ] 
荣誉值:4
信誉值:0
注册日期:2008-10-30 16:26
我想问个问题mov ax,code  ;这里的CODE什么意思,是assume cs:code吗?如果是那code和CS中内容是一样的吗
                            
请大侠解释下
tianyanly1984
[第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是伪指令,没有对应机器码,由编译器执行.也不知道我的科不科学,这是我的理解!!!
hanlsheng
[第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
我想这个程序更好理解!
lewvan00
[第31楼]   [ 回复时间:2009-04-14 23:07 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-03-31 10:39
mov 语句不同的寻址方式该指令需要的字节不一样 有的是3个有的是2个~~~
am i right?
zhenglxd
[第32楼]   [ 回复时间:2009-05-04 12:58 ]   [引用]   [回复]   [ top ] 
荣誉值:30
信誉值:0
注册日期:2009-04-09 10:05
题目要你做什么你就做什么,懂命题作文不?
zhy_zhy
[第33楼]   [ 回复时间:2009-07-13 15:00 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:2
注册日期:2009-06-29 14:39
支持sub cx,5!!!
当然20楼的也可以。
但我觉得王爽老师并不是让我们去背指令长度吧?前面根本没有类似的语句要求我们或告诉我们啊,突然出现在试验题里也不太正常吧?
inuyashall
[第34楼]   [ 回复时间:2009-08-01 00:11 ]   [引用]   [回复]   [ top ] 
荣誉值:9
信誉值:1
注册日期:2009-05-09 14:55
to 2L:
Program terminated normally 的意思不是正常终止么?- -
chen19910919
[第35楼]   [ 回复时间:2009-08-28 02:32 ]   [引用]   [回复]   [ top ] 
荣誉值:15
信誉值:0
注册日期:2009-07-08 20:35
回复:[贴 主]
------------------
楼主的那个结论是个错的,MOV CX ,“” 后面应是1A=26才对
sigh
[第36楼]   [ 回复时间:2009-09-17 10:26 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-09-16 04:17
这帖讨论的真透彻,确实sub cx比较好
zhengxinyi
[第37楼]   [ 回复时间:2009-09-21 17:19 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-09-21 16:51
前几天看到了有人发了一篇帖子,提到训练营的教程有很多错误,而且又涉嫌抄袭,那位网友应该是为了引起汇编网的注意吧,发了很多帖子,不过全都被管理员删掉了。
训练营的教程到底是怎么回事呢?
据我所知,确实有不少人对此有意见了,汇编网的回答又让人不满意。
我也发很多帖子,看看会怎么样
zhllhz
[第38楼]   [ 回复时间:2009-12-20 12:56 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:4
注册日期:2009-12-18 19:17
回复:[第14楼]
------------------
网只连接到的文章被删除了。。。。
继续思考
renhaidulang
[第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
huibianzhiwang
[第40楼]   [ 回复时间:2011-08-16 00:33 ]   [引用]   [回复]   [ top ] 
荣誉值:3
信誉值:0
注册日期:2011-07-19 22:32
24楼总结的很不错 我也是最近才悟出来的!
laymond
[第41楼]   [ 回复时间:2018-01-22 13:10 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2018-01-22 12:51
回复:[第14楼]
------------------
10年过去了,学习汇编的 人还多么,14楼说法 是对的,我是直接查看 指令占用字节数,在来确定cx的次数,虽然复制过程 loop 指令对应的值不一样,但是指向的地址和原来一样就行。
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved