我创建了一个程序来选择对单词向量进行排序,但是有一个问题:排序是完全错误的。
我的载体:VET_2 DW 2, 7, 0, 1, 4, 8, 9, 3, 6, 5
; Selection Sort
SELECTION_SORT PROC
; AX = j & aux CX = i
; BX = offset/min DX = data and others
PUSH 0 ; to initialize i
MOV SI, [OFFSET VET_2]
; ----- start for(int i = 0; i < n-1; i++) -----
SLC_LOOP_FORA: ; outer loop
CALL RESET_REGIST ; reset some AX, BX, CX & DX
CALL RESET_VAR ; used to reset AUX
POP CX ; initialize i
CMP CX, 18 ; check if it's smaller than n-1 (20-2=18)
JGE SLC_FIM ; if bigger, goes to the end
MOV BX, CX ; offset receive i, the position of the smaller
; ----- start j = i+1 -----
MOV AX, CX ; AX = j.
ADD AX, 2 ; j = i+1
; ----- end j = i+1 -----
; ----- start for(int j = i+1; j < n; j++) -----
SLC_LOOP_DENTRO: ; inner loop
MOV DX, [SI+BX] ; move the smaller element to DX
MOV BX, AX ; offset receives j
CMP DX, [SI+BX] ; compare if VET_2[min]<=VET_2[j]
JL SLC_DENTRO_PULAR ; if lesser, ignore the code below
MOV BX, AX ; offset receive j, position of the smaller element
SLC_DENTRO_PULAR:
ADD AX, 2 ; inc 2 in j
CMP AX, 20 ; compare j (ax) with n
JL SLC_LOOP_DENTRO ; if it's smaller, repeat inner loop
; ----- end for(int j = n+1; j < n; j++) -----
CMP CX, BX ; compare i with the position of the smaller element
JE SLC_LOOP_FORA ; if equals, repeat outer loop, otherwise do the swap
PUSH BX ; position of the smaller element
PUSH [SI+BX] ; put vet[min] top of the stack
; ----- start aux = vet[i] -----
MOV BX, CX ; offset (BX) receives i
MOV DX, [SI+BX] ; DX receives vet_2[i]
MOV AUX, DX ; AUX receives DX
; ----- end aux = vet[i] -----
; ----- start vet[i] = vet[min] -----
POP AX ; AX receives the top of the stack (vet_2[min])
MOV [SI+BX], AX ; vet_2[i] receives DX (smaller element)
; ----- end vet[i] = vet[min] -----
; ----- start vet[min] = aux -----
POP BX ; offset (BX) receives the position of the smaller element from the stack
MOV DX, AUX ; DX receives AUX
MOV [SI+BX], DX ; vet_2[min] receives DX
; ----- end vet[min] = aux -----
ADD CX, 2 ; INC 2 on i
PUSH CX ; put in the stack
JMP SLC_LOOP_FORA repeat outer loop
; ----- end for(int i = 0; i < n-1; i++) -----
SLC_FIM: ; end the procedure
RET
SELECTION_SORT ENDP
在进行呼叫选择排序之前: 2 7 0 1 4 8 9 3 6 5
呼叫选择后的排序过程: 5 2 7 0 1 4 8 9 3 6
错误在哪里?有人可以帮我吗?
答案 0 :(得分:2)
当您不需要交换2个元素时,您仍然需要提高CX
中的下限。 cmp cx, bx
je SLC_LOOP_FORA
忽略了这一点。而且,它使您的堆栈不平衡(弹出次数超过了推送的次数)。
通过引入额外的标签可以轻松地解决问题(包括堆栈不平衡):
PUSH 0 ; to initialize i
MOV SI, OFFSET VET_2
SLC_LOOP_FORA: ; outer loop
...
CMP CX, BX ; compare i with the position of the smaller element
JE NO_SWAP ; if equals, repeat outer loop, otherwise do the swap
...
NO_SWAP:
ADD CX, 2 ; INC 2 on i
PUSH CX ; put in the stack
JMP SLC_LOOP_FORA ; repeat outer loop
; AX = j & aux CX = i ; BX = offset/min DX = data and others PUSH 0 ; to initialize i MOV SI, [OFFSET VET_2]
如果您愿意重新分配寄存器,则可以极大地简化该程序。
具有类似寄存器的分配
; AX = j & aux DI = i
; SI = offset/min DX = data and others
PUSH 0 ; to initialize i
MOV BX, OFFSET VET_2
交换代码,例如会变成以下3条指令:
mov ax, [bx+si]
xchg ax, [bx+di]
mov [bx+si], ax
答案 1 :(得分:1)
elementsRow.length
我从未见过可以这样做的汇编器!上面的设置yarn add --dev jest
寄存器等于第一个数组元素的内容,因此MOV SI, [OFFSET VET_2]
。不太有用。
可接受的获取载体地址的说明是:
SI
或
SI=2
或
mov si, offset VET_2
答案 2 :(得分:-3)
selection_sort_i64:
; /*
; Input:
; RDI = long long * array
; RSI = length
;
; Pseudo-C code:
;
; for (int i = 0; i < n - 1; ++i) {
; min = i
; for (int j = i + 1; j < n; ++j) {
; if a[j] < a[min]; min = j
; swap(i, min)
;*/
I64_SIZE equ 8
LG_I64_SIZE equ 3
cmp rsi, 1
jle .end ; Just end it if length <= 1
xchg rsi, rdi ; rsi => left pointer
mov rcx, rdi ; rcx => length
; RDX will be the boundary for i: RSI + (N-1)*sizeof(int64)
lea rdx, [rsi + rcx * LL_SIZE - LL_SIZE]
; /*
; Let's explain what's happening here.
; RSI will be &a[i], RDX will be it's right boundary
; RDI will be &a[j] (&a[i + 1]) and will loop n-i times
; RCX will be n-i and will be the counter for the inner loop
; RAX will track our minimum in the remaining of the array
; RBX will
; */
.outer_loop:
cmp rsi, rdx
jge .end ; while (i < n - 1) {
mov rax, [rsi] ; min = a[i]
mov rbx, rsi ; min_i = i
push rax
mov rdi, rsi
add rdi, I64_SIZE ; j = i + 1 // rdi => right pointer
dec rcx ; // rcx = n - i, inner loop counter
push rcx
.inner_loop:
cmp rax, [rdi] ; if (min > a[j])
jle .min_less_or_equal
mov rbx, rdi ; min_i = j
mov rax, [rdi] ; min = a[j]
.min_less_or_equal:
add rdi, I64_SIZE ; j += 1
loop .inner_loop
pop rcx ; // restore inner loop counter
pop rax ; // restore a[i]
cmp rsi, rbx ; // swap if minimum found
jz .no_min ; if (i != min_i)
mov rdi, [rbx] ; temp = a[min]
mov [rbx], rax ; a[min] = a[i]
mov [rsi], rdi ; a[i] = temp
.no_min:
add rsi, I64_SIZE ; i += 1
jmp .outer_loop ; } // end outer loop
.end:
ret
希望这行得通。谢谢。