Определение байтов в GCC Inline Assembly в Dev-C ++ (. Ascii в синтаксисе AT & T в Windows) - PullRequest
10 голосов
/ 14 сентября 2010

Код ниже просто показывает окно сообщения на экране.
Адреса жестко закодированы для облегчения:

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?

Обратите внимание, что я использую Dev-C ++ в Windows XP SP3

Спасибо!

1 Ответ

9 голосов
/ 14 сентября 2010

Да, используя директивы ассемблера внутри встроенного ассемблера. Хитрость заключается в том, чтобы поместить строку в нужное место (раздел данных), что можно сделать, переключившись с помощью .section .data, а затем снова переключившись обратно с помощью .section .text.

Вы должны присвоить данным метку, чтобы вы могли ссылаться на нее; Я бы рекомендовал использовать здесь локальный синтаксис меток (где метка - это число, например, 1:, и вы ссылаетесь на него как 1b для первой метки 1: в обратном направлении или 1f для первой 1: пометьте вперед - см. документацию для сборщика GNU для получения более подробной информации.

Как это:

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, на которой можно было бы это протестировать, но она компилируется нормально и выглядит так, как будто она должна работать правильно, используя кросс-компилятор MinGW в Linux (я считаю, что Dev-C ++ основан на MinGW) .

Примечание: этот метод обычно применим при использовании цепочки инструментов GNU. Если вы создаете бинарные файлы ELF (например, собственный Linux), есть более удобный способ вернуться к текстовому разделу, который должен использовать .previous, что означает «независимо от того, каким разделом был предыдущий .section». (Приведенный выше пример работает в Linux, если вы измените _puts на puts, чтобы учесть различные соглашения о префиксе символов.)

...