Я пытаюсь отсортировать массив с помощью функций, которые находят наименьшее число в массиве, а другая меняет местами две переменные. Но по какой-то причине массив не меняется и остается прежним. Я думаю, что у меня проблема со стеком, но я не могу его найти.
Это мой код: извините, он длинный и неорганизованный. Я только начал сборку. `
org 100h
jmp start
array db 1,9,3,6,3 **;should get 1,2,3,6,9**
min_in_array dw ?
start:
lea si, array
push 5
push si
call sortArray
pop bx
pop bx
mov ah, 0
int 16h
ret
;doesn't work
PROC sortArray
push bp
mov bp, sp
mov dx, 0 ;the index
mov cx, [bp+6];size
mov di, [bp+4];array
loop_arr:
add di, dx
push di
call findMin
pop di
sub di, dx
add di, min_in_array
push dx
push di
call swap
pop di
pop dx
sub di, min_in_array
inc dx
mov ax, [di]
loop loop_arr
mov sp, bp
pop bp
ret
ENDP sortArray
;works
PROC findMin
push bp
mov bp, sp
sub sp, 4
mov cx, 0 ;init the counter
mov di, [bp+4]
mov al, [bp-2] ;initialising the min save var
mov al, [di]
mov bx, [bp-4] ;the index to save
mov bx, 0
run:
cmp al, [di]
ja change_min
cmp cx, 4 ;check if cx is lower than the size of the array
inc cx ;+1
inc di ;move forward in the array
jb run ;check again
jmp fin ;finished - cx = size
change_min:
mov al, [di] ;change the min
mov bx, cx ;assign the index
inc di
cmp cx, 4
je fin
inc cx
jmp run
fin:
mov sp, bp
pop bp
mov cx, 0
mov min_in_array, bx
ret
ENDP findMin
;function works
PROC swap
;creates fram
push bp
mov bp,sp
sub sp,2 ;make space for local temp
mov bx, [bp+6]
mov cx, [bp+4]
;swaping using the temp varaiable
mov [bp-2], bx
mov bx, cx
mov cx, [bp-2]
;close frame
mov sp, bp
pop bp
ret
ENDP swap
`
У меня проблема со стеком, но я не могу его найти.
Ваше использование стека на самом деле нормально: пролог, эпилог, очистка.
Но есть еще одна вещь, в которой стек хорош, и это сохранение значений регистров. Ваша процедура sortArray зависит от регистра CX, но вы уничтожаете его значение в процедурах findMin и swap!
Вы говорите, что findMin работает, но я вас уверяю, что это не так. Помимо отсутствия сохранения CX и содержания большого количества неиспользуемого кода, findMin всегда обрабатывает 5 элементов, даже несмотря на то, что предоставленный адрес перемещается вверх с каждым вызовом, что означает, что вы обрабатываете мусор, который следует за исходным массивом в памяти. Более того, результат, который вы сохраняете в переменной min_in_array, является смещением в несортированном разделе массива, но после возврата sortArray будет использовать это же значение в качестве смещения в исходном массиве. Нельзя так работать...
Вы говорите, что обмен работает, но я уверяю вас, что это не так. То, что вы предоставляете этой процедуре, является смещением в исходном массиве и (ошибочно рассчитанным) адресом в исходном массиве. Вы извлекаете эти аргументы из стека и только меняете их местами в регистрах, не более того. Вы никогда не читаете/записываете в массив, поэтому обмен не происходит.
Посмотрите, указывает ли следующий код в правильном направлении:
add di, dx
push cx ; Number of elements in the unsorted partition
push di ; Address of the start of the unsorted partition
call findMin ; -> AX (BL CX SI)
pop di
pop cx
push ax ; Address of the Min from the unsorted partition
push di ; Address of the start of the unsorted partition
call swap
...
; IN () OUT (ax) MOD (bl,cx,si)
PROC findMin
push bp
mov bp, sp
mov cx, [bp + 6]
mov si, [bp + 4]
min:
mov bl, [si]
mov ax, si
run:
dec cx
jz done
inc si
cmp bl, [si]
jb run
jmp min ; Go change min
done:
pop bp
ret
ENDP findMin