10-20彙編
阿新 • • 發佈:2020-12-11
技術標籤:王爽組合語言學習筆記
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)]
程式碼地圖還是值得紀念的