Задачи по ассемблеру
Задача 1. Составить программу нахождения в заданном массиве однобайтовых чисел со знаком максимального числа и его номера (первого из таких). Для нахождения максимума и его номера написать подпрограмму.
Параметры: адрес массива, количество элементов и адреса результатов передаются через стек.
Кадр стека данной задачи. Распределение регистров. Основная программа и подпрограмма.
assume cs:prog, ds:data, ss:stek;
data SEGMENT
mas db 2, 5, 3, 1, 2, 7, 9, 6
n db 100
max db?
nmax db?
data ENDS
stek SEGMENT STACK
db 40 dup(?)
top dw?
stek ENDS
prog SEGMENT
start: mov ax, data
mov ds, ax
mov ax, stek
mov ss, ax
mov sp, offset top
sub sp,2
mov dx, offset mas
push dx
mov ax,8
push ax
call obrab
pop ax
mov max, ah
mov nmax, al
mov dl, max
add dl,48
mov ah,2
int 21h
mov dl, nmax
add dl,48
mov ah,2
int 21h
mov ah,8
int 21h
mov ah,4Ch
int 21h
obrab proc
push bp
mov bp, sp
push cx
mov cx,4[bp]
push si
mov si,6[bp]
push bx
mov bh, byte ptr [si] ;max
mov bl,1 ;nmax
push ax
mov al, bl ;tekn
dec cx
jz m3
m1:
inc si
inc al
cmp byte ptr [si],bh
jl m2
mov bh, byte ptr [si]
mov bl, al
m2:
loop m1
m3:
mov 8[bp],bl
mov 9[bp],bh
pop ax
pop bx
pop si
pop cx
pop bp
ret 4
obrab endp
prog ENDS
END start
Задача 2.
; Составить на языке ассемблера IBM PC подпрограмму подсчета суммы и
; количества положительных и кратных 8 элементов заданного массива
; двухбайтовых чисел со знаком.
; Параметры: адрес массива, количество чисел в нем и результаты, передаются через стек.
;————————————————————-
; Решение 1: выталкивание и вталкивание параметров
kolsum PROC
; Распределение регистров: Кадр стека:
; si — адрес текущего числа | |
; ax — текущий элемент массива | Адрес возврата | Результаты:
; bx — искомая сумма | Адрес массива | <- количество
; cx — искомое количество | Кол. чисел массива | <- сумма
; di — адрес возврата
; dx — адрес конца массива = адрес массива + длина в байтах
b1: pop di ; & возврата
pop si ; & массива
pop dx ; количество чисел в массиве
add dx, dx ; количество байт в массиве (= sal dx,1)
add dx, si ; & байта за последним элементом массива
xor bx, bx ; 0 -> сумма
xor cx, cx ; 0 -> количество
; Цикл обработки массива: блоки b2-b5
b2: cmp si, dx
je b6 ; конец массива
b3: mov ax,[si] ; текущее число
cmp ax,0
jle b5 ; число <= 0
test ax,7 ; выделить 3 мл. бита = число % 8
jnz b5 ; остаток!= 0 (не кратно 8)
b4: inc cx ; количество ++
add bx, ax ; сумма + число -> сумма
b5: add si,2 ; адрес следующего числа
jmp b2 ; на обработку следующего числа
; Завершение процедуры
b6: push bx ; сумма
push cx ; количество
push di ; адрес возврата
ret ; возврат
kolsum ENDP
; Решение 2: базовая адресация параметров в стеке
kolsum PROC
; Распределение регистров: Кадр стека:
; si — адрес текущего числа | |
; ax — текущий число BP->0 | старое BP |
; bx — искомая сумма 2 | Адрес возврата | Результаты:
; cx — искомое количество 4 | Адрес массива | <- количество
; bp — адрес кадра стека 6 | Кол. чисел массива | <- сумма
; dx — адрес конца массива = адрес массива + длина в байтах
b1: push bp ; Сохранение bp
mov bp, sp ; адрес кадра стека
push si
mov si,4[bp] ; & массива
push dx
mov dx,6[bp] ; количество чисел в массиве
add dx, dx ; колич. байт в массиве (или sal dx,1)
add dx, si ; & байта за концом массива
push bx
xor bx, bx ; 0 -> сумма
push cx
xor cx, cx ; 0 -> количество
push ax
; Цикл обработки массива: блоки b2 — b5
. . .
; Завершение процедуры
b6: mov 4[bp],cx ; количество — в стек
mov 6[bp],bx ; сумма — в стек
pop ax
pop cx
pop bx
pop dx
pop si
pop bp ; восстановление bp
ret ; возврат (без удаления результата)
kolsum ENDP
Задача 3.
; Составить на языке ассемблера IBM PC подпрограмму обмена местами двух крайних тетрад
; (четверок бит, шестнадцатеричных цифр) в каждом двухбайтовом элементе заданного
; массива: 0x1234 —> 0x4231 (где 0x — 16-я система в языке C).
; Параметры: адрес массива и его длина в байтах, передаются через стек.
;————————————————————-
; Решение 1: доступ к параметрам через PUSH/POP, цикл без LOOP
obmen PROC
; Распределение регистров: Кадр стека:
; si — адрес текущего элемента | |
; ax — текущий элемент массива | Адрес возврата |
; bx — для обмена тетрад | Адрес массива |
; bp — адрес возврата | Длина массива |
; cl — величина сдвига (неудобно для LOOP: CX занят)
; dx — адрес конца массива = адрес массива + длина в байтах
b1: pop bp ; & возврата
pop si ; & массива
pop dx ; длина массива (байт)
add dx, si ; & байта за последним элементом массива
mov cl,4 ; величина сдвига: 4 -> cl
; Цикл обработки массива: блоки b2-b4 (>= 0 повторов)
b2: cmp si, dx
je b5 ; конец массива
b3: ; обмен крайних тетрад текущего элемента
mov ax,[si] ; 0x1234 -> ax=(ah, al) элемент: 4 тетрады
/ mov bh, al ; 0x34 -> bh
| shl bh, cl ; 0x34 << 4 = 0x40 -> bh
(*) | mov bl, ah ; 0x12 -> bl
| shr bl, cl ; 0x12 >> 4 = 0x01 -> bl (bx = 0x4001)
| and ax,0FF0H ; 0x1234 & 0x0FF0 = 0x0230 -> ax
or ax, bx ; 0x0230 | 0x4001 = 0x4231 -> ax
mov [si],ax ; запись результата в массив
b4: add si,2 ; & следующего элемента
jmp b2 ; | Вместо (*) короче:
; Завершение процедуры | 0x1234 = ax
b5: push bp ; & возврата | ror ax, cl ; 0x4123 -> ax
ret ; возврат | ror ah, cl ; 0x1423 -> ax
obmen ENDP ; | rol ax, cl ; 0x4231 -> ax
; Решение 2: организация цикла командой LOOP (хуже, что >0 повт.)
obmen PROC
; Распределение регистров: Кадр стека:
; si — адрес текущего элемента | |
; ax — текущий элемент массива | Адрес возврата |
; bx — для обмена тетрад | Адрес массива |
; bp — адрес возврата | Длина массива |
; cl — величина сдвига
; cx — cчетчик цикла ; dl — для сохранения cl
b1: pop bp ; & возврата
pop si ; & массива
pop cx ; длина массива (байт)
shr cx,1 ; количество элементов: cx / 2 -> cx
mov dl,4 ; величина сдвига: 4 -> dl
; Цикл обработки массива: блоки b2-b5 (> 0 повторов)
b2:
b3: ; обмен крайних тетрад текущего элемента
xchg cl, dl ; сохранение счетчика цикла cl <-> dl
. . .
xchg cl, dl ; восстановление счетчика цикла cl <-> dl
b4: add si,2 ; адрес следующего элемента
b5: loop b2 ; на обработку следующего элемента
; Завершение процедуры
b6: push bp ; адрес возврата
ret ; возврат
obmen ENDP
; Решение 3: доступ к параметрам через BP — длиннее
obmen PROC
; Распределение регистров: Кадр стека:
; si — адрес текущего элемента bp —> 0 | Старое bp |
; ax — текущий элемент массива 2 | Адрес возврата |
; bx — для обмена тетрад 4 | Адрес массива |
; bp — адрес кадра стека 6 | Длина массива |
; cl — величина сдвига
; cx — cчетчик цикла ; dl — для сохранения cl
b1: push bp ; сохранение bp
mov bp, sp ; адрес кадра стека
mov si,4[bp] ; & массива
mov cx,6[bp] ; длина массива (байт)
shr cx,1 ; количество элементов: cx / 2 -> cx
mov cl,4 ; величина сдвига: 4 -> cl
; Цикл обработки массива: блоки b2-b5
. . .
; Завершение процедуры
b6: pop bp ; восстановление bp
ret 4 ; удаление параметров и возврат
obmen ENDP