call
1. call
- 作用:
- call s 会将 ip = ip + call s 指令所占的字节数 作为新的 ip 存到栈中
- 跳转到 s 标号处, ip 为 s 标号的地址, 不是栈中存的 ip
- 与 ret 连用
assume cs:code
code segment
start:
mov ax,1000H
call s
over:
mov ax,4c00h
int 21h
s: mov ax,1001H
mov bx,1002H
ret ;ip 又会被修改回来
code ends
end start
-u
0E24:0000 B80010 MOV AX,1000
0E24:0003 E80500 CALL 000B
0E24:0006 B8004C MOV AX,4C00
0E24:0009 CD21 INT 21
0E24:000B B80110 MOV AX,1001
0E24:000E BB0210 MOV BX,1002
0E24:0011 C3 RET
0E24:0012 36 SS:
0E24:0013 7813 JS 0028
0E24:0015 FF368813 PUSH [1388]
0E24:0019 FF368613 PUSH [1386]
0E24:001D CF IRET
0E24:001E FA CLI
0E24:001F 1F POP DS
-t
AX=1000 BX=0000 CX=0012 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0E14 ES=0E14 SS=0E23 CS=0E24 IP=0003 NV UP EI PL NZ NA PO NC
0E24:0003 E80500 CALL 000B
-t
AX=1000 BX=0000 CX=0012 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=0E14 ES=0E14 SS=0E23 CS=0E24 IP=000B NV UP EI PL NZ NA PO NC
0E24:000B B80110 MOV AX,1001
-t
AX=1001 BX=0000 CX=0012 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=0E14 ES=0E14 SS=0E23 CS=0E24 IP=000E NV UP EI PL NZ NA PO NC
0E24:000E BB0210 MOV BX,1002
-t
AX=1001 BX=1002 CX=0012 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=0E14 ES=0E14 SS=0E23 CS=0E24 IP=0011 NV UP EI PL NZ NA PO NC
0E24:0011 C3 RET
-t
AX=1001 BX=1002 CX=0012 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0E14 ES=0E14 SS=0E23 CS=0E24 IP=0006 NV UP EI PL NZ NA PO NC
0E24:0006 B8004C MOV AX,4C00
2. call far ptr s
-
相当于
- push cs
- push ip
- jmp s
-
与 retf 连用
-
call far ptr s 后, 如果提前 pop, 就跳不回去了
assume cs:code
code segment
start:
call far ptr s
over:
mov ax,4c00h
int 21h
s:
mov ax,1000h
retf
code ends
end start
-u
0E24:0000 9A0A00240E CALL 0E24:000A
0E24:0005 B8004C MOV AX,4C00
0E24:0008 CD21 INT 21
0E24:000A B80010 MOV AX,1000
0E24:000D CB RETF
0E24:000E 68 DB 68
0E24:000F 5E POP SI
0E24:0010 19FF SBB DI,DI
0E24:0012 36 SS:
0E24:0013 7813 JS 0028
0E24:0015 FF368813 PUSH [1388]
0E24:0019 FF368613 PUSH [1386]
0E24:001D CF IRET
0E24:001E FA CLI
0E24:001F 1F POP DS
-r
AX=0000 BX=0000 CX=000E DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0E14 ES=0E14 SS=0E23 CS=0E24 IP=0000 NV UP EI PL NZ NA PO NC
0E24:0000 9A0A00240E CALL 0E24:000A
-t
AX=0000 BX=0000 CX=000E DX=0000 SP=FFFC BP=0000 SI=0000 DI=0000
DS=0E14 ES=0E14 SS=0E23 CS=0E24 IP=000A NV UP EI PL NZ NA PO NC
0E24:000A B80010 MOV AX,1000
-d ss:FFF0
0E23:FFF0 00 00 00 00 00 00 0A 00-24 0E 21 08 05 00 24 0E ........$.!...$.
-t
AX=1000 BX=0000 CX=000E DX=0000 SP=FFFC BP=0000 SI=0000 DI=0000
DS=0E14 ES=0E14 SS=0E23 CS=0E24 IP=000D NV UP EI PL NZ NA PO NC
0E24:000D CB RETF
-t
AX=1000 BX=0000 CX=000E DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0E14 ES=0E14 SS=0E23 CS=0E24 IP=0005 NV UP EI PL NZ NA PO NC
0E24:0005 B8004C MOV AX,4C00
-d ss:FFF0
0E23:FFF0 00 00 00 10 00 00 00 10-00 00 05 00 24 0E 21 08 ............$.!.
3. 下面指令执行后, ax 中是多少
内存地址 机 器 码 汇编指令
1000:0 B8 06 00 mov ax,6
1000:2 FF D0 call ax ; push ip = 5
1000:5 40 inc ax
1000:6 mov bp,sp
add ax, ss:[bp] ; 6 + 5 = 11 = BH
4. 对比
jmp word ptr ds:[0] ip = ds:[0]
修改ip
call word ptr ds:[0] ip = ds:[0]
mov ax,1000H 会 push 该条命令的ip, ret会pop ip
jmp dword ptr ds:[0] ip = ds:[2]
call dword ptr ds:[0] 会 push cs, push ip, retf 会 pop ip, pop cs
5. 监测点 10.5
- 下面的程序执行后, ax 的数值为多少?
assume cs:code
stack segment
dw 8 dup (0)
stack ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,16 ; 空栈
mov ds,ax ; 寄存器DS指向栈的段地址
mov ax,0
call word ptr ds:[0EH] ; 0011
; 首先执行push IP(下一条inc的偏移地址,0011), 此时SP=0EH(16 -2);
; 再执行jmp word ptr ds:[0EH], 目的偏移地址由ds:[0EH]给出
; 因为DS和SS指向同一片内存, 且(SP)=0EH, 所以ds:[0EH]相当于栈顶元素IP的值, 即0011, 程序顺序执行
inc ax ;ax=1
inc ax ;ax=2
inc ax ;ax=3
code ends
end start
-u
0E25:0000 B8240E MOV AX,0E24
0E25:0003 8ED0 MOV SS,AX
0E25:0005 BC1000 MOV SP,0010
0E25:0008 8ED8 MOV DS,AX
0E25:000A B80000 MOV AX,0000
0E25:000D FF160E00 CALL [000E]
0E25:0011 40 INC AX
0E25:0012 40 INC AX
0E25:0013 40 INC AX
6. 监测点 10.5 第二题
- 下面的程序执行后, ax 和 bx 中的数值为多少?
assume cs:code
data segment
dw 8 dup (0)
; -u
; 0E25:0000 B8240E MOV AX,0E24
; 0E25:0003 8ED0 MOV SS,AX
; 0E25:0005 BC1000 MOV SP,0010
; 0E25:0008 36 SS:
; 0E25:0009 C70600001A00 MOV WORD PTR [0000],001A
; 0E25:000F 36 SS:
; 0E25:0010 8C0E0200 MOV [0002],CS
; 0E25:0014 36 SS:
; 0E25:0015 FF1E0000 CALL FAR [0000]
; 0E25:0019 90 NOP
; 0E25:001A B81A00 MOV AX,001A
; 0E25:001D 36 SS:
; 0E25:001E 2B060C00 SUB AX,[000C]
; 0E25:0022 8CCB MOV BX,CS
; 0E25:0024 36 SS:
data ends
code segment
start:
mov ax,data
mov ss,ax
mov sp,16 ; 空栈, 大小为16字节
mov word ptr ss:[0], offset s ; 001A
; -d ss:0
; 0E24:0000 1A 00 00 00 00 00 24 0E-00 00 0F 00 25 0E 21 08 ......$.....%.!.
mov ss:[2],cs
; -d ss:0
; 0E24:0000 1A 00 25 0E 00 00 24 0E-00 00 14 00 25 0E 21 08 ..%...$.....%.!.
call dword ptr ss:[0]
; push 0E25, 0019,跳到 0E25:001A, 也就是s标号处, nop 被跳过
; -d ss:0
; 0E24:0000 1A 00 24 0E 00 00 1A 00-25 0E 21 08 19 00 25 0E ..$.....%.!...%.
nop
s:
mov ax,offset s ; ax = 001A
; ax=ax-ss:[0cH], ss:[0cH]的值为栈顶元素, 即nop指令的偏移地址, 即s.IP-nop.IP为nop指令长度, 即为1
sub ax,ss:[0cH] ; ax = 001A - 0019 = 1
mov bx,cs ; bx = 0E25
; bx=bx-ss:[0eH], ss:[0eH]的值为第二栈顶元素, 即nop指令的段地址, 即cs-nop.CS, 即为0
sub bx,ss:[0eH] ; bx = 0E25 - 0E25
code ends
end start