由此可看出串操作指令的寻址特点:
源操作数用寄存器ESI间接寻址,默认在DS指向的数据段,但可以改变;目的操作数用寄存器EDI间接寻址,只能在ES指向的附加数据段;每执行一次串操作,源指针ESI和目的指针EDI将自动修改:±1(字节),±2(字)或±4(双字)。指针的增量和减量控制由DF标志确定,DF=0,进行增量;DF=1,进行减量。
push eax
mov eax,[esi] mov es:[edi],eax add esi,4 add edi,4
〔习题3.30〕
说明如下程序执行后的显示结果:
msg
again:
; 数据段
byte 'WELLDONE',0 ; 代码段
mov ecx,(lengthof msg)-1 mov ebx,offset msg mov al,[ebx] add al,20h mov [ebx],al add ebx,1 loop again
mov eax,offset msg call dispmsg
如果将其中语句“mov ebx,offset msg”改为“xor ebx,ebx”,则利用EBX间接寻址的两个语句如何修改成EBX寄存器相对寻址,就可以实现同样功能? 〔解答〕
显示结果:welldone EBX寄存器相对寻址:
mov al,msg[ebx] mov msg[ebx],al
〔习题3.31〕
下面程序的功能是将数组ARRAY1的每个元素加固定值(8000H),将和保存在数组ARRAY2。在空白处填入适当的语句或语句的一部分。
array1 array2
again:
; 数据段
dword 1,2,3,4,5,6,7,8,9,10 dword 10 dup(?) ; 代码段
mov ecx,lengthof array1 mov ebx,0
mov eax,array1[ebx*4] add eax,8000h
mov ______________ add ebx,__________ loop again
mov array2[ebx*4],eax
〔解答〕
-21 -
add ebx,1
〔习题3.32〕
上机实现本章的例题程序,编程实现本章的习题程序。
第4章 汇编语言程序设计
〔习题4.1〕简答题
(1)是什么特点决定了目标地址的相对寻址方式应用最多? (2)什么是奇偶校验?
(3)为什么判断无符号数大小和有符号大小的条件转移指令不同? (4)双分支结构中两个分支体之间的JMP指令有什么作用? (5)为什么特别强调为子程序加上必要的注释?
(6)子程序采用堆栈传递参数,为什么要特别注意堆栈平衡问题? (7)参数传递的“传值”和“传址”有什么区别? (8)INCLUDE语句和INCLUDELIB有什么区别? (9)混合编程有什么优势?
(10)运行Windows程序,有时为什么会提示某个DLL文件不存在? 〔解答〕
① 当同一个程序被操作系统安排到不同的存储区域执行时,指令间的位移没有改变,目标地址采用相对寻址可方便操作系统的灵活调度。
② 数据通信时,数据的某一位用做传输数据的奇偶校验位,数据中包括校验位在内的“1”的个数恒为奇数,就是奇校验;恒为偶数,就是偶校验。
③ 无符号数和有符号数的操作影响两组不同的标志状态位,故判断两个无符号数和有符号数的大小关系要利用不同的标志位组合,所以有对应的两组指令。
④ 双分支结构中两个分支体之间的JMP指令,用于实现结束前一个分支回到共同的出口作用。
⑤ 完整的子程序注释可方便程序员调用该子程序,子程序注释包括子程序名、子程序功能、入口参数和出口参数、调用注意事项和其他说明等。
⑥ 子程序保持堆栈平衡,才能保证执行RET指令时当前栈顶的内容是正确的返回地址。主程序也要保持堆栈平衡,这样才能释放传递参数占用的堆栈空间,否则多次调用该子程序可能就致使堆栈溢出。
⑦ “传值”是传递参数的一个拷贝,被调用程序改变这个参数不影响调用程序;“传址”时,被调用程序可能修改通过地址引用的变量内容。
⑧ INCLUDE语句包含的是文本文件、是源程序文件的一部分;INCLUDELIB语句包含的是子程序库文件。
⑨ 取长补短。
⑩ Windows程序在运行时需要加载其配套的动态链接库DLL文件,当其没有被搜索到时就会提示不存在。 〔习题4.2〕判断题
(1)指令指针或者还包括代码段寄存器值的改变将引起程序流程的改变。 (2)JMP指令对应高级语言的GOTO语句,所以不能使用。
(3)因为条件转移指令Jcc要利用标志作为条件,所以也影响标志。
(4)JA和JG指令的条件都是“大于”,所以是同一个指令的两个助记符。 (5)控制循环是否结束只能在一次循环结束之后进行。
-22 -
(6)介绍LOOP指令时,常说它相当于DEC ECX和JNZ两条指令。但考虑对状态标志的影响,它们有差别。LOOP指令不影响标志,而DEC指令却会影响除CF之外的其他状态标志。
(7)CALL指令用在调用程序中,如果被调用程序中也有CALL指令,说明出现了嵌套。
(8)子程序需要保护寄存器,包括保护传递入口参数和出口参数的通用寄存器。 (9)利用INCLUDE包含的源文件实际上只是源程序的一部分。
(10)导入库文件和静态子程序库文件的扩展名都是LIB,所以两者性质相同。 〔解答〕
① 对 ⑥ 对
② 错 ⑦ 对
③ 错 ⑧ 错
④ 错 ⑨ 对
⑤ 错 ⑩ 错
〔习题4.3〕填空题
(1)JMP指令根据目标地址的转移范围和寻址方式,可以分成四种类型:段内转移、__________,段内转移、__________和段间转移、__________,段间转移、__________。
(2)假设在平展存储模型下,EBX=1256H,双字变量TABLE的偏移地址是20A1H,线性地址32F7H处存放3280H,执行指令“JMP EBX” 后EIP=__________,执行指令“JMP TABLE[EBX]”后EIP=__________。
(3)“CMP EAX,3721H”指令之后是JZ指令,发生转移的条件是EAX=__________,此时ZF=__________。
(4)小写字母“e”是英文当中出现频率最高的字母。如果某个英文文档利用例题4-11的异或方法进行简单加密,统计发现密文中字节数据“8FH”最多,你判断该程序采用的字节密码可能是__________。
(5)循环结构程序一般有三个部分组成,它们是__________,循环体和__________部分。
(6)例题4-14程序中的RET指令,如果用POP EBP指令和JMP EBP指令替换,此时EBP内容是__________。
(7)过程定义开始是“TEST PROC”语句,则过程定义结束的语句是__________。宏定义开始是“DISP MACRO”语句,则宏定义结束的语句是__________。
(8)利用堆栈传递子程序参数的方法是固定的,例如寻址堆栈段数据的寄存器是__________。
(9)MASM汇编语言中,声明一个共用的变量应使用__________伪指令;而使用外部变量要使用__________伪指令声明。
(10)调用ReadConsole函数时,用户在键盘上按下数字8,然后回车,则键盘缓冲区的内容依次是__________。 〔解答〕
① 相对寻址,间接寻址,直接寻址,间接寻址 ② 1256H,3280H ③ 3721H,1 ④ EAH
⑤ 循环初始,循环控制 ⑥ REPT1标号的地址 ⑦ TEST ENDP,ENDM ⑧ EBP
⑨ PUBLIC,EXTERN
-23 -
⑩ 38H 0DH 0AH 〔习题4.4〕
为了验证例题4-1程序的执行路径,可以在每个标号前后增加显示功能。例如使得程序运行后显示数码1234。 〔解答〕
labl1:
labl2:
labl3:
labl4:
jmp labl1 ; 相对寻址 nop
mov eax,'?' call dispc mov eax,'1' call dispc
jmp near ptr labl2 ; 相对近转移 nop
mov eax,'?' call dispc mov eax,'2' call dispc
mov eax,offset labl3 jmp eax ; 寄存器间接寻址 nop
mov eax,'?' call dispc mov eax,'3' call dispc
mov eax,offset labl4 mov nvar,eax jmp nvar ; 存储器间接寻址 nop
mov eax,'?' call dispc mov eax,'4' call dispc
〔习题4.5〕
使用“SHR EAX,2”将EAX中的D1位移入CF标志,然后用JC/JNC指令替代JZ/JNZ指令完成例题4-3的功能。 〔解答〕
mov eax,56h shr eax,2 jnc nom ...
; 假设一个数据 ; D1位移入CF标志
; D1=0条件成立,转移 ; 余同原程序
〔习题4.6〕
执行如下程序片断后,CMP指令分别使得5个状态标志CF、ZF、SF、OF和PF为0还是为1?它会使得哪些条件转移指令指令Jcc的条件成立、发生转移?
mov eax,20h cmp eax,80h
〔解答〕
CF=1 ZF=0 SF=1 OF=0 PF=1
-24 -
可以使得条件成立、发生转移的指令有:JC JS JP JNZ JNO 〔习题4.7〕
将例题4-4程序修改为实现偶校验。建议进一步增加显示有关提示信息的功能,使得程序具有更加良好的交互性。 〔解答〕
include io32.inc .data
msg1 byte 'Please input a character: ',0
msg2 byte 'The ASCII code of the charater you entered is: ',0 msg3 byte 'The code with even parity is: ',0 .code start: mov eax,offset msg1 call dispmsg call readc call dispcrlf mov ebx,eax mov eax,offset msg2 call dispmsg mov eax,ebx call dispbb call dispcrlf and al,7fh jp next or al,80h next: mov ebx,eax mov eax,offset msg3 call dispmsg mov eax,ebx call dispbb exit 0 end start
〔习题4.8〕
在采用奇偶校验传输数据的接收端应该验证数据传输的正确性。例如,如果采用偶校验,那么在接收到的数据中,其包含“1”的个数应该为0或偶数个,否则说明出现传输错误。现在,在接收端编写一个这样的程序,如果偶校验不正确显示错误信息,传输正确则继续。假设传送字节数据、最高位作为校验位,接收到的数据已经保存在Rdata变量中。 〔解答〕
Rdata error
done:
; 数据段 byte 57h byte 'Error !',0 ; 代码段
mov al,Rdata and al,0ffh jp done mov eax,offset error call dispmsg
;保存接收的数据
;标志PF反映“1”的个数 ;个数为偶数,正确继续 ;个数为奇数,显示出错
-25 -