- •7. Упрощенные директивы определения сегментов.
- •8. Организация и использование стека.
- •10. Организация обслуживания прерываний. Типы прерываний. Таблица векторов прерываний.
- •11. Подпрограммы. Передача параметров. Ближние и дальние процедуры.
- •15. Организация циклов, условных и безусловных переходов
- •17. Обработчики прерываний и резидентные программы.
- •19. Интерфейс модулей, написанных на языке ассемблера с модулями, написанными на языке с.
19. Интерфейс модулей, написанных на языке ассемблера с модулями, написанными на языке с.
Команды ассемблера в тексте программы на C без изменения вкл. в формируемый компилятором код. Для встроенного ассемблера разр. использовать: - машинные команды; строковые команды; - все инструкции передач управления с прямой или косвенной адресацией; - директивы описания и определения данных. Нельзя исп. директивы, управляющие его работой: ASSUME,SEGMENT,ENDS,PROC,ENDP,ORG и т.д. а также имя группы DGROUP, имена сегментов _TEXT,_STACK,_DATA и т.п. Можно ссылаться на описанные в С переменные. Группа инструкций, заключенная в фигурные скобки, не требует повторения перед каждой из них ключевого слова “asm”.
#include <iostream.h>
#progme inline
asm v1 dw 10
asm v2 dw 90
void main(void)
{unsigned i;
again:
asm {mov ax,v2
add ax,v1
push ax
mov i,ax
}
printf(“i=%d”,i);
if(i>190)
asm jmp _end_
else if (i==150)
asm {
mov ah,2
mov dl,7
int 21h
}
asm {
pop ax
mov v2,ax
jmp again
}
_end_:
puts(“конец проги”);
}
20. Вызов из программы, написанной на языке С , процедур, написанных на ассемблере.
Общая схема: 1) Процедуры на asm и C объединяются совместно, используя файл-проект. В этом случае перечисляются C функции и имена объектных модулей, написанных на asm после трансляции их с помощью TASM. 2) Компиляция из командной строки: а) выполнить трансляцию модуля на С; б) выполнить трансляцию модуля на ассемблере; в) выполнить объединение объектных модулей. ASM процедура должна удовлетворять ниже перечисленным требованиям: - гарантировать получение необходимой информации редактором связей; - обеспечить получ. значений аргументов, переданных ей при вызове, и видимость всех внешних переменных; - должно собл. соотв. моделей памяти, используемых при компиляции C-функции и при обработке asm процедур. В этой связи ассемблерная процедура должна: а) использовать правило именования сегментов, принятое в С; б) явно описывать все глобальные и внешние идентификаторы; в) поддерживать принятую в С посл. передачи аргументов и возврата значений в точку вызова. Все внешние переменные, на которые ссылается ассемблерная процедура. и описанные в С-функциях как внешние, должны объявляться в asm блоке явно с исп. директивы extrn имя_переменной: тип. Если имеются переменные, описанные в ассемблерном модуле, значения которых исп. в С функции. то они в asm модуле объявляются с атрибутом public.
C_asm.cpp
extern void asm f1(int *i1,int *i2,unsigned long l);
void main (void)
{int i=5,j=7;
unsigned long l=0x12345678;
asm_f1(&I,&j,l);
printf(“i=%d,j=%d,l=%lx/n”,i,j,l); }
Вызов процедуры аsm
.model small .code
public asm_f1
asm_f1 PROC near
push bp
mov bp,sp
push si,di
mov si,[bp+4]
mov di,[bp+6]
mov bx,[bp+8]
mov ax,[bp+10]
mov cx,[si]
xchg cx,[di]
mov [si],cx
pop di si
pop bp
ret
asm_f1 endp
end
21. Вызов из ассемблерной программы функций на языке С.
Для каждой прогаммы нужно указать, какие переменные она передаёт в другой модуль и какие переменные она получает из другого модуля.
Фкнкция С++ должна быть описанна в асм. после дерективы EXTERN.
Описание глобальных переменных происходит следующим образом:
-если она обявлена в асм., то должна иметь атрибут PUBLIC а в С++ - EXTERN
-если она обявлена в С++ как внешняя, тогда в асм. она должна иметь атрибут EXTERN
Если функция на С++ возрващает 16-битное значение(char,short,int,enum) то оно будет помещенов регистр АХ, если 32-битное(long) - то DX:AX причём старшая часть в DX
22. Использование встроенного ассемблера.
Необходимо задать дерективу #pragma inline
Асм. команду записывают в виде asm код_операции операнды (;) или (новая строка)
код_операции - (mov,xor...) Если необходимо задать много асм. команд, то они заключаются в фигурные скобки.
Коментарии ожно записывать только в форме, принятой в языке С++.
21. Транспонирование матрицы заданной в кодовом сегменте.
.model small
.stack 100h
.code
start:
jmp continue ; оставить место для матрицы
razmer equ 4
matrix dw 1,2,3,4
dw 5,6,7,8
dw 9,10,11,12
dw 13,14,15,16
continue:
push cs
pop ds ; направляем ds на сегмент кода
mov si,2 ; si - указывает на matrix[0][1]
mov bx,razmer ; в bx - размер матрицы
shl bx,1 ; bx=bx*2, то есть bx указывает на matrix[1][0]
mov ax,bx ; в ax - смещение, равное длине строки
mov cx,razmer ; в cx - razmer
dec cx ; количество перестановок на 1 меньше, чем размер матрицы
loop1: ; внешний цикл по строкам
push cx ; сохранить cx в стеке
loop2: ; внутренний цикл по столбцам (выше главной диагонали)
mov dx,matrix[bx] ; в dx - элемент ниже диагонали
mov di,matrix[si] ; в di - элемент выше диагонали
mov matrix[bx],di ; переставляем их
mov matrix[si],dx
add si,2 ; смещаемся вправо
add bx,ax ; смещаемся вниз
loop loop2 ; цикл повторяется cx раз
pop cx ; восстанавливаем сохраненное cx
push ax ; сохраняем в стеке длину строки
mov ax,razmer ; вычисляем, на сколько сместиться, чтобы оказаться
sub ax,cx ; главной диагональю
inc ax
shl ax,1
add si,ax ; смещаемся на matrix[i][i+1], i - номер очередного ци
mov bx,si ; уставнавливаем bx на si
pop ax ; восстанавливаем длину строки
add bx,ax ; смещаем bx на строку вниз
sub bx,2 ; и на 1 элемент назад
loop loop1 ; цикл, пока cx != 0
mov ah,4ch
int 21h
end start
22. Ввод символа. Определить его позицию в строке и вывести на экран
.model small
.stack 100h
.data
stroka db 80 dup(?),'$'
symb db ?,' ','$' ; можно и не выделять память для символа
msg_in db 0ah,0dh,"Vvedite simvol:",0ah,0dh,"$"
msg db 0ah,0dh,"Simvol ","$"
msg1 db "nayden! Ego index - ","$"
msg_err db "ne nayden.","$"
c10 dw 10
.code
start:
mov ax,@data
mov ds,ax
xor bx,bx ; в bx - индекс вводимого символа
input_loop:
mov ah,01h ; считываем символ
int 21h
cmp al,13 ; если это enter
je for_find ; то конец ввода
mov stroka[bx],al ; иначе записываем символ в строку
cmp bx,80 ; если ввели 80 символов
je for_find ; то конец ввода
inc bx ; увеличиваем bx
jmp input_loop
for_find:
lea dx,msg_in ; вывод msg_in
mov ah,09h
int 21h
mov ah,01h ; ввод нужного символа
int 21h
mov byte ptr symb,al ; сохраняем его в symb ( можно использовать любой из свободных регистров, если хошь)
mov cx,bx ; в cx - длина строки
xor bx,bx ; bx - индекс элемента
mov ah,byte ptr symb ; в ah - нужный символ
find:
cmp ah,stroka[bx] ; сравниваем текущий элемент с нужным симв
je found ; если совпадают, то jmp на found
inc bx ; переход к следующему элементу
loop find ; цикл повторяется cx раз
lea dx,msg ; если символ не найден, то
mov ah,09h ; вывод msg
int 21h
lea dx,symb ; вывод самого символа
int 21h
lea dx,msg_err ; вывод msg_err
int 21h
jmp end_program ; завершить программу
found: ; если найден символ
lea dx,msg ; вывод msg
mov ah,09h
int 21h
lea dx,symb ; вывод самого символа
int 21h
lea dx,msg1 ; вывод msg1
int 21h
mov ax,bx ; сохраняем индекс в ax
xor cx,cx ; cx - счетчик цифр
number_to_string:
xor dx,dx ; подготовка к делению
div c10 ; деление
add dx,30h ; в dx - ASCII-код остатка от деления
push dx ; сохраняем его в стеке
inc cx ; инкремент счетчика цифр
cmp ax,0 ; цикл, пока частное ненулевое
jne number_to_string
out_index_loop: ; цикл вывода индекса
pop dx ; извелекаем очередную цифру
mov ah,02h ; выводим ее на экран
int 21h
loop out_index_loop
end_program:
mov ah,4ch
int 21h
end start
25.Ввод с клавиатуры и умножение длинных чисел
.model small
.stack 100h
.data
num1 dd 0
num2 dd 0
proizv dd 0,0
msg1 db 0ah,0dh,"Vvedite pervoe chislo:",0ah,0dh,"$"
msg2 db 0ah,0dh,"Vvedite vtoroe chislo:",0ah,0dh,"$"
c10 dw 10
.code
start:
mov ax,@data
mov ds,ax
lea dx,msg1 ; вывод на экран msg1
mov ah,09h
int 21h
call input ; ввод первого числа
lea bx,num1 ; записываем введенное длинное число в num1:
mov word ptr[bx],si ; младшее слово
mov word ptr[bx+2],di ; старшее слово
lea dx,msg2 ; вывод на экран msg2
mov ah,09h
int 21h
call input ; ввод второго числа
lea bx,num2 ; записываем введенное длинное число
mov word ptr[bx],si
mov word ptr[bx+2],di
mov ax,word ptr num1 ; перемножение чисел (смотри конспект)
mul word ptr num2
mov word ptr proizv,ax
mov word ptr proizv+2,dx
mov ax,word ptr num1
mul word ptr num2+2
add word ptr proizv+2,ax
adc word ptr proizv+4,dx
mov ax,word ptr num1+2
mul word ptr num2
add word ptr proizv+2,ax
adc word ptr proizv+4,dx
mov ax,word ptr num1+2
mul word ptr num2+2
add word ptr proizv+4,ax
adc word ptr proizv+6,dx
mov ah,4ch
int 21h
input proc ; процедура ввода длинного числа
xor si,si ; возвращает число в di:si
xor di,di
loop1:
mov ah,01h
int 21h
cmp al,13
je end_input
sub al,30h
xor bx,bx
mov bl,al
mov ax,di
mul c10
mov di,ax
mov ax,si
mul c10
add ax,bx
adc dx,di
mov di,dx
mov si,ax
jmp loop1
end_input:
ret
input endp
end start
26. Обработка переполнения при делении чисел. Числа ввести с клавиатуры
Используя команды DIV и особенно IDIV, очень просто вызвать
пеpеполнение. Прерывания приводят (по крайней мара в системе, используемой
при тестировании этих программ) к непредсказуемым результатам. В операциях
деления предполагается, что частное значительно меньше, чем делимое.
Деление на ноль всегда вызывает прерывание. Но деление на 1 генерирует
частное, которое равно делимому, что может также легко вызвать прерывание.
Рекомендуется использовать следующее правило: если делитель - байт,
то его значение должно быть меньше, чем левый байт (AH) делителя: если
делитель - слово, то его значение должно быть меньше, чем левое слово (DX)
делителя. Проиллюстрируем данное правило для делителя, равного 1:
Операция деления: Делимое Делитель Частное
Слово на байт: 0123 01 (1)23
Двойное слово на слово: 0001 4026 0001 (1)4026
В обоих случаях частное превышает возможный размер. Для того чтобы
избежать подобных ситуаций, полезно вставлять перед командами DIV и IDIV
соответствующую проверку. В первом из следующих примеpов предположим, что
DIVBYTE - однобайтовый делитель, а делимое находится уже в регистре AX. Во
втором примере предположим, что DIVWORD - двухбайтовый делитель, а делимое
находится в регистровой паре DX:AX.
Слово на байт Двойное слово на байт
CMP AH,DIVBYTE CMP DX,DIVWORD
JNB переполнение JNB переполнение
DIV DIVBYTE DIV DIVWORD
Для команды IDIV данная логика должна учитывать тот факт, что либо
делимое, либо делитель могут быть отрицательными, а так как сравниваются
абсолютные значения, то необходимо использовать команду NEG для временного
перевода отрицательного значения в положительное.
27. Дана строка в сегменте кода. Отсортировать методом выборки
.model small
.stack 100h
.code
start:
jmp continue
stroka db 254, 0 dup(255)
continue:
push cs
pop ds ; направляем ds на сегмент кода
mov bx,2
xor dx, dx
mov ah, 0Ah
int 21h
mov ah, 0dh
xor di,di
loop1:
mov al,stroka[bx]
cmp ah,stroka[bx+1] ; проверка, конец строки или нет
je end_program
mov si,bx
inc si
loop2: ; поиск
cmp ah,stroka[si]
je end_loop1
cmp al,stroka[si]
jna next_iter ; поиск
mov al,stroka[si] ; минимального
mov di,si ; элемента
next_iter:
inc si
jmp loop2
end_loop1:
mov dh,stroka[bx] ;перестановка
mov stroka[bx],al ;
mov stroka[di],dh
inc bx
jmp loop1
end_program:
mov ah,09h
lea dx,stroka
int 21h
mov ah,4ch
int 21h
end start
28 Транспонировать битовую матрицу использую операторы сдвига.
.model small
.stack 100h
.data
mes1 db 10,13,"Vvedite elementy matricy(8 elem)!!$"
mes2 db 10,13,"$"
mas db 8 dup(0)
mas_tr db 8 dup(0)
.code
begin:
mov ax,@data ;перемещаем сегмент данных в ах
mov ds,ax ;перемещаем сегмент данных в dx
lea dx,mes1 ;в dx адрес mes1
mov ah,9h ;вывод строкм mas1
int 21h
xor bx,bx
mov cx,8
again: ;ввод массива
mov ah,1
int 21h
sub al,'0'
mov mas[bx],al
inc bx
loop again ;повторение цикла again, пока сх не = 0
lea dx,mes2 ;адрес mes2 в dX
mov ah,9
int 21h
mov cx,8
xor bx,bx
xor dh,dh
output: ; вывод матрицы
mov dl,mas[bx]
add dx,30h
mov ah,2
int 21h
inc bx
loop output
mov cx,8
lea di,mas_tr
repeat: ;транспонирование
push cx
mov cx,8
lea si,mas
rep1:
rol BYTE PTR[si],1
rcl al,1
inc si
loop rep1
pop cx
mov [di],al
inc di
loop repeat
exit:
mov ah,4с00h
int 21h end begin
29. В сегменте данных дана матрица. Отсортировать ее побочную дигональ
.model small
.stack 100h
.data
razmer equ 4
matrix dw 1,2,3,13
dw 5,6,10,8
dw 9,7,11,12
dw 4,14,15,16
.code
start:
mov ax,@data
mov ds,ax
mov cx,razmer
dec cx
mov bx,cx
shl bx,1 ; bx - смещение (длина строки -2)
loop1:
mov si,bx
push cx
loop2:
mov dx,matrix[si] ;
mov di,matrix[si][bx] ; перестановка
cmp dx,di ;
jl cont_loop2
mov matrix[si],di
mov matrix[si][bx],dx
cont_loop2:
add si,bx ;
loop loop2 ; смещение на следующую строку
pop cx ;
loop loop1
lea dx,matrix
mov ah,4ch
int 21h
end start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Отсортировать элементы главной диагонали матрицы.
;
; 18.06.04
;
.model small
.stack 300h
.data
N equ 4 ; РАЗМЕР МАТРИЦЫ
THE_MATRIX db 'C', '1', '1', '1'
db '2', 'B', '2', '2'
db '3', '3', 'A', '3'
db '4', '4', '4', 'W','$'
str1 db 0dh,0ah,'$'
str2 db ' $'
.code
program:
mov ax, @data
mov ds, ax
mov cx, N
mov si, offset THE_MATRIX
push cx
mov cx, N
dec cx
;;;обычная сортировка пузырьком
sort_loop:
mov bx, si
add bx, N
inc bx
push cx
cmp_loop:
mov al, [si]
cmp al, [bx]
jna cont
mov dl, byte ptr [bx]
mov byte ptr [bx], al
mov byte ptr [si], dl
cont:
add bx, N
inc bx
loop cmp_loop
pop cx
add si, N
inc si
loop sort_loop
;;; Вывод матрицы
lea si,THE_MATRIX
mov cx,0
w3:
push cx
mov cx,0
w1:
mov ah,2
mov dx,[si]
int 21h
mov ah,9
lea dx,str2
int 21h
inc cx
cmp cx, n
je w2
inc si
jmp w1
w2:
mov ah,9
lea dx,str1
int 21h
inc si
pop cx
inc cx
cmp cl,n
jne w3
exit:
mov ax, 4c00h
int 21h
end program
30. Найти сумму элементов четных строк матрицы.
.model small
.stack 100h
.data
mes1 db 10,13,"Vvedite elementy matricy(5*4)!!$"
mes3 db 10,13,"Suuma 4etnyx strok(5*4):$",10,13
mes2 db 10,13,"$"
mas db 20 dup(0)
sum dw 5 dup(0)
.code
begin:
mov ax,@data
mov ds,ax
lea dx,mes1
mov ah,9h
int 21h
xor bx,bx
mov cx,20
again:
mov ah,1
int 21h
sub al,'0'
mov mas[bx],al
inc bx
loop again
lea dx,mes2
mov ah,9
int 21h
mov cx,20
xor bx,bx
xor dh,dh
output:
mov dl,mas[bx]
add dx,30h
mov ah,2
int 21h
inc bx
loop output
xor cx,cx
mov cl, 4 ;4islo strok
lea bx,mas ;adres matricy
add bx,4 ;perexod na 4etnuju str
mov si,0
p2: push cx
mov di,0
xor dx,dx ; dlja xranenija summy
mov cx,4 ; kol-vo stolbcov
p1:
mov al,[bx+di]
cbw
add dx,ax
inc di
loop p1
mov sum[si],dx
add si,2
add bx,8 ;na sled 4etnuju stroku
pop cx
dec cx
loop p2
xor dx,dx
lea dx,mes3
mov ah,9
int 21h
mov dx,sum[0]
add dx,30h
mov ah,09h
int 21h
mov dx,sum[2]
add dx,30h
mov ah,09h
int 21h
exit:
mov ah,4ch
int 21h
end begin
31 Ввести массив чисел, найти min и max, вывести на экран
.model small
.stack 100h
.data
massiv dw 80 dup(?)
msg1 db 0ah,0dh,"Vvodite chisla ",0ah,0dh,"$"
msg2 db 0ah,0dh,"max = $"
msg3 db 0ah,0dh,"min = $"
c10 dw 10
.code
start:
mov ax,@data
mov ds,ax
mov ah,09h ; вывод приглашения для ввода чисел
lea dx,msg1
int 21h
mov di,0 ; в di - max
mov si,32767 ; в si - min
xor dx,dx ; в dx - очередное число
input_loop:
mov ah,01h ; ввод символа
int 21h
cmp al,0dh ; если enter
je chislo ; то занести число в массив
cmp al,20h ; если пробел
je chislo ; то занести число в массив
sub al,30h ; вычитаем '0'
mov cl,al ; сохраняем цифру в cl
mov ax,dx ; в ax - введенное число
mul c10 ; умножаем на 10
xor ch,ch
add ax,cx ; добавляем цифру из al
mov dx,ax ; число снова в dx
jmp input_loop
chislo:
mov bx,cx ; в bx - порядковый номер очередного числа
shl bx,1 ; теперь - смещение очередного числа в массиве
mov massiv[bx],dx ; записываем в массив число
inc cx ; увеличиваем счетчик введенных чисел
cmp dx,si ; сравниваем число с минимальным
jb minimum ; если оно меньше, то jmp на minimum
cmp dx,di ; сравниваем число с максиальным
jg maximum ; если оно больше, то jmp на maximum
jmp chislo_cont ; иначе jmp на chislo_cont
minimum:
mov si,dx ; запоминаем минимальное число в si
jmp chislo_cont
maximum:
mov di,dx ; запоминаем максимальное число в di
chislo_cont:
xor dx,dx ; dx в ноль
cmp cx,80 ; если ввели 80-ое число
je end_input ; то конец ввода
cmp al,0dh ; если был нажат enter
je end_input ; то конец ввода
jmp input_loop
end_input:
mov ah,09h ; вывод на экран msg2
lea dx,msg2
int 21h
mov ax,di ; передаем в функцию output max через ax
call output ; выводим это число
lea dx,msg3 ; вывод на экран msg3
mov ah,9
int 21h
mov ax,si ; передаем в ouptput min через ax
call output ; выводим это число
mov ah,4ch ; завершение программы
int 21h
output proc ; процедура вывода числа, находящегосы в ax
xor cx,cx ; счетчик цифр
div_loop:
xor dx,dx ; подготовка к делению
div c10 ; деление
add dx,30h ; в dx - ASCII-код остатка от деления
push dx ; сохраняем его в стеке
inc cx ; инкремент счетчика
cmp ax,0 ; деление, покуда частное не нулевое
je out_loop
jmp div_loop
out_loop: ; цикл вывода числа
pop dx ; извлекаем из стека очередной остаток
mov ah,02h ; и выводим его на экран
int 21h
loop out_loop ; цикл продолжается cx раз
ret
output endp
end start
32. В сегменте данных расположены числа в формате двойного слова. С клавиатуры вводится число и определяется, имеется ли это число в сегменте данных.
.model small
.stack 100h
.data
massiv dd 12345678,13579246,24681357
chislo dd 0
c10 dw 10
str1 db 0ah,0dh,"Vvedite chislo:",0ah,0dh,'$'
str2 db 0ah,0dh,"Vvedennoe chislo ne naydeno.",0ah,0dh,'$'
str3 db 0ah,0dh,"Vvedennoe vami chislo naydeno!",'$'
.code
.386
start:
mov ax,@data
mov ds,ax
mov ah,09h
lea dx,str1
int 21h
input_loop:
mov ah,01h
int 21h
cmp al,0dh
je end_input
sub al,30h
xor bx,bx
mov bl,al
xor dx,dx ; ввод длинного числа
mov ax,word ptr[chislo+2]
mul c10
mov word ptr[chislo+2],ax
mov ax,word ptr[chislo]
mul c10
add dx,word ptr[chislo+2]
add ax,bx
mov word ptr[chislo],ax
mov word ptr[chislo+2],dx
jmp input_loop
end_input:
mov cx,offset chislo ; в сх - количество чисел
sub cx,offset massiv
shr cx,2
mov ax,word ptr[chislo] ; в ax - младшее слово числа
mov dx,word ptr[chislo+2] ; в dx - старшее слово числа
cmp_loop: ; цикл сравнения
mov bx,cx
dec bx
shl bx,2
add bx,offset massiv
cmp ax,word ptr[bx]
je continue_cmp
jmp cmp_end
continue_cmp:
add bx,2
cmp dx,word ptr[bx]
je find
cmp_end: ; если ничего не найдено
loop cmp_loop
mov ah,09h
mov dx,offset str2
int 21h
jmp end_start
find: ; если число найдено
mov ah,09h
mov dx,offset str3
int 21h
end_start:
mov ah,4ch
int 21h
end star
33. Ввести массив чисел и отсортировать методом пузырька
.model small
.stack 100h
.data
massiv dw 80 dup(?)
msg db "Vvodite chisla cherez probel, okonchanie vvoda - ENTER",0ah,0dh,'$'
c10 dw 10
.code
start:
mov ax,@data
mov ds,ax
mov ah,09h ; вывод msg
lea dx,msg
int 21h
xor bx,bx ; bx - смещение в массиве вводимого числа
xor dx,dx ; dx - вводимое число
input_loop:
mov ah,01h ; считваем очередной символ
int 21h
cmp al,0dh ; если это enter
je chislo
cmp al,20h ; или пробел
je chislo
sub al,30h ; иначе - получаем цифру
mov cl,al ; сохраняем ее в cl
mov ax,dx ; в ax - вводимое число
mul c10 ; умножаем на 10
xor ch,ch
add ax,cx ; добавляем к результату последнюю цифру
mov dx,ax ; в dx - полученное число
jmp input_loop
chislo: ; если окончен ввод числа
mov massiv[bx],dx ; запись этого числа в массив
add bx,2 ; смещаемся к следующему элементу
cmp bx,160 ; если массив заполнен
je end_input ;
cmp al,0dh ; или последнее число
je end_input ; то конец ввода
xor dx,dx ; обнуляем dx для ввода следующего числа
jmp input_loop
end_input:
mov cx,bx ; в cx - (количество введенных чисел + 1) * 2
shr cx,1 ; cx = cx \ 2
dec cx ; теперь в cx - количество введенных чисел
call sort ; сортировка
mov ah,4ch
int 21h
sort proc
loop1:
xor bx,bx ; bx - смещение в массиве
push cx ; сохраняем cx в стеке
loop2:
mov ax,massiv[bx]
cmp ax,massiv[bx][2] ; сравниваем два соседних элемента
jl cont_loop2 ; если правый больше левого, то продолжить цикл
mov dx,massiv[bx][2] ; иначе - перестановка
push massiv[bx][2]
push massiv[bx]
pop massiv[bx][2]
pop massiv[bx]
cont_loop2:
add bx,2 ; смещаемся к следующему элементу в массиве
loop loop2
pop cx ; восстанавливаем cx
loop loop1
ret
sort endp
end start
34.Вывести строку в обратном порядке.
.model small
.stack 100h
.data
msg1 db 0Ah,0Dh,"Enter string <80(char)",0Ah,0Dh,'$'
string db 80 dup(?)
msg2 db 0Ah,0Dh,"Reversing string",0Ah,0Dh,'$'
.code
start: mov ax,@data
mov ds,ax
lea dx,msg1
mov ah,09h
int 21h
mov cx,80
xor si,si
l1: mov ah,01h
int 21h
cmp al,0Dh
je continue
mov string[si],al
inc si
loop l1
continue: mov ah,09h
lea dx,msg2
int 21h
cmp si,0
je exit
dec si
mov cx,si
l2: mov si,cx
mov dl,string[si]
mov ah,02h
int 21h
loop l2
mov dl,string[0]
mov ah,02h
int 21h
exit:
mov ah,4Ch
int 21h
end start
35. Ввести с клавиатуры массив чисел. Найти суммы положительных и отрицательных чисел. Вывести результат.
.model small
.stack 256
.data
mas dw 8 dup(0)
zz db 0Dh, 0Ah,'-$'
.code
start:
mov ax,@data
mov ds,ax
mov cx,8
mas_in:
xor bx,bx
num_s_in:
cmp bx,6
je end_num_s_in
mov ah,01h
int 21h
cmp al,0Dh
je end_num_s_in
inc bx
xor ah,ah
push ax
jmp num_s_in
end_num_s_in:
mov bp,1
xor di,di
num_p:
cmp bx,1
je end_num_p
pop ax
sub al,'0'
mul bp
add di,ax
mov ax,bp
mov bp,10
mul bp
mov bp,ax
dec bx
jmp num_p
end_num_p:
pop ax
cmp al,'-'
jne ee
neg di
ee:
mov ax,cx
;sub ax,2
shl ax,1
mov si,offset mas
add si,ax
mov word ptr [si],di
loop mas_in
____SOBSTVENNO SLOGENIE____
mov di,offset mas
xor ax,ax ;summa bolhih 0
xor bx,bx ;summa menshih 0
mov cx,9
add_num:
cmp word ptr[di],0
jl add_less_zero
add ax,word ptr [di]
jmp e
add_less_zero:
add bx,word ptr [di]
e:
add di,2
loop add_num
___VYVOD_______
div_num_s:
mov cx,10
xor bp,bp
div_num:
cmp ax,0
je end_div_num
xor dx,dx
div cx
add dx,'0'
push dx
inc bp
jmp div_num
end_div_num:
vyvod:
cmp bp,0
je end_vyvod
pop ax
mov ah,02h
mov dl,al
int 21h
dec bp
jmp vyvod
end_vyvod:
cmp bx,0
je exit
neg bx
mov ah,9
mov dx,offset zz
int 21h
mov ax,bx
xor bx,bx
jmp div_num_s
exit:
mov ax,4C00h
int 21h end start
36.Дан массив строк. Найти строку с max длинной и вывести ее на экран.
.model small
.stack 100h
.data
str0 db "Hello",'$'
str1 db "Good day",'$'
str2 db "Hi!",'$'
str3 db "How do you do?",'$'
str4 db "I greet you",'$'
StrArray dw offset str0
dw offset str1
dw offset str2
dw offset str3
dw offset str4
StrCount dw 5
.code
program:
mov ax, @data
mov ds, ax
mov si, offset StrArray ; si - начало массива строк
mov cx, StrCount ; инициализация счетчика
xor ax, ax ; в ax - макс. длина строки
calc_length:
mov bx, [si] ; bx - смещение текущей строки
add si, 2 ; si сдвигается на следующую строку
push cx ; сохраняем счетчик
call str_len ; определяем длину строки
cmp ax, cx
ja end_loop ; если найденная длмна больше макс.
mov ax, cx ; сохраняем эту длину в ax
mov dx, bx ; сохраняем в dx смещение строки
end_loop:
pop cx ; восстанавливаем счетчик
loop calc_length
mov ah, 9 ; выводим макс. строку на экран
int 21h
mov ax, 4c00h
int 21h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Находит длину строки
; bx - смещение строки
; Результат: cx - искомая длина
str_len proc near
push bx
push ax
xor cx, cx
mov al, '$'
mov ah, 0
len_lp:
cmp al, [bx]
je end_len
cmp ah, [bx]
je end_len
inc cx
inc bx
jmp len_lp
end_len:
pop ax
pop bx
ret
str_len endp
end program
37. Перевод числа из одной системы счисления в другую. Данные вводить с клавиатуры.
.modl small
.stack 256
.data
Mess1 db 'Enter number in 10c: $'
Mess2 db 0Dh, 0Ah,'Result in 16c: $'
.code
start:
mov ax,@data
mov ds,ax
mov ah,9
mov dx,offset Mess1
int 21h; Выводим первое сообщение
xor bx,bx
num_in:
; Вводим символы числа, пока не нажмется энтэр
mov ah,01h
int 21h
cmp al,0Dh
je end_num_in
sub al,'0' ; переводим в десятичный вид
xor ah,ah
push ax ; и ложим его в стек
inc bx
jmp num_in
end_num_in:
mov cx,1
num_preobr:
cmp bx,0
je end_num_preobr ; если цифры ;числа закончились, то переходим на ;end_num_preobr
pop ax
xor dx,dx ; умножаем на число в cx (1, 10, 100, 1000, …)
mul cx
; и добавляем к конечному числу
add di,ax
dec bx
; умножаем на 10, чтобы получить 10, 100, 1000, …
mov ax,10
mul cx
mov cx,ax
jmp num_preobr
end_num_preobr:
; Выводится сообщение 2
mov ah,9
mov dx,offset Mess2
int 21h
; начало коныертации в 16 систему
mov ax,di
mov bx,0
mov cx,16
num_convert:
; непосредственно перевод
cmp ax,0
je end_convert
xor dx,dx
; делим на систему счисления
div cx
; сравниваем остаток от деления с 9, если больше, добавляем ‘7’, иначе ‘0’
cmp dx,9
ja above_9
add dx,'0'
jmp next
above_9:
add dx,'7'
next:
push dx
inc bx
jmp num_convert
end_convert:
out_num:
; если цифры закончились, то переходим ;на end_out_num
cmp bx,0
je end_out_num
pop dx
mov ah,02h
int 21h
dec bx
jmp out_num
end_out_num:
mov ax,4C00h
int 21h
end start
38.Вычислить сумму столбцов матрицы с полным вводом/выводом (программа типа exe)
.model small
.stack 300h
.code
endl macro
push ax dx
mov ah, 02h
mov dl, 0Ah
int 21h
mov dl, 0Dh
int 21h
pop dx ax
endm
outint macro value
local outint_l1, outint_l2
push ax bx cx dx
mov ax, value
mov bx, 10
xor cx, cx
outint_l1:
xor dx, dx
div bx
push dx
inc cx
cmp ax, 0
jne outint_l1
mov ah, 02h
outint_l2:
pop dx
add dl, '0'
int 21h
loop outint_l2
pop dx cx bx ax
endm
proc readint
push cx si bx dx
mov buf_str, 8
mov ah, 0Ah
lea dx, buf_str
int 21h
xor cx, cx
mov si, 2
xor ax, ax
mov bx, 10
in_loop:
mul bx
mov dl, [buf_str+si]
sub dl, '0'
add ax, dx
inc si
inc cl
cmp cl, [buf_str+1]
jl in_loop
pop dx bx si cx
endl
ret
endp
start:
mov ax, @data
mov ds, ax
xor cx, cx
xor dx, dx
xor di, di
input_loop:
push dx
mov ah, 09h
lea dx, str_1
int 21h
outint cx
lea dx, str_2
int 21h
mov si, sp
mov dx, [ss:si]
outint dx
lea dx, str_3
int 21h
call readint
mov word ptr matrix[di], ax
add di, 2
pop dx
inc cx
cmp cx, N
jl input_loop
xor cx, cx
inc dx
cmp dx, N
jl input_loop
xor ax, ax
cont_summ:
mov si, ax
shl si, 1
xor dx, dx
cont_summ_2:
add dx, word ptr matrix[si]
add si, N*2
cmp si, N*N*2
jl cont_summ_2
outint dx
endl
inc ax
cmp ax, N
jl cont_summ
mov ax, 4C00h
int 21h
.data
N equ 3
matrix db N*N*2 dup(?)
buf_str db 10 dup(?)
str_1 db "Input matrix[$"
str_2 db "][$"
str_3 db "]:",10,13,"$"
sum1 dw 0
sum2 dw 0
end start
39. Перевод строки в число.
.model small
.stack 100h
.data
num dw ?
c10 db 10
.code
begin:
mov ax,@data
mov ds,ax
xor bx,bx
again:
mov ah,1
int 21h
cmp al, 0dh ; если энтер, то закончим ввод
je con
sub al,'0' ; вычитаем ‘0’ из символа для
xor ah,ah ;
mov si,ax
mov ax,bx ; помещаем конечный на данный момент результат в ax
mul c10 ; и умножаем его на 10
add ax,si ; добавляем к полученному значению введенную только что цифру
mov bx, ax ; формируем в bx конечное на данный момент значение
jmp again ; зацикливаем
con:
mov num,bx ; полученное число
mov ax, 4c00h
int 21h
end begin
40. В сегменте данных дана матрица. Отсортировать ее побочную дигональ
.model small
.stack 100h
.data
razmer equ 4
matrix dw 1,2,3,13
dw 5,6,10,8
dw 9,7,11,12
dw 4,14,15,16
.code
start:
mov ax,@data
mov ds,ax
mov cx,razmer
dec cx
mov bx,cx
shl bx,1 ; bx - смещение (длина строки -2)
loop1:
mov si,bx
push cx
loop2:
mov dx,matrix[si] ;
mov di,matrix[si][bx] ; перестановка
cmp dx,di ;
jl cont_loop2
mov matrix[si],di
mov matrix[si][bx],dx
cont_loop2:
add si,bx ;
loop loop2 ; смещение на следующую строку
pop cx ;
loop loop1
lea dx,matrix
mov ah,4ch
int 21h
end start
41.Вводится матрица чисел. Найти сумму элементов по каждой диагонали и вывести на экран.
.model small
.stack 300h
.code
endl macro
push ax dx
mov ah, 02h
mov dl, 0Ah
int 21h
mov dl, 0Dh
int 21h
pop dx ax
endm
outint macro value
local outint_l1, outint_l2
push ax bx cx dx
mov ax, value
mov bx, 10
xor cx, cx
outint_l1:
xor dx, dx
div bx
push dx
inc cx
cmp ax, 0
jne outint_l1
mov ah, 02h
outint_l2:
pop dx
add dl, '0'
int 21h
loop outint_l2
pop dx cx bx ax
endm
proc readint
push cx si bx dx
mov [buf_str], 8
mov ah, 0Ah
lea dx, buf_str
int 21h
xor cx, cx
mov si, 2
xor ax, ax
mov bx, 10
in_loop:
mul bx
mov dl, [buf_str+si]
sub dl, '0'
add ax, dx
inc si
inc cl
cmp cl, [buf_str+1]
jl in_loop
pop dx bx si cx
endl
ret
endp
start:
mov ax, @data
mov ds, ax
xor cx, cx
xor dx, dx
xor di, di
input_loop:
push dx
mov ah, 09h
lea dx, str_1
int 21h
outint cx
lea dx, str_2
int 21h
mov si, sp
mov dx, [ss:si]
outint dx
lea dx, str_3
int 21h
call readint
mov word ptr matrix[di], ax
add di, 2
pop dx
inc cx
cmp cx, N
jl input_loop
xor cx, cx
inc dx
cmp dx, N
jl input_loop
xor si, si
xor ax, ax
count_sum1:
add ax, word ptr matrix[si]
add si, N*2+2
cmp si, N*N*2
jl count_sum1
mov sum1, ax
mov si, N*2-2
xor ax, ax
count_sum2:
add ax, word ptr matrix[si]
add si, N*2-2
cmp si, N*(N-1)*2+2
jl count_sum2
mov sum2, ax
mov ah, 09h
lea dx, str_4
int 21h
outint sum1
lea dx, str_5
int 21h
outint sum2
lea dx, str_6
int 21h
mov ax, 4C00h
int 21h
.data
N equ 3
matrix db N*N*2 dup(?)
buf_str db 10 dup(?)
str_1 db "Input matrix[$"
str_2 db "][$"
str_3 db "]:",10,13,"$"
str_4 db "Sum1=$"
str_5 db 10,13,"Sum2=$"
str_6 db 10,13,"$"
sum1 dw 0
sum2 dw 0
end start
42. Работа с окнами в текстовом режиме.
Работа с окнами в текстовом режиме. (результат работы проги: синее окно,
;в нем - зеленое окно, в зеленом окне - текст :))
.MODEL small
.STACK 100h
.DATA
str_ db 'TEXT'
len equ $-str_
.CODE
main:
mov ax, @data
mov ds, ax
mov es, ax
mov ah, 06h ;очистка окна
mov al, 00h ;режим окна
mov bh, 17h ;видео-атрибут для пустых строк
mov cx, 0000h ;очистка экрана от (00;00) до (24;79)
mov dx, 1b4fh
int 10h
mov ax, 0600h ;в ah - 06h в al - 00h
mov bh, 20h
mov cx, 0a1ch
mov dx, 0c31h
int 10h
mov ah, 13h ;вывод на экран в позиции курсора
mov al, 0 ;не менять положение курсора
mov bh, 0 ;номер страницы
mov bl, 07h ;цвет выводимого текста
mov cx, len
mov dx, 0b25h ;координаты на экране (dh - y, dl - x)
lea bp, str_ ;адрес выводимой строки
int 10h
mov ah, 4ch
int 21h
end main
43.Сложение и вычитание длинных чисел.
.model small
.stack 100h
.data
num1 dw 1234h, 5678h
num2 dw 8765h, 4321h
res1 dw 0,0
res2 dw 0,0
.code
start:
mov ax, @data
mov ds, ax
; сложение
mov ax, num1[0]
add ax, num2[0]
mov res1[0], ax
mov ax, num1[2]
adc ax, num2[2]
mov res1[2], ax
; вычитание
mov ax, num1[0]
sub ax, num2[0]
mov res2[0], ax
mov ax, num1[2]
sbb ax, num2[2]
mov res2[2], ax
mov ax, 4C00h
int 21h
end start