在 C++ 中的函数内执行程序集
Posted
技术标签:
【中文标题】在 C++ 中的函数内执行程序集【英文标题】:executing assembly within a function in c++ 【发布时间】:2011-05-15 14:39:45 【问题描述】: 长 getesp() __asm__("movl %esp,%eax"); 无效的主要() printf("%08X\n",getesp()+4);为什么 esp 在设置堆栈帧之前指向值,它与下面的代码有什么区别?
无效的主要() __asm__("movl %esp,%eax");【问题讨论】:
【参考方案1】:在我做了gcc -S file.c
之后
getesp:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
#APP
# 4 "xxt.c" 1
movl %esp,%eax
# 0 "" 2
#NO_APP
leave
ret
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $20, %esp
call getesp
addl $4, %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
addl $20, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
getesp
有一个pushl
,它操纵esp
并通过内联和ebp
在eax
中获取操纵的esp
。
调用函数来获取堆栈指针并将其放入main
肯定是不同的,并且相差 12 个字节(在这种特定情况下)。这是因为当您执行call
时会推送eip
(如果不是段间,并且对于linux/unix 正常程序执行它只是eip
)(需要引用),接下来在getesp
函数中还有另一个push
和 ebp
之后堆栈指针减 4。因为 eip
和 ebp
是 4 个字节,所以现在总差值为 12 个字节。实际上我们可以在函数调用版本中看到。
没有函数调用就没有eip
和其他esp
操作的推送,所以我们在主设置后得到esp
值。
我对 AT&T 不满意,所以这里是 Intel 语法中的相同代码和下面的 Intex 语法 asm 转储。请注意,在 printf
调用 __asm__
内的 main 值进入 a
没有推送或其他 esp
修改,因此, __asm__
内 main 获得 esp
值,该值设置在主要由sub esp, 20
行。如上所述,我们通过调用 getesp
获得的值是(您所期望的) - 12 。
C 代码
#include <stdio.h>
int a;
long getesp()
__asm__("mov a, esp");
int main(void)
__asm__("mov a,esp");
printf("%08X\n",a);
getesp ();
printf("%08X\n",a);
我的输出是针对特定运行的:
BF855D00
BF855CF4
英特尔语法转储是:
getesp:
push ebp
mov ebp, esp
sub esp, 4
#APP
# 7 "xt.c" 1
mov a, esp
# 0 "" 2
#NO_APP
leave
ret
main:
lea ecx, [esp+4]
and esp, -16
push DWORD PTR [ecx-4]
push ebp
mov ebp, esp
push ecx
sub esp, 20
#APP
# 12 "xt.c" 1
mov a,esp
# 0 "" 2
#NO_APP
mov eax, DWORD PTR a
mov DWORD PTR [esp+4], eax
mov DWORD PTR [esp], OFFSET FLAT:.LC0
call printf
call getesp
mov eax, DWORD PTR a
mov DWORD PTR [esp+4], eax
mov DWORD PTR [esp], OFFSET FLAT:.LC0
call printf
add esp, 20
pop ecx
pop ebp
lea esp, [ecx-4]
ret
我希望这会有所帮助。
【讨论】:
以上是关于在 C++ 中的函数内执行程序集的主要内容,如果未能解决你的问题,请参考以下文章
WinSCP .NET 程序集失败,在 C# Azure 函数中的 Session.Open 中出现“未找到 winscp.exe 可执行文件”