disp:
next: done: cmp eax,0 jz next mov ebx,1 add al,30h call dispc loop again
; EAX=0,说明是前导0,不显示
; EAX≠0,没有前导0了,令EBX=1≠0
〔习题4.17〕
已知一个字符串的长度,剔除其中所有的空格字符。请从字符串最后一个字符开始逐个向前判断、并进行处理。 〔解答〕
string
outlp:
inlp:
next:
done:
; 数据段
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
〔习题4.18〕
第3章习题3.14在屏幕上显示ASCII表,现仅在数据段设置表格缓冲区,编程将ASCII代码值填入留出位置的表格,然后调用显示功能实现(需要利用双重循环)。 〔解答〕
table
tab1
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
- -25
start:
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
proc
shl dh,4 mov al,dh and dl,0fh or al,dl ret endp
〔习题4.20〕
乘法的非压缩BCD码调整指令AAM执行的操作是:AH←AL÷10的商,AL←AL÷10的余数。利用AAM可以实现将AL中的100内数据转换为ASCII码,程序如下:
xor ah,ah aam
add ax,3030h
利用这段程序,编写一个显示AL中数值(0~99)的子程序。 〔解答〕
disp99
proc
xor ah,ah aam
add ax,3030h
- -26
disp99 push ax mov al,ah call dispc pop ax
call dispc ret endp
〔习题4.21〕
编写一个源程序,在键盘上按一个键,将其返回的ASCII码值显示出来,如果按下ESC键(对应ASCII码是1BH)则程序退出。请调用书中的HTOASC子程序。 〔解答〕
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:
; 代码段,主程序 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
; 调用子程序
; 32位二进制数的输出
; 要输出的字符个数 ; AL循环左移一位 ; 取AL最低位
; 转化成相应的ASCLL码值 ; 以二进制的形式显示
- -27
dispbd ret endp
〔习题4.23〕
将例题4-16的32位寄存器改用16位寄存器,仅实现输出-215~+215-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
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
- -28