X86汇编-汇编程序设计1作业
1. 编写完整源程序,用API输入一串字符串,然后将该字符串进行大小写互换(如大写则变小写,如小写则变大写),将其存储到一个数组中,并用API输出。
结合表格可知,大小写的区别仅在于第五位,因此仅需要将编码中的第五位进行改变就可以实现大小写变换
以小写变大写为例,下面给出源码
.386
.model flat,stdcall
option casemap:none
include Stdlib.Inc
includelib Stdlib.lib
include kernel32.inc
includelib kernel32.lib
.data
string db 64 dup(0)
len db 0
s db 0
store db 64 dup(0)
.code
.startup CONSOLE
invoke Readln,offset string,offset string,64
mov len,al
mov esi,0
mov ecx,dword ptr len
circle: mov al,string[esi]
and al,11011111b
mov string[esi],al
inc esi
loop circle
invoke Readln,offset string,offset store,16
invoke Writeln,offset store
.exit 0
效果如下
这个题目解题过程中循环次数出现问题,究其原因,是给ecx赋值的时候是mov cl,len
,仅仅改变了ecx的低字节,若原来ecx高位有值,则会出现问题
2. 编写完整源程序,用API输入一串字符串,然后将该字符串逆序存储到另一个数组中,并用API输出。
基本原理是堆栈操作,但是有很多细节需要注意
.386
.model flat,stdcall
option casemap:none
include Stdlib.Inc
includelib Stdlib.lib
include kernel32.inc
includelib kernel32.lib
.data
string db 64 dup(0)
len db 0
store db 64 dup(0)
.code
.startup CONSOLE
invoke Readln,offset string,offset string,64
mov len,al
mov esi,0
mov ecx,dword ptr len
take: movzx eax,string[esi]
push eax
inc esi
loop take
mov esi,0
mov ecx,dword ptr len
fetch: pop eax
mov store[esi],al
inc esi
loop fetch
invoke Writeln,offset store
.exit 0
在压栈的时候,数值上必须一个字节一个字节地压栈,但是实际压栈涉及32位操作,因此属于将较小值拷贝到较大值中,用到movzx
出栈的时候情况相反,仅仅需要出栈的32位的最后八位,因此将eax的al部分存入目标地址即可
效果如下
实验中的问题与收获
实验过程中最无语的在于readln
的使用,如果提前设置好字符串,则会很快的编写好程序
首先是对于readln的第一个参数,其实设置空数组指针就可以,这个必须有
另外对于readln之后的寄存器值,eax会记录字符串长度,对之后的循环次数有帮助
最后,在调试的时候,我开始在各个循环里调用api看输出,导致ecx被修改,循环次数出现问题