鱼C论坛

 找回密码
 立即注册
查看: 5791|回复: 6

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

[复制链接]
发表于 2012-11-21 21:49:17 | 显示全部楼层 |阅读模式
5鱼币
第十章的一个例子程序不能理解"call dword ptr 内存单元",这指令,是远转移,到底压入栈的是下一条指的CS:IP,还是跟"jmp far ptr 内存单元 "指令一样,是将内存地址起始处的两个字中,高字节为CS地址,低字节为偏移地址。看代码:
assume cs:code
code segment
start:        mov sp,10h
                mov ax,0123h
                mov ds:[0],ax
                mov word ptr ds:[2],0
                call dword ptr ds:[0]
                
                mov ax,4c00h
                int 21h
                code ends
        end start
这段代码在我的win7系统上执行到 mov ds:[0],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:[0],offset s
                mov ss:[2],cs
                call dword ptr ss:[0]
                nop
                s:mov ax,offset s
                sub ax,ss:[0ch]
                mov bx,cs
                sub bx,ss:[0eh]
                
                mov ax,4c00h
                int 21h
                code ends
        end start
call dword ptr ss:[0] ;这条指令执行的后,却同样是将下一条地址的CS:IP压入栈中。这里跟例子程序又不相附,看到这样头晕眼又花的。又理不通了,请大虾指点迷津啊!谢谢你们。

最佳答案

查看完整内容

call 是调用子程序指令,一般和ret指令共同使用,call调用,ret返回,call指令将下一条要执行的指令的地址压入栈内(例子中mov ax,4cooh的地址),然后转到子程序去执行,(即jmp到call指令后面的地址去执行)遇到ret指令时,返回主程序继续执行(弹出mov ax,4c00h的地址给cs:ip),例子中没有ret,不会返回继续执行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
发表于 2012-11-21 21:49:18 | 显示全部楼层

call 是调用子程序指令,一般和ret指令共同使用,call调用,ret返回,call指令将下一条要执行的指令的地址压入栈内(例子中mov ax,4cooh的地址),然后转到子程序去执行,(即jmp到call指令后面的地址去执行)遇到ret指令时,返回主程序继续执行(弹出mov ax,4c00h的地址给cs:ip),例子中没有ret,不会返回继续执行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-11-21 22:03:25 | 显示全部楼层
补充一下,请看例子程序的执行结果:
assume cs:code
code segment
start:        mov sp,10h
                mov ax,0123h
                mov ds:[0],ax
                mov word ptr ds:[2],0
                call dword ptr ds:[0]
                
                mov ax,4c00h
                int 21h
                code ends
        end start

QQ截图20121121221146.png

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2012-11-22 10:19:58 | 显示全部楼层
lyoal 发表于 2012-11-21 22:03
补充一下,请看例子程序的执行结果:

首先你的程序不太完整,没有指定ds的值,后面直接使用,mov ds:[0],ax中ds:【0】地址也就不明确了,其次在上面堆栈的程序中先将要跳转到的地方的地址,写入了堆栈段,mov word ptr ss:[0],offset s
mov ss:[2],cs
也就是说call dword ptr ss:【0】以后跳到cs段的s标号处执行
在你的程序中随便定义一个数据段
data segmeng
db 1
data ends
assume cs:code,ds:data
QQImage_1391123.jpg 然后剩下的问题就是,将你想要跳转的地址写到dword ptr ds:[0]的位置就行了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-11-22 12:36:55 | 显示全部楼层
本帖最后由 lyoal 于 2012-11-22 12:39 编辑
ACC 发表于 2012-11-22 10:19
首先你的程序不太完整,没有指定ds的值,后面直接使用,mov ds:[0],ax中ds:【0】地址也就不明确了,其次 ...

首先非常感谢ACC的解答,但是学生还是有点迷不过来,call dword ptr ds:[0],这条指令执行前,将下一条指令的CS:IP压入栈,这里的下一条指令不就是 mov ax,4c00h 吗?
还有就是这个例子程序是书上的,我没有去改,所以没有那个数据段定义。原来是数据的问题,但是这个“call far ptr 内存单元” 执行原理还是有点朦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2012-11-23 09:59:08 | 显示全部楼层
顶顶顶顶顶顶顶
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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指令配合使用,方便子程序的调用,书本只是就该指令单一功能举例,可能理解上会用歧义,但结果还是正确的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-27 14:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表