汇编call的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汇编call的问题相关的知识,希望对你有一定的参考价值。

CALL BX
;BX的内容是子程序的偏移量
CALL WORD1
;WORD1是内存字变量,其值是子程序的偏移量

小问题???call 子程序的偏移量,到低什么是子程序的偏移量??

内存地址 机器码 汇编指令 执行后情况

1000:0 b8 00 00 mov ax,0 ax=0 ip指向1000:3

1000:3 e8 01 00 call s pop ip ip指向1000:7

1000:6 40 inc ax

1000:7 58 s:pop ax ax=6

这个结果是如何出来的,详细些,最好用数一步步来,(用debug进行跟踪确认,“call 标号”是将该指令后的第一个字节偏移地址入栈,再转到标号处执行指令)
这句话,我不明白

这个问题我刚学习汇编的时候也是搞不清楚,下面我慢慢给你解释:
首先,你要明确有关CS:IP 的一些问题:1. CS:IP存储的是代码的地址,这个地址指向即将执行的代码。2. 那么CS:IP在什么时候指向即将执行的代码呢?举例如下:mov ax,78H mov bx ,24H 当 mov ax,78H 指令被读取之前,CS:IP 是指向它本省的,读取之后,IP 的值自动增加,增加多少呢?答曰:是指令mov ax,78H的长度,所以IP值自动增加后CS:IP指向下一条指令即:mov bx,24H。IP值自动增加之后,才执行本条指令(mov ax,78H)。3. 以你所说的例子进行分析:mov ax,0 call s inc ax s:pop ax 一共四条指令。执行完 mov ax,0 CS:IP=1000:3 读取指令 call s 后,CS:IP=1000:6也就是 指向 inc ax 指令的。
接下来,具体说说call s 指令的执行过程:上面说过,读取call s 指令后 CS:IP已经指向了 inc ax,可是我们现在不执行它,我们要跳转去执行用“s”标记的 pop ax 指令!!!于是call命令就先把当前执行的状态,也就是CS:IP值先存起来,放进栈中,到用的时候,再取出来(这里"取出来"可以理解为,恢复CS:IP的值,接着没有执行的往下继续执行!)。那这存起来的CS:IP 是多少呢?答曰:1000:6(指向 inc ax )所以这里的call s 指令相当于 push ip jmp near ptr s 即:把IP的值入栈,再跳转去执行s标记的pop ax 指令。
最后 是pop ax 指令的执行,我们根据上面可以知道在此指令之前IP入栈,所以出栈的是IP,并且把这个IP保存在ax 中,IP=6,所以ax=6。

补充:1.到底什么是子程序的偏移量?
偏移量=call 指令即将跳转至的子程序地址(子程序的第一个字节)减去 call 指令读取后 CS:IP指向的指令,在这里相当于s子程序的地址减去指令 inc ax 的地址。
2.call 命令还有一种形式:call far ptr 标号
它相当于:push cs
push ip
jmp far ptr 标号

中间的一些细节,说的不是太清楚,不懂得请继续提问!呵呵
参考技术A call就是调用一个函数,偏移是那个函数的地址和当前地址的差值

在汇编 x86 中使用 CALL、RET

【中文标题】在汇编 x86 中使用 CALL、RET【英文标题】:Using CALL, RET in assembly x86 【发布时间】:2016-04-12 09:11:09 【问题描述】:

考虑以下使用pushpopcall 的简单汇编代码

CDSEG SEGMENT
MAIN PROC FAR
    ASSUME CS:CDSEG,DS:DTSEG
    MOV AX,DTSEG
    MOV DS,AX

    MOV AX,1010H        ; (1)
    PUSH AX             ; (2)
    CALL FOO            ; (3)
    ADD AX,2            ; (7)
MAIN ENDP   
FOO PROC   
    POP AX              ; (4)
    ADD AX,1            ; (5)
    RET                 ; (6)
FOO ENDP
END MAIN

我的期望是看到

(1) ax = 1010h, stack=????
(2) ax = 1010h, stack=1010h
(3) 
(4) ax = 1010h, stack=????
(5) ax = 1011h
(6)
(7) ax = 1012h

但是,模拟器显示

(1) ax = 1010h, stack=????
(2) ax = 1010h, stack=1010h
(3) 
(4) ax = 000Ch, stack=????
(5) ax = 000Dh
(6) The control never goes back to the main proc
(7) ???

什么问题?

【问题讨论】:

【参考方案1】:

CALL 将返回地址压入堆栈,这就是允许RET 返回该地址的原因。当您在FOOPOP AX 时,您正在从堆栈中弹出返回地址。当您输入FOO 时,您在CALL 之前PUSHed 的值不在堆栈顶部,而是在[SP+2]

【讨论】:

稍微扩展一下,程序通常不会压栈的值,而是通过栈帧访问它们(使用bp寄存器,需要手动设置) 或没有堆栈帧,直接使用sp。如果您的函数的堆栈上也有局部变量,则堆栈帧很有用。 简单地说:你搞砸了堆栈!因为你弹出了调用的返回地址,所以PROC 返回到无处/某处。

以上是关于汇编call的问题的主要内容,如果未能解决你的问题,请参考以下文章

汇编Call指令问题

汇编语言中的call是啥意思

汇编语言中的call是啥意思?

汇编语言 call怎么用

关于汇编call指令的请教

汇编call 命令 解析