我的任務是設計一個dword分區子程序(divdw),它不會在8086程序集中溢出(我在MS-DOS中使用masm5.0/masm.exe和masm5.0/link.exe和debug.exe )。 AX
,CX
和DX
用於保存divdw的結果。以下代碼無法運行。在8086程序集中,如何在子程序中使用堆棧?
這裏是任務:
輸入:
(AX)=低16位的雙字被除數
(DX)=雙字被除數的高16位的
(CX) = 16位除數
輸出:
(AX)=結果的低16位
(DX)=高16位的結果的
(CX)=剩餘
我以前calc下divdw式中:
被除數/除數= QUOT(被除數/除數的高16位)+
(REM(被除數/除數的高16位)* 2^16 + 16低位被除數的)/除數
這裏是我的代碼:
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
在這段代碼中,我試圖用pop
和push
,但沒有定義堆棧段。這是否允許? (在調試器中,我發現給出了SS:SP
,但push
無法正常工作。)
如果沒有,我應該在哪裏定義堆棧以及如何使用它?
如果我在主程序中定義一個堆棧段,似乎我需要在過程的開始時保存SS
和SP
值,但我應該在哪裏保存它們?我可以將它們保存在堆棧中,還是必須將它們保存在內存中的某個位置?
開始主要程序是爲了測試而給出的。
謝謝!
編輯:
謝謝兩位!在你的幫助下,我完成了這項任務。現在的代碼如下:
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
編輯在20170724
另一個版本中擺脫的SS:[08H],以及使用其他3個寄存器來存儲。我不確定這是否更好,但它有效。
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
這是如何加載/鏈接?該堆棧應該由加載程序準備 –
我在MS-DOS中使用masm5.0/masm.exe和masm5.0/link.exe和debug.exe。 – cmal
只有16個字節的堆棧?你一定是在開玩笑! – Fifoernik