My task is to design a dword division child procedure (divdw) that will not overflow in 8086 assembly (I use masm5.0/masm.exe and masm5.0/link.exe and debug.exe in MS-DOS). AX
, CX
, and DX
are used to save the result of divdw. The following code cannot run yet.
Here is the task:
input:
(ax)=low 16 bit of a dword dividend
(dx)=high 16 bit of a dword dividend
(cx)=16 bit divisor
output:
(ax)=low 16 bit of the result
(dx)=high 16 bit of the result
(cx)=remainder
The formula I used to calc divdw:
dividend/divisor = quot(high 16 bit of dividend / divisor) +
( rem(high 16 bit of dividend / divisor) * 2^16 + low 16 bit of dividend ) / divisor
Here is my code:
assume cs:code
code segment
start: mov ax,4240h
mov dx,000fh
mov cx,0ah
call divdw
mov ax,4c00h
int 21h
divdw: push bx
push dx ;ss:[0ch]
mov ax,dx
mov dx,0
div cx
mov ax,0 ;rem, only need dx
mov bx,ss:[0ch]
div bx
;; finish 1
push dx
push ax
;; get dx, into ax
mov ax,ss:[0ch]
div cx
;; finish 2
push ax
pop dx ;ax after 2
pop ax ;ax after 1
pop cx ;dx after 1
;; recover bx
pop bx
pop bx
ret
code ends
end start
In this code, I am trying to use pop
and push
but did not define a stack segment. Is this permitted? (In the debugger I found the SS:SP
is given but the push
cannot work correctly.)
If not, where should I define the stack and how to use it?
If I define a stack segment in the main procedure, it seems I need to save the SS
and SP
values in the beginning of the procedure, but where should I save them? Can I save them in the stack, or must I save them somewhere in memory?
The start main procedure is given for the purpose of testing.
Thanks!
Edit:
Thank you both! With your help, I finished this task. Code is now as follows:
assume cs:code,ss:stack
stack segment
dw 8 dup (0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,16
mov ax,4240h
mov dx,000fh
mov cx,0ah
call divdw
mov ax,4c00h
int 21h
divdw: push bx
push dx ;ss:[0ah]
push ax ;ss:[08h]
mov ax,dx ;ax=0fh
mov dx,0 ;dx=0
div cx ;ax=1,dx=5
push ax ;1, quot, should be dx when ret, as the high 16 bit of result
;; use dx=5 and 4240h to do div
mov ax,ss:[08h] ;ax=4240h. rem, only need dx of last result, use low 16bit of dividend, ie. ax, as ax
div cx ;ax=86a0h,dx=0h
;ax already is low 16bits of quot
mov cx,dx ;rem, store in cx
pop dx ;1, high 16 bits of quot
pop bx ;discard original ax
pop bx ;discard original dx
pop bx ;recover original bx
ret
code ends
end start
Edited on 20170724
Yet another version, get rid of the ss:[08h], and used another 3 registers to store. I am not sure whether this is better, but it works.
assume cs:code,ss:stack
stack segment
db 16 dup (0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,16
mov ax,4240h
mov dx,000fh
mov cx,0ah
call divdw
mov ax,4c00h
int 21h
divdw: push bp
mov bp,sp
push si
push bx
push dx
push ax
mov si,sp
mov ax,dx ;ax=0fh
mov dx,0 ;dx=0
div cx ;ax=1,dx=5
push ax ;1, quot, should be dx when ret, as the high 16 bit of result
;; use dx=5 and 4240h to do div
mov ax,ss:[si] ;ax=4240h. rem, only need dx of last result, use low 16bit of dividend, ie. ax, as ax
div cx ;ax=86a0h,dx=0h
;ax already is low 16bits of quot
mov cx,dx ;rem, store in cx
pop dx ;1, high 16 bits of quot
pop bx ;discard original ax
pop bx ;discard original dx
pop bx ;recover original bx
pop si
mov sp,bp
pop bp
ret
code ends
end start
mov ax,ss:[08h]
. That's not good programming practise. Why don't you use the stack frame pointerBP
like both answerers told you? – Fifoernik