2010-09-14 2 views
9

Код ниже показывает только окно сообщений на экране.
Адреса зашиты для облегчения:Определение байтов в GCC Inline Assembly в Dev-C++ (. Ascii в синтаксисе AT & T в Windows)

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" 
    ); 
} 

(я не комментировал весь код, потому что мой вопрос не совсем о коде)

Мой вопрос: Есть ли способ, чтобы написать string "user32.dll" в сборке inline без нажатия вручную в стек? Я имею в виду, как это в NASM: db 'Hello'

Я знаю, что в AT & T синтаксис я мог бы сделать .ascii 'Hello' или .string 'Hello', но как насчет в GCC инлайн?

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

Спасибо!

ответ

9

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

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

+0

Прохладный! «1:» означает, что это метка на адрес строки? Является ли инструкция «pushl $ 1b» нажатием адреса «Hello»? Что такое ".previous"? Благодаря! – jyz

+0

":" .previous "работает в Windows? Я не умею .. Я использую Dev-Cpp Portable – jyz

+1

@jyzuz: нет, кажется, нет, извините. Я обновил свой ответ с помощью «1:' действительно является меткой, а '1b» относится к нему (см. документацию ассемблера, с которой я связан в моем обновленном ответе), так что да, 'pushl $ 1b' подталкивает значение метки, которое это адрес строки - как константа в стеке. –