Ответ 1
Вот решение для EMU8086:
.stack 100h
.data
msj1 db 'Enter first number: $'
msj2 db 'Enter second number: $'
num1 dw ? ;FIRST NUMBER OF INTERVAL.
num2 dw ? ;SECOND NUMBER OF INTERVAL.
str db 6 ;MAX NUMBER OF CHARACTERS ALLOWED (4).
db ? ;NUMBER OF CHARACTERS ENTERED BY USER.
db 6 dup (?) ;CHARACTERS ENTERED BY USER.
crlf db 13,10,'$' ;LINE BREAK.
plus db '+$' ;PLUS SIGN TO DISPLAY.
back db 8,'$' ;CURSOR WILL MOVE ONE PLACE BACK (TO THE LEFT).
ekual db '=$' ;EQUAL SIGN TO DISPLAY.
suma dw 0 ;SUMATORY OF ALL NUMBERS BETWEEN NUM1 AND NUM2.
.code
;INITIALIZE DATA SEGMENT.
mov ax, @data
mov ds, ax
;DISPLAY MESSAGE FOR FIRST NUMBER.
mov ah, 9
mov dx, offset msj1
int 21h
;CAPTURE NUMBER AS STRING.
mov ah, 0Ah
mov dx, offset str
int 21h
;CONVERT CAPTURED NUMBER FROM STRING TO NUMERIC.
mov si, offset str ;PARAMETER FOR STRING2NUMBER.
call string2number
mov num1, bx ;RETURNED VALUE.
;DISPLAY TWO LINE BREAKS.
mov ah, 9
mov dx, offset crlf
int 21h
mov ah, 9
mov dx, offset crlf
int 21h
;DISPLAY MESSAGE FOR SECOND NUMBER.
mov ah, 9
mov dx, offset msj2
int 21h
;CAPTURE NUMBER AS STRING.
mov ah, 0Ah
mov dx, offset str
int 21h
;CONVERT CAPTURED NUMBER FROM STRING TO NUMERIC.
mov si, offset str ;PARAMETER FOR STRING2NUMBER.
call string2number
mov num2, bx ;RETURNED VALUE.
;DISPLAY TWO LINE BREAKS.
mov ah, 9
mov dx, offset crlf
int 21h
mov ah, 9
mov dx, offset crlf
int 21h
;ASURE FIRST NUMBER IS LESS THAN THE SECOND.
mov ax, num1
cmp ax, num2
jbe fine ;IF AX < NUM2 JUMP FINE.
xchg ax, num2 ;EXCHANGE : NUM2=AX, AX=NUM2.
mov num1, ax ;NUM1=NUM2.
fine:
;DISPLAY THE INTERVAL.
call display_interval
;WAIT UNTIL USER PRESS ANY KEY.
mov ah,7
int 21h
;FINISH PROGRAM.
mov ax, 4c00h
int 21h
;------------------------------------------
;DISPLAY ALL NUMBERS BETWEEN NUM1 AND NUM2
;SEPARATED BY '+' AND DISPLAYS THE SUM
proc display_interval
interval:
;ADD CURRENT NUMBER TO SUMA.
mov ax, num1 ;AX = CURRENT NUMBER.
add suma, ax
;CONVERT CURRENT NUMBER TO STRING TO DISPLAY IT.
call dollars ;FILL "STR" WITH '$'. NEEDED TO DISPLAY.
call number2string ;PARAMETER = AX. RETURNS IN VARIABLE "STR".
;DISPLAY NUMBER CONVERTED TO STRING.
mov ah, 9
mov dx, offset str
int 21h
;DISPLAY PLUS SIGN.
mov ah, 9
mov dx, offset plus
int 21h
;NEXT NUMBER TO DISPLAY.
inc num1
mov ax, num1
cmp ax, num2
jbe interval ;IF AX <= NUM2 THEN REPEAT.
;DISPLAY THE SUMA.
;DISPLAY BACKSPACE (TO DELETE LAST PLUS SIGN).
mov ah, 9
mov dx, offset back
int 21h
;DISPLAY EQUAL SIGN.
mov ah, 9
mov dx, offset ekual
int 21h
;CONVERT SUMA TO STRING TO DISPLAY IT.
call dollars ;FILL "STR" WITH '$'. NEEDED TO DISPLAY.
mov ax, suma
call number2string ;PARAMETER = AX. RETURNS IN VARIABLE "STR".
;DISPLAY NUMBER CONVERTED TO STRING.
mov ah, 9
mov dx, offset str
int 21h
ret
endp
;------------------------------------------
;CONVERT STRING TO NUMBER IN BX.
;SI MUST ENTER POINTING TO THE STRING.
proc string2number
;MAKE SI TO POINT TO THE LEAST SIGNIFICANT DIGIT.
inc si ;POINTS TO THE NUMBER OF CHARACTERS ENTERED.
mov cl, [ si ] ;NUMBER OF CHARACTERS ENTERED.
mov ch, 0 ;CLEAR CH, NOW CX==CL.
add si, cx ;NOW SI POINTS TO LEAST SIGNIFICANT DIGIT.
;CONVERT STRING.
mov bx, 0
mov bp, 1 ;MULTIPLE OF 10 TO MULTIPLY EVERY DIGIT.
repeat:
;CONVERT CHARACTER.
mov al, [ si ] ;CHARACTER TO PROCESS.
sub al, 48 ;CONVERT ASCII CHARACTER TO DIGIT.
mov ah, 0 ;CLEAR AH, NOW AX==AL.
mul bp ;AX*BP = DX:AX.
add bx,ax ;ADD RESULT TO BX.
;INCREASE MULTIPLE OF 10 (1, 10, 100...).
mov ax, bp
mov bp, 10
mul bp ;AX*10 = DX:AX.
mov bp, ax ;NEW MULTIPLE OF 10.
;CHECK IF WE HAVE FINISHED.
dec si ;NEXT DIGIT TO PROCESS.
loop repeat ;COUNTER CX-1, IF NOT ZERO, REPEAT.
ret
endp
;------------------------------------------
;FILLS VARIABLE STR WITH '$'.
;USED BEFORE CONVERT NUMBERS TO STRING, BECAUSE
;THE STRING WILL BE DISPLAYED.
proc dollars
mov si, offset str
mov cx, 6
six_dollars:
mov bl, '$'
mov [ si ], bl
inc si
loop six_dollars
ret
endp
;------------------------------------------
;NUMBER TO CONVERT MUST ENTER IN AX.
;ALGORITHM : EXTRACT DIGITS ONE BY ONE, STORE
;THEM IN STACK, THEN EXTRACT THEM IN REVERSE
;ORDER TO CONSTRUCT STRING (STR).
proc number2string
mov bx, 10 ;DIGITS ARE EXTRACTED DIVIDING BY 10.
mov cx, 0 ;COUNTER FOR EXTRACTED DIGITS.
cycle1:
mov dx, 0 ;NECESSARY TO DIVIDE BY BX.
div bx ;DX:AX / 10 = AX:QUOTIENT DX:REMAINDER.
push dx ;PRESERVE DIGIT EXTRACTED FOR LATER.
inc cx ;INCREASE COUNTER FOR EVERY DIGIT EXTRACTED.
cmp ax, 0 ;IF NUMBER IS
jne cycle1 ;NOT ZERO, LOOP.
;NOW RETRIEVE PUSHED DIGITS.
mov si, offset str
cycle2:
pop dx
add dl, 48 ;CONVERT DIGIT TO CHARACTER.
mov [ si ], dl
inc si
loop cycle2
ret
endp
Далее ваш код с некоторыми изменениями, теперь он принимает два параметра из стека и внутренне помещает их в переменные num1 и num2. Я не забочусь о параметрах для всей "печати":
proc display_interval
;RETRIEVE PARAMETERS.
pop ax ;RETURN ADDRESS.
pop num2 ;NUM2.
pop num1 ;NUM1.
push ax ;RETURN ADDRESS BACK (NECESSARY FOR "RET").
print msg4
interval:
;ADD CURRENT NUMBER TO SUMA.
mov ax, x ;AX = CURRENT NUMBER.
add k, ax
;CONVERT CURRENT NUMBER TO STRING TO DISPLAY IT.
call dollars ;FILL "STR" WITH '$'. NEEDED TO DISPLAY.
call number2string ;PARAMETER = AX. RETURNS IN VARIABLE "STR".
;DISPLAY NUMBER CONVERTED TO STRING.
mov ah, 9
mov dx, offset str
int 21h
;DISPLAY PLUS SIGN.
mov ah, 9
mov dx, offset plus
int 21h
;NEXT NUMBER TO DISPLAY.
inc x
mov ax, x
cmp ax, y
jbe interval ;IF AX <= NUM2 THEN REPEAT.
;DISPLAY THE SUMA.
;DISPLAY BACKSPACE (TO DELETE LAST PLUS SIGN).
print back
;DISPLAY EQUAL SIGN.
print equal
;CONVERT SUMA TO STRING TO DISPLAY IT.
call dollars ;FILL "STR" WITH '$'. NEEDED TO DISPLAY.
mov ax, k
call number2string ;PARAMETER = AX. RETURNS IN VARIABLE "STR".
;DISPLAY NUMBER CONVERTED TO STRING.
mov ah, 9
mov dx, offset str
int 21h
ret
endp
Процедура "display_interval" должна быть вызвана следующим образом:
mov ax, 1
push ax ;FIRST PARAMETER.
mov ax, 5
push ax ;SECOND PARAMETER.
call display_interval