|
楼主 |
发表于 2008-10-26 15:08
|
显示全部楼层
第三章、汇编语言
1. 问:在逻辑运算一节,书上说“NOT”为求反操作,这里的求反操作是何意?
在循环移位指令里,书上举例:SAL 左移一位,相当于乘以二;SAR 右移一位,相当于除以二;请问除SAL和SAR外的其它移位指令也有此功能吗?
答:求反操作就是将目的操作数的内容按位变反。例如,AL=01000110B,则执行NOT AL指令后,AL=10111001B。
除SAL、SAR指令外,SHL、SHR指令也有此功能。循环移位指令没有此功能。
2. 问:TEST指令到底是怎么回事?NZ和Z到底是怎么得到的?若是要检查好几位的话,要怎么检查呢?
答:AND指令属于逻辑操作指令,它是对两个操作数(源操作数和目的操作数)进行“与”操作,操作是按位进行的,即源操作数bit7和目的操作数bit7相与,源操作数bit6和目的操作数bit6相与,and so on。与操作的结果最后被送到目的操作数中,也就是说,原来的目的操作数被破坏了。
TEST指令与AND指令类似,也是对两个操作数进行“与”操作。但TEST不把结果送到目的操作数,只是设置一下标志位(请复习一下:逻辑操作指令会影响哪些标志位?)。这就给我们带来了一个好处:你如果想测试操作数某几位的状态,但又不想破坏操作数的内容,就可以用TEST指令。(AND/TEST这一对指令的关系与SUB/CMP这一对指令的关系一样:操作相同,不同之处是结果送不送到目的操作数中。)
一般来说,逻辑指令和算术运算指令都会根据运算结果设置标志位,所以你提出的“NZ和Z到底是怎么得到的?”这个问题应该这样回答:NZ和Z是根据指令操作的结果所得到的,或者说是由CPU根据指令的运算结果来设置各个标志位得到的。
Z和NZ都是指ZF标志的状态,ZF=1时称为Z(即Zero的缩写),ZF=0时称为NZ(即Not Zero的缩写)。其实Z和NZ这两种状态都只用于条件转移指令中,如“JZ XXX”(意思是如果ZF标志等于1就转移到标号为XXX的指令处执行)或“JNZ XXX”(意思是如果ZF标志等于0就转移到标号为XXX的指令处执行)。
注意,如果运算的结果为0,ZF会被设置成1,如果运算的结果不为0,ZF会被设置成0。所以ZF代表了运算结果是否为0:若ZF=1,运算结果肯定为0;反之,运算结果肯定不为0。
若要检查一个操作数中某几位的状态,可设置另一个操作数中相应的位为1,其他位为0,然后进行TEST操作。如要检查AL的bit7、bit6、bit5是否全是0,另一操作数应该是11100000B,测试指令为TEST AL,11100000B。
3. 问:有一段代码:
AND AX,AX
JZ STOP
这个JZ是对哪一个标志位说的呢?
答:JZ当然是对ZF标志说的,因为AND AX,AX会影响ZF标志位的。
4. 问:
MOV DI,1000H
MOV CX,64H
MOV AL,2AH
AGAIN:MOV [DI],AL
INC DI
DEC CX
JNZ AGAIN
HLT
程序中 INC DEC 如何影响标志位,MOV [DI],AL中的DI可否用别的寄存器替代?
答:INC/DEC将影响ZF,OF,PF,AF,SF,但不影响CF。
因为这里是MOV指令,DI寄存器当然就可以用其他3个能够作为指针的寄存器代替,例如
SI,BX,BP(BP要指定段超越前缀)。
5. 问:以下这两条指令哪里错了?
MOV DS,BP
MOV DATA[SI],ES:AX
答:第一条没错。第二条的寄存器前不应该有段超越前缀,因为寄存器不是内存单元,它没有地址。
6. 问:过程调用返回语句RET后加数字表示什么?比如RET 4。
答:表示把栈顶内容弹出到指令指针后再扔掉栈顶的n个字节(n为偶数)。栈顶的这n个字节是调用子程序前压入堆栈的子程序入口参数。仅当用堆栈传递参数时才会使用这种指令。
这种参数处理方法也可用其它方法替代,如在主程序的调用指令后用几个POP指令把调用之前压入的参数扔掉。
7. 问:请问汇编中有无浮点数?有书上说,用DQ,DT等定义的实数如:-5.12E-1表示-0.512,应该没错吧,但这样的数据在程序运算中是怎样具体进行的?我曾经试过,有提示警告说字长有问题。而且得不到有意义的结果。
如:
DATA DQ -5.12E-1
MOV AX,120
MUL DATA
请问AX中的结果?恳请老师能详细解答!
答:汇编语言程序中可以使用浮点数,有两个方法:1)自己编写浮点运算子程序;2)使用CPU的浮点指令(486以上级别的CPU支持浮点操作)。
DQ定义的数据类型是每个元素8个字节,你用16位的乘法操作当然就不对了,因为AX是16位的寄存器,与DQ定义的数据类型不一致。如果一定要这样做,应把最后一句改为 MUL WORD PTR DATA,这样语法就正确了,但这样得到的结果并不是所期望的。
8. 问:
Object filename [2.OBJ]:
Source listing [NUL.LST]: 2
Cross-reference [NUL.CRF]:
2.asm(25): error A2071: Forward needs override or FAR
49922 + 416126 Bytes symbol space free
0 Warning Errors
1 Severe Errors
请指教!
答:看见第4行的提示了吗?意思是:在2.ASM程序文件中的第25行有一个错误。
因为没看见你的源程序,不好说具体是什么原因。估计是转移指令中的转移目的地址有问题,可能超出转移范围。最后一行“1 Severe Errors”是说有一个严重错误!通常这样的错误是不可饶恕的,你应该重新修改程序。
9. 问:请问:
LEA BX,ARRAY
LEA DI,RESULT
MOV CL,4
AGAIN: MOV AL,[BX]
TEST AL,80H
JZ NEXT
NEG AL
MOV [DI],AL
INC BX
INC DI
DEC CL
JNZ AGAIN
该指令是什么意思?完成的功能是什么?
答:首先,你程序段中的NEXT标号是在哪定义?我猜可能是在INC BX指令处吧。假定是这样的话,这个程序段是找出ARRAY数组中的负数,然后求出它们的绝对值再送到RESULT数组中。程序段中的NEG AL指令为求补指令,可以看出,程序中只对负数求补。
10. 问:从FIRST开始存放着100个字符的字符串,结束符为"$",统计该字符串中字母"B"的个数。这道题该如何编程。
答:请看下面:
mov si,offset first ;指向FIRST数组
mov cx,100 ;循环次数
mov dl,0 ;用于存放"B"的个数
kkk: lodsb ;取一个字符
cmp al,"$" ;串结束?
jz quit ;若结束,则退出
cmp al,"B" ;否则判断字符是否是"B"
jnz qqq
inc dl ;若是"B",则"B"的个数加1
qqq: loop kkk ;循环,直到整个串搜索完
quit: hlt ;程序执行完后,dl中有"B"的个数
11. 问:请问什么时候用逻辑尺?具体怎么用啊?能举个例子吗?谢谢!
答:逻辑尺用于对一批数据进行处理,而处理的方法又无规律可言(即无法用循环的方法处理)。例如,有16个数据(Ai)存于buffer开始的缓冲区中,要求对第2、4、5、6、9、11、12、14个数据进行F1(Ai)=2Ai的运算,对其余的数据进行F2(Ai)=Ai-3的运算。
可以看出,对这些数据元素进行F1运算还是F2运算无法用它们的下标来确定。这时,用逻辑尺就非常合适。特别是当数据元素很多时,用逻辑尺方法比用其他方法具有更好的程序结构。
12. 问:$的含义?
答:$是指当前地址(即分配地址的地址计数器的内容,它是在汇编时的一个动态值)。例如上例中,最初地址计数器内容为0,汇编时分析出SHR1占据两个字节,于是分配给数据段的0号单元和1号单元(即SHR1=0),接着地址计数器增加到2;再汇编到SHR2时,分析出它占据16个字节,则顺序分配给2号单元(即根据地址计数器的当前值进行分配)到17号单元(即SHR2=2),分配完后,地址计数器的内容增加为18,所以遇到$时,汇编程序就用18代替$符号,即18-0=18,也即CNT=18。 MOV CX,CNT自然就是MOV CX,18了。
13. 问:怎么用debug运行连接过的程序?
答:在dos窗口中键入以下命令:
debug <你的可执行程序的名字> <回车>
debug运行后,你的程序就被加载到内存中,可以调试执行了。debug的各种调试命令见实验指导书中的附录。
14. 问:我们的微机是赛扬的CPU,为什么再运行汇编时,一闪即过了,看不到结果?
答:不要在Windows下直接点击运行。应该先进入DOS方式(运行COMMAND或点击开始菜单中的DOS方式命令),然后在DOS方式下运行就不会出现这个问题了。 |
|