2010-09-14 8 views
9

Aşağıdaki kod ekranda yalnızca bir Mesaj Kutusu gösteriyor. GCC Inline Derlemesindeki Baytları Tanımlama Dev-C++ (Windows'da AT & T sözdiziminde ascii)

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

Benim sorum (benim sorum kodu ilgili değil çünkü tüm kodu yorum yapmadı): yazmak için bir yolu var mı
adresleri kolaylaştırmak için önceden kodlanmıştır dizgeyi "user32.dll" derleme kümesine el ile itmeden, satır içi satır içi? Ben NASM'ın böyle demek: db 'Hello'

Ben & T sözdizimi AT I gcc inline yaklaşık .ascii 'Hello' veya .string 'Hello' ama nasıl yapabileceğinizi biliyor?

Windows XP SP3 ++

Teşekkür Dev-C kullanıyorum lütfen unutmayın!

cevap

9

Evet, inline assembler'ınızın içindeki assembler yönergeleri kullanılarak. Hile, dizeyi .section .data kullanarak değiştirerek yapabileceğiniz doğru yere (veri bölümü) yerleştirmek ve .section .text ile tekrar tekrar değiştirmektir.

Verilere etiket verebilmeniz için bir etiket vermeniz gerekir; Burada yerel etiket sözdizimi kullanarak öneriyoruz (etiket bir sayı, örneğin 1: olduğunu ve ilk 1: etiket yönlendirme olup 1f geriye ilk 1: etiket için ya 1b olarak başvurmak, ya da nerede - daha fazla ayrıntı için GNU assembler documentation bakınız) . Bunun gibi

:

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

Ben bu test etmek kullanışlı Windows sistem yok, ama Linux üzerinde bir MinGW çapraz derleyici kullanarak doğru olanı yapıyor olması gerektiği gibi Tamam derler ve bakar (Dev-C++'nin MinGW'ye dayandığına inanıyorum).

Not: Bu teknik genellikle bir GNU takım zinciri kullanıldığında uygulanabilir. ELF ikili dosyaları (örneğin, yerel Linux) oluşturuyorsanız, .previous olan "önceki .section'un önceki bölümü ne olursa olsun" anlamına gelen metin bölümüne geri dönmenin daha iyi bir yolu vardır. (Yukarıdaki örnek, farklı sembol önekleme kurallarını hesaba katmak içindeğerini puts olarak değiştirirseniz Linux üzerinde çalışır.)

+0

Cool! "1:" ifadesi, dizenin adresi için bir etiket anlamına gelir mi? "Merhaba" adresini iterek "pushl $ 1b" talimatı var mı? Ne "? Önemsiz" yapar? Teşekkürler! – jyz

+0

":" .previous "Windows üzerinde çalışıyor muyum? Yapamıyorum .. Dev-Cpp Portable kullanıyorum – jyz

+1

@jyzuz: hayır, öyle değil, üzgünüm, bu konuda üzgünüm. Bu şekilde yuvarlak. '1:' gerçekten bir etiket ve '1b' ise onu ifade eder (güncellenmiş cevabımda bağladığım montajcı belgelerine bakın), bu yüzden evet,' 1 $ itmeli 'etiketin değerini iter. dizenin adresi - yığının üzerine bir sabit olarak. –