1: Near 近端使用
C语言实现:
#include <stdio.h>
#include <stdlib.h>
void print(){ printf("proc"); } int main(int argc, char *argv[]) { print(); return 0; }
汇编实现:
datas segment x db 'proc$'; datas ends stacks segment stack dw 100 dup(?) stacks ends codes segment assume cs:codes,ss:stacks,ds:datas main proc ; 主程序 start: mov ax,datas; mov ds,ax; call max mov ah,4ch; int 21h main endp print proc near ;子程序 push bp; mov bp,sp; mov dx,offset x; mov ah,09; int 21h pop bp ret 0 print endp codes ends end start
near 调用没有段地址:使用的就是偏移地址 call 000C 地址就是子程序的入口地址
2: Far 远端使用
print 函数我们实现在另一个文件, C语言默认函数的extern的 也就是全局的
// A文件 #include<stdio.h> void print(){ printf("proc"); }
// 主调用文件 #include <stdio.h> #include <stdlib.h> extern void print(); int main(int argc, char *argv[]) { print(); return 0; }
汇编实现:
;A文件public printx '声明为远端函数 datas segment x db 'proc$'; datas ends assume cs:codes,ds:datas codes segment print proc far push dx push ax push bp; mov bp,sp; mov ax,datas;这里我们直接在本段进行处理 ,如果不在本段处理 需要将main的段内存的偏低地址,push 到堆栈中操作内容 mov ds,ax mov dx,offset x;取得偏移地址 mov ah,09; int 21h; pop dx pop ax pop bp retf print endp codes ends end
;Main 文件 stacks segment stack dw 100 dup(0) stacks ends; extrn printx:far ;标识远端程序 不写 将会汇编错误 , codes segment assume cs:codes,ss:stacks main proc start: call far ptr printx mov ah,4ch int 21h; hlt main endp codes ends end start
注意: 以上两个文件编译没有问题,但是链接 如果按照我们过去的思路 将会出现下面的错误: 表示我们调用的函数需要声明 否则无法链接
注意: 调用了多少个far子程序 那么链接时候需要
link main.obj+pro1.obj+pro2.obj+''' 依次类推
debug:
主程序为: 调用地址 0779:0000
看一下调用地址的子程序地址:
3:Far使用过程的问题
如果声明为跨段调用,因为段限制为64k, 需要使用call far ptr进行调用
下面的声明形式是错误的:
stacks segment stack dw 100 dup(0) stacks ends; extrn printx:far codes segment assume cs:codes,ss:stacks start: call far ptr printx mov ah,4ch int 21h; hlt codes ends end start
正确的声明形式:
stacks segment stack dw 100 dup(0) stacks ends; extrn printx:far codes segment assume cs:codes,ss:stacks main proc ; 主程序也必须声明为 过程 这里 near调用还是有很大的区别的 start: call far ptr printx mov ah,4ch int 21h; hlt main endp codes ends end start
4: 参数传递的问题:
4.1 寄存器传递参数
datas segment x db 'proc$'; datas ends stacks segment stack dw 100 dup(?) stacks ends codes segment assume cs:codes,ss:stacks,ds:datas main proc ; 主程序 start: mov ax,datas; mov ds,ax; mov dx,offset x; 直接使用 传递给寄存器dx call far ptr print mov ah,4ch; int 21h main endp print proc mov ah,09; 使用寄存器dx int 21h retf print endp codes ends end start
4.2 内存传递参数
datas segment x db 'proc$'; datas ends stacks segment stack dw 100 dup(?) stacks ends codes segment assume cs:codes,ss:stacks,ds:datas main proc ; 主程序 start: mov ax,datas; mov ds,ax; call far ptr print mov ah,4ch; int 21h main endp print proc mov dx,offset x; 取得数据段首地址 mov ah,09; 输出dx的数据值 int 21h retf print endp codes ends end start
4.3 内存传递参数的改进(栈恢复)
如果用到ax bx cx dx si di 需要进行恢复
datas segment x db 'proc$'; datas ends stacks segment stack dw 100 dup(?) stacks ends codes segment assume cs:codes,ss:stacks,ds:datas main proc ; 主程序 start: mov ax,stacks;初始化栈 mov ss,ax; mov ax,datas;初始数据段 mov ds,ax; xor ax,ax mov ax,offset x; push ax;ax偏移地址入栈 call print mov ah,4ch; int 21h main endp print proc push bp; mov bp,sp mov dx,[bp+4];寻地址 mov ah,09; int 21h pop bp ret 2;保持恢复 print endp codes ends end start