汇编实验:屏幕窗口程序(代码有较为详细的注释)
實(shí)驗(yàn)3.4 屏幕窗口程序
1.題目:屏幕窗口程序
2.實(shí)驗(yàn)要求:
在屏幕上開(kāi)出三個(gè)窗口,它們的行列坐標(biāo)按照教材要求。光標(biāo)首先定位在右窗口最下面一行的行首(15,50),如從鍵盤(pán)輸入字符,則顯示在右窗口,同時(shí)也顯示在下窗口的最下面一行。若需要將字符顯示于左窗口,則先按下鍵,接著再?gòu)逆I盤(pán)輸入字符,字符就會(huì)從左窗口的最下行開(kāi)始顯示,同時(shí)下窗口也顯示出左窗口的內(nèi)容。如若再按下鍵,輸入字符就會(huì)接在先前輸入的字符之后顯示出來(lái)。當(dāng)一行字符顯示滿(mǎn)后(左右窗口一行向社會(huì)20個(gè)字符,下窗口一行顯示50個(gè)字符),窗口自動(dòng)向上卷動(dòng)一行,輸入字符繼續(xù)顯示最低一行,窗口最高一行向上卷動(dòng)后消失。
代碼:
datas segment cury db 15curx db 50 ;光標(biāo)初始位置lx db 10 ly db 15 ;記錄左窗口的當(dāng)前光標(biāo)位置,初始化為左窗口初始位置rx db 50 ry db 15 ;記錄右窗口的當(dāng)前光標(biāo)位置,初始化為右窗口的初始位置dwx db 15dwy db 22 ;記錄下窗口當(dāng)前的光標(biāo)位置,初始化為下窗口初始位置ulrow db 0ulcow db 0lrrow db 0lrcol db 0windowflag db 1 ;=1,右邊窗口,=2,左邊窗口 datas ends;宏指令clear清屏 clear macro a,b,c,dmov al,0 ;上卷行數(shù)為0mov bh,7 ;卷入行屬性為07,是正常屬性mov ch,a ;左上角行號(hào)mov cl,b ;左上角列號(hào)mov dh,c ;右下角行號(hào)mov dl,d ;右下角列號(hào)mov ah,6 int 10h endm ;-------------------------------------------------------------宏指令 scroll向上卷動(dòng)一行 scroll macro cont,ulrow,ulcol,lrrow,lrcol mov al,cont ;上卷行數(shù) mov bh,70h ;卷入行屬性 mov ch,ulrow ;左上角行號(hào) mov cl,ulcol ;左上角列號(hào) mov dh,lrrow ;右下角行號(hào) mov dl,lrcol ;右下角列號(hào) mov ah,6 int 10h ;BIOS調(diào)用,上卷 endm ;--------------------------------------------------------------宏指令postc 光標(biāo)定位 post_c macro y,x ;設(shè)置光標(biāo)在 (y,x)位置,設(shè)置光標(biāo)行列位置 mov bh,0 ;注意這里坐標(biāo)是(行號(hào),列號(hào))的形式,行號(hào)是y,列號(hào)是x)mov ah,2 mov dh,y ;int10h中,ah=2時(shí),設(shè)置光標(biāo)位置,dh為行號(hào),dl為列號(hào)mov dl,x int 10h endm ;---------------------------------------------------------------在當(dāng)前窗口和下窗口顯示 display macro mov bh,0 mov cx,1 mov ah,0ah ;在當(dāng)前的窗口的光標(biāo)位置處打印字符 int 10h post_c dwy,dwx ;重新設(shè)置當(dāng)前光標(biāo)位置到下窗口的正確位置處mov bh,0 mov cx,1 mov ah,0ah ;在下窗口輸出 int 10h endm ;----------------------------------------------------------------接收字符并判斷 getchar macro input: ;輸入鍵盤(pán)上的字符 mov ah,0 int 16h ;BIOS調(diào)用,從鍵盤(pán)讀字符 cmp ah,4bh ;判斷輸入字符是否為左向鍵 掃描碼jnz no_left post_c ly,lx mov windowflag,2 jmp input no_left: cmp ah,4dh jnz no_right ;判斷輸入字符是否為右向鍵 post_c ry,rx mov windowflag,1 jmp inputno_right: cmp ah,01h ;判斷輸入字符是否為ESC ;jz exit jnz continue1clear 0,0,24,79 ;屏幕總大小為25*80的ret continue1:display ;不是左右鍵和ESC那么就嵌套調(diào)用 宏display (顯示輸入的可打印的字符)inc dwx ;先顯示字符,再將下窗口該行的光標(biāo)的列號(hào)加1,再來(lái)比較是否要上卷cmp dwx,65 ;判斷下窗口是否上卷 jle isright ;isright表示下窗口中當(dāng)前光標(biāo)行可以向右走scroll 1,18,15,22,65 ;到了一行的最右端,要向上卷一行mov dwx,15 ;上卷一行后,當(dāng)前列號(hào)變?yōu)楫?dāng)前窗口最左邊的列的列號(hào)isright: cmp windowflag,1 ;判斷是否在右窗口 jnz displeft dispright: ;判斷右窗口是否上卷 inc rx cmp rx,70jle rightexit ;rightexit表示右窗口中當(dāng)前光標(biāo)行可以向右走,不用上卷scroll 1,5,50,15,70 mov rx,50 rightexit: ;右窗口輸出 post_c ry,rx jmp input displeft: ;判斷左窗口是否上卷 inc lx cmp lx,30 jle leftexit scroll 1,5,10,15,30 mov lx,10 leftexit: ;左窗口輸出 post_c ly,lx jmp inputendm ;getchar macro endm;---------------------------------------------------------------------codes segment assume cs:codes,ds:datas start: main proc far push ds sub ax,ax push ax mov ax,datas mov ds,ax clear 0,0,24,79 scroll 10,5,10,15,30 ;scroll也可以設(shè)置窗口make three windowsscroll 10,5,50,15,70 scroll 4,18,15,22,65 ;上卷4行,是因?yàn)橄麓翱谝还材苋菁{4行,得到一個(gè)空內(nèi)容的窗口post_c cury,curx getcharret main endp codes ends end start運(yùn)行截圖:
相關(guān)問(wèn)題和體會(huì):
1.對(duì)于主程序中清屏后,要進(jìn)行scroll 10,5,10,15,30 ;自己一開(kāi)始不是很理解這里為什么還要卷屏,還沒(méi)有向三個(gè)窗口輸入文字呢,為什么就要上卷了呢?原來(lái)是scroll也可以用來(lái)設(shè)置窗口,因?yàn)樵趕croll中設(shè)置了窗口左上角和右下角的坐標(biāo),而且上卷的行數(shù)正好是窗口的最下面的行號(hào)和最上面的行號(hào)之間的差值。由于:“窗口最高一行向上卷動(dòng)后消失”這就意味著一次性向上卷動(dòng)10行會(huì)讓在左邊的窗口中的內(nèi)容消失,同時(shí)自然而然地在屏幕上設(shè)置了一個(gè)左邊的清空的窗口。
2.匯編中 jump out of range 錯(cuò)誤應(yīng)該怎樣改正?
一種方法:
8086指令中的條件轉(zhuǎn)移指令,采用的都是短轉(zhuǎn)移,采用8位的相對(duì)位移量。
也就是說(shuō),條件跳轉(zhuǎn)的目標(biāo)指令在內(nèi)存中的地址,與該條件轉(zhuǎn)移指令之間的距離,不能超過(guò) -128 ~+127的范圍。
例如:可能是兩條 je exit_m 指令中exit_m標(biāo)號(hào)的語(yǔ)句離這里太遠(yuǎn),中間夾了太長(zhǎng)的代碼,超過(guò)了條件轉(zhuǎn)移允許的范圍。
對(duì)于這種情況,可以在較近處設(shè)一個(gè)條件轉(zhuǎn)移的跳轉(zhuǎn)目標(biāo),這個(gè)目標(biāo)處再用一條 JMP 無(wú)條件轉(zhuǎn)移指令實(shí)現(xiàn)接力。
·······································································
相對(duì)轉(zhuǎn)移指令,轉(zhuǎn)移范圍,是在-128~+127。
程序編寫(xiě)長(zhǎng)了,就會(huì)遇上,越界的問(wèn)題。
特別是使用宏指令的時(shí)候,特別容易越界。
level_up:
inc level
cmp level,50
**** je level_10 --改跳為接力點(diǎn)
cmp level,51
****je level_20
cmp level,52
****je level_30
……
level_10: jmp level_1 --在這里再跳一次
level_20: jmp level_2
level_20: jmp level_3
……
(由于自己一開(kāi)始沒(méi)有處理好當(dāng)掃描碼是ESC時(shí),要ret,那里寫(xiě)成了
cmp ah,01h ;判斷輸入字符是否為ESC
jz exit
結(jié)果編譯時(shí)報(bào)出jump out of range的錯(cuò)誤,是因?yàn)樽约喊裡xit: ret 放在了input的最后面,而jz exit和標(biāo)號(hào)exit之間的代碼段相距太遠(yuǎn)了(因?yàn)橹虚g有很多宏,展開(kāi)就比較長(zhǎng)了)而這個(gè)問(wèn)題用上面的跳轉(zhuǎn)接力棒的方法好像行不通,所以,轉(zhuǎn)換了方式,不如把jnz exit換為jnz continue,而continue標(biāo)號(hào)處的代碼距離jnz continue很近,不會(huì)報(bào)錯(cuò),這樣就解決了這個(gè)問(wèn)題 。這里比較細(xì),平時(shí)看程序也沒(méi)意識(shí)到會(huì)存在這個(gè)問(wèn)題 )
總結(jié)
以上是生活随笔為你收集整理的汇编实验:屏幕窗口程序(代码有较为详细的注释)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: win10下mysql 8.0.18 安
- 下一篇: 伪指令PAGE和TITLE说明