.model small
.data
nizA db 1,2,3,4,5,6,7,8
nizB db 8 dup(?)
len equ 8
.code
main proc
mov si,0
mov di,0
mov cx,len
program:
mov al,nizA[si] ;problem is here it always stores CDh in AL
cbw ;convert AL to AX so i can divide
mov bl,2 ;The number I want to divide so I test if its even or not
div bl ;Overflow message
cmp ah,0
je next:
input:
mov dl,nizA[si]
mov nizB[di],dl
inc di
next:
add si,2
loop program
endp
end
I have this code here, for my finals that I need to make, very simple. Find odd numbers from even indexes of given array. So naturally it means I increase SI
by 2 and I put that array element in AL
. But no matter what number is in array, what gets stores in AL
is always hex number CD, which then, if it was stored as it was supposed to, I want to do CBW
to convert to AX
and be able do divide with BL
I now just have error message from EMU 8086 saying
divide error - overflow. to manually process this error, change address of INT 0 in interrupt vector table.
Which surely is related to CD number, I only have two problems here
When a DOS .EXE starts, the DS
segment register does not point at your program's .data section! The DS
segment register points at the ProgramSegmentPrefix aka PSP. This 256-byte area is where DOS keeps some important data about the running program, and where you can retrieve the program's command line at offset address 128.
You found the value CDh when your code ran because that happens to be the very first byte in the PSP. It is the opcode for the int 20h
instruction that always begins the PSP.
What you need to write is the following:
.code
main proc
mov ax, @data
mov ds, ax
Actually it does make sense. Because you are using CBW
to extend the dividend into AX
, and because the value in AL
erroneously is CDh, the new value in AX
becomes FFCDh. When your code then divides this by 2 (using mov bl, 2
div bl
) the quotient is much larger than what can be stored in the division's dedicated quotient register AL
. That's why you get the "divide error".
mov ax, @data
mov ds, ax
mov si, 0
mov di, 0
mov cx, len/2
program:
mov al, nizA[si]
mov ah, 0 ; For UNSIGNED division don't use CBW
mov bl, 2
div bl
cmp ah, 0 ; Remainder
je next
mov dl, nizA[si] ; Reload
mov nizB[di], dl
inc di
next:
add si, 2
loop program
TEST
and adding some extra improvements too: mov ax, @data
mov ds, ax
xor si, si ; Better than 'mov si, 0` for zeroing a register
xor di, di ; idem
program:
mov al, nizA[si]
test al, 1
jz IsEven
mov nizB[di], al ; Only storing 'odd' values
inc di
IsEven:
add si, 2 ; Next 'even' index
cmp si, len
jb program
See how TEST AL, 1
is non-destructive on the AL
register and that therefore you don't need to reload the value before writing to the nizB array?
Also note that you don't always need a separate loop counter. Here I have used the source array index instead.