I want to sum an array elements. This array contains positive and negative numbers.
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
The sum (DX:AX
) using this code = 0003 FFAE H which is wrong. I think that the right answer is
FFFFFFAE H.
1- How can I fix this problem?
2- How can I know whether a number in a register (AX for example) is positive or negative?
I use emu8086
It seems that you don't handle integer overflow appropriately. Carry flag is for unsigned addition and subtraction, but you want signed addition. Overflow flag is for signed addition, it's set always when the sign changes.
Edit: Previous untested code didn't work properly. Here's the corrected (and self-contained) code. Tested with 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
The above code does the signed integer addition for 8-bit values (the 8-bit values are extended to 16-bit values). Register usage has been changed to allow usage of cbw
for cleaner code. Adding negative numbers has been converted to subtraction, for simplicity. Hardcoded offset of array (mov si, 0002h
, which works only if the array is located at offset 2) has been replaced with lea si,array
:
size_of_array dw 7 array db -3, 10, -7, 14, 9, -5, -100
And the corresponding changes in the code:
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
And how to check if a number is negative or positive? Well, you check the highest bit. For example, as in my code (test
does logical AND but doesn't save the result, it only updates the flags):
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: