|
主题 : : 那位哥给分析一下实验研究3.1的程序 [待解决] |
回复[ 4次 ]
点击[ 606次 ] | |
|
|
|
|
[帖 主]
[ 发表时间:2011-05-03 18:17 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-04-29 18:09 |
main()
{
*(char *)0x2000='a';
*(int *)0x2000=0xf;
*(char far *)0x20001000='a';
_AX=0x2000;
*(char *)_AX='b';
_BX=0x1000;
*(char *) (_BX+_BX)='a';
*(char far *)(0x20001000+_BX)=*(char *)_AX;
}
最后的赋值是多少?
重点分析
*(char *) (_BX+_BX)='a';
*(char far *)(0x20001000+_BX)=*(char *)_AX;
对应汇编如下:
-u 1fa
0B85:01FA 55 PUSH BP
0B85:01FB 8BEC MOV BP,SP
0B85:01FD C606002061 MOV BYTE PTR [2000],61
0B85:0202 C70600200F00 MOV WORD PTR [2000],000F
0B85:0208 BB0020 MOV BX,2000
0B85:020B 8EC3 MOV ES,BX
0B85:020D BB0010 MOV BX,1000
0B85:0210 26 ES:
0B85:0211 C60761 MOV BYTE PTR [BX],61
0B85:0214 B80020 MOV AX,2000
0B85:0217 8BD8 MOV BX,AX
0B85:0219 C60762 MOV BYTE PTR [BX],62
0B85:021C BB0010 MOV BX,1000
0B85:021F 03DB ADD BX,BX
0B85:0221 C60761 MOV BYTE PTR [BX],61
0B85:0224 8BD8 MOV BX,AX
0B85:0226 8A07 MOV AL,[BX]
0B85:0228 33C9 XOR CX,CX
0B85:022A 81C30010 ADD BX,1000
0B85:022E 81D10020 ADC CX,2000
0B85:0232 8EC1 MOV ES,CX
0B85:0234 26 ES:
0B85:0235 8807 MOV [BX],AL
0B85:0237 5D POP BP
0B85:0238 C3 RET
0B85:0239 C3 RET
0B85:023A 55 PUSH BP
0B85:023B 8BEC MOV BP,SP | | |
|
|
|
|
[第1楼]
[ 回复时间:2012-03-13 16:25 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2012-01-05 18:58 |
*(char *) (_BX+_BX)='a'; 这个你应该自己可以看懂 主要说下下边那条吧。
*(char far *)(0x20001000+_BX)=*(char *)_AX;
对应汇编代码:
0B85:0224 8BD8 MOV BX,AX
0B85:0226 8A07 MOV AL,[BX] ;上边两条指令暂存*(char *)_AX到AL中。
0B85:0228 33C9 XOR CX,CX ;CX异或CX=0,相当于CX初始化。
0B85:022A 81C30010 ADD BX,1000 ;BX加上0x20001000的偏移地址,得到偏移地址放到BX中
0B85:022E 81D10020 ADC CX,2000 ;cx存放段地址,但上边BX可能产生近位,所以要ADC
0B85:0232 8EC1 MOV ES,CX ;段地址放到段寄存器ES.
0B85:0234 26 ES:
0B85:0235 8807 MOV [BX],AL ;将AL的值也就是*(char *)_AX存到ES:[BX]即*(char far *)(0x20001000+_BX)中
0B85:0237 5D POP BP
0B85:0238 C3 RET
0B85:0239 C3 RET
0B85:023A 55 PUSH BP
0B85:023B 8BEC MOV BP,SP
上边是我个人的理解,有错误的还要相互学习。 | | |
|
|
|
|
[第2楼]
[ 回复时间:2012-03-13 23:31 ]
[引用]
[回复]
[ top ] | |
荣誉值:405
信誉值:0
注册日期:2008-01-19 14:51 |
|
|
|
|
|
[第3楼]
[ 回复时间:2013-05-07 14:26 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2013-02-26 12:52 |
我更感疑惑的是这一句:
*(char *) (_BX+_BX)='a';
看表达式,感觉BX寄存器不应该被改变的。
事实是,编译后它会分解为两条汇编指令:
ADD BX,BX
MOV BYTE PTR [BX],61
也就是说,编译系统直接改变BX的值了,并且一直到后面再使用的时候都不再恢复原值。
我打算睏个小觉起来再进一步试验了。 | | |
|
|
|
|
[第4楼]
[ 回复时间:2013-05-07 17:57 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2013-02-26 12:52 |
刚才试着写了下面这段:
main()
{
_AX=0x1000;
_BX=0x1000;
_DX=_AX+_BX;
*(char *) _AX='a';
*(char *) (_AX+_AX)='b';
*(char *) (_BX+_BX)='c';
_DX=_AX+_BX;
printf("%d\n",_DX);
}
结果发现,编译到下面这一句时,BX的数值就被改变了!
*(char *) (_AX+_AX)='b'; MOV BX,AX
ADD BX,AX
MOV BYTE PTR [BX],62
由此可见,BX寄存器是固定用于索引值(偏移地址)的,如果在C语言中引用BX寄存器,是不是很没有“安全感”啊?
回过头再看,其实在前一句 *(char *) _AX='a'; 这里BX就被赋值为AX了,只是我设计的代码未够合理,两个寄存器初始化的值都等于0x1000,才导致自己忽略这一步骤罢了。 | | |