11

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

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++

谢谢!

4

1 回答 1

10

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

您必须给数据一个标签,以便您可以参考它;我建议在这里使用本地标签语法(其中标签是一个数字,例如1:,并且您将其引用为向后1b的第一个标签或向前的第一个标签 - 有关更多详细信息,请参阅GNU 汇编器文档)。1:1f1:

像这样:

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 。)

于 2010-09-14T19:36:53.853 回答