C语言是一门强大并且灵活多变的语言。我一直想学好它,但是总是感觉自己进步不大,对于许多书中所讲解的语言特性理解的不深。为了进一步学习C语言,我觉得看它所编译出的汇编代码是一个不错的选择。由于相同的C语言代码在各种编译器下产生的汇编代码不尽相同,但是分析时又必须选择一种。这里采用TC2.0来实现分析工作,具体方法就是使用TC编辑环境编辑C语言源程序,使用tcc –S 源文件.c 来生成源文件.ASM文件,对ASM文件进行分析。
c源代码
void main()
{
}
使用tcc –S 命令得到相应的汇编代码为
ifndef
??version
?debug
macro
endm
endif
?debug S "c:/tcprj/main/main.c"
_TEXT
segment byte public 'CODE'
DGROUP group
_DATA,_BSS
assume cs:_TEXT,ds:DGROUP,ss:DGROUP
_TEXT
ends
_DATA
segment word public 'DATA'
d@
label byte
d@w
label word
_DATA
ends
_BSS
segment word public 'BSS'
b@
label byte
b@w
label word
?debug C E91BACB93414633A5C746370726A5C6D61696E5C6D61696E2E63
_BSS
ends
_TEXT
segment byte public 'CODE'
;
?debug L 1
_main
proc near
@1:
;
?debug L 3
ret
_main
endp
_TEXT
ends
?debug C E9
_DATA
segment word public 'DATA'
s@
label byte
_DATA
ends
_TEXT
segment byte public 'CODE'
_TEXT
ends
public _main
end
其中很多都是调试信息,由于调试信息是给后续的程序看的,不是给人看的,所以以后分析的汇编代码都是去掉调试信息的代码。那么把以上代码的调试信息去掉以后如下:
_TEXT
segment byte public 'CODE' ;定义代码段
DGROUP group
_DATA,_BSS ;将_DATA _BSS两段合为一组
assume cs:_TEXT,ds:DGROUP,ss:DGROUP ;
_TEXT
ends ;代码段结束
_DATA
segment word public 'DATA' ;数据段,存放初始化的数据
d@
label byte
d@w
label word
_DATA
ends
_BSS
segment word public 'BSS' ;数据段,存放未初始化的数据
b@
label byte
b@w
label word
_BSS
ends
_TEXT
segment byte public 'CODE' ;代码段
_main
proc near
@1:
ret
_main
endp
_TEXT
ends ;代码段结束
_DATA
segment word public 'DATA' ;数据段
s@
label byte
_DATA
ends ;数据段结束
_TEXT
segment byte public 'CODE' ;代码段
_TEXT
ends ;代码段结束
public _main ;声明_main 过程
end
段的定义为:段名 SEGMENT [定位类型] [组合类型] [‘类别’]。这段程序中存在着多个段 ,详细讲解几个。
1、_TEXT(段名) segment
byte(定位类型) public (组合类型)'CODE' (类别)
2、_DATA(段名) segment
word(定位类型)public (组合类型)'DATA'(类别)
3、_BSS(段名) segment word (定位类型)public (组合类型)'BSS' (类别)
byte定位类型表示段的起始地址使用下一个可用字节地址。 word定位类型表示段的起始地址使用下一个字地址。public 组合类型表示当前段与其它模块中组合类型为public的同名段组合成一个段。
以上程序框架使用了一些指令与伪指令。其中的各种指令与伪指令的详细说明请参考汇编语言教材,这里不详述汇编语言的知识,而把侧重点放在c语言代码在汇编层次是如何解释的。我参考的是杨季文编著的《80X86 汇编语言程序设计教程》。