在汇编中添加带符号的数字

时间:2013-11-30 15:57:34

标签: assembly x86 signed addition x86-16

我想总结一个数组元素。该数组包含正数和负数。

array db 07, 00, -3, 10, -7, 14, 9, -5, -100


lea ax, data
mov ds, ax
mov es, ax

lea si, array
mov cx, [si] 
mov si, 0002h
xor ax, ax
xor dx, dx 
Addition:
mov bl, [si]
cmp bl, 00h
jl NEGATIVE
xor bh, bh ;
jmp NEXTT
NEGATIVE:
mov bh, 0ffh
NEXTT:
add ax, bx
adc dx, 0
add si, 1
loop Addition

使用此代码的总和(DX:AX)= 0003 FFAE H,这是错误的。我认为正确的答案是 FFFFFFAE H。

1-如何解决此问题?

2-如何知道寄存器中的数字(例如AX)是正数还是负数?

我使用的是emu8086

1 个答案:

答案 0 :(得分:5)

您似乎没有适当地处理整数溢出。进位标志用于无符号加法和减法,但您需要已签名添加。溢出标志用于签名添加,它始终在符号更改时设置。

修改:之前未经测试的代码无法正常运行。这是更正(和自包含)的代码。用MASM 6.11测试。

.model small
.stack 4096

.data
array_size      dw 7
array           db -3, 10, -7, 14, 9, -5, -100
numbers         db '0123456789abcdef'

.code
start:
        mov     ax,seg array_size ; lea ax, data
        mov     ds,ax
        mov     es,ax

        mov     cx,[array_size]   ; cx = array size in bytes.
        lea     si,array          ; si points to the array.

; number is computed in dx:bx.

        xor     dx,dx
        xor     bx,bx

adding_loop:
        mov     al,[si]           ; number is read in al.
        cbw                       ; cbw sign-extends al to ax.
        test    ax,ax             ; check the sign of the addend.
        js      negative

positive:                         ; the addend is positive.
        add     bx,ax             ; add.
        adc     dx,0              ; carry.
        jmp     next_number

negative:                         ; the addend is negative.
        neg     ax                ; ax = |ax|.
        sub     bx,ax             ; subtract.
        sbb     dx,0              ; borrow.

next_number:
        inc     si                ; next number.
        loop    adding_loop

; result now in dx:bx.

        mov     ax,bx             ; result now in dx:ax.

; the rest of the code is only for printing.

        push    bx                ; push lower word.
        mov     bx,dx             ; copy the upper word to bx.
        call    print_word_in_hexadecimal

        push    dx                ; push upper word.
        mov     ah,2
        mov     dl,':'
        int     21h               ; print ':'
        pop     dx                ; pop upper word.

        pop     bx                ; pop lower word.
        call    print_word_in_hexadecimal

        mov     ah,4ch
        int     21h

; input:        bx: word to be printed.
; output:       -
print_word_in_hexadecimal:
        push    bx
        push    cx
        push    dx
        mov     cl,4              ; count for rol.
        mov     ch,4              ; 4 nibbles in each word.
next_nibble:
        rol     bx,cl             ; rotate 4 bits to the left.
        push    bx                ; push rotated word.
        and     bx,0fh
        mov     dl,[bx+numbers]
        mov     ah,2              ; print character.
        int     21h
        pop     bx                ; pop rotated word.
        dec     ch
        jnz     next_nibble

        pop     dx
        pop     cx
        pop     bx
        ret
end start

上面的代码对8位值进行有符号整数加法(8位值扩展为16位值)。注册用法已更改为允许使用cbw更清晰的代码。为简单起见,添加负数已转换为减法。数组(mov si, 0002h的硬编码偏移量仅在数组位于偏移量2时有效)已替换为lea si,array

size_of_array dw 7
array         db -3, 10, -7, 14, 9, -5, -100

代码中的相应更改:

lea si, size_of_array ; or you can replace these 2 lines with:
mov cx, [si]          ; 1. mov cx,size_of_array (TASM/MASM syntax).
lea si, array

如何检查数字是负数还是正数?好吧,你检查最高位。例如,在我的代码中(test执行逻辑AND但不保存结果,它只更新标志):

        test    ax,ax    ; do logical AND for ax,ax but don't save the result.
        js      negative ; jumps if the number is negative.

positive:
        ; the number is positive.
        jmp     my_label

negative:
        ; the number is negative.

my_label: