zoukankan      html  css  js  c++  java
  • 汇编子程序模块化(near&far)

    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 printx 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 printx 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子程序 那么链接时候需要

    # 使用方式1
    link main.obj+pro1.obj+pro2.obj+''' 使用+链接依次类推

    # 使用方式2
    link main.obj+pro1.obj pro2.obj+''' 使用空格链接依次类推

     debug: 

    主程序为: 调用地址 0779:0000

     看一下调用地址的子程序地址:

     3:Far使用过程的问题

      如果声明为跨段调用,因为段限制为64k, 需要使用call far ptr进行调用

    下面的声明形式是错误的: (并不是错误的,学校上机的时候在32位系统 能够正确使用,但是同样的程序在msbox就不行)

    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 需要进行恢复

         为什么需要恢复:

          如果在主程序中用到了一个xx寄存器,然后在子程序中也用到了这个xx寄存器,那么当子程序返回到主程序的时,主程序中存放参数的内存地址已经没有记录了,程序出错

    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

     提高资料:https://wenku.baidu.com/view/3109f194690203d8ce2f0066f5335a8103d2665a.html

     

     

  • 相关阅读:
    linux virtualbox
    cboard安装
    test
    kafka安装
    OLAP解释
    php 连接数据库直接转成json格式
    hive学习
    mariadb修改密码
    mariadb anzhuang
    IDEA12 中写hql语句编译器莫名报错
  • 原文地址:https://www.cnblogs.com/dgwblog/p/11914837.html
Copyright © 2011-2022 走看看