Posts Tagged ‘Assemler’
Ассемблер в Visual C++
Вчитися програмувати на ассемблері важко, бо щоб написати програму яка видає хоч якийсь результат (типу „Привіт світ!”) потрібно дуже багато знати. Ввід і вивід в ассемблері пов’язаний з складними функціями API, викликати які — велика морока. Крім того більшість компіляторів — консольні набори з компілятора, лінкера, дебагера, які потрібно запускати з складними параметрами командного рядка і окремо. Але є набагато простіший спосіб вивчення ассемблера, для таких чайників як і я.
Для цього не потрібно нічого, крім знайомого Visual C++. Можна навіть щось інше, навіть древній Turbo C, але там взаємодія з підпрограмами може бути інша, крім того навчитися програмувати для систем i386, можна тільки в 32 розрядних середовищах. Чим добре Visual C++? Тут не потрібно абсолютно все писати на ассемблері. Ввід і вивід можна здійснювати за допомогою зручних scanf і printf.
Досить вступів, думаю можна перейти до теорії. Часто можна почути слова x86, i386 сумісність. Це слово означає, що програма виконується на даній і всіх наступних архітектурах. Я вже згадував про архітектури до i386. В архітектурі x86 (процесор 8086), були 16 розрядні регістри ax,bx, cx, dx. В 32 розрядній архітектурі i386 їх було розширено, і до імені додали e (extended). Проте старі назви все ще залишились, для досягнення сумісності. Також, можна було отримувати доступ до окремих байтів регістру за допомогою букв h (hi – старший) l (lo – молодший). Загалом до того що міститься скажімо в регістрі eax можна було дістатись за такими іменами: eax,ax,ah,al. Ось маленька схемка:
А тепер краще не покладатись на слова, а перевірити все на практиці. Відкриваємо студію, і створюємо новий консольний проект
#include <stdlib.h> //Підключаємо стандартні бібліотеки #include <stdio.h> unsigned int LoWord(unsigned int a) // Підпрограма написана на ассемблері { _asm // така директива каже компілятору, що після неї іде оператор на ассемблері. { //(або кілька операторів, якщо в дужках. mov eax,a; // Переносимо значення зі змінної а в регістр eax mov ebx,0; // Ініціалізуємо ebx нулем mov bx,ax; // Переносимо значення з ax в bx mov a,ebx; // Тепер записуємо значення ebx назад в а }; return a; // Повертаємо результат функції } unsigned int LoByte(unsigned int a) { _asm { mov ebx,a; mov eax,0; mov al,bl; // Переміщуємо молодщий байт ax в bx } //Тут я забув написати return, але нічого страшного. Результат по замовчуванню береться з eax } int main(void) { unsigned int x; // Можна і зі знаком, але давайте зробимо все простіше scanf("%X",&x); // Вводимо натуральне 32 розрядне число в шіснадцятковій системі printf("\n Lo word (ax): %X\n",LoWord(x)); // і виводимо молодше слово числа printf("\n Lo byte (al): %X\n",LoByte(x)); // і виводимо молодше слово числа system("pause"); // Почекати поки користувач побачить результат return 0; }
Приклад, як для привітання зі світом, трохи заскладний, зате ілюстративний. Використовується шістнадцядкова система, тому для заповнення всіх 32 бітів, потрібно ввести 8 цифр. Програма занесе їх в eax, і виведе вміст ax і al.
От і все. Розберусь більше — напишу більше.