Drip 2018-08-04
通过上次C程序与汇编程序相互交互看到了不同编译器之间合作的可能,最后的结果都是机器码,上次说过还有种通过C程序生成汇编代码后在其函数部分可以自己编写汇编代码然后与C程序进行连接的。
这里就分析一下一个简单的C程序被翻译成汇编后是什么样的:
ifndef ??version ;汇编伪指令,语义应该和C语言类似,如果名称 ??version 未定义则进入内部
?debug macro ;在数据声明中,一个值,汇编程序分配但未初始化。
endm ;终止宏或重复的块。
endif ;汇编伪指令,语义应该和C语言类似,ifndef的闭合标签
?debug S "test.c"
_TEXT segment byte public 'CODE' ;段定义,地址对齐方式为比特,公有类型,段类别为'CODE'
DGROUP group _DATA,_BSS ;段声明,将一组段_DATA,_BSS添加到名称DGROUP中
assume cs:_TEXT,ds:DGROUP,ss:DGROUP ;段的作用声明,可以启到寄存器值的错误检查作用
_TEXT ends ;_TEXT段结束 该段对之后的代码段栈段数据段进行了声明
_DATA segment word public 'DATA' ; _DATA段开始,地址对齐方式为字,公有类型,段类别为'DATA'
d@ label byte ;定义名为 d@ 的标签,类型为字节
d@w label word ;定义名为 d@w 的标签,类型为字
_DATA ends ;_DATA段结束
_BSS segment word public 'BSS' ;BSS段开始,地址对齐方式为字,公有类型,段类别为'DATA'
b@ label byte ;定义名为 b@ 的标签,类型为字节
b@w label word ;定义名为 b@w 的标签,类型为字
?debug C E9E862014D06746573742E63 ;在数据声明中,一个值,汇编程序分配但未初始化。
_BSS ends ;BSS段结束(该段就是未初始化的全局变量区段,程序开始时会被初始化0)
_TEXT segment byte public 'CODE' ;_TEXT段开始
; ?debug L 2 ;在数据声明中,一个值,汇编程序分配但未初始化。
_main proc near ;子程序 _main 寻址方式为 near(在C语言中也就是main)
push bp ;子程序代码....
mov bp,sp
sub sp,2
; ?debug L 4
mov word ptr [bp-2],1
; ?debug L 5
@1:
; ?debug L 6
mov sp,bp
pop bp
ret
_main endp ;子程序代码部分结束
_TEXT ends ;_TEXT段结束
?debug C E9
_DATA segment word public 'DATA' ;_DATA段开始
s@ label byte ;声明名称为 s@ 的标签,类型为字节
_DATA ends ;_DATA段结束
_TEXT segment byte public 'CODE' ;_TEXT段开始
_TEXT ends ;_TEXT段开始
public _main ;声明子程序 _main 是公有的
end ;结束
通过翻阅官方资料,大略把这些代码阅读完了,因为是编译器自动生成的,所以可能有些赘余的地方,比如最后四句,声明了段开始然后立即结束,在这两句中没有向段中添加任何内容,还有被注释掉的; ?debug …. 这些可能是用于TCC调试的额外信息,所以关于?debug的应该都可以去掉。在该代码中可以总结几个比较奇怪的地方:
1. 以 ?debug 开头的可以当作是额外的调试信息
2. 中间由 label的代表这是一个标签信息,在该伪指令前后分别是标签名和类型,在段开始声明的地方定义的标签可以当作是为了寻址该段首而定义的,因为标签名和段名首字母一样,并且加了个@,很生动形象。
因为我没有使用过这种方法实现混合编程,所以也没特别走心,只是对照官方文档进行了简单的对比而已,当然的我也会对其进行理解和思考。通过这种形式就能和其它C源程序进行连接了,还是有研究价值的。下次继续研究这个时,我会多定义几个不同类型的函数与变量,以及自定义一些标号,再次深究,这次的研究都到此为止了。