|
一、转移地址在内存中的 CALL
格式一:call word ptr 内存单元地址
相当于进行了:
push IP
jmp word ptr 内存单元地址 格式二:call dword ptr 内存单元地址
相当于进行了:
push CS
push IP
jmp dword ptr 内存单元地址
EXP1:
mov sp,10h
mov ax,0123h
mov ds:[0],ax ;ds:[0]-->23h, ds:[1]-->01h
mov word ptr ds:[2],0 ;ds:[2]--->00h, ds:[3]-->00h
call dword ptr ds:[0]
;执行call,ds:[2-3]==>cs(0000h), ds:[0-1]===>IP(0123h), sp = 0ch
EXP2:(执行后,ax的数值为多少)
assume cs:code
stack segment
dw 8 dup(0)
stack ends
code segment
start:
mov ax, stack
mov ss, 16
mov ds, ax ; 数据段和堆栈段共用
mov ax, 0
call word ptr ds:[0EH]
inc ax
inc ax
inc ax
code ends
end start
分析: 在把 call 读入指令缓冲器时,IP 指向 inc ax 这条指令,系统把此时的 IP压栈保存。由程序设置知道,数据段和堆栈段共用,所以 word ptr ds:[0EH] 中的内容正好是 堆栈中保存的IP。所以,执行CALL语句,相当于程序顺序执行。因此,连续执行3次 ax 后 ax = 3.。
EXP3: (执行程序后,ax 和 bx 中的数值为多少)
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 ;s的偏移地址送入ss:[0-1]
mov ss:[2], cs ;cs值送入 ss:[2-3]
call dword ptr ss:[0]
nop
s:
mov ax, offset s ;读入 s 处的地址
sub ax, ss:[0ch] ;ss:[0CH- 0DH]实际上就是 nop 指令所在的偏移地址,故 ax =1
mov bx, cs
sub bx, ss:[0EH] ;ss:[0EH-0FH]实际上就是CS,所以此处 bx = 0
code ends
end start 分析: 读入 call dword ptr ss:[0] 到指令缓冲器时,CS 先入栈保存,接着是 nop指令所在的地址入栈保存,最后是ss:[0Ch - 0Dh] 存有 nop 指令处的地址内容(IP),ss:[0EH - 0FH] 则为当前CS 内容。
call dword ptr ss:[0] 执行是,ss:[2-3] 写入 CS,ss:[1-0]写入IP(高字节写入CS,低字节写入IP)。这样,程序实际就从 s 标号处执行。
|
|