前言
本文章纯粹用于记录我自己在学习汇编语言中记录的笔记
文章中可能会存在许多错误或混淆的地方,欢迎大家指出
也请各位大佬多多包涵
=================================================================================
了解基础指令
首先我们先来了解一下在汇编语言调用子程序时会用到的几个指令
===========================================================================
1.指令MOV
MOV OPRD1 OPRD2
功能: 本指令将一个源操作数送到目的操作数中,即OPRD1<–OPRD2.
说明: 1. OPRD1 为目的操作数,可以是寄存器、存储器、累加器.
---- OPRD2 为源操作数,可以是寄存器、存储器、累加器和立即数.
===========================================================================
2.指令call
CALL OPRD
*功能:过程调用指令
注意: CALL指令执行过程中即完成两件事
1.保存返回地址到堆栈
2.跳转到子程序中*
===========================================================================
3.指令ret
功能: 当调用的过程结束后实现从过程返回至原调用程序的下一条指令,本指令不影响标
---- 志位.
ret实现过程中即完成:
在堆栈顶部取出返回地址 并且放置到IP寄存器
再跳转到IP寄存器
===========================================================================
观察进入子程序过程
assume cs:code
code segment
SetAx proc
mov Ax,0ffffh
ret
SetAx endp
Start:
call SetAx
int 21h
code ends
end start
用XP系统自带的debug分析软件可以看到我们此时的SP寄存器 即栈顶寄存器与BP寄存器都指向的是0
在执行了CALL指令后 我们SP寄存器地址指向了FFFE 即进行了减二
此时 正如我们先前在介绍CALL指令所说的
1.保存返回地址到堆栈
2.跳转到子程序中*
此时SP指向的FFFE地址存储的正是返回地址
在执行完子程序里面的代码后 即将进行RET指令的操作
在执行完ret指令后 SP寄存器地址又重新指向回了0
正如上面所说的 ret指令执行的过程即是:在堆栈顶部取出返回地址 并且放置到IP寄存器
再跳转到IP寄存器
分析在堆栈传参过程中的过程
#include <iostream>
int add(int a, int b)
{
return a + b;
}
int main()
{
add(1, 2);
return 0;
}
我们先用C++简易的创造一个函数
***在转到反汇编后 我们着重注意这三处地方
而这也是实现堆栈传参的重要所在
==================================================================================
接着我们自己尝试使用汇编语言进行还原
assume cs:code
code segment
SetAx proc
push bp
mov bp,sp
mov si,[bp+4]
pop bp
ret
SetAx endp
start:
mov ax,4
mov bx,5
push ax
push bx
call SetAx
add sp,4
mov ax,4c00h
int 21h
code ends
end start
可以看到此时我们FFF8地址存储的东西正是原始bp
此时再进行-t时 我们注意到SP寄存器与BP寄存器的地址都指向了FFF8 这正是mov bp,sp 这条指令的效果
可以看到在成功给si寄存器传参之后 我们的SP地址在逐渐往前进 这也是堆栈传参中重要的一步:平栈
最后利用add指令完成最后的平栈