使用8086匯編,輸出99乘法表
程序運行截圖如下:
要用匯編輸出乘法表,實現思路有以下幾點:
1.顯示出等式:可以觀察到乘法表的有9行,第1行有9列,第2行有8列,第3行有7列...而且每行的等式的第一個乘數都是該行所有的列數,等式的第二個乘數是該行所有的列數遞減1(為第一個等式的情況下為列數)。如第一行有9列,等式的第1個乘數都為9,第1個等式的第2個乘數為列數9,第2個等式的第2個乘數為列數9-1=8,第3個等式的第2個乘數為列數9-1-1=7。
由這些特點可以得出用兩層循環,並利用匯編loop指令的特點:每次到執行loop指令的時候,cx減一。可設置一個外層循環計數為9,內層循環計數隨外層計數改變而改變,如第一次循環:外層計數等於9,內層計數等於9,循環9次打印出9個等式,等式第一個乘數都為9,等式第二個乘數從9開始遞減;第二次循環:外層計數等於8,內層計數等於8,打印出8個等式,等式第一個乘數都為8,等式第二個乘數從8開始遞減...
2.計算等式:計算等式的值,我們需要存下兩個乘數,再用乘法指令進行計算
3.顯示計算出來的值:由於99乘法表計算出來的值為1到81。匯編中用顯示數值要進行相應的轉換,0-9之間的數轉換比較方便,用數值加上30h轉為ASCII碼輸出。對於不只有個位的數值,可以用除10法進行轉換,把各個位上的數轉換出來,再套用顯示0-9的方法進行顯示,如81,轉為8、1,分別輸出兩個字符8和1,即可在屏幕上得到81的效果。(除10法在前一篇博客中有比較詳細的介紹)
個人在實現的時候有一些問題,詳見注釋,請高手指點,謝謝
代碼如下(是可以跑通的...)
DATAS SEGMENT CRLF db 13,10,'$' number dw ?,?,?,? ;存放乘數和被乘數 buf db ?,?,?,? ;緩存轉換出來的數字 DATAS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS START: MOV AX,DATAS MOV DS,AX mov cx,9 ;外層循環9次 s1: mov [number],cx ;存放乘數 push cx ;保存外層計數 push cx ;乘數進棧 s2: ;內層循環,循環次數由外層循環來決定 ;顯示乘數 mov dx,[number] add dx,30h ;轉換到ASCII mov ah,2 int 21h ;顯示x號 mov dl,78h mov ah,2 int 21h ;顯示第二個乘數 mov [number+1],cx push cx ;第二個乘數進棧 mov dx,cx add dx,30h mov ah,2 int 21h ;顯示=號 mov dl,3dh mov ah,2 int 21h ;計算兩數相乘的結果,並顯示 pop dx ;取出第二個乘數 pop ax ;取出第一個乘數 push ax ;第一個乘數再次進棧,在下次內層循環中推出再次使用 ;想直接用內存單元里面放的數據來相乘,但是結果不對 ;所以最后用棧存放乘數再取出解決了問題 ;調試發現第二個乘數[number+1]中的值是對的,但是[number]中的值不對 ;很疑惑的是上面打印[number]的值顯示結果正確 ;那為什么在下面的指令中使用值就不對了呢? ;mov dx,[number] ;mov ax,[number+1] mul dx ;相乘,結果在AX中 mov bx,10 ;准備除以10 mov si,2 ;循環2次,最大到十位 (乘法表最大為81,所以最大到十位) toDec: ;把各個位轉換為數值,如ax中的81,轉換為 8,1存在內存中 mov dx,0 div bx ;除10法得到各個位上的數值 mov [buf+si],dl ;余數為該位上的值,第一次循環為個位,第二次為十位...;存到內存中 dec si cmp ax,0 ;商是否為0,為0算法結束 ja toDec output: ;輸出內存中存放的轉換數值數 inc si mov dl,[buf+si] add dl,30h ;轉為ascii mov ah,2 int 21h cmp si,2 jb output mov dl,20h mov ah,2 int 21h loop s2 ;內層循環結束 lea dx,crlf ;輸出回車換行 mov ah,9 int 21h pop cx pop cx ;還原外層計數 loop s1 mov ah,1 ;停留等待結束 int 21h MOV AH,4CH INT 21H CODES ENDS END START