實驗4 8086標志寄存器及中斷
實驗任務1
任務點1
驗證add對ZF和CF的影響
可以看到對ZF和CF都造成了影響
驗證inc對ZF和CF的影響
只對ZF造成影響
測試代碼如下
assume cs:code,ds:data
data segment
db 16 dup(0)
data ends
stack segment
db 128 dup(0)
top equ $+1
stack ends
code segment
start:
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,top
mov ax,0ffffh
add ax,1
;測試add對CF和ZF的影響
mov ax,1
add ax,1
;恢復測試之前的影響,即無進位
mov ax,0ffffh
inc ax
;測試inc對CF和ZF的影響
mov ah,4ch
int 21h
code ends
end start
任務點2
TASK_1.ASM代碼
assume cs:code, ds:data
data segment
x dw 1020h, 2240h, 9522h, 5060h, 3359h, 6652h, 2530h, 7031h;一個128位數字
y dw 3210h, 5510h, 6066h, 5121h, 8801h, 6210h, 7119h, 3912h;一個128位數字
data ends
code segment
start:
mov ax, data
mov ds, ax
mov si, offset x
mov di, offset y
call add128
mov ah, 4ch
int 21h
add128:
push ax
push cx
push si
push di
sub ax, ax
mov cx, 8
s: mov ax, [si]
adc ax, [di]
mov [si], ax
inc si
inc si
inc di
inc di
loop s
pop di
pop si
pop cx
pop ax
ret
code ends
end start
對於inc
能否用add
替換的回答
inc
的結果
add
的結果
可以看到沒有任何區別,這是因為代碼中給出的數據不會產生任何進位,所以add
和inc
在這種特殊的情況下無區別
下面修改代碼里面的數據,使其能產生進位
data segment
x dw 9020h, 2240h, 9522h, 5060h, 3359h, 6652h, 2530h, 7031h
y dw 9210h, 5510h, 6066h, 5121h, 8801h, 6210h, 7119h, 3912h
data ends
inc
的結果
add
的結果
這就有了區別了
后16位的運算需要用到前16位運算的進位值,所以不能用add
因為根據之前的實驗,add
會對CF
標志寄存器造成影響,inc
則不會。
運行並觀察數據段的變化
做加法之前
做加法后
可以看到進行了加法,但並沒有產生進位
接下來的運行結果類似,並沒有產生進位
實驗任務2
代碼以及注釋解析
assume cs:code, ds:data
data segment
str db 80 dup(?);80個字節未初始化的內存空間
data ends
code segment
start:
mov ax, data
mov ds, ax
mov si, 0
s1:
mov ah, 1;int 21h中斷的參數,表示輸入單個字符
int 21h;調用中斷例程
mov [si], al;將結果存入ds:[si]中
cmp al, '#';與'#'比對,影響標志寄存器ZF,運算結果為0表示相同,則ZF標志寄存器變為ZR
je next;if(al == '#'(ZF == ZR)) goto next
inc si;偏移地址加一
jmp s1;繼續輸入一個字符
next:
mov ah, 2;int 21h中斷的參數,表示打印一個ASCII字符
mov dl, 0ah;換行
int 21h;調用中斷例程
mov cx, si;將輸入的字符的數量(不包括#)賦給cx寄存器
mov si, 0;將si寄存器置零
s2: mov ah, 2;int 21h中斷的參數,表示打印一個ASCII字符
mov dl, [si];將ds:[si]出內存的值賦給dl
int 21h;調用中斷例程
inc si;偏移地址+1
loop s2;循環,直到cx=0
mov ah, 4ch;int 21h中斷的參數,表示回到DOS
int 21h;執行中斷例程
code ends
end start
運行結果
實驗任務2
代碼
assume cs:code,ds:data
data segment
x dw 91, 792, 8536, 65521, 2021
len equ $ - x
data ends
stack segment
db 64 dup(0)
top equ $+1
stack ends
code segment
start:
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,top
mov cx,len/2
mov bx,0
s1:
mov ax,ds:[bx]
push bx
push cx
call printNumber
call printSpace
pop cx
pop bx
add bx,2
loop s1
mov ah,4ch
int 21h
printNumber:
;ax dx
;ax 被除數,直到
;cx計有多少位,然后循環出棧輸出
mov bx,10
mov cx,0
s2:
mov dx,0
div bx
;ax 商
;dx 余數
push dx
inc cx
cmp ax,0
jne s2
s3:
mov ah,2
pop dx
or dl,30h
int 21h
loop s3
ret
printSpace:
mov ah,2
mov dl,20h
int 21h
ret
code ends
end start
運行結果
實驗任務4
代碼
assume cs:code,ds:data
data segment
str db "assembly language, it's not difficult but tedious"
len = ($ - str)
data ends
stack segment
db 128 dup(0)
top equ $ + 1
stack ends
code segment
start:
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,top
mov si,0
mov cx,len
call strupr
mov ah,4ch
int 21h
strupr:
;0100 0001 A
;0110 0001 a
s:
cmp byte ptr ds:[si],61h
jb s1
cmp byte ptr ds:[si],7ah
ja s1
mov dl,ds:[si]
and dl,11011111B
mov ds:[si],dl
s1:
inc si
loop s
ret
code ends
end start
運行結果
實驗任務5
代碼注釋解析
assume cs:code, ds:data
;輸入7,則屏幕顯示yes
;否則輸出no
data segment
str1 db "yes", '$'
str2 db "no", '$'
data ends
code segment
start:
mov ax, data
mov ds, ax
mov ah, 1;輸入一個字符
int 21h
mov ah, 2;int 10h 2號功能,設置光標位置
mov bh, 0;頁號
mov dh, 24;行號
mov dl, 70;列號
int 10h;BIOS中斷例程調用
cmp al, '7'
je s1;ZF == ZR 跳轉,相等跳轉
mov ah, 9;輸出字符串
mov dx, offset str2;字符串首地址
int 21h;DOS中斷例程
jmp over
s1: mov ah, 9;輸出字符串
mov dx, offset str1;字符串首地址
int 21h;DOS中斷例程
over:
mov ah, 4ch
int 21h;DOS中斷例程
code ends
end start
運行結果
實驗任務6
實驗子任務1
將例程直接內嵌進task6_1.asm的代碼中了
運行結果如下
中斷和軟中斷的區別
中斷,其實就是中斷源發出中斷信號,CPU暫定當前的程序,轉而去執行其他程序,即改變CS:IP
中斷源有很多,CPU內部的中斷源發出中斷信號,外部設備發出的中斷信號。
硬件中斷指的就是外部設備發出的電信號中斷信號,需要中斷控制器,排隊器等硬件電路實現。
軟中(內)斷就是CPU內部產生的中斷信號,比如除法溢出,或者程序調用中斷例程,感覺和call類似。
實驗子任務2
實現了書本上對於0號中斷例程的修改。
代碼
assume cs:code
code segment
start:
mov ax,0
mov es,ax;目的段地址
mov ax,cs
mov ds,ax;源段地址
mov di,200h
mov si,d0s
mov cx,d0len
movd0:;將代碼復制到0:200處
mov al,ds:[si]
mov es:[di],al
inc si
inc di
loop movd0
;設置中斷表,中斷表處於內存中
;中斷表ip: 中斷號*4
;中斷表cs: 中斷號*4+2
mov ax,0
mov ds,ax
mov word ptr ds:[0],200h
mov word ptr ds:[2],0
;測試例程
mov ax,1000h
mov bh,1
div bh
;測試例程
mov ax,4c00h
int 21h
d0:
d0s equ $
;將字符串常駐內存
jmp short d0start
db "overflow!"
d0start:
mov ax,cs
mov ds,ax
mov si,202h
mov ax,0b800h
mov es,ax
mov di,12*160+36*2
mov cx,9
s: mov al,[si]
mov es:[di],al
inc si
add di,2
loop s
;iret;中斷返回,這里不返回,直接調用DOS中斷,返回DOS,不然會卡死
mov ah,4ch
int 21h
d0len equ $-d0s
code ends
end start