10.20汇编

Posted on Oct 20, 2020

实验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

好家伙,真写了我一晚上,大概只有写过的人才能体会看到这个页面时心中的舒坦吧。

代码地图还是值得纪念的