原创 MASM的ORG、生成COM/EXE文件的研究、EXE重定位、入门汇编程序

2011-2-26 21:03 3483 6 6 分类: 工程师职场

MASM的ORG、生成COM/EXE文件的研究、EXE重定位、入门汇编程序

wxleasyland

2011.2.26

 

.model tiny是生成COM文件,参见《汇编伪指令.DOC》http://blog.csdn.net/pizi0475/archive/2010/05/26/5626696.aspx

 

 

程序标准写法(程序I)

程序简化段定义伪指令的写法(程序II)

COM文件大小

COM分析

如果生成EXE

0

.MODEL TINY

ORG 100H

START:

mov ax,offset message

message db 'this is'

END START

.model tiny

ORG 100H

START:

mov ax,offset message

message db 'this is'

END START

 

不行,编译出错,提示程序必须要在SEGMENT段中。

 

1

.MODEL TINY

.CODE

ORG 100H

START:

mov ax,offset message

message db 'this is'

END START

.model tiny

CODE SEGMENT

ASSUME CS:CODE,DS:CODE

ORG 100H

START:

mov ax,offset message

message db 'this is'

CODE ENDS

END START

10字节

生成的二个文件完全相同

生成的COM正确。

OFFSET MESSAGE值为103H,正确。

 

0BBF:0100  B8 03 01 74 68 69 73 20-69 73 C7 80 E4 7F A3 E8   ...this is......

 

0BBF:0100 B80301 MOV AX,0103

如果去掉.model tiny,只有程序II可以编译。程序I编译出错,必须要指定.model。

 

生成EXE778字节。

文件头512+内容266字节(其中先100H个00H,再3个字节程序+7个字符'this is')

 

OFFSET MESSAGE定位正确

程序起点定位正确。

2

.MODEL TINY

.CODE

jmp start

ORG 100H

START:

mov ax,offset message

message db 'this is'

END START

.model tiny

CODE SEGMENT

ASSUME CS:CODE,DS:CODE

jmp start

ORG 100H

START:

mov ax,offset message

message db 'this is'

CODE ENDS

END START

10字节

生成的二个文件完全相同。

生成的文件与上面的文件完全相同。

生成的COM正确。

OFFSET MESSAGE值为103H,正确。

 

0BBF:0100  B8 03 01 74 68 69 73 20-69 73 C7 80 E4 7F A3 E8   ...this is......

 

0BBF:0100 B80301 MOV  AX,0103

 

相当于jmp start这行是不存在的。

 

生成EXE778字节。

文件头512+内容266字节(其中先2个字节程序jmp start+254个00H,再3个字节程序+7个字符'this is')

 

OFFSET MESSAGE定位正确

程序起点定位正确。

相当于jmp start这行是不存在的。

3

.MODEL TINY

.CODE

mov ax,1234H

ORG 100H

START:

mov ax,offset message

message db 'this is'

END START

.model tiny

CODE SEGMENT

ASSUME CS:CODE,DS:CODE

mov ax,1234H

ORG 100H

START:

mov ax,offset message

message db 'this is'

CODE ENDS

END START

10字节

生成的二个文件完全相同。 生成的文件与上面的文件完全相同。

生成的COM正确。

OFFSET MESSAGE值为103H,正确。

 

0BBF:0100  B8 03 01 74 68 69 73 20-69 73 C7 80 E4 7F A3 E8   ...this is......

 

0BBF:0100 B80301 MOV AX,0103

 

相当于mov ax,1234H这行是不存在的。

 

 

原理同上

4

.MODEL TINY

.CODE

START:

ORG 100H

mov ax,offset message

message db 'this is'

END START

.model tiny

CODE SEGMENT

ASSUME CS:CODE,DS:CODE

START:

ORG 100H

mov ax,offset message

message db 'this is'

CODE ENDS

END START

266字节

生成的二个文件完全相同

生成的COM错误。

文件最开头会生成100H长的00H。程序从这些00H开始运行。

OFFSET MESSAGE值为103H。

 

0BC0:0100  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................

0BC0:0200  B8 03 01 74 68 69 73 20-69 73 F6 46 FA 02 74 0A   ...this is.F..t.

 

0BC0:0200 B80301 MOV AX,0103

 

生成EXE778字节。

文件头512+内容266字节(其中先100H个00H,再3个字节程序+7个字符'this is')

 

OFFSET MESSAGE定位正确

程序起点定位正确。(程序起点从那100H个00H处开始)

5

.MODEL TINY

.CODE

message db 'this is'

ORG 100H

START:

mov ax,offset message

END START

.model tiny

CODE SEGMENT

ASSUME CS:CODE,DS:CODE

message db 'this is'

ORG 100H

START:

mov ax,offset message

CODE ENDS

END START

3字节

生成的二个文件完全相同

生成的COM错误。

OFFSET MESSAGE值为00H,错误。

'this is'不见了!

0B54:0100  B8 00 00 59 00 50 E8 B7-9E 88 86 F0 FE 2A E4 50   ...Y.P.......*.P

0B54:0100 B80000 MOV AX,0000

 

生成EXE771字节。

文件头512+内容259字节(其中先是7个字符'this is',再249个00,再3字节程序,即程序前面是256个字节)

 

OFFSET MESSAGE定位正确

程序起点定位正确。

即ORG 100H指相对本段起点偏移100H处

6

.MODEL TINY

.CODE

ORG 100H

message db 'this is'

START:

mov ax,offset message

END START

.model tiny

CODE SEGMENT

ASSUME CS:CODE,DS:CODE

ORG 100H

message db 'this is'

START:

mov ax,offset message

CODE ENDS

END START

3字节

生成的二个文件完全相同。但文件与上面的文件不同。

生成的COM错误。

OFFSET MESSAGE值为100H,正确。

'this is'不见了!

0BC0:0100  B8 00 01 83 FF FF 74 1B-0B FF 74 17 8B 1E 28 42

 

0BC0:0100 B80001 MOV AX,0100

 

生成EXE778字节。

文件头512+内容266字节(其中先100H个00H,再7个字符'this is'+3个字节程序)

 

OFFSET MESSAGE定位正确

程序起点定位正确。

 

 

 

 

 

 

 

 

 

 

 

 

 

总结:

.com文件

.model tiny时,按生成COM文件方式,程序起点从END START表示的这个START标志开始!  这个标志以前的程序都不会编译到COM文件中去!!

 

MASM开始编译时,是认为程序段的开头是0000:0000!!(注:是程序段SEGMENT,不是START开始标志),以此来计算数据的偏移。比如第4个字节处是message db 'this is',则程序引用时,就知道message的偏移地址是0003,即OFFSET message是0003。

 

程序开始标志之前,用ORG 100H,编译器MASM就知道随后的程序从100H地址开始。比如第4个字节处是message db 'this is',则程序引用时,就知道message的偏移地址是0103,即OFFSET message是0103

 

第一个程序不用ORG 100H时相当于:

0000:0000   CODE SEGMENT

START:

0000:0000   mov ax,offset message   注:这时 offset message值为0003H

0000:0003   message db 'this is'

 

第一个程序相当于:

0000:0000   CODE SEGMENT

0000:0000   ORG 100H

START:

0000:0100   mov ax,offset message   注:这时 offset message值为0103H

0000:0103   message db 'this is'

 

第六个程序相当于:

0000:0000   CODE SEGMENT

0000:0000   ORG 100H

0000:0100   message db 'this is'

START:

0000:0107   mov ax,offset message    注:这时 offset message值为100H

 

第五个程序相当于:

0000:0000   CODE SEGMENT

0000:0000   message db 'this is'

0000:0007   ORG 100H

START:

0000:0100   mov ax,offset message  注:这时 offset message值为0000H

 

 

因为从START:开始的程序才会编译到COM文件中,所以第五、六个程序生成的COM文件才3个字节!

 

用ORG 100H,是因为COM文件运行时,是从IP=100H偏移地址开始的,即CS:0100,不是从IP=0000H处开始的!IP=0000H处是PSP,占用256字节。

 

 

 

.exe文件

生成EXE文件时,从程序“开头”开始的所有的内容都会编译到EXE文件中去!

程序的“运行起点”也是从END START表示的这个START标志开始,但是,只是CS:IP指向了这个START标志,其它的段或数据可以放在其它地方。这是因为EXE文件有“EXE文件头”,里面有CS和IP信息,所以程序“运行起点”可以从任何一个地方开始!

EXE程序载入到内存时,都是载入到CS:0000处,这时,如果START在0000H,则起始IP=0000H,如果START在0100H,则起始IP=0100H。

MASM开始编译时,是认为第一个段的开头是0000:0000!!(注:是段SEGMENT,不一定是程序段,任何段都可以)

比如一个程序:

0000:0000   CODE SEGMENT        注:这里是程序的“开头”

0000:0000   ORG 100H

0000:0100   message db 'this is'

START:                    注:这里是程序的“运行起点”,为0000:0107

0000:0107   mov ax,offset message2    注:这时 offset message2值为50H,即message2的偏移地址是50H

0000:010A   mov bx, DATA           注:这时DATA值为11H,即DATA段的段地址值为11H

0000:010D   CODE ENDS

 

0011:0000   DATA SEGMENT

0011:0000   ORG 50H               注:ORG 表示是相对于“本段”偏移,而不是相对于程序的“开头”

0011:0050   message2 db 'this is'       注:message2的地址就是0011:0050

0011:0057   DATA ENDS

段的默认对齐方式是PARA,即16的倍数,所以第二个段DATA SEGMENT是从0011:0000开始的,即0000:0110。也就是,0000:010D~0000:010F处,要填充3个00H才行!

所以如果程序开头的地址是0000:0000,则在0011:0050处可以找到message2。

但是,实际EXE调入内存运行时,程序“开头”的地址不是0000:0000!!但一定CS:0000(即16的倍数)!!!CS可以是任何数。

这时,IP=0107H,直接放在EXE文件头中,所以DOS知道从CS:IP=CS:107是程序“运行起点”。(如果DOS将程序“开头”载入到CS:0001,那实际运行起点就变成CS:0108了,就乱套了,因为EXE文件头中指示的IP仍是107H,DOS仍从CS:0107执行程序,那程序就乱了。  所以,程序“开头”一定CS:0000,而不会是CS:000X!!蓝色的000实际是并入到CS中去的。

这时CS是任意的,内存中要如何找到message2?

可见,message2的偏移地址仍会是0050H,不会改变,只是段地址会随着CS而改变,message2在内存中的实际段地址=CS+0011H。所以要重定位

所以,mov ax,offset message2这个地方的offset message2不需要重定位,而mov bx, DATA这个地方的DATA需要重定位!!

这就是EXE文件头中“重定位项”的原理!

这个程序里只有这一个重定位点,所以EXE文件头中的重定位项只有一个,重定位项的值为这个DATA在程序中的位置!

如果程序中DATA出现了2次,则就会有2个重定位点。。。依此类推。

 

 

我的入门汇编ASM程序

;EASYLAND:对书上的完整的汇编程序进行试验,2011.2

;不区分大小写

;默认是十进制数。而十六进制数要加H,如10H。和DEBUG不一样!

; MASM611下,  ml my1.asm即可生成EXE文件 ,或者 masm my1.asm 生成my1.obj文件,再link my1.obj 生成exe文件

; ml /Fl my1.asm 表示同时生成列表文件.lst。 ML的命令行参数区分大小写,即F要大写!!

; ml /Fl /Sg my1.asm 表示同时生成列表文件.lst,并且在列表文件中,列出由汇编程序产生的组合指令

 

 

MYSTACK SEGMENT PARA STACK 

; MYSTACK是程序段名

; PARA表示本程序段定位方式是PARA型

; STACK表示本程序段是堆栈,如果不写STACK,则链接时会提示WARNGING:NO STACK SEGMENT

       DB 12 DUP(0)

MYSTACK ENDS

 

 

MYDATA SEGMENT PARA           ;可以有多个段,没有关系

       ORG 2

       MESSAGE DB 'THIS IS A SAMPLE!$'

MYDATA ENDS

 

 

MYDATA2 SEGMENT PARA

       MESSAGE2 DB 'THIS IS A SAMPLE2!$'    ; MESSAGE2名称不能与前面MESSAGE重名,不然出错

MYDATA2 ENDS

 

 

;ORG 8     ;这一行是错的,ORG不能放在段外,要放在段内,就是SEGMENT内

 

 

MYCODE SEGMENT PARA

       ASSUME CS:MYCODE,DS:MYDATA,SS:MYSTACK  ;这一行是通知MASM用的,不写也行

;ORG 8   ;这一行是对的。ORG 8 表示下面的语句要从相对于“本段的开头”的偏移8个字节处开始。

         ;本段的开头地址如果是XXXX:0000,则下面的语句要从XXXX:0008开始!

MYSTART PROC FAR    ;定义一个子程序,子程序名字叫START。也可以不用子程序,直接用标号,即mystart:

;mystart:

       MOV AX,MYDATA  ; 这个地方在生成EXE文件后,MYDATA2处会变成一个“重定位项”

       MOV DS,AX          

;一定要赋值DS,因为DS和ES一开始并不是指向MYDATA的段地址的,而是指向EXE程序的PSP段地址,参见DOS的EXE文件装载运行原理

       MOV AH,9

       ;ORG 11  ;ORG可以放在这里,表示下面的语句要从XXXX:000B开始!如果值小,则会覆盖前面的语句。

       MOV DX,OFFSET MESSAGE   ;OFFSET MESSAGE表示MESSAGE相对于它所在的那个段的偏移!这里是2,因为MESSAGE前面有一个ORG 2

       INT 21H           ;显示字符串,字串以$结束

       CALL MYFUN2

       MOV AH,4CH

       INT 21H           ;退出到DOS

MYSTART ENDP              ;用mystart标号时,本行就省略了

 

MYFUN2 PROC FAR

       MOV AX,MYDATA2    ; 这个地方在生成EXE文件后,MYDATA2处会变成一个“重定位项”

       MOV DS,AX  

       MOV AH,9

       MOV DX,OFFSET MESSAGE2     ;这里OFFSET MESSAGE 的值为0

       INT 21H

       RET

MYFUN2 ENDP

 

 

MYCODE ENDS

 

 

END MYSTART   ;表示本程序从START这个子程序开始运行

 

 

 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条