汇编 - 如何在两个数字之间进行求和(间隔)

时间:2015-04-23 09:38:02

标签: assembly x86

嘿,伙计们能帮帮忙吗?我不知道如何在两个数字之间进行求和 例如:

第一个数字> 1

第二个数字> 5

总和将是> 1 + 2 + 3 + 4 + 5 = 15

我只做了两个数字的总和。我不知道如何做这个数字序列,我的代码如下。谢谢

MAIN:
    MOV AX, SEG DATA
    MOV DS,AX

    mov ah, 9h                  ; msg for first number
    lea dx, msg
    int 21H

    mov ah, 1h                  ; read char
    int 21H

    sub al, '0'                 ; strip ASCII
    mov x, al                   ; storing first number

    mov ah, 9h                  ; msg for second number
    lea dx, msg2
    int 21H

    mov ah, 1h                  ; read char
    int 21H

    sub al, '0'
    mov y, al                   ; storing second number

    mov ah, 9h                  ; msg for sum
    lea dx, msg3
    int 21H

    mov dl, x
    add dl, y
    add dl, '0'                 ; x + y

    mov ah, 2h                  ; printing
    int 21H


    MOV AX,4C00H    ;end
    INT 21H

CODE ENDS
    END MAIN

4 个答案:

答案 0 :(得分: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中。我没有处理所有&#34; print&#34;的参数。 :

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  

程序&#34; display_interval&#34;应该像这样调用:

mov  ax, 1
push ax      ;FIRST PARAMETER.
mov  ax, 5
push ax      ;SECOND PARAMETER.
call display_interval

答案 1 :(得分:0)

这是伪代码(由你来翻译成汇编):

count = firstNumber
endCount = secondNumber + 1
total = 0
while count != endCount
    total = total + count
    count = count + 1

答案 2 :(得分:0)

您可以使用条件跳转来执行此操作。 下面是一个简单的代码段,其中ebx包含要添加的当前数字,ecx包含循环运行的次数(即second_number - first_number +1)。 sum将存储在eax中。

mov eax,0               ; initialise sum with 0
mov ebx,dword[first_number]    ;initialise ebx with first_number
mov ecx,dword[second_number]  
sub ecx,dword[first_number]
inc ecx                 ; ecx content will be end_number - start_number + 1, now
calculation:            ; after calculation sum can be accessed from eax
        add eax,ebx     ; sum = sum + ebx content
        inc ebx         ; ebx = ebx + 1
        dec ecx         ; ecx = ecx - 1
        cmp ecx,0h      ; ecx == 0 ?
        jne calculation ; if not then once again go through calculation.

答案 3 :(得分:0)

proc display_interval

    push BP                 
    mov BP, SP
    mov AX, [BP+4]
    mov SP, BP
    pop BP

    print msg4
interval:    
    mov  ax, num1       ;AX = CURRENT NUMBER.
    add  suma, ax
    ;CONVERT CURRENT NUMBER TO STRING.
    call dollars        ;FILL "STR" WITH '$'.
    call number2string  ;PARAMETER = AX.

    mov  ah, 9
    mov  dx, offset str
    int  21h

    mov  ah, 9
    mov  dx, offset plus
    int  21h

    inc  num1
    mov  ax, num1
    cmp  ax, num2
    jbe  interval   ;IF AX <= NUM2


    ;BACKSPACE (DELETE LAST +).
    print back
    print equal

    call dollars        ;FILL "STR" WITH '$'.
    mov  ax, suma
    call number2string  ;PARAMETER = AX.

    mov  ah, 9
    mov  dx, offset str
    int  21h

    ;-------------------------------------------
    ;IF SUMA IS EVEN RET WILL JUMP FEW ROWS BELOW(d2)
    mov dx,0                ;dividing
    mov bl,suma
    mov ax,bx
    mov cl,2
    div cl                  ;the remainder from division stores in AH
    mov dl,ah
    add dl,48               ;48 ASCII is 0, for compare
    cmp dl,48               ;0?
    je  d2                  
                            ;dividing end
    pop ax
    mov sp,bp
    pop bp
    ret                     ;normal RET

d2: pop ax
    mov dx,583              ;number whitch it jumps from RET
    mov [bp+2],dx
    mov sp,bp
    pop bp
    ret                     ; jumping RET, if suma is even

endp