英文:
Allocate and initialize a vector of 20 elements in the range [20-200]. Calculate and print the average of elements divisible by 3
问题
我不知道我做错了什么。我是一个初学者。请帮助我。
这是我的代码:
DOSSEG
.MODEL SMALL
.STACK 32
.DATA
VECTOR DB 5 DUP(20H,20H,20H) ;20 DE NR PE MAXIM 3 CIFRE
KBD DB 4,0,0,0,0,0
TEN_POWER DW 100,10,1
NUMERE DB 0Dh,0Ah,'Nr=$'
MEDIE_ELEM_DIV3 DB 0
NR_ELEMENTE_DIV3 DB 0
SUMA DW 0
MSJ_SUMA DB 'SUMA=$'
FLAG DB 0
MSJ_CONTOR DB 'NR_DIV3=$'
NUMAR DW 0
NUMASC DB 0Dh,0Ah,'Suma= $'
.CODE
START:
MOV AX, @DATA
MOV DS, AX
CALL CITESTE
CALL CRLF
CALL AFISARE
CALL CRLF
CALL SUMA_NUMERE
CALL AFISARE_SUMA
CALL CRLF
CALL AFISARE_CONTOR
MOV AH, 4CH
INT 21H
CITESTE:
MOV CX, 5
MOV DI,(OFFSET VECTOR)+3
AGAIN: PUSH CX
MOV DX,OFFSET NUMERE
MOV AH,9
INT 21H ; afiseaza sir de interogare
MOV [KBD+1],0
MOV AH,0Ah
MOV DX,OFFSET KBD
INT 21H ; citeste numar cu 1 pana la 3 cifre
MOV CL,[KBD+1]
MOV CH,0
MOV SI,(OFFSET KBD)+2
PUSH DI
SUB DI,CX
NEXT:
MOV AL,[SI]
MOV [DI],AL
INC SI
INC DI
LOOP NEXT
POP DI
ADD DI,3
POP CX
LOOP AGAIN
RET
AFISARE:
MOV CX, 5
MOV SI,OFFSET VECTOR
DISP:
CALL CRLF
PUSH CX
MOV CX,3
NUM:
MOV AH,2
MOV DL,[SI]
INT 21h ; afiseaza sirul de numere
INC SI
LOOP NUM
POP CX
LOOP DISP
RET
CRLF:
MOV AH,2
MOV DL,0Ah
INT 21h
MOV AH,2
MOV DL,0Dh
INT 21h
RET
SUMA_NUMERE:
MOV CX, 5 ;ITERARE CELE 20 ELEM VECTOR
MOV SUMA, 0 ; INITIALIZARE CU 0
MOV [NR_ELEMENTE_DIV3], 0
MOV BP, 0
ASC_BIN:
PUSH CX
MOV CX, 3 ;AM 3 CIFRE
MOV BX, 10
MOV SI, OFFSET VECTOR
AGAIN2: MOV AX,[NUMAR]
MUL BX ; inmulteste suma partiala cu 10
MOV DL,[SI]
MOV DH,0
AND DL,0FH ; conversie ASCII binar pentru cifra curenta
ADD AX,DX ; aduna cifra curenta
MOV [NUMAR],AX ;NUMAR E NR MEU IN BINAR
LOOP AGAIN2
POP CX
CMP BP, 35H
JE END
INC BP
CONDITIE_DIV3:
XOR AX,AX
MOV AX,[NUMAR] ;PUN IN AX NR IN BINAR
MOV BL, 3
DIV BL ;IMPART ELEMENTUL LA 3
CMP AH, 0 ;COMPAR RESTUL CU 0
JNE NU_E_DIV3
ADD [SUMA], AX ;ADAUGA IN SUMA NR DIV 3
ADD [NR_ELEMENTE_DIV3], 1
INC SI
NU_E_DIV3:
INC SI
JMP AGAIN2
END: RET
AFISARE_SUMA:
BIN_ASC: MOV CX,4 ; din numere binare pe 16 biti
; pot rezulta siruri ASCII cu 5 cifre
MOV SI,OFFSET TEN_POWER ; pointer spre tabela puterilor lui 10
MOV DI,(OFFSET NUMASC)+7
NEXT3:
MOV AX,[SUMA]
MOV DX,0 ; pregateste deimpartitul pe 32 de biti
DIV WORD PTR [SI] ; obtine catul curent
MOV [SUMA],DX ; salveaza restul curent
OR AL,30H ; salveaza codul ASCII al cifrei curente
MOV [DI],AL
INC DI
ADD SI,2 ; avanseaza pointerul spre urmatoarea putere a lui 10
LOOP NEXT3
OR DL,30H ; salveaza codul ASCII al ultimei cifre (cifra unitatilor)
MOV [DI],DL
MOV AH, 09h
MOV DX, OFFSET NUMASC
INT 21H
RET
AFISARE_CONTOR:
AND [NR_ELEMENTE_DIV3], 0FH ; masca ultimii 4 biti - obtinem cifra coresp caracterului
MOV AH, 2 ;pregatire pt afisarea caracterului
MOV DL, 0DH ; carriage return
INT 21H ;apelarea intreruperii
MOV AH, 2
MOV DL, 0AH ;line feed
INT 21H
REZULTAT:
MOV AH, 9 ;pregatirea pentru afisarea unui string
MOV DX, OFFSET MSJ_CONTOR ;sirul FINAL 'NR_DIV3=&'
INT 21H
MOV AL, [NR_ELEMENTE_DIV3] ;NUMARUL
MOV AH, 0 ; deimpartitul este ax
MOV BL, 10 ;impart
<details>
<summary>英文:</summary>
I don't know what I'm doing wrong. I'm a beginner. Please help me.
This is my code:
DOSSEG
.MODEL SMALL
.STACK 32
.DATA
VECTOR DB 5 DUP(20H,20H,20H) ;20 DE NR PE MAXIM 3 CIFRE
KBD DB 4,0,0,0,0,0
TEN_POWER DW 100,10,1
NUMERE DB 0Dh,0Ah,'Nr=$'
MEDIE_ELEM_DIV3 DB 0
NR_ELEMENTE_DIV3 DB 0
SUMA DW 0
MSJ_SUMA DB 'SUMA=$'
FLAG DB 0
MSJ_CONTOR DB 'NR_DIV3=$'
NUMAR DW 0
NUMASC DB 0Dh,0Ah,'Suma= $'
.CODE
START:
MOV AX, @DATA
MOV DS, AX
CALL CITESTE
CALL CRLF
CALL AFISARE
CALL CRLF
CALL SUMA_NUMERE
CALL AFISARE_SUMA
CALL CRLF
CALL AFISARE_CONTOR
MOV AH, 4CH
INT 21H
CITESTE:
MOV CX, 5
MOV DI,(OFFSET VECTOR)+3
AGAIN: PUSH CX
MOV DX,OFFSET NUMERE
MOV AH,9
INT 21H ; afiseaza sir de interogare
MOV [KBD+1],0
MOV AH,0Ah
MOV DX,OFFSET KBD
INT 21H ; citeste numar cu 1 pana la 3 cifre
MOV CL,[KBD+1]
MOV CH,0
MOV SI,(OFFSET KBD)+2
PUSH DI
SUB DI,CX
NEXT:
MOV AL,[SI]
MOV [DI],AL
INC SI ; memoreaza numar
INC DI
LOOP NEXT
POP DI
ADD DI,3
POP CX
LOOP AGAIN
RET
AFISARE:
MOV CX, 5
MOV SI,OFFSET VECTOR
DISP:
CALL CRLF
PUSH CX
MOV CX,3
NUM:
MOV AH,2
MOV DL,[SI]
INT 21h ; afiseaza sirul de numere
INC SI
LOOP NUM
POP CX
LOOP DISP
RET
CRLF:
MOV AH,2
MOV DL,0Ah
INT 21h
MOV AH,2
MOV DL,0Dh
INT 21h
RET
SUMA_NUMERE:
MOV CX, 5 ;ITERARE CELE 20 ELEM VECTOR
MOV SUMA, 0 ; INITIALIZARE CU 0
MOV [NR_ELEMENTE_DIV3], 0
MOV BP, 0
ASC_BIN:
PUSH CX
MOV CX, 3 ;AM 3 CIFRE
MOV BX, 10
MOV SI, OFFSET VECTOR
AGAIN2: MOV AX,[NUMAR]
MUL BX ; inmulteste suma partiala cu 10
MOV DL,[SI]
MOV DH,0
AND DL,0FH ; conversie ASCII binar pentru cifra curenta
ADD AX,DX ; aduna cifra curenta
MOV [NUMAR],AX ;NUMAR E NR MEU IN BINAR
LOOP AGAIN2
POP CX
CMP BP, 35H
JE END
INC BP
CONDITIE_DIV3:
XOR AX,AX
MOV AX,[NUMAR] ;PUN IN AX NR IN BINAR
MOV BL, 3
DIV BL ;IMPART ELEMENTUL LA 3
CMP AH, 0 ;COMPAR RESTUL CU 0
JNE NU_E_DIV3
ADD [SUMA], AX ;ADAUGA IN SUMA NR DIV 3
ADD [NR_ELEMENTE_DIV3], 1
INC SI
NU_E_DIV3:
INC SI
JMP AGAIN2
END: RET
AFISARE_SUMA:
BIN_ASC: MOV CX,4 ; din numere binare pe 16 biti
; pot rezulta siruri ASCII cu 5 cifre
MOV SI,OFFSET TEN_POWER ; pointer spre tabela puterilor lui 10
MOV DI,(OFFSET NUMASC)+7
NEXT3:
MOV AX,[SUMA]
MOV DX,0 ; pregateste deimpartitul pe 32 de biti
DIV WORD PTR [SI] ; obtine catul curent
MOV [SUMA],DX ; salveaza restul curent
OR AL,30H ; salveaza codul ASCII al cifrei curente
MOV [DI],AL
INC DI
ADD SI,2 ; avanseaza pointerul spre urmatoarea putere a lui 10
LOOP NEXT3
OR DL,30H ; salveaza codul ASCII al ultimei cifre (cifra unitatilor)
MOV [DI],DL
MOV AH, 09h
MOV DX, OFFSET NUMASC
INT 21H
RET
AFISARE_CONTOR:
AND [NR_ELEMENTE_DIV3], 0FH ; masca ultimii 4 biti - obtinem cifra coresp caracterului
MOV AH, 2 ;pregatire pt afisarea caracterului
MOV DL, 0DH ; carriage return
INT 21H ;apelarea intreruperii
MOV AH, 2
MOV DL, 0AH ;line feed
INT 21H
REZULTAT:
MOV AH, 9 ;pregatirea pentru afisarea unui string
MOV DX, OFFSET MSJ_CONTOR ;sirul FINAL 'NR_DIV3='
INT 21H
MOV AL, [NR_ELEMENTE_DIV3] ;NUMARUL
MOV AH, 0 ; deimpartitul este ax
MOV BL, 10 ;impartitorul
DIV BL ;imparitm ax la bl -> al = catul si ah = restul
PUSH AX ;salvez pe stiva rez impartirii
CMP AL, 0 ;daca suma are o singrua cifra
JE O_CIFRA ; sare si nu o mai afiseaza pe prima
MOV DL, AL ; pt afisarea catului, adica a primei cifre din suma
OR DL, 30H ;codul ascii al caracterului coresp cifrei din tabela ascii
MOV AH, 2
INT 21H
O_CIFRA:
POP AX ;scoate din stiva continutul reg ax
MOV DL, AH ;pt afisarea restului, adica celei de a doua cifre
OR DL, 30H ;obtinerea caract corespunzator
MOV AH, 2 ;pregatirea pt afisare
INT 21H ;apelarea intreruperii
RET
END START
- I stored the numbers that I read from the stdin in ASCII and in the function where I want to make the sum.
- I iterate the array and convert each element in binary
- Then I tried to check the divisibility by dividing the number with 3.
But it doesn't work. It shows me the sum 0 and the contor of the numbers that are divisible with 3 to be 1.
I would appreciate any helpful input.
</details>
# 答案1
**得分**: 0
*NUMAR* 不正确
-
每次你想要计算它时,你需要先将其值重置为零。在*AGAIN2*循环中,你忘记了增加SI以使用所有不同的数字。一旦`inc si`放在适当的位置,你就不再需要在*NU_E_DIV3:*标签周围拥有其他`INC SI`指令。
mov NUMAR, 0
MOV CX, 3 ; AM 3 CIFRE
MOV SI, OFFSET VECTOR
AGAIN2:
MOV AX, 10
MUL NUMAR ; inmulteste suma partiala cu 10
MOV DL, [SI]
AND dx, 000Fh ; conversie ASCII binar pentru cifra curenta
ADD AX, DX ; aduna cifra curenta
MOV NUMAR, AX ; NUMAR E NR MEU IN BINAR
inc si
LOOP AGAIN2
*SUMA* 小了3倍
-
因为你在将AX除以3之后直接将AX添加到*SUMA*,所以你添加的值将不反映*NUMAR*的原始值。
MOV AX, NUMAR ; PUN IN AX NR IN BINAR
MOV BL, 3
DIV BL ; IMPART ELEMENTUL LA 3
CMP AH, 0 ; COMPAR RESTUL CU 0
JNE AGAIN2 ; NU_E_DIV3
mov ax, NUMAR
ADD [SUMA], AX
inc [NR_ELEMENTE_DIV3]
JMP AGAIN2
*SUMA_NUMERE* 循环不正确
-
你有一个`MOV CX,5`,后面没有使用,而且你有一个`CMP BP, 35H` `JE END`,这远远超过了你的数据项数量!你需要选择要使用的部分...
*AFISARE_SUMA* 做得太多
-
*TEN_POWER* 列表只有3个元素。你不能迭代4(+ 1)次(`; pot rezulta siruri ASCII cu 5 cifre`)。
<details>
<summary>英文:</summary>
*NUMAR* is not correct
-
Each time that you want to calculate it, you need to reset its value to zero beforehand. And in the *AGAIN2* loop you forgot to increment SI so as to use all the different digits. Once this `inc si` is in place, you no longer need the other `INC SI` instructions that you have around the label *NU_E_DIV3:*.
mov NUMAR, 0 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
MOV CX, 3 ; AM 3 CIFRE
MOV SI, OFFSET VECTOR
AGAIN2:
MOV AX, 10
MUL NUMAR ; inmulteste suma partiala cu 10
MOV DL, [SI]
AND dx, 000Fh ; conversie ASCII binar pentru cifra curenta
ADD AX, DX ; aduna cifra curenta
MOV NUMAR, AX ; NUMAR E NR MEU IN BINAR
inc si <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
LOOP AGAIN2
*SUMA* is 3x smaller
-
Because you add AX to *SUMA* directly after you divided AX by 3, what you add will not reflect the original value of *NUMAR*.
MOV AX, NUMAR ; PUN IN AX NR IN BINAR
MOV BL, 3
DIV BL ; IMPART ELEMENTUL LA 3
CMP AH, 0 ; COMPAR RESTUL CU 0
JNE AGAIN2 ; NU_E_DIV3
mov ax, NUMAR <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
ADD [SUMA], AX
inc [NR_ELEMENTE_DIV3]
JMP AGAIN2
*SUMA_NUMERE* does not loop good
-
You have `MOV CX,5` that you don't use later on, and you have `CMP BP, 35H` `JE END` that is much more than you have data items for!
You need to choose which you want to use...
*AFISARE_SUMA* does too much
-
The *TEN_POWER* list has but 3 elements. You can't iterate 4 (+ 1) times (`; pot rezulta siruri ASCII cu 5 cifre`).
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论