在 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 并通过内联和ebpeax 中获取操纵的esp

调用函数来获取堆栈指针并将其放入main 肯定是不同的,并且相差 12 个字节(在这种特定情况下)。这是因为当您执行call 时会推送eip(如果不是段间,并且对于linux/unix 正常程序执行它只是eip)(需要引用),接下来在getesp 函数中还有另一个pushebp 之后堆栈指针减 4。因为 eipebp 是 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++ 中的函数内执行程序集的主要内容,如果未能解决你的问题,请参考以下文章

百战c++

百战c++

百战c++

在程序集文件中调用 C++ 函数

GCC 程序集 "+t"

WinSCP .NET 程序集失败,在 C# Azure 函数中的 Session.Open 中出现“未找到 winscp.exe 可执行文件”