Войти

Показать полную графическую версию : ASSM | Моё первое ассемблироание


Страниц : 1 [2]

AnGel_of_Death
17-07-2006, 13:23
на конец -то разабрался с этим циклом. теперь работает и вот этот вариант:
look segment
org 100h
begin:
mov cx, 5
looop:
mov ah,9
mov dx,offset Ha
int 21h
loop looop
int 20h
Ha db 'hi all :P!!!!! $ '
look ends
end begin
в прошлых у меня была ошибка что я заканчиваю не только begin, а до этого еще looop. он почему-то не считал begin за метку. вот и вся проблема. всем спасибо за помощь в этом не легком труде(учебе)!!!

Admiral
28-11-2006, 05:54
Доброе время суток народ.

Есть следующий код.

;DS:DI - адрес массива

TITLE The bubble way of sorting the array

SSEG SEGMENT PARA STACK 'STACK' ;
DB 256 DUP(0)
SSEG ENDS

DSEG SEGMENT PARA PUBLIC 'DATA'
ArraySize DW 20 DUP(0) ;MAX-65535
DSEG ENDS ;DB/DW - Define Bytes/Words

CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG,DS:DSEG,SS:SSEG

BUBBLE_SORT PROC NEAR ;Procedure Definition (32-FAR)
push ds
sub ax,ax
push ax
mov ax,DSEG ;инициализируем адреса сегментов
mov ds,ax

Start: mov dx,ArraySize ; ArraySize в DX
cld ;установим в ноль флаг направления DF
cmp dx,1 ;сравниваем dx с 1
jbe sort_exit ;выйти, если нечего сортировать
dec dx ;уменьшит значение dx на единицу
sb_loop1: mov cx,dx ;установить длину цикла
xor bx,bx ;BX будет флагом обмена
mov si,di ;SI – указатель на текущий элемент
sb_loop2: lodsw ;считать следующий элемент
cmp ax,word ptr [si]
jbe no_swap
xchg ax,word ptr [si]
mov word ptr [si-2],ax
inc bx
no_swap: loop sb_loop2
cmp bx,0 ;если сортирование не закончилось
jne sb_loop1 ;перейти к следующему элементу
sort_exit: pop ax
pop ds
ret
BUBBLE_SORT ENDP
CSEG ENDS
END BUBBLE_SORT


Задача кода – инициализировать массив, заполнить его и сортировать методом пузырька.
На текущий момент код умеет задавать размерность массива в шапке.
Необходимо разместить адрес массива в DS:DI и заполнить элементы массива случайными величинами (например считать данные с памяти).

Пишу на TASMе.

Кто знает отпишитесь.

DillerInc
28-11-2006, 12:45
Admiral
Для начала одна неувязочка(то ли я туплю с утра,то ли...):

ArraySize DW 20 DUP(0)

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

Необходимо разместить адрес массива в DS:DI и заполнить элементы массива случайными величинами (например считать данные с памяти).
...указатели на массивы заносятся в регистры обычно с помощью команды LEA:


cld
lea si, source ; источник = какой-нибудь адрес в памяти
lea di, ArraySize ; приёмник
mov cx, 20h ; размер массива
rep movsw ; пересылаем из источника в приёмник двадцать слов

Admiral
06-12-2006, 04:12
Благодарю за ответ DillerInc

Для начала одна неувязочка(то ли я туплю с утра,то ли...):

ArraySize DW 20 DUP(0)

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


В новом варианте кода понятие размерность и память под эту размерность организовано как ArraySize и Array. И нет необходимости в коде программы использовать mov cx, 20h ведь можно написать следующие mov cx, ArraySize.
Это по аналоги с С где (при работе с массивами) один раз пишем const int n=10 а далее везде по коду ссылаемся на n.
Захотели поменять размерность массива - так поменяли её сразу в шапке, а не по всему коду.

Я немного структурировал код

;DS:DI – адрес массива должен быть здесь

TITLE The bubble way of sorting the array

SSEG SEGMENT PARA STACK 'STACK'
DB 16 DUP(0)
SSEG ENDS

DSEG SEGMENT PARA PUBLIC 'DATA'
Msg1 DB 0dh,' Массив не упорядоченных данных - ','$'
Msg2 DB 0ah,0dh,' Массив упорядоченных данных - ','$'
ArraySize DW 10 ;задаём размерность массива
Array DB 2,9,3,8,4,7,6,5,0,1 ;заполняем массив
i DB 0
DSEG ENDS

CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG,DS:DSEG,SS:SSEG

PROC MAIN NEAR ;главная процедура программы (по аналоги с С)
mov ax,DSEG
mov ds,ax
mov ax,0

mov cx,ArraySize
mov si,0
mov ah,09h
lea dx,Msg1
int 21h
call SHOW

call BUBBLE_SORT ;вызываем процедуру сортирования

mov cx,ArraySize
mov si,0
mov ah,09h
lea dx,Msg2
int 21h
call SHOW

exit:
mov ax,4c00h ;стандартное завершение программы
int 21h
MAIN ENDP

BUBBLE_SORT PROC NEAR

cld
lea si,Array ;source
lea di,Array ;destany
mov cx,ArraySize
rep movsw

mov dx,ArraySize
cmp dx,1
jbe sort_exit
dec dx
sb_loop1:
mov cx,dx
xor bx,bx
mov si,di
sb_loop2:
lodsw
cmp ax,word ptr [si]
jbe no_swap
xchg ax,word ptr [si]
mov word ptr [si-2],ax
inc bx
no_swap:
loop sb_loop2
cmp bx,0
jne sb_loop1
sort_exit:
ret
BUBBLE_SORT ENDP

PROC SHOW NEAR ;процедура вывода на экран массива до и после сортировки
mov ah,02h
mov dl,Array[si]
add dl,30h
int 21h
inc si
loop show
ret
SHOW ENDP

CSEG ENDS
END MAIN

Сразу хочу отметить, что работает вывод на экран, однако нет сортировки ... И всё зависит как раз от подсказанного участка кода
cld
lea si, source ; источник = какой-нибудь адрес в памяти
lea di, ArraySize ; приёмник
mov cx, 20h ; размер массива
rep movsw ; пересылаем из источника в приёмник двадцать слов

А всё таки смысл в этих строчка кода? По сути, копируем из одного источника в другой? Или здесь более сложный подход - они разрешают корректную работу lodsw. Так я нашёл код (Только заполнения и вывода на экран элементов массива) где обходятся без данного оператора и все последующие элементы читают посредством INC SI + Array[si]
TITLE Initialization massive

SSEG SEGMENT PARA STACK 'STACK' ;Сегмент стека. SSEG - это имя
DB 32 DUP(0)
SSEG ENDS

DSEG SEGMENT PARA PUBLIC 'DATA' ;Сегмент данных
Msg1 DB 0dh,' Массив не упорядоченных данных - ','$'
Msg2 DB 0ah,0dh,' Массив упорядоченных данных - ','$'
ArraySize DW 10 ;Размер под массив
Array DB 9,2,3,8,4,7,6,5,0,1 ;Память под массив элементов
i DB 0
DSEG ENDS ;DB/DW - Define Bytes/Words
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG,DS:DSEG,SS:SSEG

MASSIVE PROC NEAR ;Procedure Definition

main:
mov ax,DSEG
mov ds,ax

;вывод на экран получившегося массива

mov cx,ArraySize ;значение счетчика цикла в cx
mov si,0
mov ah,09h
lea dx,Msg1
int 21h
call show


mov cx,ArraySize ;значение счетчика цикла в cx
mov si,0
mov ah,09h
lea dx,Msg2
int 21h
call show

exit:
mov ax,4c00h ;стандартный выход
int 21h

MASSIVE ENDP ;Конец программы

PROC show NEAR
mov ah,02h ;функция вывода значения из al на экран
mov dl,Array[si]
add dl,30h ;преобразование числа в символ
int 21h
inc si
loop show
ret
show ENDP

CSEG ENDS ;Конец сегмента
END MASSIVE ;Конец файла

Однако предполагаю, что в случаи с сортированием связка INC SI + Array[si] утруднить процесс кодирования, что не совсем хорошо.

Всё же, что за source ; источник = какой-нибудь адрес в памяти нужно указывать?

P.S
В приведённом примере в указанном участке кода используется

lea si,Array ;source
lea di,Array ;destany
Естественно, что в процессе выполнения, выведенные на экран массивы, будут одинаковыми
Но если написать следующие

lea si,Array ;source
lea di,buff ;destany ,
а в шапке данных указать
DSEG SEGMENT PARA PUBLIC 'DATA'
.....
.....
buff DW 10 DUP(?)
.....
.....
DSEG ENDS
то результат работы программы будет следующим

Массив не упорядоченных данных- 2938476501
Массив не упорядоченных данных - ш001654738 ш - это не опечатка, это программа взяла из памяти

DillerInc
06-12-2006, 16:53
Admiral
ArraySize DW 10 ;задаём размерность массива
Array DB 2,9,3,8,4,7,6,5,0,1 ;заполняем массив
...ей,богу,глаз режит.У тебя получается массив Array,состоящий из десяти байт,а размер ты выставляешь в словах -- десять слов,что соответствует двадцати байтам!И чем интересно будут заполнены лишние десять байт??Шелл-кодом??
Это по аналоги с С
...не надо пока смешивать низкоуровневый асм с языком высокого уровня ;)
Тогда уж лучше используй такой вариант:

Array DB 2,9,3,8,4,7,6,5,0,1
ArrayLen = $-Array
А всё таки смысл в этих строчка кода? По сути, копируем из одного источника в другой?
...смысл обычно в том,что мы получаем копию данных,с которой потом оперируем,не трогая при этом оригинальные данные.
И если ты задал массив байт,то тогда тебе необходимо использовать команду:
rep movsb ; для пересылки байт
Однако предполагаю, что в случаи с сортированием связка INC SI + Array[si] утруднить процесс кодирования, что не совсем хорошо.
...ничего она не затруднит.Такой вариант вполне возможен,если ты хочешь просто вытащить поочерёдно каждый элемент массива(байт).Тут надо смотреть,что тебе нужно...
Всё же, что за нужно указывать?
...зависит от обстоятельств.
Например,ты открыл какой-то файл с помощью функции CreateFileA,узнал его размер(GetFileSize).Далее в соответствии с размером выделил нужную память(VirtualAlloc),чтобы считать туда этот файл(ReadFile).И после ты хочешь допустим считать заголовок файла -- вот и начинаешь обрабатывать ту память,которая была выделена функцией VirtualAlloc и куда был считан файл функицей ReadFile.Тогда указатель,возвращённый функцией VirtualAlloc,и будет твоим source.
Это всё так -- например.

Admiral
06-12-2006, 23:44
Благодарю DillerInc что так оперативно смог ответить на моё сообщение
По сложившейся традиции для начала приведу обновлённый код, который сразу отмечу, работает, как требовалось постановкой задачи!

TITLE The bubble way of sorting the array

SSEG SEGMENT PARA STACK 'STACK'
DB 16 DUP(0)
SSEG ENDS

DSEG SEGMENT PARA PUBLIC 'DATA'
Msg1 DB 0dh,' Массив не упорядоченных данных - ','$'
Msg2 DB 0ah,0dh,' Массив упорядоченных данных - ','$'
ArraySize DW 10
buff DW 10 DUP(?)
Array DW 2,9,3,8,4,7,6,5,0,1
DSEG ENDS

CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG,DS:DSEG,SS:SSEG

PROC MAIN NEAR
mov ax,DSEG
mov ds,ax
mov ax,0

mov cx,ArraySize
mov si,0
mov ah,09h
lea dx,Msg1
int 21h
call SHOW

call BUBBLE_SORT

mov cx,ArraySize
mov si,0
mov ah,09h
lea dx,Msg2
int 21h
call SHOW

exit:
mov ax,4c00h
int 21h
MAIN ENDP

BUBBLE_SORT PROC NEAR
push ax
cld
lea si,Array ;source
lea di,buff ;destany
mov cx,ArraySize
rep movsw

mov dx,ArraySize
cmp dx,1
jbe sort_exit
dec dx
sb_loop1:
mov cx,dx
xor bx,bx
mov si,di
sb_loop2:
lodsw
cmp ax,word ptr [si]
jbe no_swap
xchg ax,word ptr [si]
mov word ptr [si-2],ax
inc bx
no_swap:
loop sb_loop2
cmp bx,0
jne sb_loop1
sort_exit:
pop ax
ret
BUBBLE_SORT ENDP

PROC SHOW NEAR
mov ah,02h
mov dx,Array[si]
add dl,30h
int 21h
inc si
inc si
loop show
ret
SHOW ENDP

CSEG ENDS
END MAIN

Из изменений исправлено типы данных в шапке, а также самое главное как для переменных слов в подпрограмме выводе на экран добавлен ещё один inc si (поскольку работаем со словами, а между ними разность не si+1, а si+2).
По сути код был рабочий и в прошлой реализации за исключением не верной инициализации размерности и самого массива по типу данных.

Что натолкнуло меня на правильный ход мысли? Как раз

..ей,богу,глаз режит.У тебя получается массив Array,состоящий из десяти байт,а размер ты выставляешь в словах -- десять слов,что соответствует двадцати байтам!И чем интересно будут заполнены лишние десять байт??Шелл-кодом??

Я откорректировал код в сторону слов, а не байт, так как большая часть кода ориентировано на слова, хотя надо будет попробовать поработать и с байтами. Теоретически файл должен стать меньше, а код быстрее. Не только movsb, но и lodsb будет для байт масива будет присутствовать в коде вместо movsw и lodsw соответственно.
Так что

Array DB 2,9,3,8,4,7,6,5,0,1
ArrayLen = $-Array

ещё по используем. А какой аналог для слов?

А разница между тем какой массив (байтовый или словный) будет проявляться в реализации программы и в допустимых числовых значениях элементов:

db — резервирование памяти для данных размером 1 байт.
для чисел со знаком –128...+127;
для чисел без знака 0...255;
а для слов
dw — резервирование памяти для данных размером 2 байта.
для чисел со знаком –32 768...32 767;
для чисел без знака 0...65 535
а также как я предположил уменьшением увиличением файла, изминением быстродействием алгоритма?

А вообше бывают ли масивы

dd — резервирование памяти для данных размером 4 байта.
df — резервирование памяти для данных размером 6 байт;
dp — резервирование памяти для данных размером 6 байт.
dq — резервирование памяти для данных размером 8 байт.
dt — резервирование памяти для данных размером 10 байт.


После корректировки на вывод выдавалось только половина массива через нули, которые и есть так называемый Шелл-код. То есть неправильно выдавался массив на экран, значит и недочёт в подпрограмме вывода. Добавил ещё inc si и всё пошло как по маслу!

Итог

Массив не упорядоченных данных - 2938476501
Массив упорядоченных данных - 0123456789


P.S
А как насчёт следующих алгоритмов: быстрого сортирования и методом линейного отбора.


;***************************************************
;
;Сортирование массива методом быстрого сортирования
;
;***************************************************
;DS:DI – адреса массива
;DX – размер массива

quick_sort proc near
cmp dx,1
jle qsort_done
xor di,di
mov si,dx
dec si
shl si,1
mov ax,word ptr [bx]
step_2: cmp word ptr [bx+si],ax
jle step_3
sub si,2
jmp short step_2
step_3: cmp si,di
je step_5
add di,2
cmp word ptr [bx+di],ax
jl step_3
step_4: mov cx,word ptr [bx+di]
xchg cx,word ptr [bx+si]
mov word ptr [bx+di],cx
jmp short step_2
step_5: xchg ax,word ptr [bx+di]
mov word ptr [bx],ax
push dx
push di
push bx
mov dx,di
shr dx,1 ;загрузка длины массива
call quick_sort ;сортирование
pop bx
pop di
pop dx
add bx,di
add bx,2 ;загрузка начала массива
shr di,1
inc di
sub dx,di ;загрузка длины массива
call quick_sort ;сортирование
qsort_done: ret
quick_sort endp


а также


;***************************************************
;
;Сортирование массива методом линейного отбора
;
;***************************************************
;DS:DI (ES:SI) – адреса массивов
;DX – количество элементов массива
do_swap: lea bx,word ptr [di-2]
mov ax,word ptr [bx] ;новое наименьше число
dec cx ;если поиск минимального завершён
jcxz tail ;перейти в конец
loop1: scasw ;сравнить минимальное в AX
;со следующим элементом
ja do_swap
loop loop1 ;продолжить сравнение
tail: xchg ax,word ptr [si-2]
mov word ptr [bx],ax

linear_sel_sort: proc near ;точка входу в процедуру
mov bx,si
lodsw
mov di,si
dec dx
mov cx,dx
jg loop1
ret
linear_sel_sort: endp



Заменив подпрограмму, на один из указанных алгоритмов получил ошибку исполняемого файла. Для данных алгоритмов необходимо писать свою шапку инициализации массива?
И что за новенькое DS:DI (ES:SI)?

Какие будут комментарии по поводу данных алгоритмов и их реализации на ассемблере?

И в общем реакция на написанное.

DillerInc
07-12-2006, 21:23
Так что

Array DB 2,9,3,8,4,7,6,5,0,1
ArrayLen = $-Array

ещё по используем. А какой аналог для слов?

...сейчас проверял -- размер в таком варианте высчитывается как для байтов.Т.е. при словах:

Array DW 2,9,3,8,4,7,6,5,0,1
ArrayLen = $-Array
...ArrayLen будет равен 14h(двадцать) байт,а не 0Ah(десять).Можно конечно в коде поизвращаться,например:

cld
lea esi, Array
mov ecx, ArrayLen
shr ecx, 1 ; делим содержимое ECX на два

Насчёт быстродействия и размера кода я как-то сильно сомневаюсь,что ты заметишь что-либо,или даже что эта разница вообще присутствует.По-любому,работая в win32,тебе придётся использовать массивы,состоящие из двойных слов(DWORD),например массив адресов чего-либо.
есть так называемый Шелл-код
...ладно :) насчёт шеллкода я тут походу переборщил,но чисто для справки:
Шелл-код(shellcode) -- это эксплойт,вредоносный байт-код,который внедряется в тело чужой программы с целью получения контроля над ней.Одной из распространнёных ошибок,использующихся для внедрения шеллкода,является переполнение буфера.
Для данных алгоритмов необходимо писать свою шапку инициализации массива?
...ну,да.Тут дан только код с комментариями,что в регистрах SI и DI находятся указатели на массивы.Тебе нужно организовать какую-то память под эти массивы.Будь то твоя секция данных или ещё что-то в этом роде.А то иначе приложение запросто упадёт с ошибкой доступа.
И что за новенькое DS:DI (ES:SI)
...у Юрова написано следующее:

Цепочка-источник,адресуемая операндом source,может находится в текущем сегменте данных,определяемом регистром DS. Цепочка-приёмник,адресуемая операндом destination,должна быть в дополнительном сегменте данных,алресуемым сегментным регистром ES.
В общем,не забивай голову.Надо лишь точно знать какие регистры(ESI, EDI, EAX)используются в конкретных цепочечных командах,а для этого надо просто почитать какой-нибудь справочник по ассемблеру.

bes1de
23-12-2006, 23:26
имееца блок схема ..помогите написать код на batronix для 8051.mc

http://img355.imageshack.us/img355/3488/bspn7.th.gif (http://img355.imageshack.us/my.php?image=bspn7.gif)




© OSzone.net 2001-2012