美文网首页
【汇编语言】第 10 章 CALL 和 RET 指令

【汇编语言】第 10 章 CALL 和 RET 指令

作者: gfson | 来源:发表于2017-07-13 09:59 被阅读0次

    版权声明:本文为 gfson 原创文章,转载请注明出处。
    注:作者水平有限,文中如有不恰当之处,请予以指正,万分感谢。

    10.1 ret 和 retf

    10.2 检测点 10.1

    • 答案:
    • 1000h
    • 0

    10.3 call 指令

    call 指令的种类:

    • call 标号
    • call far ptr 标号
    • call 16 位 reg
    • call word ptr 内存单元地址
    • call dword ptr 内存单元地址

    10.4 检测点 10.2 - 10.5

    • 答案:

    ax 中的数值为 6,注意执行完 call s 后,IP 先变为 6,然后将 IP 的值压栈,最后跳转至 s。

    • 答案:

    ax 中的数值为 1010H,注意执行完 call far ptr s 后,IP 先变为 8,然后将 CS、IP 的值分别为 1000 和 8 依此压栈,最后再跳转至 s 继续执行。

    • 答案:

    ax 中的数值为 0BH。

    • 答案:

    (1)

    • ax 中的数值为 3,注意 ds 与 ss 中存放的段地址相同,在执行了 call word ptr ds:[0EH] 之后,程序会先将下一条指令 inc ax 的偏移量压栈,然后跳转到栈顶所指向的指令的位置,即跳转至第一条 inc ax 的位置,故最后 ax 的值为 3。
    • 注意 :在使用 Debug 单步跟踪的时候,由于 t 命令所导致的中断,而影响了栈中的值。

    (2)

    • ax 中的数值为 1,bx 中的数值为 0,注意到程序的一开始将 a 的偏移量和 cs 放入 ss:[0] 和 ss:[2] 中,然后调用 call 指令,将 CS 和 IP(nop 指令的偏移量)依此压栈后跳转到 s 处继续执行,ax 最终为 s 的偏移量减去 nop 指令所在位置的偏移量,为 1,bx 最终为 cs 的段地址相减,为 0。

    10.5 call 和 ret 的配合

    利用 call 和 ret 的配合来实现子程序机制

    10.6 mul 指令

    10.7 子程序模板

    10.8 实验 10

    实验题目篇幅太长,此处不予摘录,请参考原书。

    答案

    • 显示字符串
    assume cs:code, ss:stack
    stack segment
    dw 16 dup (0)
    stack ends
    data segment
    db 'Welcome to masm!', 0
    data ends
    code segment
    start:  mov dh, 8
    mov dl, 3
    mov cl, 2
    mov ax, data
    mov ds, ax
    mov ax, stack
    mov ss, ax
    mov sp, 32
    mov si, 0
    call show_str
    mov ax, 4c00h
    int 21h
    show_str:
    push cx
    push bx
    push ax
    push si
    push di
    push es
    ;using cx, bx, ax, si, di, es
    mov ax, 0b800h
    mov es, ax
    mov bx, 0
    mov di, 0
    mov al, 160
    mul dh
    add bx, ax
    mov al, 2
    mul dl
    add bx, ax ;bx stores address of start character
    mov al, cl ;al stores the color of character
    char:   mov ch, 0
    mov cl, ds:[si]
    jcxz zero
    mov ch, al
    mov es:[bx+di], cx
    add di, 2
    inc si
    jmp char
    zero:   pop es
    pop di
    pop si
    pop ax
    pop bx
    pop cx
    ret
    code ends
    end start
    
    • 解决除法溢出的问题
    assume cs:code, ss:stack
    stack segment
    dw 16 dup (0)
    stack ends
    code segment
    start:  mov ax, stack
    mov ss, ax
    mov sp, 32
    mov ax, 4240h
    mov dx, 000fh
    mov cx, 0ah
    call divdw
    mov ax, 4c00h
    int 21h
    divdw:  push bx
    mov bx, ax ; bx stores L
    mov ax, dx ; ax stores H
    mov dx, 0
    div cx ; after div, ax holds int(H/N), dx holds rem(H/N)
    push ax ; push int(H/N) temporarily
    mov ax, bx ; ax stores L
    div cx
    mov cx, dx
    pop dx
    pop bx
    ret
    code ends
    end start
    
    • 数值显示
    assume cs:code, ss:stack
    stack segment
    dw 16 dup (0)
    stack ends
    data segment
    db 10 dup (0)
    data ends
    code segment
    start:  mov ax, data
    mov ds, ax
    mov ax, stack
    mov ss, ax
    mov sp, 32
    mov ax, 12666
    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 si
    push di
    push dx
    push bx
    push cx
    mov di, 0
    mov dx, 0
    mov bx, 10
    devide: mov cx, ax
    jcxz stop
    div bx
    inc di
    push dx
    mov dx, 0
    jmp devide
    stop:   mov cx, di
    string: pop bx
    add bx, 30h
    mov [si], bl
    inc si
    loop string
    pop cx
    pop bx
    pop dx
    pop di
    pop si
    pop ax
    ret
    show_str:
    push cx
    push bx
    push ax
    push si
    push di
    push es
    ;using cx, bx, ax, si, di, es
    mov ax, 0b800h
    mov es, ax
    mov bx, 0
    mov di, 0
    mov al, 160
    mul dh
    add bx, ax
    mov al, 2
    mul dl
    add bx, ax ;bx stores address of start character
    mov al, cl ;al stores the color of character
    char:   mov ch, 0
    mov cl, ds:[si]
    jcxz zero
    mov ch, al
    mov es:[bx+di], cx
    add di, 2
    inc si
    jmp char
    zero:   pop es
    pop di
    pop si
    pop ax
    pop bx
    pop cx
    ret
    code ends
    end start
    

    10.9 课程设计 1

    课程设计 1 要求请参考原书。

    • 答案:
    ;注:函数中的标号为防止冲突,都加了本函数名为前缀
    ;在Debug中输入“-g 90”,直接运行到结束
    assume cs:code
    data segment
    db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
    db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
    db '1993','1994','1995'
    ;以上是表示21年的21个字符串
    dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
    dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
    ;以上是表示21年公司总收的21个dword型数据
    dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
    dw 11542,14430,45257,17800
    ;以上是表示21年公司雇员人数的21个word型数据
    data ends
    agency segment
    db 8 dup(0)
    agency ends
    
    code segment
    start: mov ax,0b800h
    mov es,ax
    mov di,0
    mov cx,80*24
    x: mov byte ptr es:[di],' ' ;将屏幕清空
    mov byte ptr es:[di+1],0
    inc di
    inc di
    loop x
    mov ax,data
    mov es,ax
    mov di,0
    mov bx,0
    mov ax,agency
    mov ds,ax
    mov si,0
    mov dh,4
    mov cx,21
    x1: push cx
    mov ax,es:[di]
    mov ds:[si],ax
    mov ax,es:[di+2]
    mov ds:[si+2],ax
    mov byte ptr ds:[si+4],0 ;显示年份
    mov dl,0
    mov cl,2
    call show_str
    mov ax,es:[84+di]
    push dx
    mov dx,es:[84+di+2]
    call dtoc_dword ;显示收入
    pop dx
    mov dl,20
    mov cl,2
    call show_str
    
    mov ax,es:[84+84+bx]
    call dtoc_word
    mov dl,40 ;显示雇员数
    mov cl,2
    call show_str
    
    mov ax,es:[84+di]
    push dx
    mov dx,es:[84+di+2]
    div word ptr es:[84+84+bx] ;计算人均收入并显示
    call dtoc_word
    pop dx
    mov dl,60
    mov cl,2
    call show_str
    
    add di,4
    add bx,2
    add dh,1
    pop cx
    loop x1
    mov ax,4c00h
    int 21h
    
    ;名称:show_str
    ;功能:在屏幕的指定位置,用指定颜色,显示一个用0结尾的字符串
    ;参数:(dh)=行号,(dl)=列号(取值范围0~80),(cl)=颜色,ds:si:该字符串的首地址
    ;返回:显示在屏幕上
    show_str:
    push ax
    push cx
    push dx
    push es
    push si
    push di
    mov ax,0b800h
    mov es,ax
    mov al,160
    mul dh
    add dl,dl
    mov dh,0
    add ax,dx
    mov di,ax
    mov ah,cl
    show_str_x:
    mov cl,ds:[si]
    mov ch,0
    jcxz show_str_f
    mov al,cl
    mov es:[di],ax
    inc si
    inc di
    inc di
    jmp show_str_x
    show_str_f:
    pop di
    pop si
    pop es
    pop dx
    pop cx
    pop ax
    ret
    ;名称:dtoc_word
    ;功能:将一个word型数转化为字符串
    ;参数:(ax)=word型的数据,ds:si指向字符串的首地址
    ;返回:ds:[si]放此字符串,以0结尾
    dtoc_word:
    push ax
    push bx
    push cx
    push dx
    push si
    mov bx,0
    dtoc_word_x:
    mov dx,0
    mov cx,10
    div cx
    mov cx,ax
    add dx,'0'
    push dx
    inc bx
    jcxz dtoc_word_f
    jmp dtoc_word_x
    dtoc_word_f:
    mov cx,bx
    dtoc_word_x1:
    pop ds:[si]
    inc si
    loop dtoc_word_x1
    pop si
    pop dx
    pop cx
    pop bx
    pop ax
    ret
    ;名称:dtoc_dword
    ;功能:将一个double word型数转化为字符串
    ;参数:(dx)=数的高八位,(ax)=数的低八位
    ;返回:ds:[si]放此字符串,以0结尾
    ;备注:会用到divdw函数
    dtoc_dword:
    push ax
    push bx
    push cx
    push dx
    push si
    mov bx,0
    dtoc_dword_x:
    mov cx,10
    call divdw
    push cx
    inc bx
    cmp ax,0
    jne dtoc_dword_x
    cmp dx,0
    jne dtoc_dword_x
    mov cx,bx
    dtoc_dword_x1:
    pop ds:[si]
    add byte ptr ds:[si],'0'
    inc si
    loop dtoc_dword_x1
    pop si
    pop dx
    pop cx
    pop bx
    pop ax
    ret
    ;名称:divdw
    ;功能:除法,被除数32位,除数16位,商32位,余数16位,不会溢出
    ;参数:(dx)=被除数高16位,(ax)=被除数低16位,(cx)=除数
    ;返回:(dx)=商高16位,(ax)=商低16位,(cx)=余数
    divdw:
    push bx
    push ax
    mov ax,dx
    mov dx,0
    div cx
    mov bx,ax
    pop ax
    div cx
    mov cx,dx
    mov dx,bx
    pop bx
    ret
    
    code ends
    end start
    

    相关文章

      网友评论

          本文标题:【汇编语言】第 10 章 CALL 和 RET 指令

          本文链接:https://www.haomeiwen.com/subject/nscyhxtx.html