7.6問(wèn)題
問(wèn)題:[bx+idata]的靈活運(yùn)用
編程闰挡,將datasg段中每個(gè)單詞的頭一個(gè)字母改成大寫
assume cs:codesg,ds:datasg
datasg segment
db '1\. file '
db '2\. edit '
db '3\. search '
db '4, view '
db '5\. option '
db '6\. help '
datasg ends
?
code segment
start:......
codesg ends
end start
分析:
其中定義的字符串在內(nèi)存中的存放是這樣的:
定義了6個(gè)字符串锐墙,每個(gè)長(zhǎng)度都是16個(gè)字節(jié),需要進(jìn)行6次循環(huán)长酗,用一個(gè)變量R定位行溪北,用常量定位列。過(guò)程如下:
BX先存放第一行的地址
mov cx花枫,6 因?yàn)榭偣灿辛?/p>
s:改變第BX行刻盐,第3列的字母為大寫改變BX的值使它指向下一行的地址。
loop
也就是說(shuō)劳翰,使用bx作變量敦锌,定位每行的起始地址,用3定位要修改的列佳簸,用[bx+idata]的方式來(lái)對(duì)目標(biāo)單元進(jìn)行尋址
代碼:
assume cs:codesg,ds:datasg
datasg segment
db '1\. file '
db '2\. edit '
db '3\. search '
db '4, view '
db '5\. option '
db '6\. help '
datasg ends
?
code segment
start: mov ax,datasg
mov ds,ax
mov bx,0
mov cx,6
s:mov al,[bx+3] ;注意單位是字節(jié)乙墙,所以是al
and al,11011111b
mov [bx+3],al
add bx,16
loop s
mov ax,4c00h
int 21h
codesg ends
end start </pre>
7.7問(wèn)題
問(wèn)題:[bx+SI]的靈活運(yùn)用
編程,將datasg段中每個(gè)單詞改寫成大寫字母
assume cs:codesg,ds:datasg
datasg segment
db 'ibm '
db 'dec '
db 'dos '
db 'vax '
datasg ends
?
code segment
start:......
codesg ends
end start
分析:
其中定義的字符串在內(nèi)存中的存放是這樣的:
在datasg中定義了4個(gè)字符串生均,每個(gè)長(zhǎng)度為16個(gè)字節(jié)听想,因?yàn)樗麄兪沁B續(xù)存放的,我們可以將這4個(gè)字符串看成一個(gè)4行16列的二維數(shù)組马胧,按照要求汉买,需要修改每一個(gè)單詞,即二維數(shù)組的每一行的前三列佩脊。
進(jìn)行4*3次的二重循環(huán)蛙粘,使用R定位行,變量C定位列威彰。外層循環(huán)按行來(lái)進(jìn)行出牧,內(nèi)層循環(huán)按列來(lái)進(jìn)行。過(guò)程如下:
-
R=第一行的地址
mov cx歇盼,4
S0:C=第一列的地址
mov cx舔痕,3
s:改變R行,C列的字母為大寫
C=下一列的地址
loop s
R=下一行的地址
loop s0
使用bx來(lái)作變量豹缀,定位每行的起始地址伯复,用si定位要修改的列,用[bx+si]的方式來(lái)對(duì)目標(biāo)單元進(jìn)行尋址
代碼:
assume cs:codesg,ds:datasg
datasg segment
db 'ibm '
db 'dec '
db 'dos '
db 'vax '
datasg ends
?
code segment
start:mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4
s0:mov si,0
mov cx,3
s:mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s
add bx,16
loop s0
mov ax,4c00h
int 21h
codesg ends
end start
這段代碼邢笙,會(huì)陷入死循環(huán)啸如,原因是cx的使用,程序是二重循環(huán)鸣剪,但是只用了一個(gè)循環(huán)計(jì)數(shù)器组底,造成在進(jìn)行內(nèi)層循環(huán)的時(shí)候覆蓋了外層循環(huán)的循環(huán)計(jì)數(shù)值。
在debug這個(gè)程序筐骇,可以發(fā)現(xiàn)是因?yàn)閏x的錯(cuò)誤導(dǎo)致的债鸡,但是多用一個(gè)計(jì)數(shù)器又不可能,因?yàn)閘oop指令默認(rèn)使用cx為循環(huán)計(jì)數(shù)器铛纬。所以應(yīng)該在每次開(kāi)始內(nèi)層循環(huán)的時(shí)候厌均,將外層的cx值保存起來(lái),在執(zhí)行外層循環(huán)的loop指令前告唆,再恢復(fù)外層循環(huán)的cx數(shù)值棺弊,可以使用dx來(lái)保存。
改進(jìn)后的代碼:
assume cs:codesg,ds:datasg
datasg segment
db 'ibm '
db 'dec '
db 'dos '
db 'vax '
datasg ends
?
code segment
start:mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4
s0:mov dx,cx ;使用dx寄存器來(lái)臨時(shí)保存cx的值
mov si,0
mov cx,3
s:mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s
add bx,16
mov cx,dx ;在這里再恢復(fù)cx的值
loop s0
mov ax,4c00h
int 21h
codesg ends
end start
這個(gè)程序使用dx來(lái)臨時(shí)保存cx的值擒悬,這是可以的模她,但是有可能dx這個(gè)值在內(nèi)層循環(huán)中也會(huì)被使用,在這個(gè)程序中懂牧,si侈净,cx,ax僧凤,bx畜侦,顯然不能存放cx中的數(shù)據(jù),因?yàn)檫@些寄存器在循環(huán)中也要使用躯保,cs旋膳,ip,ds當(dāng)然也不能使用途事,因?yàn)閏s:ip時(shí)刻指向當(dāng)前指令验懊,ds指向datasg段。
所以現(xiàn)在討論的是盯孙,程序中經(jīng)常需要進(jìn)行數(shù)據(jù)的暫存鲁森,可能是寄存器中的也可能是內(nèi)存中的,我們應(yīng)該怎么樣做更為合理振惰。
通用的方案是:使用內(nèi)存歌溉,可以將需要暫存的數(shù)據(jù)放到內(nèi)存單元中,需要使用的時(shí)候骑晶,再?gòu)膬?nèi)存單元中恢復(fù)痛垛,這樣就需要開(kāi)辟一段內(nèi)存空間。
再改進(jìn)后的代碼:
assume cs:codesg,ds:datasg
datasg segment
db 'ibm '
db 'dec '
db 'dos '
db 'vax '
dw 0 ;定義一個(gè)字桶蛔,用來(lái)保存cx
datasg ends
?
code segment
start:mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4
s0:mov ds:[40H],cx ;使用定義的字ds:[40H]來(lái)臨時(shí)保存cx的值
mov si,0
mov cx,3
s:mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s
add bx,16
mov cx,ds:[40H] ;在這里再恢復(fù)cx的值
loop s0
mov ax,4c00h
int 21h
codesg ends
end start
多定義一個(gè)字匙头,也就是說(shuō),使用ds:[40H]來(lái)存放cx的值仔雷。
但是蹂析,上面的方法還是很麻煩舔示,因?yàn)槿绻枰4娑鄠€(gè)數(shù)據(jù)的時(shí)候,必須要記住數(shù)據(jù)存放到了哪個(gè)單元电抚,容易混亂惕稻,所以更好的方法是使用棧
最終改進(jìn)的程序:
assume cs:codesg,ds:datasg,ss:stacksg
datasg segment
db 'ibm '
db 'dec '
db 'dos '
db 'vax '
dw 0 ;定義一個(gè)字,用來(lái)保存cx
datasg ends
?
stacksg segment
dw 0,0,0,0,0,0,0,0 ;定義一個(gè)棧段蝙叛,容量為16個(gè)字節(jié)
stacksg segment
?
code segment
start:mov ax,stackag
mov ss,ax
mov sp,16
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4
s0:push cx ;使用定義的棧臨時(shí)保存cx的值
mov si,0
mov cx,3
s:mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop s
add bx,16
pop cx ;在這里再恢復(fù)cx的值
loop s0
mov ax,4c00h
int 21h
codesg ends
end start
7.9問(wèn)題
問(wèn)題:[bx+si+idata]的靈活運(yùn)用
編程俺祠,將datasg段中每個(gè)單詞的前四個(gè)字母改為大寫字母
assume cs:codesg,ds:datasg,ss:stacksg
stacksg segment
dw 0,0,0,0,0,0,0,0
stacksg ends
datasg segment
db '1.display '
db '2.brows '
db '3.replace '
db '4.modify '
datasg ends
code segment
start:......
codesg ends
end start
分析:
其中定義的字符串在內(nèi)存中的存放是這樣的:由于數(shù)據(jù)是連續(xù)存放的,可以將這四個(gè)字符串看作一個(gè)4行16列的二維數(shù)組借帘,按照要求蜘渣,需要修改每個(gè)單詞的前4個(gè)字母,即二維數(shù)組的每一行的3~6列肺然。需要進(jìn)行4*4的二重循環(huán)蔫缸,用變量R定位行,常量3定位每行要修改的起始列际起,變量C定位相對(duì)于起始列的要修改的列捂龄,
首先使用R定位第一行,循環(huán)修改R行的3+C列
然后再用R定位到下一行加叁,再次循環(huán)修改R行的3+C列
使用bx來(lái)做變量倦沧,定位每行的起始地址,用si定位要修改的列它匕,用[bx+3+si]的方式來(lái)對(duì)目標(biāo)單元進(jìn)行尋址展融。
代碼:
assume cs:codesg,ds:datasg,ss:stacksg
stacksg segment
dw 0,0,0,0,0,0,0,0
stacksg ends
?
datasg segment
db '1.display '
db '2.brows '
db '3.replace '
db '4.modify '
datasg ends
?
code segment
start:mov ax,stacksg
mov ss,ax
mov sp,16 ;讓CPU知道和棧段掛鉤
mov ax,datasg
mov ds,ax ;讓CPU知道和ds掛鉤
mov bx,0
mov cx,4
s0:push cx ;用來(lái)保存cx的值
mov si,0 ;定義列
mov cx,4
s:mov al,[bx+si+3] ;這里是定位到每個(gè)要索引的字母,每行總共有四個(gè)字母
and al,11011111b
mov [bx+si+3],al
inc si ;使它指向同一行的下一個(gè)字母
loop s
add bx,16
pop cx
loop s0
mov ax,4c00h
int 21h
codesg ends
end start