//目录

汇编实验十:编写子程序

预备知识:

(1)

ret  :修改IP  IP = SS*16 + SP   SP+=2

retf :修改CS,IP  IP = SS*16 + SP ,SP+=2 , CS = SS*16 + SP , SP+=2

Source Code:

 

assume cs:code

stack segment
    db 16 dup (0)
stack ends

code segment
    mov ax,4c00H
    int 21H

    start:
        mov ax,stack
        mov ss,ax
        mov sp,16
        mov ax,0
        push ax
        mov bx,0
        ret
code ends
end start
View Code

 

 

IP指向了栈顶元素,栈顶元素等于0,那么下一条命令就是返回程序;

 

Source Code:

assume cs:code

stack segment
    db 16 dup (0)
stack ends

code segment
    mov ax,4c00h
    int 21h
start:
    mov ax,stack
    mov ss,ax
    mov sp,16
    mov ax,0
    push cs
    push ax
    mov bx,0
    retf
code ends
end start
View Code

IP还是指向栈顶元素,下一条命令是返回程序;

也就是说,

ret 相当于 pop IP;

retf 相当于 pop IP,pop CS;

 

(2)call:内存中转移

call word ptr 相当于 push IP,jmp word ptr

call dword ptr 相当于 push CS,push IP,jmp dword ptr

 

Source Code:

assume cs:code

stack segment
    dw 8 dup (0)
stack ends

code segment
start:
    mov ax,stack
    mov ss,ax
    mov sp,16
    mov ds,ax
    mov ax,0
    call word ptr ds:[0EH]
    inc ax
    inc ax
    inc ax
    mov ax,4c00H
    int 21H
code ends
end start
View Code

 

 

(3)mul,乘法指令

1、8位,一个数在AL中,一个在内存中,结果在AX中

2、16位,一个在AX中,一个在内存中,结果,高位在DX中,低位在AX中;

 

 

(4)call和ret的配合:模块化程序

 Source Code:

assume cs:code

data segment
    dw 1,2,3,4,5,6,7,8
    dd 0,0,0,0,0,0,0,0
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    mov si,0
    mov di,16

    mov cx,8
    s:
        mov bx,[si]
        call cube
        mov [di],ax
        mov [di].2,dx
        add si,2
        add di,4
        loop s

    mov ax,4c00H
    int 21H
cube:
    mov ax,bx
    mul bx
    mul bx
    ret
code ends
end start
View Code

 

(5)批量数据传递,放到内存中,或者栈中;

 Source Code:

assume cs:code

data segment
    db 'conversation'
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    mov si,0
    mov cx,12
    call capital
    mov ax,4c00h
    int 21h

capital:
    and byte ptr [si],11011111b
    inc si
    loop capital
    ret
code ends
end start
View Code

 

(6)解决寄存器的冲突,就是将子程序用到的寄存器入栈;

Source Code:

assume cs:code

data segment
    db 'word',0
    db 'unix',0
    db 'wind',0
    db 'good',0
data ends

code segment
start:
    mov ax,data
    mov ds,ax
    mov bx,0

    mov cx,4
    s:
        mov si,bx
        call capital
        call change
        add bx,5
        loop s
    mov ax,4c00h
    int 21h

    capital:
        push cx
        push si
    change:
        mov cl,[si]
        mov ch,0
        jcxz ok
        and byte ptr [si],11011111b
        inc si
        jmp short capital

    ok:
        pop si
        pop cx
        ret
code ends
end start
View Code

 

试验任务:

显示字符串(注意DOS下一列占两个字符)

Source Code:

assume cs:code

data segment
    db 'I am TreeDream!',0
data ends

code segment
start:
    mov dh,8
    mov dl,3
    mov cl,2

    mov ax,data
    mov ds,ax
    mov si,0

    call show_str

    mov ax,4c00H
    int 21H

show_str:
    push dx
    push cx
    push ax
    push ss
    push si

    mov ax,0B800H
    mov es,ax   ;用于显示的栈段

    mov al,0a0h
    dec dh      ;行数以0标号
    mul dh      ;行的偏移
    mov bx,ax

    mov al,2    ;dos显示一列占两个字节
    dec dl
    mul al
    add bx,ax   ;显示的起始地址计算完

    mov di,0    ;数据段指针
    mov si,0

    mov al,cl   ;cx用于循环

s:
    mov ch,0
    mov cl,ds:[di]
    jcxz ok     ;判断cx是否为0
    mov ch,al
    mov es:[bx+si],cx   ;显示

    add si,2
    inc di
    jmp short s
ok:
    pop si
    pop ss
    pop ax
    pop cx
    pop dx
    ret
code ends
end start
View Code

 

 

(2)除法溢出

assume cs:code,ss:stack

stack segment
    dw 8 dup (0)
stack ends

code segment
start:
    mov ax,stack
    mov ss,ax
    mov sp,16

    mov ax,1000H
    mov dx,1
    mov bx,1
    div bx

    mov ax,4c00h
    int 21h

code ends
end start
View Code

除法的结果超过16为,ax中存不下;

解决方案,公式是X/N = int(H/N)*65536 + (rem(H/N)*65536 + L) / N

公式很好理解,但是程序不是很好理解;

Source Code:

assume cs:code,ss:stack

stack segment
    dw 8 dup (0)
stack ends

code segment
start:
    mov ax,stack
    mov ss,ax
    mov sp,16

    mov ax,4240H
    mov dx,00fH
    mov cx,0aH
    call divdw

    mov ax,4c00h
    int 21h
divdw:
    push ax
    mov ax,dx
    mov dx,0
    div cx

    mov bx,ax
    pop ax
    div cx

    mov cx,dx
    mov dx,bx
    ret


code ends
end start
View Code

 

 

第一次除法:

ax = 1,dx = 5

 

 第二次除法的时候,第一次的除法余数将是第二次除法的高位

 

(3)数值显示

Source Code:

assume cs:code

data segment
    db 10 dup (0)
data ends

stack segment
    dw 8 dup(0)
stack ends

code segment
start:
    mov ax,42243
    mov bx,data
    mov ds,bx
    mov bx,stack
    mov ss,bx
    mov sp,10h
    mov si,0
    call dtoc

    mov dh,8
    mov dl,3
    mov cl,2
    call show_str
    mov ax,4c00h
    int 21h

dtoc:
    push ax
    push bx
    push si
    mov bx,10
    mov si,0

s0:
    mov dx,0
    div bx  ;dx 余数,ax商
    add dx,30h  ;余数入栈
    push dx
    mov cx,ax   ;一直除到商为0
    inc si
    inc cx      ;每次循环cx会减1,然而cx是用来存商的;
    loop s0

    mov cx,si   ;cx循环次数,即有多少位
    mov si,0
s1:
    pop ds:[si]
    inc si
    loop s1

    pop si
    pop bx
    pop ax
    ret


show_str:
    push ax
    push dx
    push cx
    push si
    mov di,0
    mov bl,dh
    dec bl
    mov al,160
    mul bl
    mov bx,ax
    add dl,dl
    add bl,dl
    mov ax,0b800h
    mov es,ax
    mov al,cl
s:
    mov ch,0
    mov cl,ds:[si]
    jcxz ok
    mov es:[bx+di],cl
    mov es:[bx+di+1],al
    add di,2
    inc si
    loop s
ok:
    pop si
    pop cx
    pop dx
    pop ax
    ret
code ends
end start
View Code

 

posted @ 2017-06-01 17:18  小草的大树梦  阅读(1367)  评论(0编辑  收藏  举报