Добавление подписанных чисел в сборке
Я хочу суммировать элементы массива. Этот массив содержит положительные и отрицательные числа.
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 ответ:
Похоже, что вы не обрабатываете переполнение целых чисел должным образом. Флаг 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: