10.20汇编
实验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
好家伙,真写了我一晚上,大概只有写过的人才能体会看到这个页面时心中的舒坦吧。

