zoukankan      html  css  js  c++  java
  • 练习3:参数值传递的汇编实质

    参数值传递的汇编实质,就是在堆栈上创建存储区,看看以下实现:

    先来看看Delphi代码,传一个数组参数进去

    1 procedure SortIt(a: array of Integer);
    2 var
    3   i, j: Integer;
    4 begin
    5   j := Length(a);
    6   for i:=1 to j do
    7     a[i-1] := i;
    8 end;

    调用代码为:

    procedure TForm1.btn1Click(Sender: TObject);
    var
      a: array[0..1] of Integer;
    begin
      SortIt(a);
      ShowMessage('a[0]: ' + IntToStr(a[0]) + #13#10 + 'a[1]: ' + IntToStr(a[1]));
    end;

    看看汇编代码是怎样干的:

    Unit1.pas.44: SortIt(a);
    ;调用前准备
    lea eax,[ebp-$08]  ;定义的局部变量放在堆栈里,2个数组元素,32位系统里占8字节,
                          ;根据定义的局部变量顺序压栈,这儿只定义了数组A,所以堆栈里
                          ;就只有8字节,此句的意思是,把ebp-8的值放到eax中,这个值是
                          ;指向a[1]的内存地址,所以执行后eax中为a[0]元素的内存地址
    mov edx,$00000001
    call SortIt

     函数入口:

     1 ;函数入口处代码
     2 00452688 55               push ebp             ;这两行为堆栈框架,函数开始前必这样做以保存调用前
     3 00452689 8BEC             mov ebp,esp          ;的堆栈数据,同时为同时为函数创造干净的堆栈环境
     4 0045268B 53               push ebx             ;要用到ebp,先保存原值,不要破坏它
     5 0045268C 8BCA             mov ecx,edx          ;edx值为1,看起来用于下面的循环,ecx一般用于计数
     6 0045268E 85C9             test ecx,ecx         ;test和and类似,不同的是,只影响标志寄存器,不影响结果
     7 00452690 7807             js +$07              ;如果sf为1,这是符号位,如果ecx为ffff ffff,数组就爆了,不能是大于这个值
     8 00452692 8B1C88           mov ebx,[eax+ecx*4]  ; 记得eax为a[0]吧,此处ecx为1, eax+4刚好为a[1]地址,把a[1]的值取到ebx
     9 00452695 49               dec ecx
    10 00452696 53               push ebx     ; 把a[1]值入栈
    11 00452697 79F9             jns -$07     ;返回上面的mov ebx,[eax+ecx*4],再来一次,这样的话又能把a[0]值入栈
    12 00452699 8BC4             mov eax,esp  ;这个时候堆栈里从低地址到高地址已形成a[0]、a[1]的结构,把堆栈指针指向a[0],
    13                                        ;一个新的临时参数环境就构造好了,后面对数组的存取就只在这儿进行,不会影响
    14                                        ;原值,高明呀,原来是这样实现的!

    函数退出时:

    1 ;函数结束堆栈要恢复到入来前的状态,这叫堆栈平衡
    2 004526B5 8BE5             mov esp,ebp   ;记得函数进来前ebp指向栈顶吧,这一下直接回到进来前状态
    3 004526B7 5D               pop ebp       ;是push ebp和mov ebp,esp的倒过来,就恢复了。
    4 004526B8 C3               ret 
  • 相关阅读:
    PHP siege 压测 QPS大小
    macOs 使用Homebrew升级到MySQL 8系列之后,php无法连接解决方法
    Nginx无法加载.woff .eot .svg .ttf等解决办法
    layer 点击弹出图片
    glusterFS系统中文管理手册(转载)
    Linux 命令行总结
    linux /proc/meminfo 文件分析(转载)
    每秒执行一个shell脚本(转载)
    python SMTP邮件发送(转载)
    Python XML解析(转载)
  • 原文地址:https://www.cnblogs.com/IceAir/p/3071716.html
Copyright © 2011-2022 走看看