lowercase dword ? ; Win32 Console Application ; 统计msg串中的空格的个数与小写字母的个数, ; 并分别将它们存入space单元与lowercase单元中。 ; 目的:学习简单的关于分支与数组处理的算法。 ; 学习 if ('a'<= a[i])&&(a[i]<='z') lowercase++;中 ; 逻辑与表达式在汇编语言中的实现。 ; 算法描述 ; 1. space=lowercase=0; ; 2. for i=0 to n-1 do ; 2.1 if a[i]==' ' then space++; ; 2.2 if 'a'<= a[i] <='z' then lowercase++; ; 合理分配寄存器:采用loop循环,ecx=lengthof msg-1 ; space=eax=0,lowercase=ebx=0,esi=offset msg,做指针 .686 .model flat,stdcall option casemap:none includelib msvcrt.lib printf PROTO C : dword,:vararg .data msg byte 'I love XUT !',13,10,0 space dword ? lowercase dword ? fmtStr byte ' space=%d lowercase=%d',13,10,0 ;格式描述串 .code main proc mov ecx,lengthof msg-1 xor eax,eax ;space=eax=0 mov ebx,eax ;lowercase=ebx=0 mov esi,offset msg ;指向msg首地址 again: mov dl,[esi] cmp dl,' ' jnz letter ;if a[i]==' ' then space++; inc eax ;注意:转换成汇编语言时,测试的是不是空格时则转去测试字母。 letter: cmp dl,'a' jb next ;注意:测试的是a[i]<'a'。 cmp dl,'z' ja next ;注意:测试的是a[i]>'z'。 inc ebx ;lowercase++ next: inc esi ;指向下一个字符 24
loop again mov space,eax mov lowercase,ebx invoke printf,offset fmtStr,eax,ebx ret ;return to Windows main endp ;end of main end main ;end of assembly 6. 编程写一个完整的程序,将字符串msg中所有的小写字母转换为大写字母。数据段的定义如下: .data msg byte 'I love XUT !',13,10,0 ; Win32 Console Application ; 将字符串msg中所有的小写字母转换为大写字母 ; 目的:学习简单的关于分支与数组处理的算法。 ; 学习 if ('a'<= a[i])&&(a[i]<='z') a[i]=a[i]-0x20;中 ; 逻辑与表达式在汇编语言中的实现。 ; 算法描述 ; 1. for i=0 to n-1 do ; if 'a'<= a[i] <='z' then a[i]=a[i]-20H; ; 小写字母与大写字母的ASCII码的差值为20H, 也可以用 ; a[i]=a[i]&0x5f ; 合理分配寄存器:采用loop循环,ecx=lengthof msg-1 ; esi=offset msg,做指针。 .686 .model flat,stdcall option casemap:none includelib msvcrt.lib printf PROTO C : dword,:vararg .data msg byte 'I love XUT !',13,10,0 fmtStr byte 'msg: %s',13,10,0 ;格式描述串 .code main proc mov ecx,lengthof msg-1 mov esi,offset msg ; 指向msg首地址 again: mov dl,[esi] cmp dl,'a' jb next ; 注意:测试的是a[i]<'a'。 cmp dl,'z' ja next ; 注意:测试的是a[i]>'z'。 25
sub dl,20h ; and dl,5fh mov [esi],dl next: inc esi ; 指向下一个字符 loop again invoke printf,offset fmtStr,offset msg ret ;return to Windows main endp ;end of main end main ;end of assembly 7. array是一无符号数数组,数据段的定义如下。要求:编程写一个完整的程序求出数组元素中偶数的和,并将它存入esum单元中。 .data array dword 12,34,123,78,43,234,79,86,98,20 esum dword ? ; Win32 Console Application ; 求数组中所有偶数元素的和。 ; 目的:学习简单的关于分支与数组处理的算法。 ; 算法描述 ; 1. esum=0; ; 2. for i=0 to n-1 do ; if a[i] is evennunber then esum=esum+a[i]; ; 判断偶数,采用 test 指令测试最低位。 ; 合理分配寄存器:采用loop循环,ecx=lengthof array ; esum=eax=0,esi=0,做下标,采用带比例因子的相对寻址处理数组。 .686 .model flat,stdcall option casemap:none includelib msvcrt.lib printf PROTO C : dword,:vararg .data array dword 12,34,123,78,43,234,79,86,98,20 esum dword ? fmtStr byte ' esum=%d',13,10,0 ;格式描述串 .code main proc mov ecx,lengthof array xor eax,eax ;esum=eax=0 mov esi,eax ;数组下标 again: mov ebx,array[esi*4] test ebx,1 jnz next ;if a[i] is evennunber then esum=esum+a[i]; 26
add eax,ebx ;注意:转换成汇编语言时,测试的是不是偶数时则取下一个数测试。 next: inc esi loop again mov esum,eax invoke printf,offset fmtStr,esum ret ;return to Windows main endp ;end of main end main ;end of assembly 8. “回文串”是一个正读和反读都一样的字符串,比如“eye”、“level”、“noon”等。请写一个程序测试一字符串是否是“回文”, 是“回文”则显示“Y”,否则显示“N”。 显示一个字符的子程序为:dispc,入口参数:AL=要显示个字符的SACII码。 ; Win32 Console Application palindrome ; 测试一字符串是否是“回文”, 是“回文”则显示“Y”,否则显示“N”。 ; 算法描述: ; left,right分别指向串的第一个和最后一个元素,采用首尾比较。 ; 1. left=0,right=n-1 ,flag='Y' ; ; 2. while left call dispcrlf ret ;return to Windows main endp ;end of main end main ;end of assembly 9. 回文是指正读和反读都一样的数或文本。例如:11、121、12321等,编写程序,求10到10000之间所有回文数并输出。显示一个无符号数的子程序为:dispuid,入口参数:EAX=要显示无符号数的值。 ; Win32 Console Application ; 求10到10000之间所有回文数并输出。 ; 目的:学习如何利用条件转移指令构造条件循环结构,多重循环的构造方法。 ; 算法思想:采用div指令把一个整数N的每一位分离出来,注意, ; 此时得到的是N的各个位的逆序序列。然后,将这个逆序序列再组合成一个新的整数M, ; 若M=N,则N是回文数。 ; 算法描述 ; 1. ecx=10 to 1000 do ; 1.1 eax=ecx被除数;ebx=10除数;esi=0新生成的数的初值。 ; 1.2 while eax<>0 do ; 1.2.1 edx=0;div ebx;esi=esi*10+edx ; 1.3 if ecx=esi then print esi include io32.inc .code main proc mov ecx,10 mov ebx,ecx ;ebx=10除数 .repeat xor esi,esi ;esi=0,是新生成的数的初值 mov eax,ecx ;eax被除数 .while (eax!=0) xor edx,edx ;edx被除数的高32位 div ebx imul esi,10 add esi,edx ;逆序生成新数,esi=esi*10+edx .endw cmp esi,ecx jne next mov eax,ecx call dispuid call dispcrlf next: inc ecx .until (ecx>10000) ret ;return to Windows 28