中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » 网络日志(Blog) » 【Redtek】 个人网志(学习笔记)
« [1] [2] [3] [4] [5] [6] [7] [8] [9] »
作者:
标题: 【Redtek】 个人网志(学习笔记) 上一主题 | 下一主题
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 61 楼』:  关于批处理嵌入超长汇编代码

[原创][批处理单行显示多种颜色字符]
http://www.cn-dos.net/forum/view ... ghlight=&page=2

上面贴子的第27楼:

  qzwqzw兄提到了:“从可读性上来讲,可以将汇编脚本分行下载批处理前段,这样的形式可以更好的注释”。

  感谢qzwqzw兄精彩的指点,原来水平无法实现这个功能,现在可以实现了:)

  而且根据qzwqzw兄指点,如果按这种方法做,可以在 .Bat 批处理中嵌入超长汇编代码,如嵌入数百行……

  也就是说可以执行非常复杂的汇编了,且还与批处理合二为一。

  而且,这种内嵌方式也解决了纯 MS-DOS 下命令行长度不能过长的一大障碍~:)


  如果哪天急了,还可以汇编、批处理、VBS三合一合写一个代码(晕晕……)

(刚才测试了一下,有一些障碍~:)

[ Last edited by redtek on 2006-12-23 at 06:14 PM ]



    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-24 06:46
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 62 楼』:  

简单做了一个批处理内嵌汇编代码的实验程序,其最主要的目地是为了完成特殊任务,同时不生成临时文件。
@echo off

        :: 批处理嵌汇编代码实验
        :: Redtek 2006   bbs.cn-dos.net

:start
        ::
        ::
        ::  执行批处理代码段,绕开汇编代码段
        Goto :BatStart

:masm
        a
        mov ah,09
        mov dx,0109
        int 21
        int 20
        db "My name is Redtek!$"
       
        g
        q


:BATStart

        ::  装入当前批处理自身,并定cs代码段为 :masm 批处理标签段内。
        ::  echo exit|cmd /k prompt n %~s0$_l$_ …… (夭折喽~~)
        ::  想到另一个办法~:)
       
        echo exit|cmd /k more +10 %~s0|debug

::        Debug 执行后会显示所执行的过程,此功能可以用将来调用汇编代码来完成复杂计算或写盘,
::        或调用Debug进行非显示方式的后台特殊工作。
::
::
::




    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-24 07:27
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 63 楼』:  【80x86汇编语言学习笔记】

连续的累加指定的内存单元,求和例程。
用 Debug 分析过程。
              assume    cs:code

        code  segment

              mov       ax,0ffffh
              mov       ds,ax
              mov       bx,0
              mov       dx,0

              mov       cx,12
          s:  mov       al,[bx]
              mov       ah,0
              add       dx,ax
              inc       bx
              loop      s

              mov       ax,4c00h
              int       21h

        code  ends
              end
指令区别:

) Masm
  mov  ax,[0]
  将值0传送给ax寄存器

) Debug 汇编直译
  mov  ax,[0]
  相当于: (ax)= ((ds)*16+0)



) Debug 汇编直译
  mov  ax,FFFF
  将 FFFFH 传送到 ax 寄存器

) Masm
  mov  ax,0FFFFH
  功能同上。但在Masm汇编代码中,数据不能以字母开头,所以前必须加0


解决办法: Masm 中使用段前缀 mov ax,ds:[0]
      相当于: (ax)=((ds)*16+0))

    

[ Last edited by redtek on 2006-12-24 at 09:42 AM ]



    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-24 10:13
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 64 楼』:  【80x86汇编语言学习笔记】

安全内存空闲空间

  Quote:
在一般PC机中,DOS方式下,DOS和其他合法的程序一般都不会使用 0:200 ~~ 0:300(00200H~~00300H)的 256 个字节的空间。

所以,我们使用这段空间是安全的~:)



  Quote:
C:\WINDOWS>debug
-r
AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0AF5  ES=0AF5  SS=0AF5  CS=0AF5  IP=0100   NV UP EI PL NZ NA PO NC
0AF5:0100 3533D2        XOR     AX,D233
-D 0:200 300
0000:0200  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0210  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0220  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0230  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0240  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0250  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0260  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0270  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0280  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0290  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:02A0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:02B0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:02C0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:02D0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:02E0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:02F0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0300  00                                                .
-Q





    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-24 22:46
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 65 楼』:  【80x86汇编语言学习笔记】

段前缀的使用


理解将内存 ffff:0 ~~ ffff:b 单元中的数据拷贝到 0:200~0:20b 单元中的过程。
0:200~~0:20b = 200:0 ~~ 200:b

通过循环拷贝地址中的内容,要初始化偏移地址变量bx,赋值循环次数变量cx,循环12次(0~~b)。

例程

  Quote:
;====================================================
;
;将内存 ffff:0 ~~ ffff:b 单元中数据拷贝到0:200~0:20b单元中
;
;====================================================

              assume    cs:code

        code  segment

              mov       bx,0        ; 偏移地址清零(也是从0开始)
              mov       cx,12       ; 循环12次
          s:  mov       ax,0ffffh
              mov       ds,ax       ; 改变ds段地址
              mov       dl,[bx]
              mov       ax,0020h
              mov       ds,ax       ; 改变ds段地址,用于写内存
              mov       [bx],dl     ; 将dl中的数据送入 0020:bx 内存
              inc       bx          ; bx地址递增1
              loop      s

              mov       ax,4c00h
              int       21h

        code  ends
              end

执行后

  Quote:
C:\Masm50>debug p112.exe
-r
AX=0000  BX=0000  CX=001C  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B49  IP=0000   NV UP EI PL NZ NA PO NC
0B49:0000 BB0000        MOV     BX,0000
-d ffff:0 b
FFFF:0000  EA 5B E0 00 F0 30 34 2F-30 32 2F 30               .[...04/02/0
-

(看一下执行前这段内存中的内容)


-
-d 0020:0 b
0020:0000  00 00 00 00 00 00 00 00-00 00 00 00               ............

(看一下上面要复制到的目标内存中的内容-没有内容)

-g

Program terminated normally

(上面 g 运行这段复制内存的代码)

(看一下执行完代码后, 0020:0 ~~ 0020:b 这段内容是否被复制过来内容了)

-d 0020:0 b
0020:0000  EA 5B E0 00 F0 30 34 2F-30 32 2F 30               .[...04/02/0

(上面这段内存是从 ffff:0 ~~ ffff:b 这段内存所复制过来的)

关于上面代码循环的改进过程……


每循环都要设置改变两次ds段地址,但效率不高。
使用两个段寄存器分别存放单元 ffff:x 和目标单元 0020:x 的段地址,效率上会提高一些。

改进例程

  Quote:
              assume    cs:code

        code  segment

              mov       ax,0ffffh
              mov       ds,ax
              mov       ax,0020h
              mov       es,ax

              mov       bx,0

              mov       cx,12
          s:  mov       dl,[bx]
              mov       es:[bx],dl
              inc       bx
              loop      s

              mov       ax,4c00h
              int       21h

        code  ends
              end

上面蓝色标注是段前缀的使用,强制指定是哪一个段。


Debug 跟踪调试结果

  Quote:
C:\Masm50>debug p112-59.exe
-r
AX=0000  BX=0000  CX=001D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B49  IP=0000   NV UP EI PL NZ NA PO NC
0B49:0000 B8FFFF        MOV     AX,FFFF
-d ffff:0 b
FFFF:0000  EA 5B E0 00 F0 30 34 2F-30 32 2F 30               .[...04/02/0
-
-d 20:0 b
0020:0000  00 00 00 00 00 00 00 00-00 00 00 00               ............-
-g

Program terminated normally
-
-d 20:0 b
0020:0000  EA 5B E0 00 F0 30 34 2F-30 32 2F 30               .[...04/02/0-
-q


实验:


1) 编程,向内存 0:200~~0:23F 依次传送数据 0~63(3FH)。
   程序中只能使用 9 条指令。

第一次的代码写内存的顺序反了,哈哈……
-d 0:200 23f
0000:0200  3F 3E 3D 3C 3B 3A 39 38-37 36 35 34 33 32 31 30   ?>=<;:9876543210
0000:0210  2F 2E 2D 2C 2B 2A 29 28-27 26 25 24 23 22 21 20   /.-,+*)('&%$#"!
0000:0220  1F 1E 1D 1C 1B 1A 19 18-17 16 15 14 13 12 11 10   ................
0000:0230  0F 0E 0D 0C 0B 0A 09 08-07 06 05 04 03 02 01 00   ................

重来……


下面是重写的代码经过Debug调试后发现 0:200 地址处内容本该被写入 00H,结果并没有被写入。

经过Debug跟踪分析,原来我是用cx=3F经循环被Loop递减运算时,当Loop遇3F为0时,则退出了,所以这个00H没机会写入。

看来这种倒着写的方法有待改进:)

(下面是错误的内容)

  Quote:
-d 0:200 23f
0000:0200  3F 01 02 03 04 05 06 07-08 09 0A 0B 0C 0D 0E 0F   ?...............
0000:0210  10 11 12 13 14 15 16 17-18 19 1A 1B 1C 1D 1E 1F   ................
0000:0220  20 21 22 23 24 25 26 27-28 29 2A 2B 2C 2D 2E 2F    !"#$%&'()*+,-./
0000:0230  30 31 32 33 34 35 36 37-38 39 3A 3B 3C 3D 3E 3F   0123456789:;<=>?

调试正确的代码:

  Quote:
;--------------------------------------------------
;    向内存 0:200~~0:23F 依次传送数据 0~63(3FH)
;--------------------------------------------------

              assume    cs:code
        code  segment

              mov       ax,20h
              mov       ds,ax
              mov       bx,0h       ; 设置偏移量

              mov       cx,64
          s:  mov       ds:[bx],bl
              inc       bx
              loop      s
              mov       ax,4c00h
              int       21h

        code  ends
              end

调试成功~:)

  Quote:
-d 0:200 23f
0000:0200  00 01 02 03 04 05 06 07-08 09 0A 0B 0C 0D 0E 0F   ................
0000:0210  10 11 12 13 14 15 16 17-18 19 1A 1B 1C 1D 1E 1F   ................
0000:0220  20 21 22 23 24 25 26 27-28 29 2A 2B 2C 2D 2E 2F    !"#$%&'()*+,-./
0000:0230  30 31 32 33 34 35 36 37-38 39 3A 3B 3C 3D 3E 3F   0123456789:;<=>?

如果没有 Debug 调试这个编译的 .exe 文件,根本没有办法直接发现程序中的问题。

越来越感觉到 Debug 就象是用于看到代程序过程并方便调试代码用的(批处理中的) Echo on 这样的命令~:)

而且,没有象 Debug 类似或是一样的工具帮助调试已编译了的代码,将寸步难行~:)


上面代码原理: 从偏移量 0~3F 一共有 64 个字节(因为偏移量0也算一个,刚才给忘了)
        所以设置循环 64 次。
        将 0:200 (段:偏移量)地址设置为 200:0000 地址( (段*16+偏移量) / 16 :0000 ),方便计算。
        所以 bx 寄存器中的偏移量就从 0000 开始计数了~:)
        只要计数累加偏移量到 64 时,那个cx计数器中的循环64次也正好结束,所有指定内存全都写入了。

[ Last edited by redtek on 2006-12-24 at 12:33 PM ]



    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-24 23:06
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 66 楼』:  【80x86汇编语言学习笔记】

关于 Debug 的一个调试技巧

  Quote:
C:\Masm50>debug p113.exe
-r
AX=0000  BX=0000  CX=0015  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B49  IP=0000   NV UP EI PL NZ NA PO NC
0B49:0000 B82000        MOV     AX,0020
-u
0B49:0000 B82000        MOV     AX,0020
0B49:0003 8ED8          MOV     DS,AX
0B49:0005 BB0000        MOV     BX,0000
0B49:0008 B94000        MOV     CX,0040
0B49:000B 881F          MOV     [BX],BL
0B49:000D 43            INC     BX
0B49:000E E2FB          LOOP    000B


0B49:0010 B8004C        MOV     AX,4C00
0B49:0013 CD21          INT     21
0B49:0015 05508D        ADD     AX,8D50
0B49:0018 46            INC     SI
0B49:0019 8050E83E      ADC     BYTE PTR [BX+SI-18],3E
0B49:001D 0D83C4        OR      AX,C483
-
-
-g 0010

AX=0020  BX=0040  CX=0000  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0020  ES=0B39  SS=0B49  CS=0B49  IP=0010   NV UP EI PL NZ AC PO NC
0B49:0010 B8004C        MOV     AX,4C00
-q

假如不再想跟踪调试上面绿色部分的代码了,想一下子执行完绿色部分的代码,
但只让程序执行到红色标注的代码处停止。

则可以用 g 命令加参数执行:

  G  0010  

含义:从当前 CS:IP 指针处执行代码,执行到标号 0010 处停止。

[ Last edited by redtek on 2006-12-24 at 12:40 PM ]



    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-25 01:35
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 67 楼』:  【80x86汇编语言学习笔记】

代码复制自身到另一块内存



) 下面的程序的功能是将 "mov ax,4c00h" 之前的指令复制到内存 0:200 处,补全程序。
  上机调试,跟踪运行结果。
;----------------------------------------
;
;             未完全的代码,待填补完
;
;----------------------------------------

              assume    cs:code

        code  segment

              mov       ax,
              mov       ds,ax
              mov       ax,0020h
              mov       es,ax
              mov       bx,0
              mov       cx,
          s:  mov       al,[bx]
              mov       es:[bx],al
              inc       bx
              loop      s

              mov       ax,4c00h
              int       21h

        code  ends
              end
根据以上代码思考问题:

1) 复制的是什么?从哪里到哪里?
2) 复制的是什么?有多少个?如何知道要复制的字节的数量?

根据上面代码,分析如下:

  (ds)*16+256B= cs 所以 cs =(ds)+10H
  
  复制的代码不能包括 “mov  ax,4c00h” 与 “int  21h” 这两句,如何知道其长度?
  反汇编这两句代码信息如下:
  
  B8004C        MOV     AX,4C00
  CD21           INT     21
  
  其中:B8004C与CD21是上面 mov ……命令的机器码,数一下。机器码是:5个字节。

  所以,(代码总长度 - 5B )=要复制的代码长度。
  即: CX-5=要复制的但又不含上面两句指令的代码总长度。

  所以,循环次数是 cs-5 。cs中具体是多少要Debug调入才知道(或是根据经验数),不过咱们把循环次数瞎添一个就知道了。


下面是补全代码以后,唯一不知道总长度,也不知道要循环多少次。
所以,用汇编代码中的cx循环次数21是瞎写的,先占个长度,这样先能编译过去再说。

然后到了Debug中所看到的红色标注部分就是代码的总长度,我们再用总长度减那两条语句的机器码长度5字节,就是cx循环次数。

  Quote:
C:\Masm50>debug p113-1.exe
-r
AX=0000  BX=0000  CX=001C  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B49  IP=0000   NV UP EI PL NZ NA PO NC
0B49:0000 8BC1          MOV     AX,CS
-u
0B49:0000 8BC1          MOV     AX,CS
0B49:0002 8ED8          MOV     DS,AX
0B49:0004 B82000        MOV     AX,0020
0B49:0007 8EC0          MOV     ES,AX
0B49:0009 BB0000        MOV     BX,0000
0B49:000C B91500        MOV     CX,0015
0B49:000F 8A07          MOV     AL,[BX]
0B49:0011 26            ES:
0B49:0012 8807          MOV     [BX],AL
0B49:0014 43            INC     BX
0B49:0015 E2F8          LOOP    000F
0B49:0017 B8004C        MOV     AX,4C00
0B49:001A CD21          INT     21
0B49:001C 3E            DS:
0B49:001D 0D83C4        OR      AX,C483
-q

长度为 0x001c ,再减那两条不包括的指令的5个字节,为 23 。即直要复制的代码长度为 23 个字节~:)
C:\Masm50>set /a 0x001c-5
23
我是用计算器算的,如果觉得用计算器算太麻烦,还可以向上面一样秀一下DOS命令~:)同样支持16进制与10进制混合运算~:)


补全后的代码

;----------------------------------------
;
;            补全后的代码,复制代码自身到内存0:200处
;
;----------------------------------------

              assume    cs:code

        code  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

        code  ends
              end
Debug跟踪过程,验证是否将自身代码复制到 0:200 处

下面是反汇编代码,方便参考。

  Quote:
C:\Masm50>debug p113-1.exe
-r
AX=0000  BX=0000  CX=001C  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B49  IP=0000   NV UP EI PL NZ NA PO NC
0B49:0000 8CC8          MOV     AX,CS
-u
0B49:0000 8CC8          MOV     AX,CS
0B49:0002 8ED8          MOV     DS,AX
0B49:0004 B82000        MOV     AX,0020
0B49:0007 8EC0          MOV     ES,AX
0B49:0009 BB0000        MOV     BX,0000
0B49:000C B91700        MOV     CX,0017
0B49:000F 8A07          MOV     AL,[BX]
0B49:0011 26            ES:
0B49:0012 8807          MOV     [BX],AL
0B49:0014 43            INC     BX
0B49:0015 E2F8          LOOP    000F
0B49:0017 B8004C        MOV     AX,4C00
0B49:001A CD21          INT     21

下面是运行代码前的目标内存状态与运行代码后的目标内存状态

  Quote:
C:\Masm50>debug p113-1.exe
-r
AX=0000  BX=0000  CX=001C  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B49  IP=0000   NV UP EI PL NZ NA PO NC
0B49:0000 8CC8          MOV     AX,CS
-d 0:200
0000:0200  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0210  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0220  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0230  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0240  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0250  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0260  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0270  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
-
-g

Program terminated normally
-d 0:200
0000:0200  8C C8 8E D8 B8 20 00 8E-C0 BB 00 00 B9 17 00 8A   ..... ..........
0000:0210  07 26 88 07 43 E2 F8 00-00 00 00 00 00 00 00 00   .&..C...........
0000:0220  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0230  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0240  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0250  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0260  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0270  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
-q

  
下面是执行后的目标内存情况(被拷了过去)

  Quote:
-d 0:200
0000:0200  8C C8 8E D8 B8 20 00 8E-C0 BB 00 00 B9 17 00 8A   ..... ..........
0000:0210  07 26 88 07 43 E2 F8 00-00 00 00 00 00 00 00 00   .&..C...........
0000:0220  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0230  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0240  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0250  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0260  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0000:0270  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

反汇编被拷贝过去的目标内存

  Quote:
-u 0:200
0000:0200 8CC8          MOV     AX,CS
0000:0202 8ED8          MOV     DS,AX
0000:0204 B82000        MOV     AX,0020
0000:0207 8EC0          MOV     ES,AX
0000:0209 BB0000        MOV     BX,0000
0000:020C B91700        MOV     CX,0017
0000:020F 8A07          MOV     AL,[BX]
0000:0211 26            ES:
0000:0212 8807          MOV     [BX],AL
0000:0214 43            INC     BX
0000:0215 E2F8          LOOP    020F

看一下主代码(进行复制的主代码)

  Quote:
C:\Masm50>debug p113-1.exe
-r
AX=0000  BX=0000  CX=001C  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B49  IP=0000   NV UP EI PL NZ NA PO NC
0B49:0000 8CC8          MOV     AX,CS
-u
0B49:0000 8CC8          MOV     AX,CS
0B49:0002 8ED8          MOV     DS,AX
0B49:0004 B82000        MOV     AX,0020
0B49:0007 8EC0          MOV     ES,AX
0B49:0009 BB0000        MOV     BX,0000
0B49:000C B91700        MOV     CX,0017
0B49:000F 8A07          MOV     AL,[BX]
0B49:0011 26            ES:
0B49:0012 8807          MOV     [BX],AL
0B49:0014 43            INC     BX
0B49:0015 E2F8          LOOP    000F

[ Last edited by redtek on 2006-12-24 at 02:56 PM ]



    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-25 02:27
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 68 楼』:  【80x86汇编语言学习笔记】

包含多个段的程序

程序取得所需空间的方法:

1) 加载程序的时候为程序分配
2) 程序在执行的过程中向系统申请


dw,字型数据。


在代码中使用数据例程
              assume    cs:code
        code  segment

              dw        0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
              mov       bx,0        ; 偏移量
              mov       ax,0
              mov       cx,8        ; 循环8次

          s:  add       ax,cs:[bx]  ; (ax)= ((ax)+(cs)*16+(bx))
              add       bx,2
              loop      s

              mov       ax,4c00h
              int       21h

        code  ends
              end
Debug 跟踪上面编译了的代码



反汇编看到其 dw 所定义的数据被定义到了代码段首(因为dw是第一条指令),其内容如下:

  Quote:
-d cs:0000 f
0B49:0000  23 01 56 04 89 07 BC 0A-EF 0D ED 0F BA 0C 87 09   #.V.............

但是,上面的代码会出现问题,因为前16个字节不是代码,而是我们定义的数据。


Debug 分析上面被编译之后的代码

  Quote:
C:\Masm50>debug p115.exe
-r
AX=0000  BX=0000  CX=0026  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B49  IP=0000   NV UP EI PL NZ NA PO NC
0B49:0000 2301          AND     AX,[BX+DI]                         DS:0000=20CD
-u
0B49:0000 2301          AND     AX,[BX+DI]
0B49:0002 56            PUSH    SI
0B49:0003 0489          ADD     AL,89
0B49:0005 07            POP     ES
0B49:0006 BC0AEF        MOV     SP,EF0A
0B49:0009 0DED0F        OR      AX,0FED
0B49:000C BA0C87        MOV     DX,870C
0B49:000F 09BB0000      OR      [BP+DI+0000],DI
0B49:0013 B80000        MOV     AX,0000
0B49:0016 B90800        MOV     CX,0008
0B49:0019 2E            CS:
0B49:001A 0307          ADD     AX,[BX]
0B49:001C 83C302        ADD     BX,+02
0B49:001F E2F8          LOOP    0019

(上面列出的前16个字节是我们定义的数据,不是指令)


(下面才是我们定义的指令,但这批令应该在程序的入口: cs:ip )
(所以,有可能会出错)

-u cs:0010
0B49:0010 BB0000        MOV     BX,0000
0B49:0013 B80000        MOV     AX,0000
0B49:0016 B90800        MOV     CX,0008
0B49:0019 2E            CS:
0B49:001A 0307          ADD     AX,[BX]
0B49:001C 83C302        ADD     BX,+02
0B49:001F E2F8          LOOP    0019
0B49:0021 B8004C        MOV     AX,4C00
0B49:0024 CD21          INT     21
0B49:0026 00EB          ADD     BL,CH
0B49:0028 0590FF        ADD     AX,FF90
0B49:002B 86FE          XCHG    BH,DH
0B49:002D FEA15607      JMP     [BX+DI+0756]
-q

在源程序中指明程序入口所在
              assume    cs:code
        code  segment

              dw        0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h

      start:  mov       bx,0
              mov       ax,0
          s:  add       ax,cs:[bx]
              add       bx,2
              loop      s

              mov       ax,4c00h
              int       21h

        code  ends
              end       start
Debug 跟踪上面编译了的代码
C:\Masm50>debug p116.exe
-r
AX=0000  BX=0000  CX=0023  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B49  IP=0010   NV UP EI PL NZ NA PO NC
0B49:0010 BB0000        MOV     BX,0000
-u
0B49:0010 BB0000        MOV     BX,0000
0B49:0013 B80000        MOV     AX,0000
0B49:0016 2E            CS:
0B49:0017 0307          ADD     AX,[BX]
0B49:0019 83C302        ADD     BX,+02
0B49:001C E2F8          LOOP    0016
0B49:001E B8004C        MOV     AX,4C00
0B49:0021 CD21          INT     21
0B49:0023 FEFE          ???     DH
0B49:0025 0000          ADD     [BX+SI],AL
0B49:0027 EB05          JMP     002E
0B49:0029 90            NOP
0B49:002A FF86FEFE      INC     WORD PTR [BP+FEFE]
0B49:002E A15607        MOV     AX,[0756]
-q
发现 ip 已指向 10  ,cpu执行时跳过了数据区。

嘿嘿……开始奇怪了,越奇怪思考起来越有味道~:)
病毒?修改程序入口?还能干什么?原由?

比较结果:一个带 end start  ,一个是 end ,比较入口不一样的地方
C:\Masm50\p>fc /b /a pok.exe pno.exe
正正在在比比较较文文件件 pok.exe 和和 PNO.EXE
00000012: AA BA
00000014: 10 00
改名比较

  Quote:
C:\Masm50\p>DEBUG POK.TXT
-D DS:100
0AF5:0100  4D 5A 23 00 02 00 00 00-20 00 00 00 FF FF 00 00   MZ#..... .......
0AF5:0110  00 00 AA 50 10 00 00 00-1E 00 00 00 01 00 00 00   ...P............
0AF5:0120  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0AF5:0130  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0AF5:0140  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0AF5:0150  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0AF5:0160  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0AF5:0170  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
-Q

C:\Masm50\p>DEBUG PNO.TXT
-R
AX=0000  BX=0000  CX=0223  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0AF5  ES=0AF5  SS=0AF5  CS=0AF5  IP=0100   NV UP EI PL NZ NA PO NC
0AF5:0100 4D            DEC     BP
-D DS:100
0AF5:0100  4D 5A 23 00 02 00 00 00-20 00 00 00 FF FF 00 00   MZ#..... .......
0AF5:0110  00 00 BA 50 00 00 00 00-1E 00 00 00 01 00 00 00   ...P............
0AF5:0120  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0AF5:0130  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0AF5:0140  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0AF5:0150  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0AF5:0160  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0AF5:0170  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
-Q

C:\Masm50\p>FC /B POK.TXT PNO.TXT
正正在在比比较较文文件件 pok.txt 和和 PNO.TXT
00000012: AA BA
00000014: 10 00

FC 执行比较的以后,将它的输出信息copy到这里居然显示“双影儿”字了,哈哈……

fc /b pok.txt pno.txt >test.txt之后,再用Debug重写一个新文件,再次16进制写这几个字,看看是不是重影儿?

打开记事这回是,copy 粘到这里。
正在比较文件 pok.txt 和
记事本内copy这内容看来没事儿,刚才重影是在 cmd 里直接copy 的……

type test.txt 一下,cmd 里copy ^
正正在在比比较较文文件件 pok.txt
好玩……

copy con a.txt 新建一个,直接打字看看 type 出来是什么……
正在比较文件 pok.tx
16进制一样,唯一区别就是 cmd 直接copy,刚一放到 [  code]里一粘就是双影,比较剪辑板?晕………………………………

会不会和 fc 在 cmd 中的输出方式有关?它用了另一种方式显示字符?
而这种方式显示的字符当 copy 到剪辑板时就变成了双字?
看来 echo 是达不到这种效果……
我看到的 fc 的输出和我copy出来的不同……
用这种方法进行防批处理运算结果输出中的防拷贝?

测试 fc 比较文件后,输出了一串中文字信息……
然后直接在cmd里鼠标右键选择copy……一粘结果还是双字……
奇怪………………

[ Last edited by redtek on 2006-12-24 at 10:49 PM ]



    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-25 05:28
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
electronixtar
铂金会员





积分 7493
发帖 2672
注册 2005-9-2
状态 离线
『第 69 楼』:  

牛人,顶

2006-12-25 07:24
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
ccwan
金牌会员




积分 2725
发帖 1160
注册 2006-9-23
来自 河北廊坊
状态 离线
『第 70 楼』:  

顶,人牛!



三人行,必有吾师焉。   学然后知不足,教然后知困,然后能自强也。
2006-12-25 07:44
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 71 楼』:  

多谢两位仁兄鼓励:)
人牛?饶了我吧,嘿嘿……应该一边看着汇编一边咬着牛肉干儿~:)`````



    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-25 10:58
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 72 楼』:  【80x86汇编语言学习笔记】

数据、代码、栈在不同的段中使用


是圣诞节?时间流逝,冲刺……


1) 代码、数据、栈放到同一个段中会使程序混乱,难以维护。
2) 如果数据、栈、代码需要的空间超过64KB,就不能放在一个段中。
   不同的安排放到不同意义标识的段中,更使代码清晰容易扩展。

将数据、代码、栈放到不同的段中,例程分析:



) 在定义 stack 栈段的代码中,编译器编译给出 "no  stack  segment" 警告,在 Google.com 查询到的解决办法:

  问: 已在程序中设有如下定义:STACK  SEGMENT ……为什么LINK 仍然警告:no  stack  segment ?

  答:将段定义修改为:STACK  SEGMENT  STACK ;后面的STACK项是组合类型,即不再出现警告信息。


多段方式的代码
              assume    cs:code,ds:data,ss:stack
        data  segment
              dw        0123h,0456h,0789h,0abch,,0defh,0fedh,0cbah,0987h
        data  ends
       stack  segment
              dw        0,0,0,0,0,0,0,0
       stack  ends
        code  segment
      start:  mov       ax,stack    ; start入口
              mov       ss,ax
              mov       sp,16
              mov       ax,data
              mov       ds,ax
              mov       bx,0
              mov       cx,8
          s:  push      [bx]
              add       bx,2
              loop      s
              mov       bx,0
              mov       cx,8
         s0:  pop       [bx]
              add       bx,2
              loop      s0
              mov       ax,4c00h
              int       21h
        code  ends
              end       start
编译可执行文件后用Debug调试,发现一个错误~:)
发现多了个 00H 00H ,源代码中定义的数据什么时候定义了这个东东?
后来一数,是多了一个数据 00H 00H ,原来是写源代码的时候多加一个逗号,编译器认为这是合法的一个数据 00 00 。

  Quote:
-d ds:0000
0B49:0000  23 01 56 04 89 07 BC 0A-00 00 EF 0D ED 0F BA 0C   #.V.............
0B49:0010  87 09 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0B49:0020  00 00 13 00 4C 0B 59 05-BC 0A 89 07 56 04 23 01   ....L.Y.....V.#.
0B49:0030  B8 4B 0B 8E D0 BC 10 00-B8 49 0B 8E D8 BB 00 00   .K.......I......
0B49:0040  B9 08 00 FF 37 83 C3 02-E2 F9 BB 00 00 B9 08 00   ....7...........
0B49:0050  8F 07 83 C3 02 E2 F9 B8-00 4C CD 21 FE 89 96 FC   .........L.!....
0B49:0060  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05   .....&.G.*.@P...
0B49:0070  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50   ..RP..F...P....P

绿色标注相当于源代码中的:
        data  segment
              dw        0123h,0456h,0789h,0abch,,0defh,0fedh,0cbah,0987h
        data  ends
红色标记是源代码中多打了个逗号所占位的。

蓝色标记为栈空间预留,相于源代中的
       stack  segment
              dw        0,0,0,0,0,0,0,0
       stack  ends
然后再 Debug 调试,紧接着就是这个有意思的错误。
但如果在 MS-DOS 下调试则没有问题,因为栈并没有越界,它就算是“指针”越界,但数据不会越界(数据长度刚刚好)。
可见(个人目前认为) CMD 太严格了!

[ Last edited by redtek on 2006-12-25 at 11:19 AM ]

附件 1: 1.GIF (2006-12-26 00:19, 14.91 K, 下载附件所需积分 1 点 ,下载次数: 2)




    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-25 22:03
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 73 楼』:  【80x86汇编语言学习笔记】

编写调试跟踪多段程序

一个小窍门

刚才希望截取 Debug 操作的过程文字,结果内容过长,无法 copy 文件。
试着Debug输出内容重向到一个文本文件内,好是好,只是生成了临时文件。

想了想发现一个好玩的办法,不生成临时文件,直接将操作过程管道输出到剪辑板内,然后我往论坛一粘就行了~:)

不过,所输出的内容是不会显示到屏幕上的。但是用熟了也用着显示什么,知道自己键入的是什么应该出现些什么就行了。
debug p123.exe|clip
下面源代码编译后调试跟踪过程
              assume    cs:code,ds:data,ss:stack
        data  segment
              dw        0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
        data  ends

       stack  segment
              dw        0,0,0,0,0,0,0,0
       stack  ends

        code  segment
      start:  mov       ax,stack
              mov       ss,ax
              mov       ax,data
              mov       ds,ax
              push      ds:[0]
              push      ds:[2]
              pop       ds:[2]
              pop       ds:[0]
              mov       ax,4c00h
              int       21h
        code  ends
              end       start
试调上面编译过的源代码

  Quote:
-r

AX=0000  BX=0000  CX=003F  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000  
DS=0B39  ES=0B39  SS=0B49  CS=0B4B  IP=0000   NV UP EI PL NZ NA PO NC
0B4B:0000 B84A0B        MOV        AX,0B4A                           
-u

0B4B:0000 B84A0B        MOV        AX,0B4A                           
0B4B:0003 8ED0          MOV        SS,AX                              
0B4B:0005 B8490B        MOV        AX,0B49                           
0B4B:0008 8ED8          MOV        DS,AX                              
0B4B:000A FF360000      PUSH        [0000]                             
0B4B:000E FF360200      PUSH        [0002]                             
0B4B:0012 8F060200      POP        [0002]                             
0B4B:0016 8F060000      POP        [0000]                             
0B4B:001A B8004C        MOV        AX,4C00                           
0B4B:001D CD21          INT        21                                 
0B4B:001F 8B87BE22      MOV        AX,[BX+22BE]                       
-d cs:0

0B4B:0000  B8 4A 0B 8E D0 B8 49 0B-8E D8 FF 36 00 00 FF 36   .J....I....6...6
0B4B:0010  02 00 8F 06 02 00 8F 06-00 00 B8 00 4C CD 21 8B   ............L.!.
0B4B:0020  87 BE 22 0B 87 C0 22 74-E1 8B 9E FE FE D1 E3 D1   .."..."t........
0B4B:0030  E3 8B 87 BE 22 8B 97 C0-22 89 86 FA FE 89 96 FC   ...."...".......
0B4B:0040  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05   .....&.G.*.@P...
0B4B:0050  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50   ..RP..F...P....P
0B4B:0060  E8 6F 70 83 C4 06 B8 CD-05 50 8D 86 00 FF 50 E8   .op......P....P.
0B4B:0070  CA 0C 83 C4 04 B8 FF FF-50 8D 86 00 FF 50 8D 46   ........P....P.F
-d ss:0

0B49:0000  23 01 56 04 89 07 BC 0A-EF 0D ED 0F BA 0C 87 09   #.V.............
0B49:0010  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0B49:0020  B8 4A 0B 8E D0 B8 49 0B-8E D8 FF 36 00 00 FF 36   .J....I....6...6
0B49:0030  02 00 8F 06 02 00 8F 06-00 00 B8 00 4C CD 21 8B   ............L.!.
0B49:0040  87 BE 22 0B 87 C0 22 74-E1 8B 9E FE FE D1 E3 D1   .."..."t........
0B49:0050  E3 8B 87 BE 22 8B 97 C0-22 89 86 FA FE 89 96 FC   ...."...".......
0B49:0060  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05   .....&.G.*.@P...
0B49:0070  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50   ..RP..F...P....P
-d ds:0

0B39:0000  CD 20 FF 9F 00 9A F0 FE-1D F0 4F 03 59 05 8A 03   . ........O.Y...
0B39:0010  59 05 17 03 59 05 48 05-01 03 01 00 02 FF FF FF   Y...Y.H.........
0B39:0020  FF FF FF FF FF FF FF FF-FF FF FF FF 06 0B 4C 01   ..............L.
0B39:0030  19 0A 14 00 18 00 39 0B-FF FF FF FF 00 00 00 00   ......9.........
0B39:0040  05 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0B39:0050  CD 21 CB 00 00 00 00 00-00 00 00 00 00 20 20 20   .!...........   
0B39:0060  20 20 20 20 20 20 20 20-00 00 00 00 00 20 20 20           .....   
0B39:0070  20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00           ........
-q

代码装入执行前与执行改变栈地址之后的数据对比

  Quote:
-R
AX=0000  BX=0000  CX=003F  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B4B  IP=0000   NV UP EI PL NZ NA PO NC
0B4B:0000 B84A0B        MOV     AX,0B4A
-T

AX=0B4A  BX=0000  CX=003F  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B4B  IP=0003   NV UP EI PL NZ NA PO NC
0B4B:0003 8ED0          MOV     SS,AX
-T

AX=0B49  BX=0000  CX=003F  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B4A  CS=0B4B  IP=0008   NV UP EI PL NZ NA PO NC
0B4B:0008 8ED8          MOV     DS,AX
-D SS:0
0B4A:0000  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0B4A:0010  B8 4A 0B 8E D0 B8 49 0B-8E D8 FF 36 00 00 FF 36   .J....I....6...6
0B4A:0020  02 00 8F 06 02 00 8F 06-00 00 B8 00 4C CD 21 8B   ............L.!.
0B4A:0030  87 BE 22 0B 87 C0 22 74-E1 8B 9E FE FE D1 E3 D1   .."..."t........
0B4A:0040  E3 8B 87 BE 22 8B 97 C0-22 89 86 FA FE 89 96 FC   ...."...".......
0B4A:0050  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05   .....&.G.*.@P...
0B4A:0060  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50   ..RP..F...P....P
0B4A:0070  E8 6F 70 83 C4 06 B8 CD-05 50 8D 86 00 FF 50 E8   .op......P....P.
-D 0B49:0
0B49:0000  23 01 56 04 89 07 BC 0A-EF 0D ED 0F BA 0C 87 09   #.V.............
0B49:0010  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0B49:0020  B8 4A 0B 8E D0 B8 49 0B-8E D8 FF 36 00 00 FF 36   .J....I....6...6
0B49:0030  02 00 8F 06 02 00 8F 06-00 00 B8 00 4C CD 21 8B   ............L.!.
0B49:0040  87 BE 22 0B 87 C0 22 74-E1 8B 9E FE FE D1 E3 D1   .."..."t........
0B49:0050  E3 8B 87 BE 22 8B 97 C0-22 89 86 FA FE 89 96 FC   ...."...".......
0B49:0060  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05   .....&.G.*.@P...
0B49:0070  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50   ..RP..F...P....P

上面是代码装入执行前和改变栈ds的对比,根据上面对比再对比整个代码使用内存的变化。

  Quote:
C:\Masm50>debug p123.exe
-r
AX=0000  BX=0000  CX=003F  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B4B  IP=0000   NV UP EI PL NZ NA PO NC
0B4B:0000 B84A0B        MOV     AX,0B4A
-d ss:0
0B49:0000  23 01 56 04 89 07 BC 0A-EF 0D ED 0F BA 0C 87 09   #.V.............
0B49:0010  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
0B49:0020  B8 4A 0B 8E D0 B8 49 0B-8E D8 FF 36 00 00 FF 36   .J....I....6...6
0B49:0030  02 00 8F 06 02 00 8F 06-00 00 B8 00 4C CD 21 C7   ............L.!.
0B49:0040  02 75 48 89 3E E6 99 FF-06 E6 99 C6 06 E8 99 FF   .uH.>...........
0B49:0050  C6 06 E9 99 00 E8 99 00-AC E8 29 E2 74 38 3C 0D   ..........).t8<.
0B49:0060  74 34 3A 06 B6 96 74 2E-3A C3 74 2A 3C 3A 74 03   t4:...t.:.t*<:t.
0B49:0070  E9 5F FF 80 3E A4 98 02-75 05 E8 74 00 EB D9 46   ._..>...u..t...F


红色标注为 ss 栈段在代码执行前未重新分配时的状态,ss 基地址批向数据在源代码中的定义:

        data  segment
              dw        0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
        data  ends
而紧跟着它后面的数据 00 00  ……则是为栈安排存储区,它在代码中是这样定义的
       stack  segment
              dw        0,0,0,0,0,0,0,0
       stack  ends
上面的定义这才是应该为栈分配的空间。

而在这一片 “内存区域” 的后面才是代码入口 ( end start ),cs段地址为:0B4BH

执行前:
|______PSP____|____ss=0b49=8个dw定义的字数据___后8个字00为栈分配___共32字节__|__代码段:  cs=0b4b__|
执行后(只执行  为ss栈赋值后),则变化如下:

其 ss=B4A0 ,被定义到了原来的栈与代码段之间了(即向下移了16个字节),
由原来装入时的 SS=0B49 向下移了 16字节。
变为: SS=B4A0。

那么 SS=B4A0 它将指向哪里?见上面反汇编分析,其指向了 dw 0,0,0……在源代码中所定义的栈区。

这是为了方便压栈用。

分析:

) CPU执行程序,程序返回前,data 段中的数据为多少?

  
  -d ds:0
  0B49:0000  23 01 56 04 89 07 BC 0A-EF 0D ED 0F BA 0C 87 09
  
) CPU执行程序,程序返回前,CS=? SS=? DS=?

  CS=0B4B  SS=0B4A  DS=0B49


) 设程序加载后,code段的段地址为X,则data段的段地址为?
  stack段的段地址为?


  stack段的段地址为: stack=(cs)*16+0B-32B
  data段的段地址为:   data=(cs)*16+0B-32B - 100H



编译下面代码,用Debug加载、跟踪、调试……
              assume    cs:code,ds:data,ss:stack

        data  segment
              dw        0123h,0456h
        data  ends

       stack  segment
              dw        0,0
       stack  ends

        code  segment
      start:  mov       ax,stack
              mov       ss,ax
              mov       sp,16
              mov       ax,data
              mov       ds,ax
              push      ds:[0]
              push      ds:[2]
              pop       ds:[2]
              pop       ds:[0]
              mov       ax,4c00h
              int       21h

        code  ends
              end       start
) CPU执行程序,程序返回前,data段中的数据为多少?
  
  DS = 0B49
  DS = 23 01 56 04


) CPU执行程序,程序返回前, CS、SS、DS都是多少?

  DS=0B49  SS=0B4A  CS=0B4B


) 设程序加载后,code段的段地址为X,则data段的段地址为?
  stack段的段地址为?

  stack段的段地址为: ( (X)*16 - 32B) / 16
  data 段的段地址为: ( (X)*16 - 32B - 256B) ) / 16
  


) 对于如下定义的段:

  name segment
    ...
  name ends

  如果段中的数据占N个字节,则程序加载后,该段实际占有空间为?

  答:如果 N < FH ,则实际占用 FH 字节。



简单总结:

(到这里,发现一个例子反复的跟踪和对比源代码被编译并反汇编后的“样子”是绝对值得的,直到脑子里已经形成视图为止。)

(每一个基础如果不打好,就向下走,会学得非常快,但越向后学难度越大、难以逾越的障碍就会越多,能力难以再提高。)

(汇编离不开Debug等调试工具,没了这些工具寸步难行。汇编学机器原理,Debug了解真象。)



将下面的程序编译连接,则Debug加载、跟踪……
              assume    cs:code,ds:data,ss:stack
        code  segment
      start:  mov       ax,stack
              mov       ss,ax
              mov       sp,16
              mov       ax,data
              mov       ds,ax
              push      ds:[0]
              push      ds:[2]
              pop       ds:[2]
              pop       ds:[0]
              mov       ax,4c00h
              int       21h
        code  ends
        data  segment
              dw        0123h,0456h
        data  ends
       stack  segment
              dw        0,0
       stack  ends
              end       start

分析:


  {PSP}{代码}{数据}{栈}




) CPU执行程序,程序返回前,data段中的数据为多少?
  
  DS=0B4C
  0B4C:0000  23 01 56 04


) CPU执行程序,程序返回前,CS=? SS=? DS=?

  SS=0B4D  CS=0B49 DS=0B4C


) 设程序加载后,code段的段地址为X,则data段的段地址为?
  stack段的段地址为?


  因为 code 段之前没  stack、data 等数据,只有 psp所占用的256B。
  所以 data 段地址为: ((CS)*16 - 256B )/ 16
  公式写得不太标准。因为文件一被装入,data段自然指向PSP,而stack与data段都在code段后面,
  所以code段地址(CS)向回移255B就是PSP。

  CX=44H 即:寄存器代码长度为:68 B
  实际手工数代码长度为:34 B
  则 68B - 34B = 34 B  则视图如下:{有效代码占34B+补满F}{data+补满到F + stack实际占用}
  (上面只是视图,不是真正计算方法)
  (因为代码结束后的空余空间在F以前是不再用了,为了整除方便)
  (所以,再有数据,如栈和数据段的超始地址都是可以将来被16整除的地址,这是最重要的一点)


  即: CX代段总长度 - (DATA: dw 0123h,0456h 独占的16倍数的起始行 = 16字节) == DATA段基地址
     (CX=68B)-(DATA: 16B)-(最后的stack所真实占用的4B)= 48B(CS段的偏移量)
     (CS=0B49H)+48B =0B4CH (这是求出的段地址)

  *  现在我们求出了已知CS地址,所以DATA段的地址为: 0B4CH
     那么假如 CS=X ,则DATA段地址为: ((x)*16+48B)/16
  
  *  既然已知DATA段地址了,那么STACK只不过是它向下的一个F篇移量,则STACK= (((x)*16+48B)/16)+16B


下面是一些求得如下公式的推理验证。

-d ss:0
0B49:0000  B8 4D 0B 8E D0 BC 10 00-B8 4C 0B 8E D8 FF 36 00
0B49:0010  00 FF 36 02 00 8F 06 02-00 8F 06 00 00 B8 00 4C
0B49:0020  CD 21 00 00 00 00 00 00-00 00 00 00 00 00 00 00

(上面 CD 21 就是代码结束了)


(下面 23 01 56 04 是 dw 0123H,0456H 所定义的数据。)
0B49:0030  23 01 56 04 00 00 00 00-00 00 00 00 00 00 00 00
(下面 00 00 00 是 stack 段在源代码中 dw 0,0 定义的栈空间)
(它们的特点:都是新起一行:)
0B49:0040  00 00 00 00 87 C0 22 74-E1 8B 9E FE FE D1 E3 D1
0B49:0050  E3 8B 87 BE 22 8B 97 C0-22 89 86 FA FE 89 96 FC
0B49:0060  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05
0B49:0070  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50
(它们为什么都要新起一行来存有被定义的新数据?)
(个人理解:)

(这是带有偏移量的数据,如果计算为无偏移量物理地址为:0B4E:1)
(当  MOV AX,0B4E:1 显然无法赋值)
(但 MOV AX,B4E1  表面上看上去是物理地址,但它不是相对段地址,所以更是出错)
(所以,偏移量只要的后面有0,方便段的物理地址(段)*16+偏移量,它的物理地址低位是0,方便再转为无偏移量

的段地址)
-d 0b4d:11
0B4D:0010     00 15 00 49 0B 59 05-56 04 23 01 FE 89 96 FC
0B4D:0020  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05
0B4D:0030  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50
0B4D:0040  E8 6F 70 83 C4 06 B8 CD-05 50 8D 86 00 FF 50 E8
0B4D:0050  CA 0C 83 C4 04 B8 FF FF-50 8D 86 00 FF 50 8D 46
0B4D:0060  80 50 E8 4D FA 83 C4 06-0A C0 75 03 E9 7B FF 5E
0B4D:0070  8B E5 5D C3 83 3E 56 07-20 72 0A B8 1C 04 50 E8
0B4D:0080  62 44 83 C4 02 B8 FF FF-50 B8 05 00 50 8D 86 7A
0B4D:0090  FE

-d 0b4e:1
0B4E:0000     00 15 00 49 0B 59 05-56 04 23 01 FE 89 96 FC
0B4E:0010  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05
0B4E:0020  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50
0B4E:0030  E8 6F 70 83 C4 06 B8 CD-05 50 8D 86 00 FF 50 E8
0B4E:0040  CA 0C 83 C4 04 B8 FF FF-50 8D 86 00 FF 50 8D 46
0B4E:0050  80 50 E8 4D FA 83 C4 06-0A C0 75 03 E9 7B FF 5E
0B4E:0060  8B E5 5D C3 83 3E 56 07-20 72 0A B8 1C 04 50 E8
0B4E:0070  62 44 83 C4 02 B8 FF FF-50 B8 05 00 50 8D 86 7A
0B4E:0080  FE
经过分析,反汇编代码 CD 21 (代码结束了)之后是 00 00 ……
因为刚才分析出必须是(段)*16+偏移量以后,其低位必须有0……
这样形容:就是当段地址*16+偏移量的物地址必须能被16整除才可以。




简单总结:

  上面的计算方法并不难,写了这么多笔记是为了推出它们的规律和都是为什么。背一个公式有记记力就行了,那么没有公式的时候怎么办?只能推出解决办法。要想找到解决办法就必须从源代码与反汇编的真实代码之间找到它们的规律,
  要找出规律就得用基础知识反复的验算。验算过程中就会发现很多不解的内容,如:为什么要空出一部分空间不用?为什么要新起一行才可以?这些书上没有,怎么办?一遍一遍推,一遍遍算,就会发现很多内容全是基础知识的扩充。



程序的入口地址分析

code segment
start: mov ax,stack ………………
        ………………
code ends
end start

如果没有在源代码中标出程序入口标置会怎么样?什么样的源代码未标置程序入口就不会运行?

分析如下:

  Quote:
              assume    cs:code,ds:data,ss:stack
        data  segment
              dw        0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
        data  ends

       stack  segment
              dw        0,0,0,0,0,0,0,0
       stack  ends

        code  segment
      start:  mov       ax,stack
              mov       ss,ax
              mov       ax,data
              mov       ds,ax
              push      ds:[0]
              push      ds:[2]
              pop       ds:[2]
              pop       ds:[0]
              mov       ax,4c00h
              int       21h
        code  ends
              end

编译后的可执行文件,代码入口就是源代码中按顺序放的数据,哈哈……无法运行~:)
从这里就可以看到 Start 与 end Start 的重要性了,它指出了代码结束与代码入口地址。不过start可以随便启名:)

  Quote:
C:\Masm50>debug aaa.exe
-r
AX=0000  BX=0000  CX=003F  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=0B3B  ES=0B3B  SS=0B4B  CS=0B4B IP=0000   NV UP EI PL NZ NA PO NC
0B4B:0000 2301          AND     AX,[BX+DI]                         DS:0000=20CD
-u
0B4B:0000 2301          AND     AX,[BX+DI]
0B4B:0002 56            PUSH    SI
0B4B:0003 0489          ADD     AL,89
0B4B:0005 07            POP     ES
0B4B:0006 BC0AEF        MOV     SP,EF0A
0B4B:0009 0DED0F        OR      AX,0FED
0B4B:000C BA0C87        MOV     DX,870C
0B4B:000F 0900          OR      [BX+SI],AX
0B4B:0011 0000          ADD     [BX+SI],AL
0B4B:0013 0000          ADD     [BX+SI],AL
0B4B:0015 0000          ADD     [BX+SI],AL
0B4B:0017 0000          ADD     [BX+SI],AL
0B4B:0019 0000          ADD     [BX+SI],AL
0B4B:001B 0000          ADD     [BX+SI],AL
0B4B:001D 0000          ADD     [BX+SI],AL
0B4B:001F 00B84C0B      ADD     [BX+SI+0B4C],BH

) 将 A 段和 B 段中的数据依次相加,将结果 C 段中。 
              assume    cs:code
           a  segment
              db        1,2,3,4,5,6,7,8
           a  ends
           b  segment
              db        1,2,3,4,5,6,7,8
           b  ends
           c  segment
              db        0,0,0,0,0,0,0,0
           c  ends

        code  segment
      start:  mov       ax,a        ; A 段
              mov       ds,ax
              mov       dx,b        ; B 段
              mov       es,dx
              mov       bx,c        ; C 段
              mov       ss,bx

              mov       bx,0        ; 清零
              mov       cx,8

          s:  mov       al,ds:[bx]  ; 把 A 段数据送入 AL
              add       al,es:[bx]  ; 将 A 段数据与 B 段偏移量为BX的数据相加,结果送入AL
              mov       ss:[bx],al  ; 把最相加结果送入目标 S 段偏移量为bx处
              add       bx,1        ; “指针”递增 1
              loop      s

              mov       ax,4c00h
              int       21h
        code  ends
              end       start
调试结果

  Quote:
-d ds:0
0B4B:0000  01 02 03 04 05 06 07 08-00 00 00 00 00 00 00 00   ................
0B4B:0010  01 02 03 04 05 06 07 08-00 00 00 00 00 00 00 00   ................
0B4B:0020  02 04 06 08 0A 0C 0E 10-00 00 00 00 00 00 00 00   ................
0B4B:0030  B8 4B 0B 8E D8 BA 4C 0B-8E C2 BB 4D 0B 8E D3 BB   .K....L....M....
0B4B:0040  00 00 B9 08 00 8A 07 26-02 07 36 88 07 83 C3 01   .......&..6.....
0B4B:0050  E2 F3 B8 00 4C CD 21 C0-22 89 86 FA FE 89 96 FC   ....L.!.".......
0B4B:0060  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05   .....&.G.*.@P...
0B4B:0070  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50   ..RP..F...P....P
-d es:0
0B4C:0000  01 02 03 04 05 06 07 08-00 00 00 00 00 00 00 00   ................
0B4C:0010  02 04 06 08 0A 0C 0E 10-00 00 00 00 00 00 00 00   ................
0B4C:0020  B8 4B 0B 8E D8 BA 4C 0B-8E C2 BB 4D 0B 8E D3 BB   .K....L....M....
0B4C:0030  00 00 B9 08 00 8A 07 26-02 07 36 88 07 83 C3 01   .......&..6.....
0B4C:0040  E2 F3 B8 00 4C CD 21 C0-22 89 86 FA FE 89 96 FC   ....L.!.".......
0B4C:0050  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05   .....&.G.*.@P...
0B4C:0060  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50   ..RP..F...P....P
0B4C:0070  E8 6F 70 83 C4 06 B8 CD-05 50 8D 86 00 FF 50 E8   .op......P....P.
-d ss:0
0B4D:0000  02 04 06 08 0A 0C 0E 10-00 00 00 00 00 00 00 00   ................
0B4D:0010  B8 4B 0B 8E D8 BA 4C 0B-8E C2 BB 4D 0B 8E D3 BB   .K....L....M....
0B4D:0020  00 00 B9 08 00 8A 07 26-02 07 36 88 07 83 C3 01   .......&..6.....
0B4D:0030  E2 F3 B8 00 4C CD 21 C0-22 89 86 FA FE 89 96 FC   ....L.!.".......
0B4D:0040  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05   .....&.G.*.@P...
0B4D:0050  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50   ..RP..F...P....P
0B4D:0060  E8 6F 70 83 C4 06 B8 CD-05 50 8D 86 00 FF 50 E8   .op......P....P.
0B4D:0070  CA 0C 83 C4 04 B8 FF FF-50 8D 86 00 FF 50 8D 46   ........P....P.F

) 用 push 指令将 a 段中 word 数据逆序存储到 b 段中。


              assume    cs:code
           a  segment
              dw        1,2,3,4,5,6,7,8
           a  ends
           b  segment
              dw        0,0,0,0,0,0,0,0
           b  ends
        code  segment
         start:
              mov       ax,a
              mov       ds,ax       ; 定义数据段 A
              mov       ax,b
              mov       es,ax       ; 定义目标数据段 B
              mov       ax,0020h    ; 定义栈使用安全空间
              mov       ss,ax       ; 定义栈
              mov       sp,100
              mov       bx,0        ; 清零
              mov       cx,8
         s0:  push      ds:[bx]     ; 数据段偏移量为[bx]的数据压栈
              add       bx,2
              loop      s0
              mov       bx,0
              mov       cx,8
         s1:  pop       es:[bx]     ; 逆序弹出存到 B 段
              add       bx,2
              loop      s1
              mov       ax,4c00h
              int       21h
        code  ends
              end       start
跟踪结果如下

  Quote:
-d es:0
0B4C:0000  08 00 07 00 06 00 05 00-04 00 03 00 02 00 01 00
0B4C:0010  B8 4B 0B 8E D8 B8 4C 0B-8E C0 B8 20 00 8E D0 BC
0B4C:0020  64 00 BB 00 00 B9 08 00-FF 37 83 C3 02 E2 F9 BB
0B4C:0030  00 00 B9 08 00 26 8F 07-83 C3 02 E2 F8 B8 00 4C
0B4C:0040  CD 21 87 BE 22 8B 97 C0-22 89 86 FA FE 89 96 FC
0B4C:0050  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05
0B4C:0060  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50
0B4C:0070  E8 6F 70 83 C4 06 B8 CD-05 50 8D 86 00 FF 50 E8

[ Last edited by redtek on 2006-12-26 at 11:21 PM ]



    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-26 01:12
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 74 楼』:  【80x86汇编语言学习笔记】

灵活定位内存地址


and和or指令


) and  指令
  都为1时为1,否则为0
  通过该指令可将操作对象的相应位设为0,其它位不变。

    设:  al,01100011B

    将 al 的第6位设为0: and al,10111111B
    将 al 的第7位设为0: and al,01111111B
    将 al 的第0位设为0: and al,11111110B


) or  指令
  都为1时为1,或有一个为1时也为1,否则为0
  通过该指令可将操作对象的相应位设为1,其它位不变。

    设:  mov al,01100011B

    将 al 的第6位设为1:   or al,01000000B
    将 al 的第7位设为1: or al,10000000B
    将 al 的第0位设为1: or al,00000001B




对比源代码定义数据与编译后的可执行文件

  Quote:
              assume    ds:data,cs:code
        data  segment
              db        'unIX'
              dw        1,2,3
              db        'foRK'
        data  ends
        code  segment
      start:
        code  ends
              end       start

见到可执行文件其上所定义的数据存放形式

  Quote:
-d ss:0
0B49:0000  75 6E 49 58 01 00 02 00-03 00 66 6F 52 4B E2 70   unIX......foRK.p
0B49:0010  83 C4 06 B8 C8 05 50 8D-46 80 50 E8 3E 0D 83 C4   ......P.F.P.>...
0B49:0020  04 C7 86 FE FE 00 00 EB-05 90 FF 86 FE FE A1 56   ...............V
0B49:0030  07 39 86 FE FE 73 7D 8B-9E FE FE D1 E3 D1 E3 8B   .9...s}.........
0B49:0040  87 BE 22 0B 87 C0 22 74-E1 8B 9E FE FE D1 E3 D1   .."..."t........
0B49:0050  E3 8B 87 BE 22 8B 97 C0-22 89 86 FA FE 89 96 FC   ...."...".......
0B49:0060  FE C4 9E FA FE 26 8A 47-0C 2A E4 40 50 8B C3 05   .....&.G.*.@P...
0B49:0070  0C 00 52 50 E8 19 46 83-C4 04 50 8D 86 00 FF 50   ..RP..F...P....P

它们是连续存放的~:)
经过分析发现原来源代码中将这些数据定义在一个标号所段内,它们就是连续存放的。如果分开定义,它们就是单独占FH。


下面对比单独定义数据,看它们是如何分布的~:)

  Quote:
              assume    cs:code,ds:data_1
      data_1  segment
              db        'Redtek'
      data_1  ends
      data_2  segment
              db        '2006.12.27'
      data_2  ends
        code  segment
      start:  mov       ax,4c00h
              int       21h
        code  ends
              end       start

Debug 分析它的分布……

  Quote:
-d ss:0
0B49:0000  52 65 64 74 65 6B 00 00-00 00 00 00 00 00 00 00   Redtek..........
0B49:0010  32 30 30 36 2E 31 32 2E-32 37 00 00 00 00 00 00   2006.12.27......

上面这两段数据的“间隔”起始偏移地址都相差FH,为了取首地址和定位方便~:)


将字符串中的第一行 “BaSiC” 字母全转成大写
              assume    cs:codesg,ds:datasg
      datasg  segment
              db        'BaSiC'
              db        'iNfOrmaTiOn'
      datasg  ends
      codesg  segment
      start:  mov       ax,datasg
              mov       ds,ax       ; 取数据段首地址
              mov       bx,0
              mov       cx,5
          s:  mov       al,ds:[bx]
              and       al,11011111b            ; 转所有字母为大写
              mov       ds:[bx],al
              inc       bx
              loop      s
              mov       ax,4c00h
              int       21h
      codesg  ends
              end       start
跟踪结果

  Quote:
-d ds:0
0B49:0000  42 41 53 49 43 69 4E 66-4F 72 6D 61 54 69 4F 6E   BASICiNfOrmaTiOn

把第一行字符串全转成大写,第二行字符串全转成小写字母
              assume    cs:codesg,ds:datasg
      datasg  segment
              db        'BaSiC'
              db        'iNfOrmaTiOn'
      datasg  ends
      codesg  segment
      start:  mov       ax,datasg
              mov       ds,ax       ; 取数据段首地址
              mov       bx,0
              mov       cx,5
          s:  mov       al,ds:[bx]
              and       al,11011111b            ; 转所有字母为大写
              mov       ds:[bx],al
              inc       bx
              loop      s

              mov       bx,5
              mov       cx,11       ; 设置循环11次,因为字母长度为11
         s1:  mov       al,[bx]
              or        al,00100000b
              mov       [bx],al
              inc       bx
              loop      s1

              mov       ax,4c00h
              int       21h
      codesg  ends
              end       start
用 Debug 跟踪结果

  Quote:
-d ds:0
0B49:0000  42 41 53 49 43 69 6E 66-6F 72 6D 61 74 69 6F 6E   BASICinformation

如果要是用到批处理里呢?
C:\WINDOWS>set /a 0X61 "&" 0xDF
65


C:\WINDOWS>set /a 97 "&" 0XDF
65
C:\WINDOWS>
0X61是小写字母 a 的 ASCII 码的16进制表现形式。a 的10进制 ASCII 码是 97

“&” 符号在批处理的 SET /? 命令帮助中是:“与” 操作。

我们最后结果所得到的 65 ,就是大写字母 A 的 10 进制的 ASCII 码表现形式。

怎么验证 65 就是大写字母 A ? ALT+65 的按键操作就出来了~:)



[bx+idta]


一种更灵活的寻址方式,它的偏移地址为(bx)+idata决定~:)

将一个内存单元的内容送入AX,这个内存单元长度为2字节(字单元),存放一个字,偏移地址为bx中数值+200,段地址在ds中。

数学化描述为: (ax)=((ds)*16+(bx)+200)

该指令也可以写成如下格式:

  mov ax,[200+bx]
  mov ax,200[bx]
  mov ax,[bx].200


下面是随便一个例子,对比上面三种命令格式机器码中的表示。
              assume    cs:code
        code  segment
      start:  mov       ax,'aa'
              mov       bx,10h
              mov       ax,[200+bx]
              mov       ax,200[bx]
              mov       ax,[bx].200

              mov       ax,4c00h
              int       21h

        code  ends
              end       start
Debug 反汇编看到机器码与反汇编指令如下:

  Quote:
0B49:0000 B86161        MOV     AX,6161
0B49:0003 BB1000        MOV     BX,0010
0B49:0006 8B87C800      MOV     AX,[BX+00C8]
0B49:000A 8B87C800      MOV     AX,[BX+00C8]
0B49:000E 8B87C800      MOV     AX,[BX+00C8]
0B49:0012 B8004C        MOV     AX,4C00
0B49:0015 CD21          INT     21

经过对比发现,机器码是一样的,看来这些格式全是MASM干的~:)


用[bx+idata]方式进行数组处理
使用数组原理实现将“两行”不同地址的字符串(第一行转大写,第二行转小写)
              assume    cs:codesg,ds:datasg
      datasg  segment
              db        'BaSiC'
              db        'MinIX'
      datasg  ends
      codesg  segment
      start:  mov       ax,datasg
              mov       ds,ax
              mov       bx,0
              mov       cx,5
          s:  mov       al,[bx]
              and       al,11011111b            ; 转大写
              mov       [bx],al     ; 转换完以后送回原处
              mov       al,5[bx]
              or        al,00100000b            ; 转小写
              mov       5[bx],al    ; 转完小写后再送回去
              inc       bx
              loop      s
              mov       ax,4c00h
              int       21h
      codesg  ends
              end       start
Debug 验证转换结果

  Quote:
-d ds:0
0B49:0000  42 41 53 49 43 6D 69 6E-69 78 00 00 00 00 00 00   BASICminix......

SI 和 DI

SI 和 DI 是 8086CPU中和bx功能相近的寄存器,SI和DI不能够分成两个8位寄存器来使用。

示例三组指令实现了相同的功能:


1) mov bx,0
   mov ax,[bx]

2) mov si,0
   mov ax,[si]

3) mov di,0
   mov ax,[di]

下面三组指令也实现了相同的功能:


1) mov bx,0
   mov ax,[bx+123]

2) mov si,0
   mov ax,[si+123]

3) mov di,0
   mov ax,[di+123]



SI 和 DI 复制字符串到另一地址
              assume    cs:code,ds:data
        data  segment
              db        'welcome to masm!'
              db        '................'
        data  ends
        code  segment
      start:  mov       ax,data
              mov       ds,ax
              mov       si,0        ; 源变址
              mov       di,16       ; 目地变址
              mov       cx,8
          s:  mov       ax,[si]
              mov       [di],ax
              add       si,2
              add       di,2
              loop      s
              mov       ax,4c00h
              int       21h
        code  ends
              end       start
更少代码的示例,Debug 分析过程……
              assume    cs:code,ds:data
        data  segment
              db        'welcome to masm!'
              db        '................'
        data  ends
        code  segment
      start:  mov       ax,data
              mov       ds,ax
              mov       si,0
              mov       cx,8
          s:  mov       ax,0[si]
              mov       16[si],ax
              add       si,2
              loop      s
              mov       ax,4c00h
              int       21h
        code  ends
              end       start
[bx+si] 和 [bx+di]


例: mov ax,[bx+si] 的含义
   将一个内存单元的内容(字单元)送入ax寄存器,偏移地址为bx+si,段地址在ds中。

描述: (ax)=((ds)*16+(bx)+(si))

Debug 查看……
              assume    cs:code

        code  segment
      start:  mov       ax,2000h
              mov       ds,ax
              mov       bx,1000h
              mov       si,0
              mov       ax,[bx+si]
              inc       si
              mov       cx,[bx+si]
              inc       si
              mov       di,si
              add       cx,[bx+di]

              mov       ax,4c00h
              int       21h
        code  ends
              end       start
[bx+si+idata] 和 [bx+di+idata]

数学描述: (ax)=((ds)*16+(si)+(idata))
              assume    cs:code
        code  segment
      start:  mov       ax,2000h
              mov       ds,ax
              mov       bx,1000h
              mov       si,0
              mov       ax,[bx+2+si]
              inc       si
              mov       cx,[bx+2+si]
              inc       si
              mov       di,si
              mov       bx,[bx+2+di]
              mov       ax,4c00h
              int       21h
        code  ends
              end       start
代码对比
0B49:0000 B80020        MOV     AX,2000
0B49:0003 8ED8          MOV     DS,AX
0B49:0005 BB0010        MOV     BX,1000
0B49:0008 BE0000        MOV     SI,0000
0B49:000B 8B4002        MOV     AX,[BX+SI+02]
0B49:000E 46            INC     SI
0B49:000F 8B4802        MOV     CX,[BX+SI+02]
0B49:0012 46            INC     SI
0B49:0013 8BFE          MOV     DI,SI
0B49:0015 8B5902        MOV     BX,[BX+DI+02]
0B49:0018 B8004C        MOV     AX,4C00
0B49:001B CD21          INT     21
使用上面原理操作多维数组


将每个单词的第一个字母改为大写字母~:)
              assume    cs:code,ds:data
        data  segment
              db        '1. file         '
              db        '2. edit         '
              db        '3. search       '
              db        '4. view         '
              db        '5. options      '
              db        '6. help         '
        data  ends
        code  segment
      start:  mov       ax,data
              mov       ds,ax
              mov       si,3        ; 定位在第3列
              mov       bx,0        ; 定位在第n行
              mov       cx,6
          s:  mov       al,[bx+si]  ; 取数组 bx行.si列
              and       al,11011111b            ; 第5位为0就是大写
              mov       [bx+si],al  ; 送回去~:)
              add       bx,10h
              loop      s
              mov       ax,4c00h
              int       21h
        code  ends
              end       start
Debug 验证结果
-d ds:0
0B49:0000  31 2E 20 46 69 6C 65 20-20 20 20 20 20 20 20 20   1. File
0B49:0010  32 2E 20 45 64 69 74 20-20 20 20 20 20 20 20 20   2. Edit
0B49:0020  33 2E 20 53 65 61 72 63-68 20 20 20 20 20 20 20   3. Search
0B49:0030  34 2E 20 56 69 65 77 20-20 20 20 20 20 20 20 20   4. View
0B49:0040  35 2E 20 4F 70 74 69 6F-6E 73 20 20 20 20 20 20   5. Options
0B49:0050  36 2E 20 48 65 6C 70 20-20 20 20 20 20 20 20 20   6. Help
多重循环转换数组中所有字母为大写
              assume    cs:code,ds:data
        data  segment
              db        'dos             '
              db        'del             '
              db        'set             '
              db        'for             '
        data  ends
        code  segment
      start:  mov       ax,data
              mov       ds,ax
              mov       bx,0
              mov       cx,4
         s0:  mov       di,0        ; 数组列指针
              mov       dx,cx       ; 保存外层循环cx计数器的值
              mov       cx,3        ; 转换列计数(共3列)
         s1:  mov       al,[bx+di]  ; 取数组第0列
              and       al,11011111b
              mov       [bx+di],al  ; 转完大写送回去
              inc       di          ; 数组列指针右移一列
              loop      s1
              mov       cx,dx       ; 恢复外层循环cx计数器的值
              add       bx,10h      ; 将数组指针下移一行
              loop      s0          ; 返回外层循环
              mov       ax,4c00h
              int       21h
        code  ends
              end       start
Debug 调试结果~:)))
-d ds:0
0B49:0000  44 4F 53 20 20 20 20 20-20 20 20 20 20 20 20 20   DOS
0B49:0010  44 45 4C 20 20 20 20 20-20 20 20 20 20 20 20 20   DEL
0B49:0020  53 45 54 20 20 20 20 20-20 20 20 20 20 20 20 20   SET
0B49:0030  46 4F 52 20 20 20 20 20-20 20 20 20 20 20 20 20   FOR
不管有多少个内、外循环,都只有一个cx计数器。
上面代码是用寄存器暂存数据。

用内存暂存数据
              assume    cs:code,ds:data
        data  segment
              db        'dos             '
              db        'del             '
              db        'set             '
              db        'for             '
        data  ends

        code  segment
      start:  mov       ax,data
              mov       ds,ax
              mov       bx,0
              mov       cx,4        ; 外循环计数器
         s0:  mov       ds:[40h],cx
              mov       si,0
              mov       cx,3        ; 内循环计数器
          s:  mov       al,[bx+si]  ; 内循环
              and       al,11011111b
              mov       [bx+si],al  ; 转完大写再送回去
              inc       si
              loop      s
              add       bx,10h      ; 外循环数组指针下移一行
              mov       cx,ds:[40h] ; 从内存单元中取出数据恢复cx计数器
              loop      s0
              mov       ax,4c00h
              int       21h
        code  ends
              end       start

-d ds:0
0B49:0000  44 4F 53 20 20 20 20 20-20 20 20 20 20 20 20 20   DOS
0B49:0010  44 45 4C 20 20 20 20 20-20 20 20 20 20 20 20 20   DEL
0B49:0020  53 45 54 20 20 20 20 20-20 20 20 20 20 20 20 20   SET
0B49:0030  46 4F 52 20 20 20 20 20-20 20 20 20 20 20 20 20   FOR
将菜单中前4个字母大写,使用栈来存储数据
              assume    cs:code,ds:data,ss:stack

       stack  segment
              dw        0,0,0,0,0,0,0,0
       stack  ends

        data  segment
              db        '1. display      '
              db        '2. brows        '
              db        '3. replace      '
              db        '4. modify       '
        data  ends

        code  segment
      start:  mov       ax,data
              mov       ds,ax
              mov       ax,ss
              mov       ss,ax
              mov       sp,0fh
              mov       bx,0
              mov       cx,4
         s0:  push      cx
              mov       si,0
              mov       cx,4
         s1:  mov       al,[bx+3+si]
              and       al,11011111b
              mov       [bx+3+si],al
              inc       si
              loop      s1
              add       bx,10h
              pop       cx
              loop      s0
              mov       ax,4c00h
              int       21h
        code  ends
              end       start
Debug 分析结果
-d ss:0
0B49:0000  00 00 00 00 00 00 00 00-00 2A 00 4E 0B 59 05 00   .........*.N.Y..
0B49:0010  31 2E 20 44 49 53 50 6C-61 79 20 20 20 20 20 20   1. DISPlay
0B49:0020  32 2E 20 42 52 4F 57 73-20 20 20 20 20 20 20 20   2. BROWs
0B49:0030  33 2E 20 52 45 50 4C 61-63 65 20 20 20 20 20 20   3. REPLace
0B49:0040  34 2E 20 4D 4F 44 49 66-79 20 20 20 20 20 20 20   4. MODIfy
[ Last edited by redtek on 2006-12-27 at 10:44 PM ]



    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-27 22:48
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 75 楼』:  【80x86汇编语言学习笔记】

数据处理

寄存器(reg)集合包括:  ax,bx,cx,dx,ah,al,bh,bl,ch,cl,dh,dl,sp,bp,si,di;

段寄存器(sreg)集合包括:ds,ss,cs,es;


要处理的数据有多长?

1) 通过寄存器名指明要处理的数据尺寸。

2) 在没有寄存器名存在的情况下,用操作符 X ptr 指明内存单元的长度。
   X 在汇编指令中可以为 word 或 bye。

   mov word ptr ds:[0],1
   inc word ptr [bx]


在没有寄存器参与的内存单元访问指令中,用 word ptr 或 byte ptr 显性地指明所要访问的内存单地长度是必要的。
否则CPU无法得知所要访问的单元是字单元还是字节单元。

  Quote:
-a
0AF5:0100 mov ax,2000
0AF5:0103 mov ds,ax
0AF5:0105 mov byte ptr [1000],1
0AF5:010A
-r
AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0AF5  ES=0AF5  SS=0AF5  CS=0AF5  IP=0100   NV UP EI PL NZ NA PO NC
0AF5:0100 B80020        MOV     AX,2000
-t

AX=2000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0AF5  ES=0AF5  SS=0AF5  CS=0AF5  IP=0103   NV UP EI PL NZ NA PO NC
0AF5:0103 8ED8          MOV     DS,AX
-t

AX=2000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=2000  ES=0AF5  SS=0AF5  CS=0AF5  IP=0105   NV UP EI PL NZ NA PO NC
0AF5:0105 C606001001    MOV     BYTE PTR [1000],01                 DS:1000=00
-t

AX=2000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=2000  ES=0AF5  SS=0AF5  CS=0AF5  IP=010A   NV UP EI PL NZ NA PO NC
0AF5:010A CD21          INT     21
-d ds:1000
2000:1000  01 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
2000:1010  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
2000:1020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
2000:1030  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
2000:1040  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
2000:1050  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
2000:1060  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
2000:1070  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

寻址方式的缩合应用

更改内存中的数据
公司名称: DEC
总载姓名: Ken Olsen
排  名: 137
收  入: 40(40亿美元)
著名产品: PDP(小型机)

              db        'DEC'       ; 公司名称
              db        'Ken Oslen' ; 总载姓名
              dw        137         ; 排  名
              dw        40          ; 收  入
              db        'PDP'       ; 著名产品
数据在内存中存放形式
0B49:0000  44 45 43 4B 65 6E 20 4F-73 6C 65 6E 89 00 28 00   DECKen Oslen..(.
0B49:0010  50 44 50 00 00 00 00 00-00 00 00 00 00 00 00 00   PDP.............

代码如下

              assume    cs:code,ds:data
        data  segment
              db        'DEC'       ; 公司名称
              db        'Ken Oslen' ; 总载姓名
              dw        137         ; 排  名
              dw        40          ; 收  入
              db        'PDP'       ; 著名产品
        data  ends
        code  segment
      start:  mov       ax,data
              mov       ds,ax
              mov       bx,0        ; 没用,就是表示寻址原理,超始位置
              mov       word ptr [bx+0ch],38    ; 修改排名为38
              add       word ptr [bx+0eh],70    ; 收入字段增加70
              mov       si,0        ; 用si定位产品字符串中的字符
              mov       byte ptr [bx+10h+si],'V'
              inc       si          ; 下移一个
              mov       byte ptr [bx+10h+si],'A'
              inc       si
              mov       byte ptr [bx+10h+si],'X'
              mov       ax,4c00h
              int       21h
        code  ends
              end       start
修改完成
0B49:0000  44 45 43 4B 65 6E 20 4F-73 6C 65 6E 26 00 6E 00   DECKen Oslen&.n.
0B49:0010  56 41 58 00 00 00 00 00-00 00 00 00 00 00 00 00   VAX.............
很象结构体

按C风格描述
/* 定义一个公司记录的结构体 */

struct company {
        char cn[3] ;                 /* 公司名称 */
        char hn[9] ;                 /* 总载姓名 */
        int pm ;                     /* 排    名 */
        int sr ;                     /* 收    入 */
        char cp[3] ;                 /* 著名产品 */
}
按C风格,用汇编语言重写上面操作数据的代码
              assume    cs:code,ds:data
        data  segment
              db        'DEC'       ; 公司名称
              db        'Ken Oslen' ; 总载姓名
              dw        137         ; 排  名
              dw        40          ; 收  入
              db        'PDP'       ; 著名产品
        data  ends
        code  segment
      start:  mov       ax,data
              mov       ds,ax
              mov       bx,0
              mov       word ptr [bx].0ch,38    ; 排名 - C: dec.pm=38
              add       word ptr [bx].0eh,70    ; 收入 - C: dec.sr=dec.sr+70
              mov       si,0
              mov       byte ptr [bx].10h[si],'V'           ; C: dec.cp[i]='V'
              inc       si          ; C: i++
              mov       byte ptr [bx].10h[si],'A'           ; C: dec.cp[i]='A'
              inc       si          ; C: i++
              mov       byte ptr [bx].10h[si],'X'           ; C: dec.cp[i]='X'
              mov       ax,4c00h
              int       21h
        code  ends
              end       start
在机器码中,上面不同书写的代码在机器码中只有一种表示
0B4B:0000 B8490B        MOV     AX,0B49
0B4B:0003 8ED8          MOV     DS,AX
0B4B:0005 BB0000        MOV     BX,0000
0B4B:0008 C7470C2600    MOV     WORD PTR [BX+0C],0026
0B4B:000D 83470E46      ADD     WORD PTR [BX+0E],+46
0B4B:0011 BE0000        MOV     SI,0000
0B4B:0014 C6401056      MOV     BYTE PTR [BX+SI+10],56
0B4B:0018 46            INC     SI
0B4B:0019 C6401041      MOV     BYTE PTR [BX+SI+10],41
0B4B:001D 46            INC     SI
0B4B:001E C6401058      MOV     BYTE PTR [BX+SI+10],58
DIV 除法操作

1) 除数:有8位和16位两种
2) 被除数:默认放在AX或DX和AX中。
   如果除数为8位,被除数则为16位。默认在AX中存放。
   如果除数为16位,被除数则为32位,在DX和AX中存放。DX存高16位,AX存低16位。
3) 结果
   如果除数为8位,则AL存放商,AH存放余数。
   如果除数为16位数,则AX存放商,DX存放余数

格式:

   div reg
   div 内存单元

   例: div byte ptr ds:[0]
  含义: (al)=(ax)/((ds)*16+0))商
      (ah)=(ax)/(ds)*16+0))余数

   div word ptr es:[0]
   (ax)=[(dx)*10000H+(ax)]/((es)*16+0)  商
   (dx)=[(dx)*10000H+(ax)]/((es)*16+0)  余数

   div byte ptr [bx+si+8]
   (al)=(ax)/((ds)*16+(bx)+(si)+8) 商
   (ah)=(ax)/(ds)*16+(bx)+(si)+8) 余数

   div word ptr [bx+si+8]
   (ax)=[(dx)*10000H+(ax)]/((ds)*16+(bx)+(si)+8) 商
   (dx)=[(dx)*10000H+(ax)]/((ds)*16+(bx)+(si)+8) 余数


计算 100001 / 100

100001(16)=186A1H
100(16)=64H

如果用 Debug 直接写汇编代码,一切都是16进制。
如果用 Masm 汇编代码写再编译,随便。

被除数是32位,那么计算除得的商与余数就必须(商16位、余数占16位),除数也占16位。

186A1H(被除数)的位低是:86A1H 、高位是:0001H


Debug 直接汇编代码如下:
C:\Masm50>debug
-A
0AF5:0100 mov dx,1
0AF5:0103 mov ax,86a1
0AF5:0106 mov bx,64
0AF5:0109 div bx
0AF5:010B
-r
AX=0000  BX=0000  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0AF5  ES=0AF5  SS=0AF5  CS=0AF5  IP=0100   NV UP EI PL NZ NA PO NC
0AF5:0100 BA0100        MOV     DX,0001
-t

AX=0000  BX=0000  CX=0000  DX=0001  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0AF5  ES=0AF5  SS=0AF5  CS=0AF5  IP=0103   NV UP EI PL NZ NA PO NC
0AF5:0103 B8A186        MOV     AX,86A1
-t

AX=86A1  BX=0000  CX=0000  DX=0001  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0AF5  ES=0AF5  SS=0AF5  CS=0AF5  IP=0106   NV UP EI PL NZ NA PO NC
0AF5:0106 BB6400        MOV     BX,0064
-t

AX=86A1  BX=0064  CX=0000  DX=0001  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0AF5  ES=0AF5  SS=0AF5  CS=0AF5  IP=0109   NV UP EI PL NZ NA PO NC
0AF5:0109 F7F3          DIV     BX
-t

AX=03E8  BX=0064  CX=0000  DX=0001  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0AF5  ES=0AF5  SS=0AF5  CS=0AF5  IP=010B   NV UP EI PL NZ NA PO NC
用 windows 计算器算 100001 / 100 = 1000.01 (十进制)
上面值做为验证之用~:)

商:1000
余数:01

它们的16进制表示:  商:03E8H  余数:0001H
商与余数各占16位,商在低位表示的寄存器中,余数在高位表示的寄存器中。

再看 Debug 结果数据:

  Quote:
AX=03E8  BX=0064  CX=0000  DX=0001  SP=FFEE  BP=0000  SI=0000  DI=0000
DS=0AF5  ES=0AF5  SS=0AF5  CS=0AF5  IP=010B   NV UP EI PL NZ NA PO NC

红色标注表示:商
绿色标注表示:余数 ~:)



Masm 汇编代码,求 1001 / 100
              assume    cs:code
        code  segment
      start:  mov       ax,1001
              mov       bl,100
              div       bl
        code  ends
              end       start
验证计算结果
AX=010A  BX=0064  CX=0007  DX=0000  SP=0000
DS=0B39  ES=0B39  SS=0B49  CS=0B49  IP=0007
AX=010A,结果正确~:)
商:0AH , 余数: 01H



伪指令 dd


定义dword(double word)-双字型数据。
双字型数据占 32 位。

如果汇编代码: dd 1
则16进制表示其所占用的空间: 00000001H


用 div 计算 data 段中第一个数据除以第二个数据后的结果,商存放在第3个数据的存储单元中。
              assume    cs:code,ds:data
        data  segment
              dd        100001      ; 32位被除数
              dw        100         ; 16位除数
              dw        0
        data  ends
        code  segment
      start:  mov       ax,data
              mov       ds,ax
              mov       ax,ds:[0]   ; 将被除数低位送入低位被除数应该在的寄存器
              mov       dx,ds:[2]   ; 将被除数的高位送dx寄存器
              div       word ptr ds:[4]         ; 用dx:ax 中的32位数据除以 ds:4 字单元中的数据
              mov       ds:[6],ax   ; 将商存储在 ds:6 字单元中
              mov       ax,4c00h
              int       21h
        code  ends
              end       start


  Quote:
-d ds:0006
0B49:0000                    E8 03-00 00 00 00 00 00 00 00

DUP 操作符

它与 db,dw,dd等数据定义伪指令配合使用,用来进行数据的重复。

db  重重的次数 dup (重复的字节型数据)
dw  重重的次数 dup (重复的字型数据)
dd  重重的次数 dup (重复的双字型数据)
              assume    cs:code,ss:stack

       stack  segment
              db        200 dup(0)  ; 定义容量为200字节
       stack  ends

        code  segment
      start:  mov       ax,4c00h
              int       21h
        code  ends
              end       start
数据分布

  Quote:
-d ss:0
0B49:0000  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0B49:0010  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0B49:0020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0B49:0030  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0B49:0040  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0B49:0050  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0B49:0060  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0B49:0070  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
-d
0B49:0080  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0B49:0090  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0B49:00A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0B49:00B0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
0B49:00C0  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00

寻址方式在结构化数据访问中的应用

[ Last edited by redtek on 2006-12-28 at 06:19 PM ]



    Redtek,一个永远在网上流浪的人……

_.,-*~'`^`'~*-,.__.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._,_.,-*~'`^`'~*-,._
2006-12-28 12:12
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
« [1] [2] [3] [4] [5] [6] [7] [8] [9] »
请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: