彙編入門學習筆記 (六)—— si、di,雙重迴圈,彙編si
瘋狂的暑假學習之 彙編入門學習筆記 (六)—— si、di,雙重迴圈
參考: 《組合語言》 王爽 第7章
1. and和or指令,與[bx+idata]
and和or,就不多說了。
[bx+idata] 這樣寫是可以的,某些情況下,比較方便。
[bx+idata] 也可以寫成 idata[bx]
直接見例子: 把’ABcde‘ 跟 ‘fGHig’ 都改成大寫(ASCII中大寫字母與小寫字母二進位中,只有第五位不同,大寫字母是0,小寫字母是1)
assume cs:code,ds:data data segmentdb 'ABcde'db 'fGHIg'data ends code segmentstart:mov ax,datamov ds,axmov bx,0mov cx,4mov al,00100000bs:or [bx],alor [5+bx],al ;[5+bx]也可以寫成5[bx]inc bxloop smov ax,4c00Hint 21Hcode endsend start
2. si,di,與[bx+si],[bx+di],[bx+si+idata],[bx+di+idata]
si與di,除了不能像bx一樣分成bh,bl,其他與bx一樣。如 mov ax,[si] 等等
[bx+si],[bx+di],[bx+si+idata],[bx+idata]
這些都是可以的,某些情況下,比較方便。
其中[bx+si]與[bx+di] 可以寫成 [bx][si],[bx][di]
[bx+si+idata],[bx+di+idata] 可以寫成idata[bx][si],idata[bx][di]
例子:複製Welcome!
assume cs:code,ds:datadata segmentdb 'Welcome! 'data endscode segmentstart:mov ax,datamov ds,axmov si,0mov cx,4s:mov ax,[si]mov 8[si],axadd si,2loop smov ax,4c00Hint 21Hcode endsend start
例子:將data中的單詞的首字母改成大寫
assume cs:code,ds:datadata segmentdb '1.file 'db '2.edit 'db '3.search'db '4.view 'data endscode segmentstart:mov ax,datamov ds,axmov bx,0mov cx,4mov al,11011111bs:and [bx+2],aladd bx,8loop smov ax,4c00Hint 21Hcode endsend start
3. 雙重迴圈
例子:data中單詞改成大寫的
assume cs:code,ds:datadata segmentdb 'ibm 'db 'dec 'db 'dos 'db 'vax 'data endscode segmentstart:mov ax,datamov ds,axmov bx,0mov al,11011111bmov cx,4s:mov cx,3mov si,0s0:and [bx+si],alinc siloop s0add bx,8loop smov ax,4c00Hint 21Hcode endsend start
上面 的代碼,是錯誤的會出現是死迴圈。因為cx不斷的被賦予3,導致外層迴圈死迴圈。
改進,在進行內層迴圈時把cx儲存起來,記憶體迴圈結束時,恢複cx。例子:
assume cs:code,ds:datadata segmentdb 'ibm 'db 'dec 'db 'dos 'db 'vax 'data endscode segmentstart:mov ax,datamov ds,axmov bx,0mov al,11011111bmov cx,4s:mov dx,cx ;dx用來臨時存放外層的cx的值mov cx,3mov si,0s0:and [bx+si],alinc siloop s0mov cx,dx;用來回複外層迴圈的cxadd bx,8loop smov ax,4c00Hint 21Hcode endsend start
上面的代碼,雖然能解決上面問題,能正常運行。但是寄存器的數量有限,有時,可能沒有其他的寄存器可以用。
解決方案,儲存在記憶體中。例子:
assume cs:code,ds:datadata segmentdb 'ibm 'db 'dec 'db 'dos 'db 'vax 'dw 0 ;定義一個字,用來儲存cxdata endscode segmentstart:mov ax,datamov ds,axmov bx,0mov al,11011111bmov cx,4s:mov ds:[20H],cx mov cx,3mov si,0s0:and [bx+si],alinc siloop s0mov cx,ds:[20H]add bx,8loop smov ax,4c00Hint 21Hcode endsend start
上面的代碼,解決了寄存器不夠的情況。但是,還是比較複雜,如果有很多迴圈,就會弄不清楚。
解決方案,使用棧來儲存恢複cx。例子1:
assume cs:code,ds:data,ss:stackdata segmentdb 'ibm 'db 'dec 'db 'dos 'db 'vax 'data endsstack segmentdw 0,0,0,0,0,0,0,0stack endscode segmentstart:mov ax,datamov ds,axmov ax,stackmov ss,axmov sp,16mov bx,0mov al,11011111bmov cx,4s:push cxmov cx,3mov si,0s0:and [bx+si],alinc siloop s0pop cxadd bx,8loop smov ax,4c00Hint 21Hcode endsend start
例子2:把data中的單詞,前3個字母改成大寫
assume cs:code,ds:data,ss:stackdata segmentdb '1.display.......'db '2.brows.........'db '3.replace.......'db '4.modify........'data endsstack segmentdw 0,0,0,0,0,0,0,0stack endscode segmentstart:mov ax,datamov ds,axmov ax,stackmov ss,axmov sp,16mov bx,0mov al,11011111bmov cx,4s:push cxmov si,0mov cx,3s0:and [bx+si+2],alinc siloop s0pop cxadd bx,10Hloop smov ax,4c00Hint 21Hcode endsend start
MOV SI, DI對嗎對
改變SI值之前先要儲存SI值
求彙編高手協助!!!謝謝了!!已經調試成功
注意三件事:(1)定義和使用類型要匹配字和位元組能混用;(2)雙重迴圈時內外迴圈初始化位置別弄錯了;(3)程式輸出十六進位數
DATA SEGMENT
CJ DB 30 DUP(?)
BUF DB 3
DB ?
DB 3 DUP(?)
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK
MAIN PROC FAR
START:PUSH DS
XOR AX,AX
PUSH AX
MOV AX,DATA
MOV DS,AX
MOV DI,OFFSET CJ
MOV CX,10
B:MOV DX,OFFSET BUF
MOV AH,0AH
INT 21H
MOV SI,OFFSET BUF
MOV BL,2
MOV AX,0
A:MOV DL,10
MUL DL
MOV DL,[SI+2]
AND DL,0FH
ADD AL,DL
INC SI
DEC BL
JNZ A
MOV [DI],AL
CALL HCHH
INC DI
LOOP B
MOV BL,2
MOV SI,OFFSET CJ
MOV CL,4
MOV CH,[SI]
C:ROL CH,CL
MOV DL,CH
AND DL,0FH
ADD DL,30H
CMP DL,3AH
JB DISP
ADD DL,7H
DISP:
MOV AH,2
INT 21H
DEC BL
JNZ C
MOV AH,1
INT 21H
EXIT:RET
MAIN ENDP
HCHH PROC
MOV DL,0DH
MOV AH,2
INT 21H
MOV DL,0AH
MOV AH,2
INT 21H
RET
HCHH ENDP
CODE ENDS
END MAIN