lyoal 发表于 2012-11-21 21:49:17

第十章的一个例子程序不能理解"call dword ptr 内存单元"

第十章的一个例子程序不能理解"call dword ptr 内存单元",这指令,是远转移,到底压入栈的是下一条指的CS:IP,还是跟"jmp far ptr 内存单元 "指令一样,是将内存地址起始处的两个字中,高字节为CS地址,低字节为偏移地址。看代码:
assume cs:code
code segment
start:        mov sp,10h
                mov ax,0123h
                mov ds:,ax
                mov word ptr ds:,0
                call dword ptr ds:
               
                mov ax,4c00h
                int 21h
                code ends
        end start这段代码在我的win7系统上执行到 mov ds:,ax 处就变样了,意思就是不能正确执行,不能如看到如例题所讲的那样在DEBUG中看到相应的结果。书面上给出的结果就是跟 "jmp far ptr 内存单元" 这条指令的执行方式类似,是取数据段起始地址处的两个字,高字节为CS地址,低字节为偏移地址

同时也看迷糊了,call far ptr 标号 ; 这条指令是将下一条地址的CS:IP压入栈中,再跳转到标号处执行。
但是,测试点10.5 中程序代码如下:
assume cs:code
data segment
        dw 8 dup (0)
data ends

code segment
start:        mov ax,data
                mov ss,ax
                mov sp,16
                mov word ptr ss:,offset s
                mov ss:,cs
                call dword ptr ss:
                nop
                s:mov ax,offset s
                sub ax,ss:
                mov bx,cs
                sub bx,ss:
               
                mov ax,4c00h
                int 21h
                code ends
        end startcall dword ptr ss: ;这条指令执行的后,却同样是将下一条地址的CS:IP压入栈中。这里跟例子程序又不相附,看到这样头晕眼又花的。又理不通了,请大虾指点迷津啊!谢谢你们。

ACC 发表于 2012-11-21 21:49:18

lyoal 发表于 2012-11-22 12:36 static/image/common/back.gif
首先非常感谢ACC的解答,但是学生还是有点迷不过来,call dword ptr ds:,这条指令执行前,将下一条指 ...

call 是调用子程序指令,一般和ret指令共同使用,call调用,ret返回,call指令将下一条要执行的指令的地址压入栈内(例子中mov ax,4cooh的地址),然后转到子程序去执行,(即jmp到call指令后面的地址去执行)遇到ret指令时,返回主程序继续执行(弹出mov ax,4c00h的地址给cs:ip),例子中没有ret,不会返回继续执行

lyoal 发表于 2012-11-21 22:03:25

补充一下,请看例子程序的执行结果:assume cs:code
code segment
start:      mov sp,10h
                mov ax,0123h
                mov ds:,ax
                mov word ptr ds:,0
                call dword ptr ds:
               
                mov ax,4c00h
                int 21h
                code ends
      end start



ACC 发表于 2012-11-22 10:19:58

lyoal 发表于 2012-11-21 22:03 static/image/common/back.gif
补充一下,请看例子程序的执行结果:

首先你的程序不太完整,没有指定ds的值,后面直接使用,mov ds:,ax中ds:【0】地址也就不明确了,其次在上面堆栈的程序中先将要跳转到的地方的地址,写入了堆栈段,mov word ptr ss:,offset s
mov ss:,cs
也就是说call dword ptr ss:【0】以后跳到cs段的s标号处执行
在你的程序中随便定义一个数据段
data segmeng
db 1
data ends
assume cs:code,ds:data
然后剩下的问题就是,将你想要跳转的地址写到dword ptr ds:的位置就行了

lyoal 发表于 2012-11-22 12:36:55

本帖最后由 lyoal 于 2012-11-22 12:39 编辑

ACC 发表于 2012-11-22 10:19 static/image/common/back.gif
首先你的程序不太完整,没有指定ds的值,后面直接使用,mov ds:,ax中ds:【0】地址也就不明确了,其次 ...
首先非常感谢ACC的解答,但是学生还是有点迷不过来,call dword ptr ds:,这条指令执行前,将下一条指令的CS:IP压入栈,这里的下一条指令不就是 mov ax,4c00h 吗?
还有就是这个例子程序是书上的,我没有去改,所以没有那个数据段定义。原来是数据的问题,但是这个“call far ptr 内存单元” 执行原理还是有点朦

紫竹人士 发表于 2012-11-23 09:59:08

顶顶顶顶顶顶顶

夏夜堆雪人 发表于 2015-8-10 11:32:41

“call dword ptr 内存单元地址”相当于:
push CS
push IP
jmp dword ptr 内存单元地址
就是将当前call指令的下一条指令的CS和IP先依次入栈,然后跳转到内存单元地址,相应的CS和IP也会发生变化,其中低地址存放转移的目的偏移地址IP,高地址存放转移的目的段地址CS。所以CALL这条指令执行后,(IP)=0123H,(CS)=0。
LZ可以再看一下“jmp dword ptr 内存单元地址”的说明。
其实CALL指令主要是和ret指令配合使用,方便子程序的调用,书本只是就该指令单一功能举例,可能理解上会用歧义,但结果还是正确的。
页: [1]
查看完整版本: 第十章的一个例子程序不能理解"call dword ptr 内存单元"