Скачиваний:
64
Добавлен:
15.06.2014
Размер:
123.39 Кб
Скачать

Предисловие

Здесь будут расписаны некоторые общие положения, функции и куски кода одинаковые во всех программах, чтобы не повторяться по сто раз. Так что, если в программе частично отсутствуют комментарии, они с большой долей вероятности будут тут.

Все программы из данного блока, написанные на TASM начинаются со строк:

.modelsmall//модель памяти small (её смысл -код в одном сегменте, а данные и //стек в другом )

.386 //в программе используются команды поддерж. процессором 80386

.stack 256h //указан размер сегмента стека = 1Кб

.data //начало сегмента данных, тут объявляются переменные

Сегмент кода начинается со строк

mov ax, @data

mov ds, ax

Их смысл в том, чтобы поместить начала адреса сегмента данных в регистр ds. А так как напрямую этого сделать нельзя, используется регистр-аккумуляторax.

ASSUME DS:@data, es:@data

Директива ASSUME позволяет турбо ассемблеру проверить допустимость каждого обращения к именованной ячейке памяти с учетом

значения текущего сегментного регистра.

xor регистр, регистр.

Очистка регистра, полезная хуйня.

Для вывода информации на экран используется фнкция 09h. Она выводит строку целиком, пока не встретиться символ конца строки - $.

lea dx, ska ;в dx переменную для вывода

mov ah, 09h ;в ah номер функции

int 21h ; выполнение функции

Для ввода информации используется фнкция 0Ah. Ввод строки символов заканчивается нажатием клавиши Enter.

lea dx, n ; в dx размер вводимой строки

mov ah, 0Ah ; в ah функцию

int 21h

Ещё одна функция вывода информации на экран. Она выводит не всю строку целиком, а заданное число символов.

lea dx, ska ;строка для вывода

mov ah, 40h

mov cx, 1 ; количество символов для вывода начиная с начала

int 21h

Функция завершения программы - 4ch. В конце каждой программы.

mov ah, 4ch

int 21h

Функция 02 выводит цифру или число, после преобразования его в символ (добавление 30h).

add dx,30h

mov ah,02

int 21h

В некоторых задачах функции ввода или вывода вынесены в отдельные процедуры.

input PROC ;процедура для ввода

mov ah, 0Ah

int 21h

ret

input ENDP ;конец процедуры

output PROC ;процедура для вывода

mov ah, 09h

int 21h

ret

output ENDP

Потом, в нужном месте, процедура вызывается командой call. Это позволяет существенно сократить объём кода, когда нужно чтонить вводить или выводить многократно.

Косвенная адресация памяти.

Предположим у нас есть строка outp dbdst$’

Она состоит из трёх элементов плюс символ конца строки. Можно

обратиться ко всей строке сразу, написав где надо outp ,а можно обратиться к каждому элементу по отдельности по порядковым номерам. Например, букваdбудет иметь номер0, букваsномер 1, букваdномер 2. Всё логично.

На практике это выглядит так: outp[0] – обращение к первому символу строки (к букве d), outp[1] – обращение ко второму символу (буквеs), понимаешь да?

Вместо цифр можно использовать регистрыbx,cx,si,di. Задать им начальное значение 0 (mov bx,0илиxor bx,bx) или любое другое. Затем инкрементировать их (inc bx) или декрементировать(dec bx) в зависимости от задачи, и таким образом проходить по строке с конца в начало или из начала в конец. И оформить всё это в виде цикла.

movcx,2

let:

xor di,di

lea dx, outp[di]

inc di

loop let

Процедура из 17 задачи

procedure proc

;cтандартным входом служит следующая группа операторов:

push bp ;сохранить регистр ВР

mov bp, sp ; установить границы стека

mov al, [bp+6]

sub al, 48

mov dl, [bp+8]

sub dl, 48

mul dl

mov [bp+4], al

mov sp, bp ; освободить память, выделенную для локальных переменных

pop bp ;восстановить регистр ВР

ret ; обязательно должно быть написано в конце процедуры

procedure endp

На WinXP не нужен никакой досбокс, поэтому компиляция и запуск осуществляются из командной строки. Пуск-Выполнить-cmd

Предположим, папка с тасмом находится на диске D:\, в папкеTasm.

В командной строке пишем

D:

CD Tasm

Программы пишутся в тестовом файле с расширение *.asm. Чтобы их запустить надо в ту же командную строку прописать три команды:

tasm.exe %имя_файла%.asm

tlink.exe %имя_файла%.obj

%имя_файла%.exe

Последний момент. Задачи с 21 по 25 написаны наVisual Studio 2011, из-за этого в более ранних версиях код может некомпилится. Чтобы всё прошло гладко нужно сначала создать проект, затем удалить все строки, кроме библиотек, начинающихся с#include… и после них вставить мой код, начиная с using namespace std;

1) Найти сумму цифр трёхзначного числа

В основе этой, и некоторых следующих задач лежит принцип деления на 10. После того как число, допустим 123, помещается в регистр ax, оно делится на 10 (десятка изначально находится в cx), его остаток оказывается в регистре dx. 123:10=12,3 (12 остаётся вax, 3- вdx). Далее 12:10=1,2 (1 вax, 2 вdx). Цифры из dx складываются друг с другом в другом регистре, в данном случае, в si. Когда в ax оказывается одна цифра, т.е. операция деления прошла два раза, цифра из ax тоже прибавляется к si. Теперь сумма цифр трёхзначного числа находиться в si. Чтобы вывести её на экран, прибавляем к ней 48 или 30h, записываем её в переменнуюoutpи выводим.

.model small

.386

.stack 256h

.data

;здесь окажется сумма чисел в символьном виде, чтобы вывести её на экран

outp db 3 dup('$')

.code

start:

mov ax, @data

mov ds, ax

mov ax, 999 ;помещаем в ax трёхзначное число

mov cx, 10 ;делитель

xor bx, bx

deep_in:

cmp bx,3

jz exit

inc bx

cwd ; Команда CWD копирует значение старшего бита

; регистра АХ на все биты регистра DX. Без неё нормально не

; поделишь.

div cx ;разделить ax на 10

add si, dx ;поместить в si остаток от деления

jmp deep_in

;-------------------------------------------------

exit:

mov ax, si ;прибавляем последнюю цифру к сумме первых двух

aam ;корректировка

add ah,30h ;преобразование в символьный вид для вывода

add al,30h

mov [outp], ah ;помещаем в переменную

mov [outp+1], al

lea dx,outp ;выводим на экран

mov ah, 09h

int 21h

mov ah, 4ch

int 21h

end start

2) Дано четырёхзначное число. Вывести число, полученное при прочтении его цифр справа налево.

Принцип такой же, как и в первой программе, только мы не складываем цифры, а выводим их сразу на экран – 1234:10 = в ax 123, в dx 4. Тут же прибавляем к dx 30h и выводим. Вот так и получаем на число в обратном порядке.

.model small

.386

.stack 256h

.data

pins dw 1234 ;наше четырёхзначное число

.code

start:

mov ax, @data

mov ds, ax

mov si, pins ;помещаем число в si

mov cx, 10 ;опять же делитель

xor bx, bx

through:

mov ax, si ;теперь помещаем число в ах

cmp bx,4

jz exit

inc bx

cwd

div cx ;делим ax на 10. В итоге частное в ax, остаток в dx.

mov si, ax ;переносим частное в si, чтоб оно не похерилось, т.к. регистр ax будет

;использоваться ниже для других целей

aam

add dx,30h ;прибавляем 30h, чтобы получить пригодный для вывода символ

mov ah,02 ;выводим

int 21h

mov dl,dh

int 21h

jmp through ; повторяем всё заново, пока цифры в числе не закончатся

;-------------------------------------------------

exit:

mov ah, 4ch

int 21h

end start

3) Дано четырёхзначное число. Определить является ли сумма двух его первых цифр сумме двух вторых.

Делим число на 10 два раза, чтобы получить две последние цифры и попутно складываем их в регистре di. Потом делим ещё один раз и складываем две первые в регистре si. В конце программы сравниваем между собой si и di и выводим соответствующее сообщение о равенстве или неравенстве.

.model small

.386

.stack 256h

.data

its dw 1234 ;число

needles db '=$' ; выведется на экран, если равно

and_pins db '!=$' ; выведется, если не равно

.code

start:

mov ax, @data

mov ds, ax

mov ax, its

mov cx, 10

xor bx, bx

xor di,di

venomous: ;обрабатываем последние две цифры

cmp bx,2

jz poison

inc bx

cwd

div cx ;поделили

add di, dx ;сложиди

jmp venomous ; переходим в начало. И так 2 раза.

xor si,si

poison: ;обрабатываем две первые цифры

cmp bx,5

jz thrill

inc bx

cwd

div cx ;поделили

add si, dx ;сложили

jmp poison

thrill:

cmp di, si ;сравниваем результаты

jz cruel

lea dx, and_pins ; если не равны, выводим !=

mov ah, 09h

int 21h

jmp exit

cruel:

lea dx, needles ; если равны, выводим =

mov ah, 09h

int 21h

;-------------------------------------------------

exit:

mov ah, 4ch

int 21h

end start

Соседние файлы в папке asma