汇编网首页登录博客注册
maxm的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
  •  做不了第一个就做最好的, 做不了最好的就做第一个。
  • 『姓名』:
  • 『性别』:保密『发送消息
  • 个人说明:不要执着于学习步骤, 宁愿多看点知识
  • 详细信息『加为好友』
学习动态
最新留言
友情链接

[2009-02-25 17:13] 推荐博文 实验7 收获比较大

一看题目不就是把一段数据赋值到内存嘛还不简单,于是打开熟悉的editplus 洋洋洒洒不一会就写下如下代码:
---------------------------------------
;实验7
assume cs:codesg

datasg segment
        db '1975', '1976', '1977', '1978', '1979', '1980'
        db '1981', '1982', '1983', '1984', '1985', '1986'
        db '1987', '1988', '1989', '1990', '1991', '1992'
        db '1993', '1994', '1995'
        ;以上是表示21年的21个字符串

        dd 16, 22, 382, 1356, 2390, 8000, 16000, 24486, 50065, 97479, 140417, 197514
        dd 345980, 590287, 803530,1183000, 1843000, 2759000, 3753000, 4649000, 5937000
        ;以上是表示21年公司总收入的21个dword型数据

        dw 3, 7, 9, 13, 28, 38, 130, 220, 478, 778, 1001, 1442, 2258, 2793, 4037, 5635, 8226
        dw 11542, 14430, 15257, 17800
        ;以上是表示21年公司雇员人数的21个word型数据
datasg ends

table segment
        db 21 dup('year summ ne ?? ')
table ends

;编程将data段中的数据按如下格式写入到table段中。并计算21年的人均收入,结果也按照图8.3所示的格式保存在table段中

codesg segment
start:        mov ax,datasg
        mov ds,ax
        mov si,0h
        mov ax,table
        mov es,ax
        mov di,0h
        mov bx,0h                                ;用 bx 来定位table(es)段中的结构体数据
        mov bp,0h                                ;我用 bp 来定位 data(ds)段中的数据
        mov cx,15h
        ;push cx                                ;这句可以注释掉因为循环里头不会修改cx的值
cycle:        
        ;利用栈拷贝年份
        push ds:[bp].0h[si]
        push ds:[bp].2h[si]
        pop es:[bx].2h[di]
        pop es:[bx].0h[di]        
        mov byte ptr es:[bx].4h[di],20h                ;拷贝一个空格

        ;利用栈拷贝收入
        add bp,54h
        push ds:[bp].0h[si]
        push ds:[bp].2h[si]
        pop es:[bx].7h[di]
        pop es:[bx].5h[di]
        mov byte ptr es:[bx].9h[di],20h                ;拷贝一个空格

        ;利用栈拷贝雇员数
        add bp,54h
        push ds:[bp].0h[si]
        pop es:[bx].0ah[di]
        mov byte ptr es:[bx].0ch[di],20h        ;拷贝一个空格

        mov dx,es:[bx].7h                        ;被除数的高16位
        mov ax,es:[bx].5h                        ;被除数的低16位
        div word ptr es:[bx].0ah                ;计算人均收入         ----- divide overflow
        mov es:[bx].0dh[di],ax                        ;人均收入保存在0dh单元
        mov byte ptr es:[bx].0fh[di],20h        ;拷贝一个空格

        add bx,10h
        loop cycle

        mov ax,4c00h
        int 21h

codesg ends
end start
--------------------------------------
然后masm 、link 、运行 ,sorry “Divede overflow!” ,不怕反正生成了.exe文件,咋debug(真是爱死你了),一路t 到除法溢出,然后 d:es:0000,结果如下:
-d es:0000
0C00:0000  31 39 37 35 20 10 00 00-00 20 03 00 20 05 00 20   1975 .... .. ..
0C00:0010  03 00 07 00 20 20 3F 3F-20 20 79 65 20 5A 51 20   ....  ??  ye ZQ
0C00:0020  79 65 61 72 20 20 73 75-6D 20 6D 20 20 3F 3F 20   year  sum m  ??
0C00:0030  79 65 61 72 20 73 75 6D-6D 20 6E 65 20 3F 3F 20   year summ ne ??
0C00:0040  79 65 61 72 20 73 75 6D-6D 20 6E 65 20 3F 3F 20   year summ ne ??
0C00:0050  79 65 61 72 20 73 75 6D-6D 20 6E 65 20 3F 3F 20   year summ ne ??
0C00:0060  79 65 61 72 20 73 75 6D-6D 20 6E 65 20 3F 3F 20   year summ ne ??
0C00:0070  79 65 61 72 20 73 75 6D-6D 20 6E 65 20 3F 3F 20   year summ ne ??
---------------------

显然是拷贝错位了?肯定是定位es段的偏移地址出错,果然经过仔细检查漏掉了很重要的一句:mov bp,0h ,因为咋bp 和ds搭配来定位datasg 段数据的,所以每次循环后都要将其置0 ,因为内存是连续的嘛^_^。好了加进去测试,运行 没报错 ^_^。然后debug 看结果
---------------
-d es:0000
0C00:0000  31 39 37 35 20 10 00 00-00 20 03 00 20 05 00 20   1975 .... .. ..
0C00:0010  31 39 37 35 20 10 00 00-00 20 03 00 20 05 00 20   1975 .... .. ..
0C00:0020  31 39 37 35 20 10 00 00-00 20 03 00 20 05 00 20   1975 .... .. ..
0C00:0030  31 39 37 35 20 10 00 00-00 20 03 00 20 05 00 20   1975 .... .. ..
0C00:0040  31 39 37 35 20 10 00 00-00 20 03 00 20 05 00 20   1975 .... .. ..
0C00:0050  31 39 37 35 20 10 00 00-00 20 03 00 20 05 00 20   1975 .... .. ..
0C00:0060  31 39 37 35 20 10 00 00-00 20 03 00 20 05 00 20   1975 .... .. ..
0C00:0070  31 39 37 35 20 10 00 00-00 20 03 00 20 05 00 20   1975 .... .. ..
----------------
天全是1975 ,看来又是内存定位错了,天仔细一看这个错误更离谱!我竟然笨到没考虑到每循环一次光把bp初始话了,而si 没变!这不扯呢?每次的ds:[bp].0h[si] 的值不就相等了吗?那时间肯定就都是1975,赶紧改过来。怎么改呢?一个年份占4 byte ,当然是 add si,4了。晕 ! 又 Divide over flow ,不管你先,debug查看内存,结果如下:
-------------
-d es:0000
0C00:0000  31 39 37 35 20 10 00 00-00 20 03 00 20 05 00 20   1975 .... .. ..
0C00:0010  31 39 37 36 20 16 00 00-00 20 09 00 20 02 00 20   1976 .... .. ..
0C00:0020  31 39 37 37 20 7E 01 00-00 20 1C 00 20 0D 00 20   1977 ~... .. ..
0C00:0030  31 39 37 38 20 4C 05 00-00 20 82 00 20 0A 00 20   1978 L... .. ..
0C00:0040  31 39 37 39 20 56 09 00-00 20 DE 01 20 05 00 20   1979 V... .. ..
0C00:0050  31 39 38 30 20 40 1F 00-00 20 E9 03 20 07 00 20   1980 @... .. ..
0C00:0060  31 39 38 31 20 80 3E 00-00 20 D2 08 20 07 00 20   1981 .>.. .. ..
0C00:0070  31 39 38 32 20 A6 5F 00-00 20 C5 0F 20 06 00 20   1982 ._.. .. ..
--------------
哎,年份字段正确了!好,现在肯定是其他字段还有错位的情况。先别这样想看上面结果的中间,其实部分的数据也都拷贝真确了 比如:最后一行的 00005fa6 = 24486 ,它可不就是82年的公司总收入!但奇怪了再往后看82年的雇员数字段:0fc5 =  4037,天!它不应该是220嘛怎么成4037了?看来是拷贝雇员数的时候定位内存出错了,显然雇员数是两个字节我循环一次却将它加了4,比如第二次循环(76年)的雇员数本来应该是 7 ,而现在却成了0009,越过了一个字。所以我们不能同时用si来定位收入和雇员数目,那怎么办呢?换个寄存其呗!可是换哪个呢?换成谁都不好使,别急这题有点巧的大家发现没?就是年份和收入字段都是4个字节,既然如此我们就可以只用一个si来同时定位源段和目的段中的这俩字段(谁也没有规定源段一定要用si ,目的段一定要用di),这样di我们就可以用来定位其他的字段了。(注意:这时空格就用[bx].idata的方式来定位了,因为前面程序拷贝空格时也用到了si和di,人均收入也用[bx].idata的方式来定位), 并且我们在定位目的段es的时候直接用 [bx].idata的方式,因为这时显然不能用 [bx].idata[si/di](si和di每次循环都要累加嘛!!!^_^^_^),最后程序改动如下:
-----------------------------------
;实验7
assume cs:codesg

datasg segment
        db '1975', '1976', '1977', '1978', '1979', '1980'
        db '1981', '1982', '1983', '1984', '1985', '1986'
        db '1987', '1988', '1989', '1990', '1991', '1992'
        db '1993', '1994', '1995'
        ;以上是表示21年的21个字符串

        dd 16, 22, 382, 1356, 2390, 8000, 16000, 24486, 50065, 97479, 140417, 197514
        dd 345980, 590287, 803530,1183000, 1843000, 2759000, 3753000, 4649000, 5937000
        ;以上是表示21年公司总收入的21个dword型数据

        dw 3, 7, 9, 13, 28, 38, 130, 220, 478, 778, 1001, 1442, 2258, 2793, 4037, 5635, 8226
        dw 11542, 14430, 15257, 17800
        ;以上是表示21年公司雇员人数的21个word型数据
datasg ends

table segment
        db 21 dup('year summ ne ?? ')
table ends

;编程将data段中的数据按如下格式写入到table段中。并计算21年的人均收入,结果也按照图8.3所示的格式保存在table段中

codesg segment
start:        mov ax,datasg
        mov ds,ax
        mov si,0h
        mov ax,table
        mov es,ax
        mov di,0h
        mov bx,0h                                        ;用 bx 来定位table(es)段中的结构体数据
        mov bp,0h                                        ;我用 bp 来定位 data(ds)段中的数据
        mov cx,15h
        ;push cx                                                ;这句可以注释掉因为循环里头不会修改cx的值
cycle:        
        ;利用栈拷贝年份
        push ds:[bp].0h[si]
        push ds:[bp].2h[si]
        pop es:[bx].2h
        pop es:[bx].0h        
        mov byte ptr es:[bx].4h,20h                ;拷贝一个空格

        ;利用栈拷贝收入
        add bp,54h
        push ds:[bp].0h[si]
        push ds:[bp].2h[si]
        pop es:[bx].7h
        pop es:[bx].5h
        mov byte ptr es:[bx].9h,20h                ;拷贝一个空格

        ;利用栈拷贝雇员数
        add bp,54h
        push ds:[bp].0h[di]
        pop es:[bx].0ah
        mov byte ptr es:[bx].0ch,20h                ;拷贝一个空格

        mov dx,es:[bx].7h                                ;被除数的高16位
        mov ax,es:[bx].5h                                ;被除数的低16位
        div word ptr es:[bx].0ah                        ;计算人均收入         ----- divide overflow
        mov es:[bx].0dh,ax                                ;人均收入保存在0dh单元
        mov byte ptr es:[bx].0fh,20h                ;拷贝一个空格

        add bx,10h
        mov bp,0h
        add si,4
        add di,2
        loop cycle

        mov ax,4c00h
        int 21h

codesg ends
end start

截取 部分结果如下
------------
0C00:0040  31 39 37 39 20 56 09 00-00 20 1C 00 20 55 00 20   1979 V... .. U.
0C00:0050  31 39 38 30 20 40 1F 00-00 20 26 00 20 D2 00 20   1980 @... &. ..
0C00:0060  31 39 38 31 20 80 3E 00-00 20 82 00 20 7B 00 20   1981 .>.. .. {.
0C00:0070  31 39 38 32 20 A6 5F 00-00 20 DC 00 20 6F 00 20   1982 ._.. .. o.
-d
0C00:0080  31 39 38 33 20 91 C3 00-00 20 DE 01 20 68 00 20   1983 .... .. h.
0C00:0090  31 39 38 34 20 C7 7C 01-00 20 0A 03 20 7D 00 20   1984 .|.. .. }.
0C00:00A0  31 39 38 35 20 81 24 02-00 20 E9 03 20 8C 00 20   1985 .$.. .. ..
0C00:00B0  31 39 38 36 20 8A 03 03-00 20 A2 05 20 88 00 20   1986 .... .. ..
0C00:00C0  31 39 38 37 20 7C 47 05-00 20 D2 08 20 99 00 20   1987 |G.. .. ..
0C00:00D0  31 39 38 38 20 CF 01 09-00 20 E9 0A 20 D3 00 20   1988 .... .. ..
0C00:00E0  31 39 38 39 20 CA 42 0C-00 20 C5 0F 20 C7 00 20   1989 .B.. .. ..
0C00:00F0  31 39 39 30 20 18 0D 12-00 20 03 16 20 D1 00 20   1990 .... .. ..
-d
0C00:0100  31 39 39 31 20 38 1F 1C-00 20 22 20 20 E0 00 20   1991 8... "  ..
0C00:0110  31 39 39 32 20 58 19 2A-00 20 16 2D 20 EF 00 20   1992 X.*. .- ..
0C00:0120  31 39 39 33 20 28 44 39-00 20 5E 38 20 04 01 20   1993 (D9. ^8 ..
0C00:0130  31 39 39 34 20 28 F0 46-00 20 99 3B 20 30 01 20   1994 (.F. .; 0.
0C00:0140  31 39 39 35 20 68 97 5A-00 20 88 45 20 4D 01 20   1995 h.Z. .E M.
-----------
注:开始将cx置成了14h,应该是15h ,21年嘛 ,太粗心了 ^_^ ^_^ ^_^ 见笑了 ^_^ ,有疏漏的地方您多指正 ^_^  。(喝水去了,近仨小时没喝一口水)
评论次数(9)  |  浏览次数(1542)  |  类型(实验) |  收藏此文  | 

[  maxm   发表于  2009-02-25 17:15  ]

欢迎大家拍砖 ^_^

[  maxm   发表于  2009-02-25 17:27  ]

可以用mov指令来传送数据的,我用了栈来传送数据即清晰又能更加熟悉栈的操作原理和过程感觉。

[  游客   发表于  2009-02-25 17:31  ]

做这个实验感觉自己逻辑分析能力有了点提高^_^

[  younggay   发表于  2009-02-26 10:24  ]

博主收获岗岗的,恭喜恭喜。

[  maxm   发表于  2009-02-26 14:12  ]

这俩天惨了^_^,上网不方便了。

[  maxm   发表于  2009-02-26 14:13  ]

想不到被推荐到首页了,还挺受宠若惊的^_^

[  maxm   发表于  2009-02-26 21:24  ]

网卡找到了^_^ ,晚上又可以上网了^_^

[  游客   发表于  2009-03-18 15:31  ]

我被卡在这一章了,就因为这个实验。

[  游客   发表于  2015-06-11 23:38  ]

表示每次运行到cx=2的时候就不能再往下一步进行了!
谁能告诉我是哪里的问题?

 
 请输入验证码  (提示:点击验证码输入框,以获取验证码