- [游客] 表示每次运行到cx=2的时候就不能再往下一步进行了! 谁能告诉我是哪里的问题? 06/11 23:38
- [游客] 这是C下的么?main中的 int c[]={6,7,8,9} ; int *p = c; 08/06 15:33
- [游客] 实现队列?呵呵,以前学C的时候也弄过队,循环队列等东西,锻炼了很多思维逻辑上的东西。 博主可以自己 08/06 15:30
- [maxm] 这实验没难度,关键是细心 几个易出错的地儿我都在注释中做了标记 希望大家别跟我一样犯糊涂 (*^ 06/04 20:58
- [maxm] 感谢fangyugirl分享心得 05/08 18:47
- [fangyugirl] 看到你说你在这章徘徊了两周,我跟你差不多的。我是做BIOS的,上班时没有事情了就看书,做课程设计一时 04/23 13:44
- [maxm] 哎,没有自己电脑。 03/19 20:57
- [游客] 然后继续编程 呵呵 03/18 20:56
- [游客] 我被卡在这一章了,就因为这个实验。 03/18 15:31
- [maxm] 最后加了点注释,程序改动如下: ;------------------------------ 03/13 15:52
[2009-02-25 17:13] 实验7 收获比较大
---------------------------------------
;实验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年嘛 ,太粗心了 ^_^ ^_^ ^_^ 见笑了 ^_^ ,有疏漏的地方您多指正 ^_^ 。(喝水去了,近仨小时没喝一口水)
[ 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的时候就不能再往下一步进行了!
谁能告诉我是哪里的问题?