0

5 つの数値を合計するアセンブリ コードを作成しました。その後、最終値がメモリに保存されます。

dtseg    segment
data     dw       27345,28521,29533,30105,32375
sum      dw       ?  
MSG1     DB "The sum is : $"  
dtseg    ends
;---------------------
cdseg    segment
main     proc     far
     assume   cs:cdseg,ds:dtseg,ss:stseg
     mov      ax,dtseg
     mov      ds,ax
     clc                       ; clear the carry
     mov      si,offset data   ; first location of data
     mov      cx,04            ; setting the counter
     mov      ax,0             ; clear ax
     mov      bx,ax            ; clear bx
back:add      ax,[si]          ; the first round: 0+27345
     adc      bx,0             ; if there is a carry, add that to bx
     inc      si               ; two inc because traversing words
     inc      si
     dec      cx               ; count down
     jnz      back             ; do that for other numbers
     mov      sum,ax           ; the final value
     mov      sum+2,bx         ; the carries are stored in bx

     lea      dx,MSG1          ; trying to display the result
     mov      ah,09h
     int      21h  
     mov      ah, 4cH          ; return to DOS
     int      21h
main     endp
cdseg    ends  
         end      main

このトピックに基づいた例に従いましたが、emu8086 では機能しません。

4

1 に答える 1

3

この例では、WORD 値をAX文字列に変換して出力する方法を示します。DWORD 値を文字列に変換したい。あなたの場合DIV、レジスタ DX:AX で DWORD を分割する利点を利用できます。例DXでは 0 に設定されているため、最初のアイデアは行を削除することxor dx, dxです。ただしDX、初めて必要な場合は、. の後に残りが保持されるため、クリアする必要がありますDIV。トリックは、div の前ではなく divのにクリアランスを実行することです。そのため、初めて使用され、繰り返しごとにクリアされます。

dtseg    segment
data     dw 27345,28521,29533,30105,32375   ; Sum: 147879

sum      dw  ?, ?               ; two WORD = one DWORD
MSG1     DB "The sum is : $"
DECIMAL  db "0000000000$"       ; space for the result
dtseg    ends
;---------------------
cdseg    segment
main     proc     far
     assume   cs:cdseg,ds:dtseg,ss:stseg
     mov      ax,dtseg
     mov      ds,ax
     clc                       ; clear the carry

     mov      si,offset data   ; first location of data
     mov      cx,5             ; setting the counter
     mov      ax,0             ; clear ax
     mov      bx,ax            ; clear bx
back:add      ax,[si]          ; the first round: 0+27345
     adc      bx,0             ; if there is a carry, add that to bx
     inc      si               ; two inc because traversing words
     inc      si
     dec      cx               ; count down
     jnz      back             ; do that for other numbers

     mov      sum,ax           ; the final value
     mov      sum+2,bx         ; the carries are stored in bx

     call mem_to_dec

     lea      dx,MSG1          ; trying to display the result
     mov      ah,09h
     int      21h
     lea      dx,DECIMAL          ; trying to display the result
     mov      ah,09h
     int      21h

     mov      ah, 4cH          ; return to DOS
     int      21h
main     endp

mem_to_dec proc
    mov ax, [sum]
    mov dx, [sum+2]

    mov bx, 10                  ; divisor
    xor cx, cx                  ; CX=0 (number of digits)

    @First_Loop:
        div bx                  ; DX:AX / BX = AX remainder: DX
        push dx                 ; LIFO
        inc cx                  ; increment number of digits
        xor dx, dx              ; Clear DX for the next DIV
        test  ax, ax            ; AX = 0?
        jnz @First_Loop         ; no: once more

        mov di, OFFSET DECIMAL  ; target string DECIMAL
    @Second_Loop:
        pop ax                  ; get back pushed digit
        or ax, 00110000b        ; to ASCII
        mov byte ptr [di], al   ; save AL
        inc di                  ; DI points to next character in string DECIMAL
        loop @Second_Loop       ; until there are no digits left

        mov byte ptr [di], '$'  ; End-of-string delimiter for INT 21 / FN 09h
        ret
mem_to_dec endp

cdseg    ends
         end      main

DIV結果がレジスタに収まらない場合、 に問題が発生しAXます。次に、オーバーフロー エラーが発生します。

于 2015-10-11T10:00:21.760 に答える