| |
BIGLIB |
| большущая библиотека (9812 книг), можно не только прочитать но и скачать бесплатно |
|
| |
ФАНТАСТИКА |
| фентези,
фантастика, фантастические повести |
|
| |
ФИЛОСОФИЯ |
книги, которые заставляют
задуматься над окружающим тебя миром.
|
|
| |
МЕДИЦИНА |
медицинские книги,
методички,
народные лечебники |
|
| |
КУЛИНАРИЯ |
рецепты
тортов, консервирование,
все о спиртных
напитках. |
|
| |
СТИХИ |
| стихи популярных
и не очень авторов |
|
| |
ТВОРЧЕСТВО |
| народное творчество,
стихи, песни и т.д. |
|
| |
ЮМОР |
| анекдоты, приколы,
смешные истории |
|
| |
ЭРОТИКА |
| эротические рассказы,
книги о технике секса,
кама-сутра и др. |
|
|
| |
 |
; Ввод:
; char far * StringToCount: указатель на "строку", в
; которой нужно выполнить подсчет строк.
Турбо Ассемблер 3.0/tasm/#2-2 = 106 =
;
; unsigned int far * CharacterCountPtr: указатель на
; целочисленную переменную, в которую нужно записать
; значение счетчика
NEWLINE EQU 0ah ; символ перевода строки в Си
.MODEL LARGE
.CODE
PUBLIC _LinaCount
_LineCount PROC
push bp
mov bp,sp
push si ; сохранить регистровую
; переменную вызывающей
; программы
push ds ; сохранить стандартный
; сегмент данных
lds si,[bp+6] ; DS:SI указывает на строку
sub cx,cx ; установить значение
; счетчика символов в 0
mov dx,cx ; установить в 0 счетчик
; строк
LineCountLoop:
lodsb ; получить следующий символ
and al,al ; это 0? конец строки?
jz EndLineCount ; да, выполнено
inc cx ; нет, подсчитать следующий
; символ
cmp al,NEWLINE ; это новая строка?
jnz LineCountLoop ; нет, проверить
; следующий символ
inc dx ; да, подсчитать еще одну
; строку
jmp LineCountLoop
EndLineCount:
inc dx ; подсчитать строку, которая
; завершается нулевым символом
les bx,[bp+10] ; ES:BX указывает на ячейку,
; в которой возвращается
; значение счетчика
mov es:[bx],cx ; задать значение переменной-
; счетчика
mov ax,dx ; возвратить счетчик строк в
; качестве значения счетчика
pop ds ; восстановить стандартный
; сегмент данных Си
pop si ; восстановить регистровую
; переменную вызывающей
; программы
pop bp
ret
_LineCount ENDP
END
Турбо Ассемблер 3.0/tasm/#2-2 = 107 =
Программу COUNTLG.ASM можно скомпоновать с CALLCT.CPP с по-
мощью следующей командной строки:
bcc -ml callct.cpp countlg.asm
Турбо Ассемблер 3.0/tasm/#2-2 = 108 =
Написание на языке Ассемблера функций-элементов С++
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Хотя можно написать функцию-элемент класса С++ целиком на
языке Ассемблера, это далеко не просто. Например, все функ-
ции-элементы классов С++ имеют "откорректированные" имена, что
обеспечивает безопасную по согласованности типов компоновку функ-
ций и делает возможным переопределение функций, а ваша ассемблер-
ная функция должна знать в точности, какое имя С++ ожидает для
данной функции-элемента. Для доступа к переменным-элементам вы
должны подготовить в ассемблерном коде определение STRUC, опреде-
ляющее все переменные-элементы с точно совпадающими размерами и
расположением. Если ваш класс является производным, то могут су-
ществовать и другие переменные-элементы, производные от базового
класса. Даже если класс не является производным (порожденным), то
расположение переменных-элементов в памяти изменяется в случае,
если класс этот включает в себя какие-либо виртуальные функции.
Если вы пишете функцию на встроенном Ассемблере, Borland С++
может взять на себя эти вопросы. Однако если вы работаете на язы-
ке Ассемблера отдельно (например, переделываете уже имеющийся
код), то существуют некоторые методы, позволяющие упростить эту
работу.
Создайте определение фиктивной функции С++ для ассемблерной
функции. Это определение удовлетворит компоновщик, так как будет
содержать откорректированное имя функции-элемента. Эта фиктивная
функция будет вызывать ассемблерную функцию и передавать ей пере-
менные-элементы и прочие параметры. Так как ассемблерный код бу-
дет иметь все нужные ему параметры посредством аргументов, вы мо-
жете не заботиться об изменениях в определении класса. Ваша
ассемблерная функция может быть описана в коде С++ как extern
"C", что показано в примерах. Например (countadd.cpp):
class count_add {
// Частные переменные-элементы (private)
int access_count; // число обращений
int count; // текущий счетчик
public:
count_add(void) { access_count=0;
count=0;
}
int get_count (void) {return Count;}
// Две функции, которые будут фактически написаны на
// Ассемблере:
void increment(void);
void add(int what_to_add=-1);
// Отметим, что умолчание влияет только
// на вызовы add; оно не влияет на код add
}
Турбо Ассемблер 3.0/tasm/#2-2 = 109 =
extern "C" {
// Для создания уникальных и осмысленных имен
// ассемблерных подпрограмм прибавим имя класса к
// имени ассемблерной подпрограммы. В отличие от прочих
// ассемблеров, Турбо Ассемблер не имеет проблем с
// длиной имен.
void count_add_increment(int *count); // Мы передадим
// указатель на
// переменную count.
// Ассемблер выполнит
// увеличение.
void count_add_add(int *count,int what_to_add);
}
void count_add::increment(void)
{
count_add_increment(&count);
}
void count_add(int what_to_add)
{
count_add(&count, int what_to_add);
}
Ваш ассемблерный модуль, определяющий подпрограммы count_add
_increment и count_add_add, должен иметь вид (COUNTADD.ASM):
.MODEL small ; выбор модели small (ближние код и данные)
.CODE
PUBLIC _count_add_increment
_count_add_increment PROC
ARG count_offset:word ; Адрес переменной-элемента
push bp ; Сохранение записи активации
; вызывающей программы
mov bp,sp ; Установка собственной записи
; активации
mov bx,[count_offset] ; Загрузка указателя
inc word ptr [bx] ; Увеличение переменной-элемента
pop bp ; Восстановление записи активации
; вызывающей программы
_count_add_increment ENDP
PUBLIC _count_add_add
_count_add_add PROC
ARG count_offset:word,what_to_add:word
push bp
mov bp,sp
mov bx,[count_offset] ; Загрузка указателя
mov ax,[what_to_add]
add [bx],ax
pop bp
ret
_count_add_add ENDP
Турбо Ассемблер 3.0/tasm/#2-2 = 110 =
end
Используя данный метод, вы можете не беспокоиться об измене-
ниях в определении класса. Даже если вы добавляете или удаляете
переменные-элементы, делаете этот класс производным или добавляе-
те виртуальные функции, вам не требуется изменять ассемблерный
модуль. Переассемблировать модуль нужно только в случае изменения
структуры переменной-элемента count, либо если вы ходите сделать
версию данного класса для модели памяти large. Переассемблирова-
ние в этих случаях необходимо, поскольку при обращении к перемен-
ной-элементу count вы имеете дело с сегментом и смещением.
Соглашения по вызовам, использующиеся в Паскале
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Итак, теперь вы уже знаете, как обычно в С++ передаются па-
|
adfun.ru
|
|
|
|