call和ret指令都是轉移指令,它們都修改IP,或同時修改IP和CS
ret和retf:
- ret指令使用棧中數據,修改IP內容,實現近轉移。進行兩步操作:(1)(IP)= ((ss) * 16 + (sp)) (2) (sp) = (sp) + 2 等價於 pop IP
- retf指令使用棧中數據,修改CS和IP內容,實現遠轉移。進行四步操作:(1)(IP)= ((ss) * 16 + (sp)) (2) (sp) = (sp) + 2 (3) (CS) = ((ss) * 16 + (sp)) (4)(sp) = (sp) + 2 等價於pop IP pop CS
call指令:
call指令進行兩步操作:(1)將當前的IP 或 CS和IP壓入棧中;(2)轉移(IP對應近轉移,CS和IP對應遠轉移)
依據位移進行的call指令:
- call 標號 進行如下操作:(1)(sp)= (sp) - 2 ((ss) * 16 + (sp)) = (IP) (2)(IP) = (IP) + 16位位移
- 等價於 push IP jmp near ptr 標號
依據地址進行的call指令:
- call far ptr 標號 進行如下操作:(1)(sp)= (sp) - 2 ((ss) * 16 + (sp)) = (CS) (sp) = (sp) - 2 ((ss) * 16 + (sp)) = (IP) (2) (CS)的地址 = 標號所在段的段地址;(IP)的地址 = 標號所在段的偏移地址
- 等價於 push CS push IP jmp far ptr 標號
- call 16 位reg 進行如下操作:(sp)= (sp) - 2 ((ss) * 16 + (sp)) = (IP) (IP) = 16位reg
- 等價於 push IP jmp near 16位reg
- call word ptr 內存單元地址 進行如下操作:(sp) = (sp) - 2 ((ss) * 16 + (sp)) = (IP) (IP) = (內存單元地址中的內容)
- 等價於push IP jmp word ptr 內存單元地址
- call dword ptr 內存單元地址 進行如下操作:(1)(sp)= (sp) - 2 ((ss) * 16 + (sp)) = (CS) (sp) = (sp) - 2 ((ss) * 16 + (sp)) = (IP) (2) (CS)的地址 = 后兩字節內容;(IP)的地址 = 前兩字節內容
- 等價於push CS push IP jmp dword ptr 內存單元地址
用call和ret實現調用子程序:
- call sub1
- ...(返回處)
- sub 1 :
- .....(子程序)
- ret (返回第二行)
mul乘法指令:
mul reg 或者 mul 內存單元
- 兩個數相乘,位數必須相等,要么都是8位(小於255),要么都是16位。不足8位的,可以擴展成16位。
- 8位乘8位時,一個數默認放在AL中,另一位數要么是放在8位寄存器中,要么是在8位內存單元中,最終結果默認在AX中
- 16位乘16位時,一個數默認放在AX中,另一位數要么是放在16位寄存器中,要么是在16位內存單元中,最終結果默認,低16位在AX中,高16位在DX中
主程序和子程序調用同一個寄存器可能會發生沖突,解決這一問題的方法是:
- 在子程序的開頭將調用的寄存器入棧,注意不要將此部分加入循環中,可以單獨放在開頭
- 在子程序返回前將調用的寄存器出棧,注意此部分同樣不要加入循環之中,與ret或者retf放在一部分
- 注意出棧和入棧的順序是相反的
