Sebagai assembler pilihan saya, saya menemukan fasm untuk menjadi program yang sangat baik dan sederhana. Ini sangat besar untuk pemula dan menggunakan intel gaya asm terkenal sintaks untuk Windows. Untuk tutorial ini, saya akan mendemokan penciptaan aplikasi konsol dengan perakitan fasm 16 dan 32 bit Majelis format.
Mari kita mulai dengan sederhana 16-bit versi. Di Majelis 16-bit, kami memiliki 2 byte register dan kami mengisi 1 byte AH mendaftar dengan nomor yang mewakili sub-function untuk mengeksekusi ketika memanggil menyela. Parameter tambahan untuk bahwa fungsi ditempatkan di berbagai register lain, biasanya mereka register akan menjadi tujuan umum register tetapi kadang-kadang juga dapat menjadi sumber
dan tujuan indeks Register (SI dan DI). Mari kita lihat pada Halo dunia com file dalam perakitan fasm:
dan tujuan indeks Register (SI dan DI). Mari kita lihat pada Halo dunia com file dalam perakitan fasm:
org 100h
mov ah,09
mov dx,msg
int 21h
mov ah,08
int 21h
int 20h
msg db "hello world!$"
Kita tahu bahwa semua com file eksekusi kode dimulai pada offset 0 � 100, jadi itu apa yang kita menempatkan sebagai baris pertama dari kode. Org 100h berarti asal (saya pikir), ditetapkan nomor akan menjadi alamat mana program akan mulai. Juga Perhatikan bahwa nilai-nilai heksadesimal nomor memiliki 'h' bahasa setelah nilai. Setelah itu kita mulai kami file com yang mana semua data dan kode berjalan di salah satu segmen. Majelis kode syntaxing terlihat standar,
mov ah,09 ;Place value 9 into ah register, index of sub-function to print str
mov dx,msg ;Place address of msg variable reference into dx for str to print
int 21h ;Execute interrupt call to print the string
mov ah,08 ;Value 8 into ah, sub-function to wait for character input (pause)
int 21h ;Execute interrupt call
int 20h ;Exit com file
msg db "hello world!$" ;The $ terminated string whose address will be
;referenced with the 'msg' keyword.
Cukup sederhana kan? Tetapi jika Anda ingin lebih banyak memori tapi masih menggunakan 16 bit kode,
Anda akan harus keluar dari file com dan menggunakan MZ format EXE program. MZ executable format tidak memiliki kode mulai 0 � 100 seperti file com, dan bukan pembatasan 64 k, file exe MZ sekarang memiliki lebih banyak memori untuk memiliki hingga untuk 4 segmen 64 k memori. Masing-masing segmen tersebut memiliki alamat mereka dirujuk dalam register yang berikut:
Anda akan harus keluar dari file com dan menggunakan MZ format EXE program. MZ executable format tidak memiliki kode mulai 0 � 100 seperti file com, dan bukan pembatasan 64 k, file exe MZ sekarang memiliki lebih banyak memori untuk memiliki hingga untuk 4 segmen 64 k memori. Masing-masing segmen tersebut memiliki alamat mereka dirujuk dalam register yang berikut:
CS = segmen kode
DS = segmen Data
ES = segmen tambahan
SS = tumpukan segmen
DS = segmen Data
ES = segmen tambahan
SS = tumpukan segmen
Untuk menggunakan MZ exe format di kode perakitan, hanya menggunakan format kata kunci
specifier di fasm seperti dalam contoh berikut:
specifier di fasm seperti dalam contoh berikut:
format MZ
entry main:start ; program entry point
stack 100h ; stack size
segment main ; main program segment
start:
mov ax,text
mov ds,ax
mov dx,hello
call extra:write_text
mov ax,4C00h
int 21h
segment text
hello db 'Hello world!',24h
segment extra
write_text:
mov ah,9
int 21h
retf
Perhatikan bahwa saya menggunakan segmen yang berbeda di sini. Aku menentukan saya di segmen baru
menggunakan kata kunci 'segmen' diikuti dengan nama yang diinginkan dari segmen. Jika Anda mengambil melihat Ralf Brown's mengganggu daftar, Anda melihat bahwa int 21/ah = 09 fungsi parameter untuk mencetak string adalah: DS:DX -> '$'-dihentikan string Bahwa berarti segmen menunjuk oleh ds ditambah offset ditemukan di dx, harus Arahkan ke string yang diakhiri dengan '$'. Sekarang dalam file com, semuanya
Terletak di satu segmen sehingga kita tidak perlu khawatir tentang hal itu. Tapi sekarang kita berurusan dengan segmen yang berbeda sehingga kita harus mengubah nilai ds register sehingga ds (dasar segmen alamat) + dx (offset alamat) = alamat data yang kami referensi ketika mempersiapkan untuk mencetak string.
menggunakan kata kunci 'segmen' diikuti dengan nama yang diinginkan dari segmen. Jika Anda mengambil melihat Ralf Brown's mengganggu daftar, Anda melihat bahwa int 21/ah = 09 fungsi parameter untuk mencetak string adalah: DS:DX -> '$'-dihentikan string Bahwa berarti segmen menunjuk oleh ds ditambah offset ditemukan di dx, harus Arahkan ke string yang diakhiri dengan '$'. Sekarang dalam file com, semuanya
Terletak di satu segmen sehingga kita tidak perlu khawatir tentang hal itu. Tapi sekarang kita berurusan dengan segmen yang berbeda sehingga kita harus mengubah nilai ds register sehingga ds (dasar segmen alamat) + dx (offset alamat) = alamat data yang kami referensi ketika mempersiapkan untuk mencetak string.
Jadi dalam program itu, kami pindah alamat segmen teks ke kapak, dan menyalin nilai tersebut ke daftar ds
Karena pesan Halo terletak di segmen yang berbeda, maka "mov dx, Halo" operasi akan menempatkan revelevant alamat segmen teks ke dx. Halo data pertama yang dinyatakan setelah menyatakan segmen teks karena data tersebut Terletak di sebuah offset 0 dari teks. Jadi alamat segmen: offset Halo adalah teks: 0000. Dari sini kita sebut label dalam segmen lain dengan menyatakan penuh segmen: offset addr menelepon dan kemudian mencetak string, kembali dan keluar.
Pindah ke 32 bit fasm adalah mana ia mendapat sedikit menarik. Sekarang di 32-bit Majelis, kami tidak memanggil menyela lagi; Sebaliknya, kita harus memanggil dll fungsi. Kami melakukannya dengan menekan argumen untuk stack dan kemudian issueing panggilan. Dalam contoh ini saya akan memanfaatkan perpustakaan msvcrt.dll dari C-
Language runtime.
Language runtime.
format PE console
entry main
include 'macro/import32.inc'
section '.data' data readable writeable
msg db "hello world!",0
p db "pause>nul",0
section '.code' code readable executable
main:
push ebp
mov ebp,esp
sub ebp,4
mov dword [esp],msg
call [printf]
mov dword [esp],p
call [system]
mov dword [esp],0
call [exit]
section '.idata' import data readable
library msvcrt,'msvcrt.dll'
import msvcrt,\
printf,'printf',\
system,'system',\
exit,'exit'
OK jadi, pertama kami memperkenalkan format executable. Ini adalah PE format eksekusi console application (ada juga format PE GUI). "entri utama" menentukan label di mana yang akan kita mulai dalam program kami, saya menggunakan utama. Di sini kami menyertakan file termasuk yang datang dengan fasm. Fasm assembler mendapat jalan termasuk file menurut inf conig file yang datang dalam direktori root download fasm. import32.Inc berisi makro definisi yang memungkinkan kita untuk dengan mudah referensi dan impor fungsi dll.
Dengan kata lain, hal ini memungkinkan kita untuk menggunakan 'Perpustakaan' dan 'import' macro.
Dengan kata lain, hal ini memungkinkan kita untuk menggunakan 'Perpustakaan' dan 'import' macro.
sekarang untuk bagian data kami, pernyataan 4 berarti bahwa bagian ini berisi data bebas-executable yang kita dapat membaca dan menulis ke selama run-time. Di dalam ini Bagian, aku telah menyatakan 2 variabel nama msg dan p, setiap variabel ini berakhir dengan karakter null.
Sekarang untuk bagian dapat dibaca dan eksekusi kode kami. Dimulai dengan entrypoint kami label utama, saya membuat bingkai tumpukan dan mengalokasikan 4 byte pada tumpukan oleh mengurangi 4 dari nilai esp. Sekarang dalam kisaran 4 byte yang ditempatkan Alamat msg di sana dan memanggil printf, selanjutnya saya menempatkan alamat data untuk perintah jeda di wilayah yang sama (Timpa alamat sebelumnya untuk
data msg saya) dan kemudian saya menelepon sistem. Kemudian saya memanggil keluar dengan dword (int)
argumen 0 pada tumpukan. Sekarang ini semua tidak diperlukan, saya hanya ingin menunjukkan kepada Anda Bagaimana bekerja panggilan stack dan dll. Saya pribadi lebih suka metode ini karena benar-benar
menunjukkan apa yang terjadi dan berusaha untuk menghemat ruang memori dengan menggunakan kembali lama blok memori yang telah ditempatkan pada tumpukan. Metode yang lebih mudah berjalan seperti ini:
data msg saya) dan kemudian saya menelepon sistem. Kemudian saya memanggil keluar dengan dword (int)
argumen 0 pada tumpukan. Sekarang ini semua tidak diperlukan, saya hanya ingin menunjukkan kepada Anda Bagaimana bekerja panggilan stack dan dll. Saya pribadi lebih suka metode ini karena benar-benar
menunjukkan apa yang terjadi dan berusaha untuk menghemat ruang memori dengan menggunakan kembali lama blok memori yang telah ditempatkan pada tumpukan. Metode yang lebih mudah berjalan seperti ini:
push msg
call [printf]
push p
call [system]
push 0
call [exit]
Sederhana: saya mendorong argumen, aku memanggil fungsi. Ini mungkin tidak membuat banyak perbedaan dalam aplikasi ini, tetapi dengan menekan setiap saya saya mengurangi 4 dari esp dan dengan demikian memori menangani bisa menambahkan hingga menjadi rumit pada tumpukan. Kecuali jika Anda adalah pengguna l337 seperti saya fine tuning data pada tumpukan, ini bukanlah menyarankan. Jika tidak, bersenang mendorong it...if Anda tahu apa yang saya maksud. Sekarang lain metode sederhana untuk pemula adalah dengan menggunakan 'memanggil' makro yang ditemukan di 'macro/proc32.inc' termasuk file. Ianya seolah-olah Anda menelepon fungsi dari bahasa tingkat tinggi.
invoke printf,msg
memanggil memanggil fungsi. Argumen pertama adalah nama fungsi dan sisanya adalah aruments untuk berfungsi. Penting untuk dicatat adalah bahwa saat memanggil fungsi dll, argumen yang diperlukan harus mendorong balik urutan dari terakhir pertama. Jadi jika saya perlu untuk memanggil printf dengan 2
argumen petunjuk: "nama adalah %s", nama Kemudian aku akan perlu untuk melakukan hal ini:
argumen petunjuk: "nama adalah %s", nama Kemudian aku akan perlu untuk melakukan hal ini:
push name
push msg
call [printf]
Namun, dalam kasus ini menggunakan memohon, makro ini secara otomatis mendorong args dalam urutan terbalik untuk Anda. Jadi Anda dapat menyebutnya biasanya seperti ini:
memanggil printf, msg, nama Untuk benar-benar mengimpor dll sebelum melakukan ini, Anda menyatakan Anda impor di Bagian '.idata'. Saya menggunakan Macro Perpustakaan dan impor. Perpustakaan makro (ditemukan di import32.inc) memungkinkan saya untuk mengimpor specifier nama dll. Dengan masing-masing Pasangan argumen untuk makro Perpustakaan, saya menetapkan nama terkait yang dll dan kemudian nama sebenarnya dari dll itu.
memanggil printf, msg, nama Untuk benar-benar mengimpor dll sebelum melakukan ini, Anda menyatakan Anda impor di Bagian '.idata'. Saya menggunakan Macro Perpustakaan dan impor. Perpustakaan makro (ditemukan di import32.inc) memungkinkan saya untuk mengimpor specifier nama dll. Dengan masing-masing Pasangan argumen untuk makro Perpustakaan, saya menetapkan nama terkait yang dll dan kemudian nama sebenarnya dari dll itu.
Untuk impor, argumen pertama harus nama terkait dll, setelah itu, masing-masing sepasang argumen akan menjadi nama specifier diinginkan untuk fungsi, diikuti dengan nama sebenarnya dari fungsi yang ditemukan di dll. Perhatikan bahwa saya juga digunakan garis miring terbalik untuk memperluas pernyataan satu baris saya pada beberapa baris untuk lebih mudah dibaca.
Nah itu saja untuk tutorial ini, check out contoh-contoh ini 2 32 bit asm dan
mereka setara C kode:
mereka setara C kode:
Name.ASM:
format PE console
entry main
include 'macro/import32.inc'
section '.data' data readable writeable
msg db "Enter your name: ",0
chrarr db "%s",0
msg2 db "Hello %s",0dh,0ah,0
p db "pause",0
section '.code' code readable executable
main:
push ebp
mov ebp,esp
sub esp,24
mov dword [esp],msg
call [printf]
lea eax,[ebp-12]
mov dword [esp+4],eax
mov dword [esp],chrarr
call [scanf]
mov dword [esp],msg2
call [printf]
mov dword [esp],p
call [system]
mov dword [esp],0
call [exit]
section '.idata' import data readable
library msvcrt,'msvcrt.dll'
import msvcrt,\
printf,'printf',\
scanf,'scanf',\
system,'system',\
exit,'exit'
Name.C:
#include "stdio.h"
#include "stdlib.h"
int main() {
char name[12];
printf("Enter your name: ");
scanf("%s",name);
printf("Hello %s\n",name);
system("pause");
return 0;
}
Loop.ASM:
format PE console
entry main
include 'macro/import32.inc'
section '.data' data readable writeable
intl db "%d",0dh,0ah,0
p db "pause>nul",0
section '.code' code readable executable
main:
push ebp
mov ebp,esp
sub esp,12
mov dword [ebp-4],1
loopA:
mov eax,dword [ebp-4]
cmp eax,11
jge BreakA
mov eax,dword [ebp-4]
mov dword [esp+4],eax
mov dword [esp],intl
call [printf]
mov eax,dword [ebp-4]
inc eax
mov dword [ebp-4],eax
jmp loopA
BreakA:
add esp,4
mov dword [esp],p
call [system]
mov dword [esp],0
call [exit]
section '.idata' import data readable
library msvcrt,'msvcrt.dll'
import msvcrt,\
printf,'printf',\
scanf,'scanf',\
system,'system',\
exit,'exit'
Loop.C:
#include "stdio.h"
#include "stdlib.h"
int main() {
int i;
for (i=1;i<11;i++) {
printf("%d\n",i);
}
system("pause>nul");
return 0;
}
Tidak ada komentar:
Posting Komentar