【asm基础】masm中的主函数与函数调用

说明

以下是在VS2012中使用masm汇编的一个例子:

.data
string_1 BYTE "Helloworld!", 0

.code
;---------------------------------------------------------
Str_len PROC USES edi,
        pString:PTR BYTE	
;
; 返回一个以\0结尾的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
;
; 返回一个以\0结尾的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,符合预期结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值