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这个子程序开始运行
文章评论(0条评论)
登录后参与讨论