返回介绍

第 10 章:CALL 和 RET 指令

发布于 2024-10-04 13:37:13 字数 15710 浏览 0 评论 0 收藏 0

检测点 10.1

补全程序 ,实现从内存 1000:0000 处开始执行指令。

assume cs:code

stack segment
    db 16 dup (0)
stack ends

code segment
start:
    mov ax,stack
    mov ss,ax
    mov sp,16
    mov ax,1000h    ; CS,先入后出
    push ax
    mov ax,0000h    ; IP
    push ax
    retf
code ends

end start

检测点 10.2

下面的程序执行后,ax 中的数值为多少?

内存地址机器码汇编指令axIP
1000: 0b8 00 00mov ax,00000h0003h
1000: 3e8 01 00call s0006h
1000: 640inc ax(该行未执行)
1000: 758s:pop ax0006h0008h

检测点 10.3

下面的程序执行后,ax 中的数值为多少?

内存地址机器码汇编指令axbxCSIP
1000: 0b8 00 00mov ax,00000h
1000: 39A 09 00 00 10call far ptr s1000h0008h

0008h

1000h

1000: 840inc ax(该行未执行)
1000: 958s: pop ax0008h(IP)1000h
add ax , ax0010h
pop bx1000h(CS)
add ax,bx1010h

检测点 10.4

下面的程序执行后,ax 中的数值为多少?

内存地址机器码汇编指令axIP
1000: 0b8 06 00mov ax,60006h0003h
1000: 3ff d0call ax(跳转到 0006h)0005h0005h
1000: 540inc ax
1000: 6mov bp,sp
add ax, [bp]000Bh

检测点 10.5

(1)下面的程序执行后,ax 中的数值为多少?(注意:用 call 指令的原理来分析,不要在 Debug 中单步跟踪来验证你的结论。对于此程序,在 Debug 中单步跟踪的结果,不能代表 CPU 的实际执行结果。)

assume cs:code

stack segment
    dw 8 dup (0)
stack ends

code segment
start:
    mov ax,stack            ; ax 存储 stack 的段地址
    mov ss,ax               ; ss 指向 stack 段
    mov sp,16               ; sp = 16,而 stack 是 8 字 == 16 字节,正好指向栈顶
    mov ds,ax               ; ds 指向 stack 段
    mov ax,0                ; ax = 0000h
    call word ptr ds:[0EH]  ; 将 CS 和 IP 分别压栈,此时 IP 为该指令后的第一个字节
                            ; 跳转地址为 ds:0E ~ ds:0F,而 ds 指向 stack 段,且栈顶恰好为第 16 个字节
                            ; 因此该 call 指令即跳转到栈顶存储的 CS 和 IP 指向的位置
                            ; 而栈顶存储的 IP 恰好指向的是下一条指令(inc ax)的地址
                            ; 故这条指令执行完,直接执行下面的指令
    inc ax                  ; ax = 0001h
    inc ax                  ; ax = 0002h
    inc ax                  ; ax = 0003h <- ax 最后的值
    mov ax,4c00h
    int 21h
code ends

end start

为什么不让使用 debug 来逐步调试?因为在执行到 CALL 指令时,显示 ds:[0eh]=065D(在我的环境中debug 后),ds:[0eh] 中的内容是中断的信息,并不是我们程序所希望的 0011H,它一下就 jmp 到 065D 的地址去了,而不是 CS:11 地址执行。

(2)下面的程序执行后, ax 和 bx 中的数值为多少?

assume cs:code

data segment
    dw 8 dup (0)
data ends

code segment
start:
    mov ax,data                     ; ax = data 段地址
    mov ss,ax                       ; ss 指向 data 段
    mov sp,16                       ; sp = 16
    mov word ptr ss:[0] , offset s  ; ss:[0] 指向 s 的偏移地址
    mov ss:[2],cs                   ; ss:[2] 指向段地址 CS
    call dword ptr ss:[0]           ; 分别将 CS 和 IP 压栈,sp = 12 = 0cH
                                    ; CS 位于 ss:[0eH],IP 位于 ss:[0cH]
                                    ; 入栈的 IP 为该指令后的第一个字节的偏移地址
                                    ;也即下面 nop 对应的地址
                                    ; 执行完跳转至 ss:[0],也即 s
    nop                             ; 机器码 90,占据一字节
s:
    mov ax,offset s                 ; ax = s 的偏移地址
    sub ax,ss:[0cH]                 ; ax = ax - ss:[0cH],也即:
                                    ; ax = s 的偏移地址 - nop 的偏移地址,而 nop 为 1字节
                                    ; 故 ax = 0001h
    mov bx,cs                       ; bx = CS 存储的段地址
    sub bx,ss:[0eH]                 ; bx = CS 存储的段地址 - ss:[0eH]
                                    ; 而 ss:[0eH] 中恰好为 CS 地址
                                    ; 故 bx = 0000h
    mov ax,4c00h
    int 21h
code ends

end start

参考链接

实验 10 编写子程序

一、显示字符串

显示字符串是现实工作中经常要用到的功能,应该编写一个通用的子程序来实现这个功能。我们应该提供灵活的调用接口,使调用者可以决定显示的位置(行、列)、内容和颜色。

描述
名称show_str
功能在指定的位置,用指定的颜色,显示一个用 0 结束的字符串。
参数

(dh)=行号(取值范围 0~24)

(di)=列号(取值范围 0~79)

(cl)=颜色

ds:si 指向字符串的首地址

返回
应用举例在屏幕的 8 行 3 列,用绿色显示 data 段中的字符串。


参考链接

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文