首页 > 其他分享 >delphi 2006中,使用stdcall调用约定时,压缩结构参数的bug分析

delphi 2006中,使用stdcall调用约定时,压缩结构参数的bug分析

时间:2024-04-29 13:34:14浏览次数:15  
标签:delphi Param eax 2006 b1 b2 stdcall edx bug

问题

今天遇到一个很奇怪的问题,有一个dephi2006写的dll,使用了stdcall的调用约定,参数传递了结构体,在函数中收到的结构体值和传入的不一致,最后一个boolean类型,应为False,收到的是True,如下图:

代码

//结构体定义
RStruct = packed record
    i1: Integer;
    i2: Integer;
    i3: Integer;
    i4: Integer;
    i5: Integer;
    b1: Boolean;
    b2: Boolean;
    b3: Boolean;
end;


procedure Fun(Param: RStruct);stdcall;
begin
  Writeln('函数收到参数:');

  Param.Print();
end;

var
  Param: RStruct;
begin
  Param.i1 := 0;
  Param.i2 := 1;
  Param.i3 := 2;
  Param.i4 := 3;
  Param.i5 := 4;
  Param.b1 := true;
  Param.b2 := False;
  Param.b3 := false;

  //Writeln('调用参数:');

  //Param.Print();

  //Writeln(LR + LR);

  Fun(Param);

  Readln;
end.

分析

为简化生成的汇编代码,删除掉了输出日志代码,只保留了必要的部分:

这里先看一个正确的例子,删除掉结构体中的i5,让结构体变小一点(在这种情况下,结果是正确的)

汇编代码如下:

关键的部分为以下内容,是对结构体中后3个布尔类型的传参

//eax 是一个32位的寄存器
//[edx + $12] 位置存储的是 b3 的值,为true(即数值1)
//此处把b3值写入到 eax 
movzx eax,[edx + $12] //eax值变为 $00000001

//eax左移16位 
shl eax, $10 //eax的值变为 $00010000

//ax寄存器为eax寄存器的低16位
//[edx + $10] 为b1,由于b1 占一个字节,b2占一个字节
//此处把b1 b2 移动到ax中(eax两个低字节)
mov ax, [edx + $10]

//eax 的布局为 [空] [b3] [b2] [b1]

//把eax 压入堆栈(压入堆栈是为了给函数传参用)
push eax


再看一下错误的例子

汇编代码如下图:


movzx eax,[edx + $14]

shl eax, $10

mov ax, [edx + $14]

push eax

//除了结构体大小变化引起的偏移量不同外,剩下的就是 
//movzx eax,[edx + $14] 和 mov ax, [edx + $14],后面的地址是相同的,都指向了b1,而前面正确的示例中 movzx指向的是b3

//这就导致最终eax中的布局变成了 [空] [b1] [b2] [b1]

总结

只有在Fun声明为stdcall时会出现这种错误,改为默认的调用约定可以正常工作, 结构体去掉packed声明也可以正常工作,改变结构体大小后,增大一些或减小一些也可以正常工作

应该是delphi的编译器在做优化时的一个bug

为避免这种莫名其妙的问题,在使用stdcall时,尽量不要使用packed record

在xe7下,测试了一下,没有这个问题

标签:delphi,Param,eax,2006,b1,b2,stdcall,edx,bug
From: https://www.cnblogs.com/qmcode/p/18165468

相关文章

  • Stegsolve有bug: 只支持32/24bit真彩色, 解析灰度图像有问题(附排查过程)
    结论:如题目所示。切勿直接相信它对灰度图像的解析 发现过程:在给学生排查毕设代码的时候,发现明明只改了0-3四个位平面,但用Stegsolve观察的时候发现连红色通道的6号位平面都出现相似的条纹了。排查的过程:首先怀疑代码哪里写错,毕竟 Stegsolve是个用得挺多的工具,......
  • delphi DBNavigator1 删除前 后 事件
    //擦除原来线procedureTForm1.DBNavigator1BeforeAction(Sender:TObject;Button:TNavigateBtn);beginifbutton=nbDeletethenDBtooLine(clBtnFace,clBtnFace);//擦除原来线end;procedureTForm1.DBNavigator1Click(Sender:TObject;Button:TNaviga......
  • ROS学习-启动服务端错误debug
    ros2runexamples_rclpy_minimal_serviceservice输入这个命令用于运行服务节点,这个服务的功能是将两个数字相加,给定a,b两个数,返回sum也就是ab之和。报错:2024-04-2713:11:39.105[RTPS_TRANSPORT_SHMError]Failedinit_portfastrtps_port7412:open_and_lock_filefailed->......
  • vscode debug: #include errors detected. Please update your includePath
    比如说文件树如下-src-x.cpp-x.hpp那么在x.cpp中直接#include"x.hpp"是没问题的,因为这个按相对路径来说可以直接搜到 但是如果文件树如下-src-x.cpp-head-x.hpp由于x.cpp和x.hpp不在同一个文件夹下,所以需要按相对路径如下#include".......
  • 如何有效报告Bug
    良好的态度:礼貌提问,保持谦卑,保持好奇;得到回答请说“谢”。准确描述问题:报错信息(文本和截图)要完整。不完整的报错信息无法获得有效回答预期结果要讲清楚,不符合预期的现象要标明常见的错误原因:路径错误:报错信息包含了路径,但被你忽略;报错信息没有直观的路径,你不知......
  • 低开开发笔记(五):修bug-深拷贝与浅拷贝
    好家伙 今天遇到一个bug 0.问题描述描述如下: 代码如下:copynodefunc(){this.copynode=this.model.selected},affixnode(){constid=this.model.selected.wid-1;constgoodnode=this.copynode......
  • CS61B Lab2 Debugging
    实验2主要内容教你使用IDE中调试步骤,学会设置断点调试代码学以只用,学会设置断点之后,就开始改代码错误了本节需要学什么?Java配置Configration当你导入一个项目模块时,需要添加修改configration的以下内容。Junit的导入有时候运行的时候会出现“junit不存在等情况”这时......
  • [NewStarCTF]flask disk debug模式下的漏洞
    打开环境,发现三个链接/list/upload/console,题目描述为flask,那就是与flask的debug模式相关的漏洞,在此之前我只听过debug的pin码漏洞,也就是关于pin码的生成的。这里提一下:点击查看代码pin码的生成取决于下面这几个因素:1.服务器运行flask所登录的用户名。2.modname2.geta......
  • ROS2学习--POP方法编写C++节点 debug过程
    一、编写C++节点并测试 1.创建功能包C++功能包使用ament-camke作为编译基础,依赖为rclcpp。打开终端,进入town_ws/src运行下面的指令,目录结构如下ros2pkgcreatevillage_wang--build-typeament_cmake--dependenciesrclcpp2.创建节点village_wang/src下创建一个wang2.cp......
  • delphi清理txt文件多余的空格
    PDF文件转存为文本,多了一堆不需要的空格,写个小程序处理一下,没逻辑,直接上代码。delphi用的是XE11.3unitUnitSmallMain;interfaceusesSystem.SysUtils,System.Types,System.UITypes,System.Classes,System.Variants,FMX.Types,FMX.Controls,FMX.Forms,FMX.Grap......