Ma tâche consiste à concevoir une procédure enfant de division dword (divdw) qui ne débordera pas dans l'assembly 8086 (j'utilise masm5.0/masm.exe et masm5.0/link.exe et debug.exe dans MS-DOS). AX
, CX
, et DX
sont utilisés pour enregistrer le résultat de divdw. Le code suivant ne peut pas encore être exécuté.Dans l'assembly 8086, comment utiliser la pile dans une procédure enfant?
Voici la tâche:
entrée:
(ax) = faible 16 bits d'un dividende dword
(dx) = haute 16 bits d'un dividende dword
(cx) = 16 bits diviseur
sortie:
(ax) = faible 16 bits du résultat
(dx) = haute 16 bits du résultat
(cx) = reste
La formule I utilisé à calco divdw:
dividende/diviseur = quot (haute 16 bits du dividende/diviseur) +
(rem (haute 16 bits du dividende/diviseur) * 2^16 + faible 16 bits du dividende)/diviseur
Voici mon 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
Dans ce code, je suis en train d'utiliser pop
et push
mais n'a pas défini un segment de pile. Est-ce permis? (Dans le débogueur, j'ai trouvé le SS:SP
mais le push
ne peut pas fonctionner correctement.)
Sinon, où dois-je définir la pile et comment l'utiliser?
Si je définis un segment de pile dans la procédure principale, il semble que je doive enregistrer les valeurs SS
et SP
au début de la procédure, mais où dois-je les enregistrer? Puis-je les sauvegarder dans la pile, ou dois-je les sauvegarder quelque part en mémoire?
La procédure de départ est donnée aux fins du test.
Merci!
Modifier:
Merci à vous deux! Avec votre aide, j'ai terminé cette tâche.Le code est maintenant comme suit:
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
Modifié le 20170724
Pourtant, une autre version, se débarrasser de la SS: [08h], et utilisé un autre 3 registres pour stocker. Je ne suis pas sûr que ce soit mieux, mais ça fonctionne.
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
Comment est-ce chargé/lié? La pile doit être préparée par le chargeur –
J'utilise masm5.0/masm.exe et masm5.0/link.exe et debug.exe sous MS-DOS. – cmal
Une pile de seulement 16 octets? Vous devez plaisanter! – Fifoernik