[英]Tracing a NCR assembly program of MASM
當我們的講師解釋時,我錯過了會議。
我知道NCR的公式
NCR = N! /(R!*(NR)!)
我沒有關注NCR PROC ,因為沒有找到因子,並且那里正在進行一些令人毛骨悚然的遞歸工作。 幫助將非常感激。
print macro str
lea dx,msg
mov ah,09h
int 21h
endm
.model small
.data
n dw 15
r dw 6
ncr dw 1
msg db "The NCR is : ","$"
.code
start: mov ax,@data
mov ds,ax
mov bx,n
mov cx,r
inc bx
call ncr1
print msg
mov ax,ncr
call display
mov ah,4ch
int 21h
ncr1 proc
cmp cx,00
je l1
push cx
dec cx
call ncr1
mov ax,bx
pop cx
sub ax,cx
mul ncr
div cx
mov ncr,ax
l1 : ret
ncr1 endp
display proc
aam
add ax,3030h
mov bx,ax
mov dl,bh
mov ah,02h
int 21h
mov dl,bl
mov ah,02h
int 21h
ret
display endp
end start
好的,我在展示如何分析匯編代碼塊時看到了一些重用價值,所以在這里。
我們在這里處理一個子程序,一段應該相對自治的代碼。
所以,首先,讓我們確定它對程序的原始影響:它的輸入,輸出和對sp
- 即它的調用約定和簽名 。
它使用哪些實體不是由它設定的?
ncr1 proc
cmp cx,00 # <-- cx
je l1
push cx
dec cx
call ncr1
mov ax,bx # <--bx
pop cx
sub ax,cx
mul ncr # <--ncr
div cx
mov ncr,ax
l1 : ret
ncr1 endp
它修改了哪些實體,之后沒有恢復?
ncr1 proc
cmp cx,00
je l1
push cx # cx->local_stack[-2]
dec cx # -->cx? (overridden)
call ncr1
mov ax,bx
pop cx # local_stack[-2]->cx => cx restored
# (the next step is actually needed to deduce push/pop
# correspondence so they should be done in parallel)
sub ax,cx
mul ncr # -->ax,dx
div cx
mov ncr,ax # -->ncr
l1 : ret
ncr1 endp
僅標記實體的最后更改(因為它們優先於先前的更改)。
它對sp
有任何凈效應嗎? (數字是相對於返回地址的當前sp
)
ncr1 proc
cmp cx,00
je l1
push cx #-2
dec cx
call ncr1 #delta is same as self
mov ax,bx
pop cx #0
sub ax,cx
mul ncr
div cx
mov ncr,ax
l1 : ret #without an argument, only cleans the return address
ncr1 endp
它沒有(因此“與self相同”為0),並且在ret
所有情況下都為0
,確認它正確處理本地堆棧。
最后,它的簽名是:
ncr1 (cx,bx,ncr) -> ax,dx,ncr
ax
和dx
可能未被使用(但它們仍然是不穩定的 )。 調用約定是自定義純寄存器,帶有一個硬編碼的輸入/輸出參數。
現在,剩下的就是跟蹤每個實體在任何時候持有的物理 - 然后是概念 - 價值:
ncr1 proc --initially: bx=N, cx=R (metavariables)
cmp cx,00 # if R==0:
je l1 # ret (ax,dx,ncr unchanged)
push cx #[-2]=R
dec cx #cx=R-1
call ncr1 #ncr1(N,R-1) -> ax,dx,ncr(probably the result)
mov ax,bx #ax=N
pop cx #cx=[-2]=R
sub ax,cx #ax=N-R
mul ncr #dx:ax=(N-R)*ncr = (N-R)*ncr1(N,R-1)
div cx #ax=[(N-R)*ncr1(N,R-1)]/R
mov ncr,ax #ncr=[(N-R)*ncr1(N,R-1)]/R
l1 : ret
ncr1 endp # -> ax,dx,ncr(the result, now we're sure)
這里是:程序計算(N,R) -> [(NR)*ncr1(N,R-1)]/R
其中N=bx
, R=cx
,結果是ncr
(其是變異的)。
看似可疑: (NR)
在規范公式中應為(N+1-R)
,符合評論62556150 。 如果我們用n=N-1
代替,它將變成: (n+1,R) -> [(n+1-R)*ncr(n+1,R-1)]/R
看起來沒問題(第一個參數永遠不會改變)...所以程序實際上計算nCr(n-1,r)
。
傳遞n+1
的選擇必須是因為n
只作為n+1
進入公式,所以這樣我們每次都會增加它的周期。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.