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

版权声明:本文为 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

推荐阅读更多精彩内容

  • 8086汇编 本笔记是笔者观看小甲鱼老师(鱼C论坛)《零基础入门学习汇编语言》系列视频的笔记,在此感谢他和像他一样...
    Gibbs基阅读 27,622评论 8 105
  • 计算机通过执行指令序列来使机器得以工作,所以对于每一系列的计算机都有指定的一组指令集供计算机使用,这组指令...
    国才阅读 4,998评论 1 10
  • 指令是使计算机执行某种特定操作的二进制编码。8086 CPU指令系统有133条指令,通常分为数据寻址方式和程序寻址...
    刀月水阅读 835评论 0 1
  • 王爽汇编全书知识点大纲 第一章 基础知识 机器语言 汇编语言的产生 汇编语言的组成 存储器 cpu对存储器的读写 ...
    2c3ba901516f阅读 956评论 0 1
  • 以前,我常说人可以在潜意识或情绪发生过程中,用意识去感知潜意识的存在,一旦成功,就能实现意识对潜意识的干预,不论是...
    adamant555阅读 157评论 0 0