goon:
again:
disp:
next: done:
jnz goon mov al,'0' call dispc jmp done mov ecx,8 xor ebx,ebx rol esi,4 mov eax,esi and eax,0fh cmp ebx,0 jnz disp cmp eax,0 jz next mov ebx,1 add al,30h call dispc loop again
; EBX=0,表示可能是前导0
; EAX低4位保存当前要显示的BCD码 ; EBX≠0,说明不是前导0,要显示 ; EBX=0,说明可能是前导0
; EAX=0,说明是前导0,不显示
; EAX≠0,没有前导0了,令EBX=1≠0
〔习题4.17〕已知一个字符串的长度,剔除其中所有的空格字符。请从字符串最后一个字符开始逐个向前判断、并进行处理。 〔解答〕
string
outlp:
inlp:
next:
done:
〔习题4.18〕第3章习题3.14在屏幕上显示ASCII表,现仅在数据段设置表格缓冲区,编程将ASCII代码值填入留出位置的表格,然后调用显示功能实现(需要利用双重循环)。 〔解答〕
table
tab1
start:
include io32.inc .data
byte ' |0 1 2 3 4 5 6 7 8 9 A B C D E F',13,10 byte '---+-------------------------------',13,10 byte 6 dup(36 dup(?),13,10) byte 0 .code
; 数据段
byte 'Let us have a try !',0dh,0ah,0 ; 代码段
mov ecx,sizeof string cmp ecx,2 jb done
lea eax,string ; 显示处理前的字符串 call dispmsg mov esi,ecx dec esi
cmp string[esi],' ' ; 检测是否是空格 jnz next ; 不是空格继续循环 mov edi,esi ; 是空格,进入剔除空格分支 dec ecx inc edi
mov al,string[edi] ; 前移一个位置 mov string[edi-1],al cmp edi,ecx jb inlp dec esi ; 继续进行 cmp esi,0 jnz outlp ; 为0结束 lea eax,string ; 显示处理后的字符串 call dispmsg
- -21
again0:
again1:
mov ebx,offset tab1 mov edx,'| 02' mov ax,2020h mov esi,6 mov [ebx],edx add ebx,4 mov ecx,16
mov word ptr [ebx],ax add ebx,2 inc al
loop again1 add ebx,2 add edx,1 dec esi jnz again0
mov eax,offset table call dispmsg exit 0 end start
〔习题4.19〕请按如下说明编写子程序:
子程序功能:把用ASCII码表示的两位十进制数转换为压缩BCD码 入口参数:DH=十位数的ASCII码,DL=个位数的ASCII码 出口参数:AL=对应BCD码 〔解答〕 asctob
asctob
〔习题4.20〕乘法的非压缩BCD码调整指令AAM执行的操作是:AH←AL÷10的商,AL←AL÷10的余数。利用AAM可以实现将AL中的100内数据转换为ASCII码,程序如下:
xor ah,ah aam
add ax,3030h
利用这段程序,编写一个显示AL中数值(0~99)的子程序。
proc
xor ah,ah aam
add ax,3030h push ax mov al,ah call dispc pop ax call dispc ret endp proc shl dh,4 mov al,dh and dl,0fh or al,dl ret endp
〔解答〕 disp99
disp99
〔习题4.21〕编写一个源程序,在键盘上按一个键,将其返回的ASCII码值显示出来,如果按下ESC键(对应ASCII码是1BH)则程序退出。请调用书中的HTOASC子程序。 〔解答〕 ; 代码段,主程序
- -22
again:
done:
call readc cmp al,1bh jz done mov bl,al mov al,':' call dispc mov al,bl rol al,4 call htoasc call dispc mov al,bl call htoasc call dispc call dispcrlf jmp again
; 调用子程序 ; 显示一个字符 ; 调用子程序 ; 显示一个字符
〔习题4.22〕编写一个子程序,它以二进制形式显示EAX中32位数据,并设计一个主程序验证。 〔解答〕
dispbd
dbd:
dispbd
〔习题4.23〕将例题4-16的32位寄存器改用16位寄存器,仅实现输出-2~+2-1之间的数据。 〔解答〕 ; 数据段 array word 12345,-1234,32767,-32768,0,667 writebuf byte 6 dup(0) ; 代码段,主程序 mov ecx,lengthof array mov ebx,0 again:
mov ax,array[ebx*2] call write call dispcrlf
inc ebx ;此时ebx代表array中的第几个数 dec ecx ;此时ecx代表循环的次数 jnz again ; 代码段,子程序
write proc ;子程序开始 push ebx push ecx push edx
15
15
; 代码段,主程序 mov eax,8F98FF00H call dispbd
; 代码段,子程序 proc push ecx push edx mov ecx,32 rol eax,1 push eax and al,01h add al,30h call dispc pop eax loop dbd pop edx pop ecx ret endp
; 调用子程序
; 32位二进制数的输出
; 要输出的字符个数 ; AL循环左移一位 ; 取AL最低位
; 转化成相应的ASCLL码值 ; 以二进制的形式显示
- -23
mov ebx,offset writebuf ;ebx指向显示缓冲区 test ax,ax jnz write1
mov byte ptr [ebx],30h inc ebx jmp write5
write1: ;若不为0则首先判断是正是负 jns write2 ;若为正则跳过下面两步到write2 mov byte ptr [ebx],'-' inc ebx neg ax write2:
mov cx,10
push cx ;将cx=10压入栈,作为退出标志
write3: ;write3是让eax循环除以10并把余数的ASCII码压入栈 cmp ax,0 jz write4 xor dx,dx div cx add dx,30h push dx jmp write3
write4: ;余数的ASCII码出栈,遇到10终止并转到write5显示结果 pop dx cmp dx,cx jz write5
mov byte ptr [ebx],dl inc ebx jmp write4
write5: ;显示结果 mov byte ptr [ebx],0 mov eax,offset writebuf call dispmsg pop edx pop ecx pop ebx ret write endp
〔习题4.24〕参考例题4-17,编写实现32位无符号整数输入的子程序,并设计一个主程序验证。 〔解答〕 ; 数据段 count =10 array dword count dup(0) temp dword ?
readbuf byte 30 dup(0)
errmsg byte 'Input error,enter again!',13,10,0 msg1 byte 'Input ten unsigned numbers,each number ends with enter key:',13,10,0 msg2 byte 'Check the numbers your inputted:',13,10,0 ; 代码段,主程序 mov eax,offset msg1 call dispmsg mov ecx,count
mov ebx,offset array again:
call read mov eax,temp mov [ebx],eax add ebx,4
- -24
dec ecx jnz again
mov eax,offset msg2 call dispmsg
mov edx,offset array mov ecx,count next:
mov eax,[edx] call dispuid call dispcrlf add edx,4 dec ecx jnz next ; 代码段,子程序 read proc push eax push ecx push ebx push edx read0:
mov eax,offset readbuf call readmsg test eax,eax jz readerr cmp eax,12 ja readerr
mov edx,offset readbuf xor ebx,ebx xor ecx,ecx mov al,[edx] cmp al,'+' jz read1 cmp al,'-' jnz read2 jmp readerr read1:
inc edx
mov al,[edx] test al,al
jz read3 ;如果为0,则说明该字符串已结束 read2:
cmp al,'0' jb readerr cmp al,'9' ja readerr sub al,30h
imul ebx,10 ;ebx用来存储处理过的数据 jc readerr movzx eax,al add ebx,eax jnc read1 readerr:
mov eax,offset errmsg call dispmsg jmp read0 read3:
mov temp,ebx pop edx pop ebx pop ecx
- -25