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
可以使得条件成立、发生转移的指令有: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 start: next:
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 mov ebx,eax .code
- -17
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 call dispmsg
;标志PF反映“1”的个数 ;个数为偶数,正确继续
;保存接收的数据
mov eax,offset error ;个数为奇数,显示出错
〔习题4.9〕
指令CDQ将EAX符号扩展到EDX,即:EAX最高为0,则EDX=0;EAX最高为1,则EDX=FFFFFFFFH。请编程实现该指令功能。 〔解答1〕
next1: done:
test eax,8000h jz next1
mov edx,0ffffffffh jmp done mov dx,0
; 测试最高位
; 最高位为0(ZF=1),转移到标号NEXT1 ; 最高位为1,顺序执行:设置EDX=FFFFFFFFH ; 无条件转移,跳过另一个分支
; 最高位为0转移到此执行:设置EDX=0
〔解答2〕
使用移位指令更好。
rol eax,1 rcr edx,1 sar edx,31 ror eax,1
〔习题4.10〕
编程,首先测试双字变量DVAR的最高位,如果为1,则显示字母“L”;如果最高位不为1,则继续测试最低位,如果最低位为1,则显示字母“R”;如果最低位也不为1,则显示字母“M”。 〔解答〕
dvar
; 数据段 dword 57h ; 代码段 mov eax,dvar test eax,80000000h jnz nextl
- -18
nextl: nextr: done:
test eax,1 jnz nextr mov al,'M' jmp done mov al,'L' jmp done mov al,'R' call dispc
〔习题4.11〕编写一个程序,先提示输入数字“Input Number:0~9”,然后在下一行显示输入的数字,结束;如果不是键入了0~9数字,就提示错误“Error!”,继续等待输入数字。 〔解答〕
inmsg ermsg again: erdisp: done:
; 数据段
byte 'Input number(0~9): ',0
byte 0dh,0ah,'Error! Input again: ',0 ; 代码段
mov eax,offset inmsg ; 提示输入数字 call dispmsg call readc cmp al,'0' jb erdisp cmp al,'9' ja erdisp call dispcrlf call dispc jmp done
mov eax,offset ermsg call dispmsg jmp again
; 数字 > 9? ; 等待按键 ; 数字 < 0?
〔习题4.12〕
有一个首地址为ARRAY的20个双字的数组,说明下列程序段的功能。
sumlp:
mov ecx,20 mov eax,0 mov esi,eax add eax,array[esi] add esi,4 loop sumlp mov total,eax
〔解答〕
求这20个双字的和,保存在TOTAL变量,不关进心进位和溢出。 〔习题4.13〕
编程中经常要记录某个字符出现的次数。现编程记录某个字符串中空格出现的次数,结果保存在SPACE单元。 〔解答〕
string space
; 数据段
byte 'Do you have fun with Assembly ?',0 dword ? ; 代码段
;以0结尾的字符串
- -19
again: next: done:
mov esi,offset string xor ebx,ebx mov al,[esi] cmp al,0 jz done cmp al,20h jne next inc bx inc esi jmp again mov space,ebx
;继续循环 ;保存结果
;空格的ASCII码是20H ;不相等、不是空格,转移 ;相等、是空格,空格个数加1 ;EBX用于记录空格数
〔习题4.14〕
编写计算100个16位正整数之和的程序。如果和不超过16位字的范围(65535),则保存其和到WORDSUM,如超过则显示‘Overflow !’。 〔解答〕
array wordsum error again: over:
; 数据段
word 2005,2008,98 dup (1394) word ?
byte 'Overflow !',0 ; 代码段 and ebx,0 mov ecx,100 xor ax,ax
add ax,array[ebx*2] jc over inc ebx loop again mov wordsum,ax mov eax,offset error call dispmsg
; 假设100个16位正整数
〔习题4.15〕
在一个已知长度的字符串中查找是否包含“BUG”子字符串。如果存在,显示“Y”,否则显示“N”。 〔解答〕
string count bug L1: LN:
; 数据段
byte 'If you find any error in the program, you can DEBUG it.' = sizeof string byte 'BUG' ; 代码段 mov ecx,count
mov edi,offset string mov esi,offset bug push edi
mov edx,sizeof bug mov al,[esi] cmp [edi],al jne L2 inc esi inc edi dec edx
- -20