12-bo‘lim
Assembler tili
Assembler nima va nima uchun kerak, haqiqiy NASM dasturi, tizim chaqiruvlari, halqa va bayroqlar hamda assemblerni qachon o'qish kerak.
Ushbu bo‘lim mundarijasi
Assembler - mashina kodining odam o'qiy oladigan shakli. Har assembler qatori odatda bitta komandaga to'g'ri keladi.
Bu bo'limda haqiqiy dastur yozamiz - nasm bilan yig'ib,
Linux da ishga tushiramiz.
Birinchi dastur #
section .data
xabar: db "Salom, arxitektura!", 10
uzunlik: equ $ - xabar
section .text
global _start
_start:
; write(1, xabar, uzunlik) tizim chaqiruvi
mov rax, 1 ; chaqiruv raqami: write
mov rdi, 1 ; birinchi argument: stdout
mov rsi, xabar ; ikkinchi argument: matn manzili
mov rdx, uzunlik ; uchinchi argument: uzunlik
syscall
; exit(0)
mov rax, 60 ; chaqiruv raqami: exit
xor rdi, rdi ; qaytish kodi 0
syscall
Uni yig'ib ishga tushirish uchun ikki buyruq yetarli:
nasm -f elf64 salom.asm -o salom.o
ld salom.o -o salom
./salom
Natija:
Salom, arxitektura!
Chiqqan faylning hajmi 10 KB dan kichik - va bu butun dastur: sarlavhasi, kodi va ma'lumoti bilan.
Bu dasturda kutubxona yo'q. printf ham, C ish vaqti
muhiti ham yo'q. Faqat protsessor komandalari va operatsion
tizimga bitta murojaat.
syscall - dastur va yadro chegarasisyscall komandasi boshqaruvni operatsion tizim yadrosiga
o'tkazadi.
Bu "Operatsion tizimlar" darsligining 2-bo'limida batafsil ko'rilgan. Bu yerdagi qism shu:
| Registr | Vazifasi |
|---|---|
rax | Chaqiruv raqami (1 = write, 60 = exit) |
rdi | 1-argument |
rsi | 2-argument |
rdx | 3-argument |
Bu chaqiruv kelishuvi (calling convention) - qaysi argument qaysi registrda kelishi haqidagi shartnoma.
Har operatsion tizim va arxitektura uchun u boshqacha. Shuning uchun assembler dasturi ko'chma emas: Linux uchun yozilgani Windows da ishlamaydi, garchi protsessor bir xil bo'lsa ham.
Dasturdagi belgilarni o'qib chiqamiz:
| Element | Ma'nosi |
|---|---|
section .data | O'zgaruvchilar bo'limi |
section .text | Kod bo'limi |
db | define byte - baytlar e'lon qilish |
equ | Doimiy e'lon qilish |
$ | Joriy manzil |
$ - xabar | Joriy manzil ayirib - ya'ni uzunlik |
_start: | Nishon (label) - manzilga nom berish |
; | Izoh |
global _start | Bu nomni bog'lovchiga ko'rsatish |
Halqa va bayroqlar #
Endi 10-bo'limdagi halqani haqiqiy protsessorda quramiz:
section .text
global _start
_start:
mov rax, 0 ; yig'indi
mov rcx, 10 ; hisoblagich
halqa:
add rax, rcx ; yig'indi += hisoblagich
dec rcx ; hisoblagich--
jnz halqa ; nol bo'lmasa - halqaga qayt
mov rdi, rax ; natijani qaytish kodiga
mov rax, 60 ; exit
syscall
Bu dastur 1 dan 10 gacha sonlarni qo'shadi. Ishga tushirib, qaytish kodini so'rasak:
nasm -f elf64 halqa.asm -o halqa.o && ld halqa.o -o halqa
./halqa; echo $?
Chiqadi: 55 - aynan 1+2+...+10.
Butun halqa uch komanda. Diqqat qiling: dec komandasi
bayroq qo'yadi, jnz esa shu bayroqqa qaraydi - ular
alohida komandalar.
Bu 9 va 10-bo'limlarda qurgan modelimizning haqiqiy temirda tasdiqlanishi.
Yuqoridagi misolda natija 55 edi va u qaytish kodiga sig'di.
Lekin qaytish kodi bitta bayt. 1 dan 100 gacha yig'indi
(5050) qaytarilsa, siz 5050 & 0xFF = 186 ni ko'rasiz.
Bu 3-bo'limdagi aylanib ketishning aynan o'zi.
Shuning uchun haqiqiy dasturlar natijani qaytish kodi bilan emas, chiqish oqimi orqali beradi. Qaytish kodi faqat "muvaffaqiyatlimi" degan savol uchun.
Assemblerni qachon yozish kerak? #
Rostini aytganda - deyarli hech qachon.
| Vazifa | Assembler kerakmi |
|---|---|
| Oddiy dastur | Yo'q |
| Tezlikni oshirish | Deyarli har doim yo'q - kompilyator yaxshiroq |
| Yadro va yuklovchi | Ha, kichik qismlarda |
| Drayverlar | Ba'zan |
| Kriptografiya | Ba'zan - vaqt bo'yicha barqarorlik uchun |
| SIMD optimallashtirish | Ko'pincha ichki funksiyalar yetarli |
Zamonaviy kompilyator registrlarni taqsimlash, komandalarni qayta tartiblash va konveyerni hisobga olishda odamdan ancha yaxshi.
Assembler yozish kamdan-kam kerak bo'ladi. Lekin uni o'qish juda foydali:
| Qachon | Nima beradi |
|---|---|
| Nosozlik qidirishda | Xato aynan qayerda ekanini ko'rasiz |
| Profillashda | Qaysi qator qimmatga tushayotganini bilasiz |
| Kompilyatorni tekshirishda | Optimallashtirish ishladimi yoki yo'q |
| Xavfsizlik tahlilida | Kod haqiqatan nima qilayotganini |
godbolt.org (Compiler Explorer) sayti aynan shu uchun
mashhur: yozgan kodingiz qaysi komandalarga aylanishini
darhol ko'rsatadi.
19-bo'limda biz ham xuddi shunday qilamiz - C kodini assemblerga aylantirib, natijani o'qiymiz.
Yuqori darajali tillarda massiv chegarasidan chiqsangiz, xato olasiz. Assemblerda esa hech qanday tekshiruv yo'q.
| Nima qilsangiz | Nima bo'ladi |
|---|---|
| Chegaradan tashqariga yozish | Boshqa ma'lumot buziladi |
| Noto'g'ri manzilni o'qish | Axlat qiymat yoki qulash |
| Stekni buzish | Dastur boshqa joyga sakraydi |
Uchinchisi - stekni to'ldirish hujumining asosi: agar dastur foydalanuvchi bergan ma'lumotni tekshirmasdan stekka yozsa, hujumchi qaytish manzilini almashtirib qo'yishi mumkin.
Himoya choralari 1-bo'limda aytilgan edi: NX, ASLR va stek kanareykalari. Bu mavzu "Kiberxavfsizlik asoslari" darsligida batafsil ko'rilgan.
Bu yerdagi xulosa: assembler hech narsani kechirmaydi. Shuning uchun uni faqat zarur bo'lganda va juda ehtiyot bilan yozing.
- Birinchi dasturni ishga tushiring.
- Xabar matnini o'zgartiring va uzunlik avtomatik moslashishini ko'ring.
exitkodini 42 ga o'zgartiring vaecho $?bilan tekshiring.- Halqa misolini ishga tushiring.
- Halqani 1 dan 100 gacha qiling - natija nima uchun 5050 emas?
deco'rnigasub rcx, 1yozing - natija o'zgardimi?jnznijzga almashtiring va nima bo'lishini oldindan ayting.- Ikki sonni ko'paytiradigan dastur yozing.
objdump -dbilan o'z dasturingizni disassembler qiling.- Assemblerni qachon yozish kerakligi haqida uch qator yozing.
Xulosa #
- Assembler - mashina kodining odam o'qiy oladigan shakli.
- Har qator odatda bitta komandaga to'g'ri keladi.
nasmyig'adi,ldbog'laydi - natijada bajariluvchi fayl chiqadi.syscallboshqaruvni yadroga o'tkazadi; argumentlar registrlarda uzatiladi.- Chaqiruv kelishuvi har OT va arxitektura uchun boshqacha.
- Shuning uchun assembler dasturi ko'chma emas.
- Halqa uch komandadan iborat: ish, kamaytirish, shartli o'tish.
decbayroq qo'yadi,jnzshu bayroqqa qaraydi - ular alohida komandalar.- Qaytish kodi bitta bayt - katta natija aylanib ketadi.
- Assembler yozish kamdan-kam kerak, lekin uni o'qish juda foydali.
Keyingi bo'limda o'z virtual protsessorimizni quramiz - komandalar to'plami, bajaruvchi va dasturlar bilan.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.