call 指令练习 :
assume cs:code,ss:stack
; call 指令
; call指令会将 cs 压栈 , ip 压栈 , 然后再 jmp
; 因此 call 不能实现段内 短 转移
stack segment
db 16 dup(0)
stack ends
code segment
start:
mov ax, stack
mov ss, ax
mov sp, 00A0H
call func
jmp finish
func:
mov ax, 1234H
mov bx, 5678H
ret
finish:
mov ax,4cH
int 21H
code ends
end start
call far 指令练习 :
assume cs:code,ds:data,ss:stack
; call far ptr [Symbol]
; 远转移 , 同时修改 cs 和 ip , 皆为 16 位
; 相当于进行 :
; push cs
; push ip
; jmp far ptr [Symbol]
; 转移的目标地址在 指令 中 , 类似于之前的 jmp far ptr [Symbol]
data segment
data ends
stack segment
db 16 dup(0)
stack ends
code segment
start:
mov ax, stack
mov ss, ax
mov sp, 16
mov ax, 0
call far ptr func ; cs 压栈 , ip 压栈
inc ax
func:
pop ax ; ip 弹栈
add ax, ax
pop bx ; cs 弹栈
add ax, bx
code ends
end start
call [REGISTER] 指令练习
assume cs:code,ds:data,ss:stack
data segment
data ends
stack segment
stack ends
code segment
start:
mov ax, stack
mov ss, ax
mov sp, 00A0H
mov ax, 000EH ; 000EH 的偏移就是 func 的物理地址
call ax
inc ax
func:
mov ax, 1234H
mov bx, 5678H
ret
finish:
mov ax,4cH
int 21H
code ends
end start
call [Memory Address] 指令练习 :
assume cs:code,ss:stack
stack segment
dw 8 dup(0)
stack ends
code segment
start:
mov ax, stack
mov ss, ax
mov sp, 0010H
mov ds, ax
call word ptr ds:[0EH]
inc ax
inc ax
inc ax
code ends
end start
retf 指令练习 :
assume cs:code,ss:stack
; 补全程序 , 实现从内存 1000:0000 处开始执行指令
; ret 指令
; 段内近转移 , 也就说 , 只修改 ip 的值 , 而且修改的位数为 16 位
; 具体实现是 pop ip
; retf 指令
; 段间转移 (远转移) , 同时修改 cs 和 ip
; 具体实现是 pop ip, pop cs
stack segment
db 16 dup(0)
stack ends
code segment
start:
; 构造一个栈
mov ax, stack
mov ss, ax
mov sp, 00A0H
; 返回地址压栈
mov ax, 1000H
push ax ; 首先 cs 段地址压栈
mov ax, 0000H
push ax ; 偏移地址 ip 压栈
retf
finish:
mov ax,4cH
int 21H
code ends
end start
下面程序执行后 , ax 的值是多少 ?
assume cs:code,ds:data,ss:stack
; 下面程序执行后 , ax 的值是多少 ?
data segment
data ends
stack segment
stack ends
code segment
start:
mov ax, 0000H ; ax 清零
call func ; 读指令 , ip自增 , ip 压栈 , jmp func
inc ax
func:
pop ax
; ax 弹栈 , 得到的值为之前被压栈的 ip 的值
; 也就是 inc ax 这条指令的偏移地址
code ends
end start