1. 程式人生 > 其它 >10-20彙編

10-20彙編

技術標籤:王爽組合語言學習筆記


title: 10.20彙編
tags: []
id: ‘273’
categories:

    • 學習
    • learn
    • 彙編學習
      date: 2020-10-20 22:08:14

實驗7之後實驗的程式碼量大幅提高,所以每章花費的時間也大幅提高了。上午只看完了第十章,會用函數了。晚上爭取完成課程設計。

CALL和RET

call可以將IP或IP和CS壓入棧中,並跳轉至標號,ret可以通過退棧獲得的值對IP修改,retf可以通過兩次退棧來對CS,IP都修改,實現段間轉移。兩者配合使用則可實現函式。

對於函式的個人建議:在函式中的所有識別符號都以函式名為字尾,這樣可以避免衝突

MUL

乘法指令,相乘的兩數位數需要相同,若為八位,被乘數預設在al中,另一個在reg或記憶體中,結果存於ax中。若為十六位,被乘數預設在ax中,另一個在reg或記憶體中,結果低位存在ax中,高位存在dx中。

實驗十

1.顯示字串

見鬼了,調了許久都沒有結果,最後終於是整出來了

assume cs:code,ds:data,ss:stack

data segment
    db 'Welcome to masm!',0
data ends

stack segment
    dd 8 dup (0)
stack ends

code segment
main:
    mov dh,8
    mov dl,3
    mov cl,2
    mov ax,data
    mov ds,ax
mov ax,stack
mov ss,ax
mov sp,32
    call clear_screen
    call show_str
    lo:
    jmp short lo
    mov ax,4c00h
    int 21h

clear_screen:
    push bx
    push cx
    push es

    mov bx,0b800h
    mov es,bx
    mov bx,0
    mov cx,2000
    sclear:
        mov word ptr es:[bx],0
        add bx,2
    loop sclear

    pop es
    pop cx
    pop bx
ret;clear_screen

show_str:
    push ax
    push bx
    push dx
    push si

    mov si,0
mov di,0
mov ax,0b800h
mov es,ax
    ;處理行地址偏移
    mov al,160
mul dh

    ;以bx為列地址偏移暫存器
    mov bx,ax
add bl,dl
add bl,dl

    mov dl,cl
    proccess:
        ;判斷字元是否為零
        mov cl,ds:[si]
        mov ch,0
        jcxz break

        mov ch,dl
        mov es:[bx][di],cx
        inc si
        add di,2
    jmp short proccess
    
    break:
    mov cl,dl
    pop si
    pop dx
    pop bx
    pop ax
ret;show_str
code ends

end main

2.解決除法溢位問題

assume cs:code,ss:stack

stack segment
    dw 8 dup(0)
stack ends

code segment
main:
    mov ax,stack
    mov ss,ax
    mov ax,4240h
    mov dx,000fh
    mov cx,0ah
    call divdw

    mov ax,4c00h
    int 21h

divdw:
    push bx

    push ax
    ;int(H/N)->[0]
    mov ax,dx
    mov dx,0
    div cx
    mov bx,ax
    ;last ax
    pop ax
    div cx
    mov cx,dx
    mov dx,bx

    pop bx
ret
code ends

end main

這個比較簡單,核心的公式為X/N=int(H/N)<<16+[rem(H/N)<<16+L]/N

齊餘數為rem([rem(H/N)<<16+L]/N),所以也很好處理,因為餘數就在dx中

3.數值顯示

assume cs:code,ds:data,ss:stack

data segment
    db 10 dup(0)
data ends

stack segment
    dd 16 dup(0)
stack ends


code segment
main:
    mov ax,12666
    mov bx,data
    mov ds,bx
    mov bx,stack
    mov ss,bx
    mov sp,64
    mov si,0
    call clear_screen
    call dtoc

    mov dh,8
    mov dl,3
    mov cl,2
    call show_str
    lo:
    jmp short lo
    mov ax,4c00h
    int 21h

clear_screen:
    push bx
    push cx
    push es

    mov bx,0b800h
    mov es,bx
    mov bx,0
    mov cx,2000
    sclear:
        mov word ptr es:[bx],0
        add bx,2
    loop sclear

    pop es
    pop cx
    pop bx
ret;clear_screen

dtoc:
    push ax
    push bx
    push cx
    push dx
    mov cx,ax
    mov bx,10
    mov dh,0
    s0:
        jcxz break
        mov ax,cx
        mov dx,0
        div bx
        add dl,48
        push dx
        mov cx,ax
        inc si
    jmp short s0

    break:
    mov cx,si
    mov si,0
    s1:
        pop dx
        mov ds:[si],dl
        inc si
    loop s1
    pop dx
    pop cx
    pop bx
    pop ax
ret

show_str:
    push ax
    push bx
    push dx
    push si

    mov si,0
mov di,0
mov ax,0b800h
mov es,ax
    ;處理行地址偏移
    mov al,160
mul dh

    ;以bx為列地址偏移暫存器
    mov bx,ax
add bl,dl
add bl,dl

    mov dl,cl
    proccess:
        ;判斷字元是否為零
        mov cl,ds:[si]
        mov ch,0
        jcxz break_s

        mov ch,dl
        mov es:[bx][di],cx
        inc si
        add di,2
    jmp short proccess
    
    break_s:
    mov cl,dl
    pop si
    pop dx
    pop bx
    pop ax
ret;show_str

code ends

end main

要注意的是模得的各位是倒序的,所以要用棧來反序

課程設計1

assume cs:code,ss:stack

data segment
    db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
    db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
    db '1993','1994','1995'

    dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
    dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000

    dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
    dw 11542,14430,15257,17800

    dw 21 dup(0) ;save the average income
data ends

stack segment
    dd 16 dup(0)
stack ends

code segment
main:
    mov ax,data
    mov ds,ax
    mov ax,stack
    mov ss,ax
    mov sp,64
    mov ax,0b800h
    mov es,ax
    call clear_screen
    mov cx,21
    s0_main:
        push cx

        ;years moved to buffer directly
        mov si,0
        mov cx,4
        s_move_years_main:
            mov ah,00000111b ;ah is the type of the number
            mov al,ds:[bx]
            mov es:8[si],al ;start from 8/2 colume,this can be changed easily
            mov es:9[si],ah ;define the word's type
            add bx,1
            add si,2
        loop s_move_years_main

        call reserve_income
        call reserve_employ
        call calc_average_income
        
        pop cx
        ;change es to change the dispying row
        mov ax,es
        add ax,0ah
        mov es,ax 
    loop s0_main
    end_programe:
    wat:
    jmp short wat
    mov ax,4c00h
    int 21h

reserve_income:
    ;it's hard to procces dword as this is a 16-bit proccesser,i decided to use div-dw to proccess it
    ;bx is used to control the address of the dword number,also control the years
    ;stack needed to reserve the number
    mov si,0
    ;divdw init
    mov ax,ds:[50h][bx]
    mov dx,ds:[52h][bx]

    push ax
    or al,dl
    or ah,dh ;only when ax==0,dx==0 then ax=0->cx=0->jcxz jmp
    pop ax
    mov cx,ax
    s_move_income:
        jcxz done_move_income
        ;divdw init
        mov cx,10
        call divdw ;ax,dx store the int(divdw)

        push cx

        push ax 
        or al,dl
        or ah,dh        
        mov cx,ax
        pop ax

        inc si
    jmp short s_move_income
    done_move_income:
    mov cx,si
    mov si,0
    mov ah,00000111b ;ah is the type of the number
    s_reserve_income:
    ;this loop is used to reserve the number sequence through the stack
        pop dx
        add dl,30h
        mov es:20[si],dl ;start from 20/2 colume,this can be changed easily
        mov es:21[si],ah ;define the word's type
        add si,2
    loop s_reserve_income
ret;reserve_income

reserve_employ:
    push bx
    mov ax,bx
    mov dx,0
    mov cx,2
    div cx
    mov bx,ax
    mov ax,ds:0a6h[bx]
    ;bx aim to control dw,so need to div 2 to control word
    mov cx,ax
    mov si,0
    mov dx,0
    s_move_sum_employ_main:
        ;this loop is used to move the employ number
        ;though employ number is word,but div can still over folw,so i use the dword div
        jcxz done_move_sum_employ_main
        mov cx,10
        div cx
        push dx
        mov dx,0
        mov cx,ax

        inc si
    jmp short s_move_sum_employ_main
    done_move_sum_employ_main:
    mov cx,si
    mov si,0
    mov ah,00000111b ;ah is the type of the number
    s_reserve_employ_main:
    ;this loop is used to reserve the number sequence through the stack
        pop dx
        add dl,30h
        mov es:40[si],dl ;start from 40/2 colume,this can be changed easily
        mov es:41[si],ah ;define the word's type
        add si,2
    loop s_reserve_employ_main
    pop bx
ret;reserve_employ

calc_average_income:

    push bx
    mov ax,bx
    mov dx,0
    mov cx,2
    div cx
    mov bx,ax
    mov cx,ds:0a6h[bx]
    pop bx
    mov ax,ds:[50h][bx]
    mov dx,ds:[52h][bx]
    call divdw
    mov ds:[0ceh][bx],ax
    mov ds:[0d0h][bx],dx;this can be throw away
;----------------------------display after----------------------------
    push ax
    or al,dl
    or ah,dh ;only when ax==0,dx==0 then ax=0->cx=0->jcxz jmp
    pop ax
    mov cx,ax
    mov si,0
    s_calc_average_income:
        jcxz done_calc_average_income
        ;divdw init
        mov cx,10
        call divdw ;ax,dx store the int(divdw)

        push cx

        push ax 
        or al,dl
        or ah,dh        
        mov cx,ax
        pop ax

        inc si
    jmp short s_calc_average_income
    done_calc_average_income:
    mov cx,si
    mov si,0
    mov ah,00000111b ;ah is the type of the number
    s_reserve_calc_average_income:
    ;this loop is used to reserve the number sequence through the stack
        pop dx
        add dl,30h
        mov es:60[si],dl ;start from 80/2 colume,this can be changed easily
        mov es:61[si],ah ;define the word's type
        add si,2
    loop s_reserve_calc_average_income
ret

clear_screen:
    push bx
    push cx
    push es

    mov bx,0b800h
    mov es,bx
    mov bx,0
    mov cx,2000
    s_clear:
        mov word ptr es:[bx],0
        add bx,2
    loop s_clear

    pop es
    pop cx
    pop bx
ret;clear_screen

divdw:
    push bx

    push ax
    ;int(H/N)->[0]
    mov ax,dx
    mov dx,0
    div cx
    mov bx,ax
    ;last ax
    pop ax
    div cx
    mov cx,dx
    mov dx,bx

    pop bx
ret

code ends

end main

好傢伙,真寫了我一晚上,大概只有寫過的人才能體會看到這個頁面時心中的舒坦吧。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-AFKA84mZ-1607419148114)(http://www.cjovi.icu/wp-content/uploads/2020/10/QQ截圖20201020220644.png)]

程式碼地圖還是值得紀念的