彙編課程設計:閏年判斷程式詳解
阿新 • • 發佈:2019-01-02
程式說明:
這是一個判斷某一年是否為潤年的程式,執行可執行程式Ifleap.exe後,輸入具體的年份,
可輸出是本年是否為閏年的提示資訊。
函式圖:
data segment ;定義資料段 infon db 0dh,0ah,'Please input a year: $' ;infon ,雙位元組,回車換行,內容 Y db 0dh,0ah,'This is a leap year! $' ;y ,雙位元組,回車換行,內容 N db 0dh,0ah,'This is not a leap year! $' ;n ,雙位元組,回車換行,內容($是結束符) w dw 0 ;w為雙字型別 buf db 8 ;開闢8個雙位元組型別的緩衝區,未賦值 db ? db 8 dup(?) data ends stack segment stack db 200 dup(0) ;開闢200個雙位元組型別的儲存空間。(保護現場用到) stack ends code segment assume ds:data,ss:stack,cs:code start:mov ax,data ;暫存器間的資料交換,把data給了資料段 mov ds,ax lea dx,infon ;在螢幕上顯示提示資訊 mov ah,9 int 21h lea dx,buf ;從鍵盤輸入年份字串 mov ah,10 int 21h mov cl, [buf+1] ;把buf+1地址指向的內容給cl,buf長度 lea di,buf+2 ;把buf+2的地址給di,buf偏移地址 call datacate ;呼叫函式datacate,傳遞引數 call ifyears ;呼叫函式ifyears,由引數判斷是否為閏年 jc a1 ;若產生進位就跳到a1處 lea dx,n ;dx載入n的地址'This is not a leap year!' mov ah,9 ;顯示dx內的內容 int 21h jmp exit ;跳到exit a1: lea dx,y ;dx載入y的地址'This is a leap year!' mov ah,9 int 21h exit: mov ah,4ch ;結束本程式,返回 DOS 作業系統 int 21h ;實現將字串的閏年轉換為數字儲存在ax中 datacate proc near; ;段內呼叫,子函式1 push cx; ;保護現場 dec cx lea si,buf+2 ;把buf+2的地址給si tt1: inc si ;移動到字串指定位置 loop tt1 ;迴圈函式是個遞增函式, loop指令的格式是:loop標號,cpu執行loop指令的時候,要進行兩步操作 ;1:(cx)=(cx)-1 ;2:判斷cx中的值,不為零則轉至標號處執行,如果為零,則向下執行 ;lea si,cx[di] pop cx ;恢復現場 mov dh,30h mov bl,10 ;乘數設定為10 mov ax,1 l1: push ax ;保護現場 sub byte ptr [si],dh ;沒有暫存器參與的記憶體單元訪問指令(DMA),si-dh儲存在si中 mul byte ptr [si] ;沒有暫存器參與的記憶體單元訪問指令(DMA),ax*si,結果放在eax中,這裡的暫存器si是16位,被乘數在ax中也是16位。 ;MUL r/m(暫存器或者記憶體) ;mul是字內乘法,把si對應的地址內一個字的長度賦給 ;如果引數是 r8/m8, 將把 AL 做乘數, 結果放在 AX ;如果引數是 r16/m16, 將把 AX 做乘數, 結果放在 EAX ;如果引數是 r32/m32, 將把 EAX 做乘數, 結果放在 EDX:EAX add w,ax ;w+ax,結果存入w,存入的是數字 pop ax ;恢復現場 mul bl ;bl*al,結果存放在ax中 dec si ;si中的內容減一 loop l1 ;l1迴圈,cx判斷次數 ret datacate endp ;實現ax中年份的判斷 ifyears proc near ;段內呼叫,子函式2 push bx ;保護現場(保護誰,就用到誰) push cx push dx mov ax,w ;把w值賦給cx,w值為 mov cx,ax ;把ax值賦給cx mov dx,0 mov bx,4 ;ax/4 div bx ;ax/bx,結果在ax中,餘數在dx中 ;如果除數是8位,那麼除法的結果AL儲存商,AH儲存餘數, ;如果除數是16位,那麼除法的結果 AX儲存商,DX儲存餘數。 cmp dx,0 ;比較餘數和0,結果存入cf標誌位(進位標誌位) jnz lab1 ;如果非0,跳轉到lab1處 mov ax,cx mov bx,100 ;ax/100 div bx cmp dx,0 ;比較餘數和0,結果存入cf標誌位(進位標誌位) jnz lab2 ;如果非0,跳到lab2 mov ax,cx mov bx,400 ;ax/400 div bx cmp dx,0 ;比較餘數和0,結果存入cf標誌位(進位標誌位) jz lab2 ;cf=0跳到lab2 lab1: clc ;清除cf標誌位,設定cf=0 jmp lab3 ;跳到lab3 lab2: stc ;cf置1 lab3: pop dx ;恢復現場 pop cx pop bx ret ifyears endp code ends end start
引數傳遞:
主函式與DATACATE的引數傳遞方式為約定單元法,約定單元為BUF、 W。
主函式與IFYEARS的引數傳遞方式為約定單元法,約定單元為W。
中斷向量的計算
中斷向量處理程式地址為1C8B:000D和1c8b:0015 .
本題用到了21H函式庫,入口地址為0:84h。
CS=421h+2h=86h
IP=421h=84h