【问题标题】:Defining Bytes in GCC Inline Assembly in Dev-C++(.ascii in AT&T syntax on Windows)在 Dev-C++ 中定义 GCC 内联汇编中的字节(Windows 上 AT&T 语法中的 .ascii)
【发布时间】:2011-04-12 08:12:04
【问题描述】:

下面的代码只是在屏幕上显示一个消息框。
为了方便起见,地址被硬编码:

int main ()
{
    asm("xorl %eax, %eax        \n"
        "xorl %ebx, %ebx        \n"
        "xorl %ecx, %ecx        \n"
        "xorl %edx, %edx        \n"
        "pushl %ecx             \n" //$0x0
        "pushl $0x20206c6c      \n" //"  ll"
        "pushl $0x642e3233      \n" //"d.23"
        "pushl $0x72657375      \n" //"resu"
        "movl %esp, %ecx        \n" //store "user32.dll" address in %ecx
        "movl $0x7c801d7b, %ebx \n" //store address of LoadLibraryA in %ebx
        "pushl %ecx             \n"
        "call *%ebx             \n"
        "movl $0xef30675e, %ecx \n"
        "addl $0x11111111, %ecx \n"
        "pushl %ecx             \n"
        "pushl $0x42656761      \n"
        "pushl $0x7373654d      \n"
        "movl %esp, %ecx        \n"
        "pushl %ecx             \n"
        "pushl %eax             \n"
        "movl $0x7c80ae40, %ebx \n"
        "call *%ebx             \n"
        "movl %esp, %ecx        \n"
        "xorl %edx, %edx        \n"
        "pushl %edx             \n"
        "pushl %ecx             \n"
        "pushl %ecx             \n"
        "pushl %edx             \n"
        "call *%eax             \n"
        "xorl %eax, %eax        \n"
        "pushl %eax             \n"
        "movl $0x7c81cb12, %eax \n"
        "call *%eax             \n"
    );
}

(我没有评论所有代码,因为我的问题不是关于代码)

我的问题是:有没有办法在汇编内联中写入字符串“user32.dll”而无需手动推送到堆栈?我的意思是在 NASM 中是这样的:db 'Hello'

我知道在 AT&T 语法中我可以使用 .ascii 'Hello'.string 'Hello' 但在 gcc inline 中呢?

请注意,我在 Windows XP SP3 上使用 Dev-C++

谢谢!

【问题讨论】:

    标签: gcc assembly inline-assembly dev-c++ att


    【解决方案1】:

    是的,通过在您的内联汇编器中使用汇编器指令。诀窍是将字符串放在正确的位置(数据部分),您可以使用.section .data 切换,然后使用.section .text 再次切换回来。

    你必须给数据一个标签,以便你可以参考它;我建议在这里使用本地标签语法(其中标签是一个数字,例如1:,您将其引用为1b 用于第一个1: 标签向后,或1f 用于第一个1:标签转发 - 有关详细信息,请参阅GNU assembler documentation)。

    像这样:

    int main(void)
    {
      asm(".section .data      \n"
          "1: .asciz \"Hello\" \n"
          ".section .text      \n"
          "pushl $1b           \n"
          "call _puts          \n"
          "add $4, %esp        \n"
         );
      return 0;
    }
    

    我没有方便的 Windows 系统来测试它,但它编译正常,看起来应该在 Linux 上使用 MinGW 交叉编译器做正确的事情(我相信 Dev-C++ 是基于 MinGW) .

    注意:这种技术通常在使用 GNU 工具链时适用。如果您正在构建 ELF 二进制文件(例如本机 Linux),有一种更简洁的方法可以切换回文本部分,即使用 .previous,这意味着“无论前面的 .section 之前的部分是什么”。 (如果您将 _puts 更改为 puts 以考虑不同的符号前缀约定,则上述示例适用于 Linux。)

    【讨论】:

    • 酷! “1:”是否意味着它是字符串地址的标签?指令“pushl $1b”是在推送“Hello”的地址吗? “.previous”做什么?谢谢!
    • ":“.previous”在 Windows 上有效吗?我不能……我正在使用 Dev-Cpp Portable
    • @jyzuz:不,似乎不是;对于那个很抱歉。我已经用一种方法更新了我的答案。 1: 确实是一个标签,1b 指的是它(请参阅我在更新的答案中链接到的汇编程序文档);所以是的,pushl $1b 将标签的值(即字符串的地址)作为常量推入堆栈。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 2021-08-23
    • 2012-03-02
    • 1970-01-01
    • 2010-12-28
    • 1970-01-01
    相关资源
    最近更新 更多