案例代码
01.使用寄存器传参调用DumpMem函数实例
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
array DWORD 1,2,3,4,5,6,7,8,9
.code
main PROC
push ebx ;保存寄存器的值
push ecx
push esi
mov esi,offset array ;初始offset
mov ecx,lengthof array ;大小,按元素个数计
mov ebx,TYPE array ;双字格式
call DumpMem ;显示内存
pop esi ;恢复寄存器的值
pop ecx
pop ebx
invoke ExitProcess,0
main ENDP
END main
02.使用寄存器参数的缺点
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
array DWORD 1,2,3,4,5,6,7,8,9
error_msg BYTE "Sometthing wrong happened!",0
.code
main PROC
push ebx ;保存寄存器的值
push ecx
push esi
mov esi,offset array ;初始offset
mov ecx,lengthof array ;大小,按元素个数计
mov ebx,TYPE array ;双字格式
call DumpMem ;显示内存
cmp eax,1 ;设置错误标志?
je error_exit ;设置标志后退出
pop esi ;恢复寄存器的值
pop ecx
pop ebx
ret
error_exit:
mov edx,offset error_msg
call WriteString ;显示错误消息
ret
invoke ExitProcess,0
main ENDP
END main
03.两数之和
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
.code
main PROC
call Example1
call WriteInt
call WaitMsg
invoke ExitProcess,0
main ENDP
Example1 PROC
push 5
push 6
call AddTwo
pop ebx ;这里单纯的只是想要将栈中的两个数值弹出
pop ebx ;暴露出返回地址
ret
Example1 ENDP
AddTwo PROC
push ebp
mov ebp,esp
mov eax,[ebp+12]
add eax,[ebp+8]
pop ebp
ret
AddTwo ENDP
END main
04.两数之和 C调用规范
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
.code
main PROC
call Example1
call WriteInt
call WaitMsg
invoke ExitProcess,0
main ENDP
Example1 PROC
push 5
push 6
call AddTwo
add esp,8 ;这里使用了C调用规范,后面的数值是子程序参数所占用堆栈空间字节数的总和
ret ;这里必须要跟上ret指令,否则会导致访问到其他位置的代码导致错误
Example1 ENDP
AddTwo PROC
enter 0,0
mov eax,[ebp+12]
add eax,[ebp+8] ;[ebp+4]这块内存存储的是主调函数调用子函数的栈帧
pop ebp
ret
AddTwo ENDP
END main
05.两数之和 STDCALL调用规范
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
.code
main PROC
mov eax,10
push eax
mov eax,20
push eax
call AddTwo
call WriteInt
call WaitMsg
invoke ExitProcess,0
main ENDP
AddTwo PROC
push ebp
mov ebp,esp
mov eax,[ebp+12]
add eax,[ebp+8] ;[ebp+4]这块内存存储的是主调函数调用子函数的栈帧
pop ebp
ret 8 ;使用STDCALL调用规范清除堆栈参数
;这里的8指的是两个32位参数所占用的字节数一共8byte
AddTwo ENDP
END main
06.局部变量的反汇编
#include<iostream>
using namespace std;
void MySub()
{
int X = 20;
int Y = 10;
}
int main()
{
//Do nothing!
system("pause");
return 0;
}
反汇编结果片段为(仅仅截取代码块内部的部分)
void MySub()
{
00007FF65C091760 push rbp
00007FF65C091762 push rdi
00007FF65C091763 sub rsp,128h
00007FF65C09176A lea rbp,[rsp+20h]
00007FF65C09176F lea rcx,[__3BCE52E7_06@局部变量的反汇编\源@cpp (07FF65C0A1029h)]
00007FF65C091776 call __CheckForDebuggerJustMyCode (07FF65C091352h)
int X = 20;
00007FF65C09177B mov dword ptr [X],14h
int Y = 10;
00007FF65C091782 mov dword ptr [Y],0Ah
}
int main()
{
00007FF65C091830 push rbp
00007FF65C091832 push rdi
00007FF65C091833 sub rsp,0E8h
00007FF65C09183A lea rbp,[rsp+20h]
00007FF65C09183F lea rcx,[__3BCE52E7_06@局部变量的反汇编\源@cpp (07FF65C0A1029h)]
00007FF65C091846 call __CheckForDebuggerJustMyCode (07FF65C091352h)
//Do nothing!
system("pause");
00007FF65C09184B lea rcx,[string "pause" (07FF65C099BB0h)]
00007FF65C091852 call qword ptr [__imp_system (07FF65C0A02F8h)]
return 0;
00007FF65C091858 xor eax,eax
}
07.局部变量符号的使用
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
X_local EQU DWORD PTR [ebp-4]
Y_local EQU DWORD PTR [ebp-8]
.code
main PROC
mov eax,10
push eax
mov eax,20
push eax
call MySub
invoke ExitProcess,0
main ENDP
MySub PROC
push ebp
mov ebp,esp
sub esp,8
mov X_local,10
mov Y_local,20
mov eax,X_local
add eax,Y_local
call WriteInt
mov esp,ebp
pop ebp
ret
MySub ENDP
END main
08.ArrayFill
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
count = 100
array WORD count DUP(0)
.code
main PROC
push offset array
push COUNT
call ArrayFill
mov esi,offset array
mov ecx,count
mov ebx,2
call DumpMem
call WaitMsg
exit
invoke ExitProcess,0
main ENDP
ArrayFill PROC
push ebp
mov ebp,esp
pushad
mov esi,[ebp+12] ;数组的偏移量
mov ecx,[ebp+8] ;数组的长度
cmp ecx,0 ;如果循环未结束
jle L2 ;如果循环结束跳出
L1:
mov eax,10000h
call RandomRange ;生成一个随机数存入eax
mov [esi],eax ;将随机数存入数组
add esi,TYPE word ;数组指针指向下一个元素位置
loop L1
L2:
popad ;程序结束 善后处理
pop ebp
ret 8 ;弹出栈中的两个参数,暴露出栈帧
ArrayFill ENDP
END main
09.无限递归
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
endlessStr BYTE "This recursion never stop",0
.code
main PROC
call Endless
invoke ExitProcess,0
main ENDP
Endless PROC
mov edx,offset endlessStr
call WriteString
call Endless
ret ;从不执行
Endless ENDP
END main
10.递归求和
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
.code
main PROC
mov ecx,5 ;计数值ecx=5
mov eax,0 ;存放和数
call CalcSum ;计算和数
L1:
call WriteDec;显示EAX
call Crlf ;换行
call WaitMsg
invoke ExitProcess,0
main ENDP
;-----------------------
CalcSum PROC
;计算整数列表的和数
;接收:ECX=计数值
;返回:EAX=和数
;-----------------------
cmp ecx,0
jz L2
add eax,ecx
dec ecx
call CalcSum
L2:
ret
CalcSum ENDP
END main
11.LEA
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
.code
main PROC
call makeArray ;函数将所有的#号都存入栈中(重复30次)
invoke ExitProcess,0
main ENDP
makeArray PROC
push ebp
mov ebp,esp
sub esp,32
lea esi,[ebp-32];lea实现从间接操作数向寄存器的赋值以及间接寻址符号内地址计算操作,整体功能上相当于高级版本的mov
mov ecx,30
L1:
mov BYTE PTR [esi],'#'
inc esi
loop L1
add esp,32
pop ebp
ret
makeArray ENDP
END main
12.计算阶乘
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
.code
main PROC
push 3 ;计算5!
call Factorial ;计算阶乘(EAX)
call WriteDec ;显示结果
call Crlf
exit
invoke ExitProcess,0
main ENDP
;----------------------------
Factorial PROC
;计算阶乘
;接收:[ebp+8]=n,需计算的数
;返回:eax=n的阶乘
;----------------------------
enter 0,0
mov eax,[ebp+8] ;获取n
cmp eax,0 ;n>0?
ja L1 ;是 继续
mov eax,1 ;否 返回0!=1
jmp L2 ;并且返回主调程序
L1:
dec eax
push eax ;Factorial(n-1)
call Factorial
;每次递归调用返回时
;都需要执行下面的指令
ReturnFact:
mov ebx,

本文通过一系列示例展示了汇编语言在函数调用、数组操作和递归计算方面的应用。包括使用寄存器传参、局部变量处理、数组填充、数组求和、递归计算整数和等。同时,还探讨了不同调用规范如stdcall和fastcall的使用,以及如何在汇编程序中实现递归和栈空间管理。
最低0.47元/天 解锁文章
476

被折叠的 条评论
为什么被折叠?



