Страница 1 из 2

Отрицательные числа в массиве

Добавлено: 04 апр 2009, 16:20
Xariec
Доброго всем времени суток. В институте дали задание, и я понял что в низкоуровневом программировании у меня обстоят дела просто ужасно, за сим обращаюсь за помощью и пояснением.
Условие:
Дан массив из десяти целых знаковых чисел (слов, байт, двойных слов). Заменить все отрицательные числа нулями.
Вот до чего пока что дошел.

Код: Выделить всё

.386
.MODEL SMALL
.STACK 4069
.data
array SBYTE 10h,-10h,20h,-20h,30h,-30h,40h,-40h,50h,-50h
zero = 0

.code
main PROC
mov cx,10 ;устанавливаем счетчик
@loop:
mov esi,OFFSET array
mov al,[esi]
inc esi

no:

main ENDP
Понимаю, что для каждого элемента надо проверить значение старшего бита или флаг SF. Как это сделать? Реализовать условие в других языках элементарно, а вот в ассемблере не могу :( Помогите пожалуйста.

Re: Отрицательные числа в массиве

Добавлено: 04 апр 2009, 20:21
somewhere
здесь это можно сделать любой операцией, отличной от mov, не изменяющей операнд. Например:
test al, al
test byte ptr [esi]
or al, al
and byte ptr [esi], 255
ну и т.д., в результате флаги установятся в зависимости от содержимого AL или [ESI], потом делаем условный переход js.
Можно сделать и без перехода (проверки), например вот таким хитрым способом.

Код: Выделить всё

movsx ax, byte ptr [esi]
not ah
and al, ah
mov [esi], al
... и все это в цикле. Вообщем разбирайтесь.

Re: Отрицательные числа в массиве

Добавлено: 04 апр 2009, 21:55
Xariec
somewhere, благодарю за скорый ответ!
Вот что у меня получилось:

Код: Выделить всё

TITLE ;Задание: Заменить все отрицательные числа массива нулями (One.asm)

.386
.MODEL COMPACT
.STACK 100h
.data
	intarray SBYTE 10h,-10h,20h,-20h,30h,-30h,40h,-40h,50h,-50h
	zero=0
.code
main PROC
	mov cx,10  ;устанавливаем счетчик цикла
	mov edi,OFFSET intarray ;загружаем адрес массива intarray
	mov eax,zero ;обнуляем аккумулятор
@loop:	
	mov eax,[edi] ;заносим значение текущего элемента массива в аккумулятор
	test eax,eax
	js SF1 ;проверяем состояниек флага знака
	loop @loop ;возвращаемся на метку @loop
SF1:
	mov [edi],zero ;заменяем отрицательное число нулем
	
main END
	INT 21h
END main
но компилятор сообщает о трёх ошибках:
Изображение

Re: Отрицательные числа в массиве

Добавлено: 06 апр 2009, 09:32
airyashov

Код: Выделить всё

TITLE ;Задание: Заменить все отрицательные числа массива нулями (One.asm)

.386
.MODEL COMPACT
.STACK 100h
.data
	intarray db 10h,-10h,20h,-20h,30h,-30h,40h,-40h,50h,-50h
	zero=0
.code
main PROC
	mov cx,10  ;устанавливаем счетчик цикла
	mov edi,OFFSET intarray ;загружаем адрес массива intarray
	mov eax,zero ;обнуляем аккумулятор
@loop:	
	mov al,[edi] ;заносим значение текущего элемента массива в аккумулятор
	test al,al
	jns next ;проверяем состояниек флага знака
	mov byte ptr[edi],zero ;заменяем отрицательное число нулем
next:
	add edi,1
	loop @loop ;возвращаемся на метку @loop

	
main ENDp
	INT 21h
END main

Re: Отрицательные числа в массиве

Добавлено: 06 апр 2009, 10:34
BBB
А почему бы просто не сравнить с нулем?
Насколько я помню ASM, есть команды проверки флагов для беззнакового сравнения (jb [Jump if Below], ja [Jump if Above]) и для знакового сравнения (jl [Jump if Less], jg [Jump if Greater])

Т.е. фрагмент может выглядеть так:

Код: Выделить всё

Cmp eax, 0
	jl SF1 ; переход, если eax меньше 0
	loop @loop ; возвращаемся на метку @loop
SF1:
	mov byte ptr[edi],zero ; заменяем отрицательное число нулем
А если есть свободный регистр, то перед циклом его можно обнулить, и проводить сравнение не с константой 0, а с этим регистром. Кажется, это будет, типа, оптимальнее в смысле быстродействия :)

Код: Выделить всё

 Xor edx, edx ; обнуляем регистр edx
Cmp eax, edx
	jl SF1 ; переход, если eax меньше 0
	loop @loop ;возвращаемся на метку @loop
SF1:
	mov byte ptr[edi],zero ;заменяем отрицательное число нулем

Re: Отрицательные числа в массиве

Добавлено: 06 апр 2009, 10:50
somewhere
&quot писал(а):А если есть свободный регистр, то перед циклом его можно обнулить, и проводить сравнение не с константой 0, а с этим регистром
Начиная с 386 нет никакой разницы. Да и способов проверки и выставления флагов великое множество. В любом случае приведеный код работать не будет и в любом случае установит первый элемент в 0. Виной тому:
1) EDI не меняется в цикле
2) Элементы массива объявлены как байты, а в коде mov eax, [edi]
3) При нахождении отрицательного числа цикл прекращается

Re: Отрицательные числа в массиве

Добавлено: 06 апр 2009, 20:38
Xariec
[quote="airyashov"][/QUOTE]
Благодарю за правку. Только поясните мне следующее:

Код: Выделить всё

	mov byte ptr[edi],zero 
Зачем в комманде пересылки мы ставим "byte ptr[edi]"?

Re: Отрицательные числа в массиве

Добавлено: 06 апр 2009, 22:22
somewhere
&quot писал(а):Зачем в комманде пересылки мы ставим "byte ptr[edi]"?
Компилятор, не обладая ИИ, не может угадать какой именно ноль записывать в память. Это может быть 8,16,32 битовый ноль. По сути нет разницы между mov [edi], byte ptr 0 или mov byte ptr [edi], 0. В обоих случаях мы дали понять, что нужно записать именно 8 бит по указанному адресу.

Re: Отрицательные числа в массиве

Добавлено: 07 апр 2009, 20:38
Xariec
Прошу прощения, но мне опять требуется ваша помощь:
Не могу найти материал и разобраться в управлении памятью в MS-DOS:
Условие таково:
Установить стратегию "последний подходящий", выделить блок памяти размером 16П, увеличить его размер до 64П

Re: Отрицательные числа в массиве

Добавлено: 08 апр 2009, 08:45
airyashov
насчет памяти это здесь
http://www.codenet.ru/progr/dos/int_0026.php
Функция DOS 48H: распределить память (дать размер памяти)
Функция DOS 49H: Освободить блок распределенной памяти
Функция DOS 4aH: Сжать или расширить блок памяти