概述
说明
以下是在VS2012中使用masm汇编的一个例子:
.data
string_1 BYTE "Helloworld!", 0
.code
;---------------------------------------------------------
Str_len PROC USES edi,
pString:PTR BYTE
;
; 返回一个以 结尾的string的长度
; 参数:pString -- 指向某string的指针
; 返回值:eax -- string的长度
; -------------------------------------------------------- -
mov edi, pString
mov eax, 0 ; 先初始化eax,后续里面要放string的长度
L1:
cmp BYTE PTR[edi], 0 ; 判断是否到了string的结尾
je L2 ; 如果到了结尾,就跳转到L2
inc edi ; 如果没有到结尾,则指针加1
inc eax ; 同时长度也加1
jmp L1
L2 :
ret
Str_len ENDP
main PROC
INVOKE Str_len, ADDR string_1
INVOKE DumpRegs ; 打印寄存器的值,这里需要关心的是EAX,它的值应该是11
exit
main ENDP
END main
代码说明:
1. 上述代码分为两个段,分别用.data和.code,按照字面意思,就是一个数据段和一个代码段。
2. 在数据段中
string_1 BYTE "Helloworld!", 0
string_1是变量名;BYTE是一个masm中的伪指令,定义了数据的类型,主要用来指定数据在内存中的大小;
后面的“Helloworld!"是具体的数据,可以看成是字符串(虽然汇编中没有“字符串”的概念),最后的0,也是数据的一部分,这里表示了字符串结尾。
3. 在.code中首先定义了一个函数,在汇编中定义函数的形式如下:
funcName PROC
;具体实现在这里
funcName ENDP
在masm中对它做了一些扩展,比如可以使用USES这个伪指令,这得USES edi表示告诉masm编译器,在函数中会使用到edi这个寄存器,因此在masm编译的时候会生成额外的代码,在函数的前后增加edi的入栈和出栈。
4. 之后的main是汇编函数的入口,它与普通的函数有些区别,最主要是最后的END main这一句。实际上正是这个END标记了程序的入口是main。因此如果把这里的main改成其他名字,只要END后面还是这个名字,那么入口不变:
notMain PROC
INVOKE Str_len, ADDR string_1
INVOKE DumpRegs ; 打印寄存器的值,这里需要关心的是EAX,它的值应该是11
exit
notMain ENDP
END notMain ; 现在程序的入口是notMain了。
另外,如果END之后不加其它东西,则表示ASM文件的结尾,每个ASM文件都需要一个END来结尾。
5. 在main函数中,有两个函数的调用,这里使用了INVOKE这个伪指令,对应的还有一个call指令也是用来调用函数的。但是差别在于,INVOKE后面可以跟参数,这里的ADDR string_1就是参数,表示的是指向string_1这个字符串的
指针,ADDR常跟INVOKE连用,用来传递参数。所以在这里call不能代替INVOKE。而之后的DumpRegsy因为不需要参数,所以可以用call来替代。
6. 由于INVOKE,USES是masm特有的,如果不想使用的话,也可以修改代码:
.data
string_1 BYTE "Helloworld!", 0
.code
;---------------------------------------------------------
Str_len PROC
;
; 返回一个以 结尾的string的长度
; 参数:pString -- 指向某string的指针
; 返回值:eax -- string的长度
; -------------------------------------------------------- -
;mov edi, pString ; 放到main中去
mov eax, 0 ; 先初始化eax,后续里面要放string的长度
L1:
cmp BYTE PTR[edi], 0 ; 判断是否到了string的结尾
je L2 ; 如果到了结尾,就跳转到L2
inc edi ; 如果没有到结尾,则指针加1
inc eax ; 同时长度也加1
jmp L1
L2 :
ret
Str_len ENDP
.code
main PROC
push edi ; USES也是masm中特有的,也去掉了,因此这里要自己保存edi
mov edi, OFFSET string_1
call Str_len
pop edi
call DumpRegs ; 打印寄存器的值,这里需要关心的是EAX,它的值应该是11
exit
main ENDP
END main
7. 程序的执行结果如下:
eax的值是0xB,即11,符合预期结果。
最后
以上就是幽默翅膀为你收集整理的【asm基础】masm中的主函数与函数调用说明的全部内容,希望文章能够帮你解决【asm基础】masm中的主函数与函数调用说明所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复