Chinaunix首页 | 论坛 | 博客
  • 博客访问: 136792
  • 博文数量: 12
  • 博客积分: 2502
  • 博客等级: 少校
  • 技术积分: 163
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-20 23:32
文章分类

全部博文(12)

文章存档

2011年(1)

2009年(11)

我的朋友

分类:

2009-10-08 22:26:58

  文\seapeek

  有时候需要利用汇编编译器来生成纯粹的二进制文件,生成方法因编译平台不一样而不同(有点废话)。汇编编译器种类繁多,在大学里普遍学习的估计就是MASM了,这是Microsoft开发的东东。另外还有Borland的TASM,开源跨平台的NASM,Linux平台下的GAS汇编。因为我学的也是MASM,所以总是不想换编译器。再说各个编译器汇编的书写格式也不尽相同,NASM与MASM虽有一点区别,但总是很容易混淆,GAS与MASM的汇编的书写则相差太远了,总感觉GAS书写的汇编有点怪怪的。这么多编译器如果东学一点西学一点,搞得脑袋晕忽忽的,太得不偿失了。综上,既然学的是MASM的汇编格式那么咱就接着用吧。那么问题就出来了,如何用MASM生成纯粹的二进制文件呢。在讨论这个之前我们先研究一下COM文件。

  COM就是DOS下纯粹的二进制可执行文件,也就是说它没有什么文件头乱七八糟的东西。DOS把COM文件中的数据原封不动地拷贝到内存中然后执行。但是在DOS环境下编制 COM 文件应遵循下列规则:

1.只能建立一个代码段,内含代码和数据段,同时不能单独设置堆栈段。
2.代码和数据只能在100H以后设置,一般用伪指令"ORG 100H"放在汇编程序的开始,程序应在 ORG 100H 定义程序段的入口。即在100H处设置一条可执行指令。
3.……

  为什么代码和数据必须从100H以后设置呢,这是因为DOS在执行COM文件的时候会把前100H字节分配给PSP(Program Segment Prefix:程序段前缀),所以没法,COM文件只好委屈委屈往后移一下了。至于PSP具体是啥内容上网搜一下一抓一大堆,不用我再啰嗦。

  唧唧歪歪说了一大通,到底怎么生成二进制文件呢,这分两种情况:

1.对于MASM6.0之前的版本(不包括6.0版本)必须要用到额外的工具,在这里特别要提到EXE2BIN。它可以将EXE文件转换为COM文件,当然这个EXE文件只能有一个段并且它的起始地址必须为100H,否则返给你一句:File cannot be converted。看到这里也许你明白了,要想获得二进制文件必须先把源程序编译成EXE文件,是够绕远道的。

有时候想让自己编写的程序的起始地址为其他值的时候怎么办呢?例如ORG 7C00H,这是操作系统被BIOS加载到内存中的地址。说起来很简单,自己编个转换程序,或者自己去改机器码,都可以。看个人修行了,哈哈。

2.对于MASM6.0及其以后的版本,就相对简单点了。有两种方法:

其一,可以在程序的开头来句伪指令:.model tiny。用ML直接编译(不加任何参数,程序汇编后立即链接成COM文件)就可以了。具体格式如下:

.MODEL TINY
.CODE
ORG 100H
START:
    PUSH CS
    POP DS;为数据段寄存器赋值
    ;在这里尽情写代码吧
    ;如果程序在DOS下运行,根据需要可加上退出程序回到DOS的代码
END START

其二,源文件采用完整的段声明(full segment declarations),用ML编译的时候加上/AT参数就可以生成COM文件了。具体如下:

CODE SEGMENT
    ASSUME CS:CODE,DS:CODE
    ORG 100H
START:
    MOV AX,CS
    MOV DS,AX
    ;你的代码
CODE ENDS
    END START

另外,如果汇编与链接分开执行的话,在连接时要用上/TINY参数,即:LINK /TINY+文件名。这样的话,链接器会给出一个警告:


不过这无伤大雅,没事。

  另外,如果在源程序中改变起始地址,编译时也会发出一个警告,提示起始偏移地址不为100H。不过,没关系可以忽略。

  以上,就写到这里了。(你还别说,虽然写的不多倒还挺费时间的)

阅读(4720) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~