Добавление подписанных чисел в сборке


Я хочу суммировать элементы массива. Этот массив содержит положительные и отрицательные числа.

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 4

1 ответ:

Похоже, что вы не обрабатываете переполнение целых чисел должным образом. Флаг Carry предназначен длябеззнакового сложения и вычитания, но вы хотитеподписанного сложения. Флаг переполнения предназначен для добавления знака, он устанавливается всегда при изменении знака.

Edit: Предыдущий непроверенный код не работал должным образом. Вот исправленный (и самодостаточный) код. Испытано с 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 делает логические и, но не сохраняет результат, он только обновляет флаги):

        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: