. : : Assembly Language : : .  |  首页  |  我提出的问题  |  我参与的问题  |  我的收藏  |  消息中心   |  游客  登录  | 
刷新 | 提问 | 未解决 | 已解决 | 精华区 | 搜索 |
  《汇编语言》论坛 ->综合研究
  管理员: assembly   [回复本贴] [收藏本贴] [管理本贴] [关闭窗口]
主题 : :  【砖头】综合研究试验2---使用寄存器  [待解决] 回复[ 11次 ]   点击[ 1437次 ]  
mywiil
[帖 主]   [ 发表时间:2009-03-19 10:07 ]   [引用]   [回复]   [ top ] 
荣誉值:61
信誉值:4
注册日期:2008-10-14 16:29
在前面,根据教材上的步骤,搭建了一个简易的C语言开发环境。然后,我们开始去对我们第一个问题进行研究。 
先思考: 
    C语言编程能不使用变量么? 

我的思考:(参考书中的一些提示) 
    首先,我们得明白,变量是干什么用的。对了,就是在程序运行的时候存储数据的。那么不用变量存储数据行不行呢?!当然行了,前面的汇编学习过程中,我们从来不用变量的。 

    那我们用什么了?寄存器和内存啊!!所以,从理论上来说,如果C语言支持对寄存器和内存的直接支配,我们就有可能不用变量来编写C程序(当然,为了说明问题,我们值编写一些简单的小程序来说明问题就OK了)。 

    这个“研究试验2”就是带领我们,通过使用寄存器来深入的理解C程序一些本质。 

    首先,我们根据教材介绍的寄存器使用方法,进行实践(1)。在我们的简易C环境下,生成ur1.exe,然后debug ur1.exe。我们之前在跟踪汇编程序的时候,我们知道,当我们设置了assume 和 end 标识后,我们就可以找到程序的入口位置了,可是,在这里,我们看不到end,所以,我们也不知道程序的入口。但是,我认为,既然main函数能被运行,它肯定是在代码段的。本来以为,debug加载后,U命令一开始就应该是main的代码的,因为我一直认为main是C程序运行的开始。不过,当我debug加载后,一看,就蒙了。不是那么回事。一开始U命令看到的都是写莫名其妙的汇编指令,我都开始怀疑,main是不是在代码段了。错了一个想法了,不能这么轻易的就认为自己的另一个想法也是错的,然后,我就开始发挥不怕苦不怕累的优良作风,我跟你U到底了。 

    双眼瞪圆了看,只要看到类似 mov reg,data的代码就看看是不是和main中的指令作用一样。经过一份苦痛的挣扎,终于找到了如下的汇编指令部分 
1547:01FB 8BEC          MOV     BP,SP 
1547:01FD B80100        MOV     AX,0001 
1547:0200 BB0100        MOV     BX,0001 
1547:0203 B90200        MOV     CX,0002 
1547:0206 8BC3          MOV     AX,BX 
1547:0208 03C1          ADD     AX,CX 
1547:020A 8AE3          MOV     AH,BL 
1547:020C 02E1          ADD     AH,CL 
1547:020E 8AC7          MOV     AL,BH 
1547:0210 02C5          ADD     AL,CH 
哈哈,终于找到了吧。小样!说明俺的推理对了一半。呵呵。 

    现在main的代码找到了,地址是1547:01FB。这个结论还没有高兴两分钟,就发现自己又错了。这不是main的起始地址。晕~~~ 

    接着往下学,把打印main地址的那段程序运行了一下,发现打印出来的数据是1fa。也就是说,main的偏移地址应该是01faH。然后回头看了一下之前跟踪的url.exe的U命令结果,发现,01faH处开始的地方还有两条指令,到底是干什么的呢?仔细看看这段汇编代码 
1547:01FA 55            PUSH    BP 
1547:01FB 8BEC          MOV     BP,SP 
1547:01FD B80100        MOV     AX,0001 
1547:0200 BB0100        MOV     BX,0001 
1547:0203 B90200        MOV     CX,0002 
1547:0206 8BC3          MOV     AX,BX 
1547:0208 03C1          ADD     AX,CX 
1547:020A 8AE3          MOV     AH,BL 
1547:020C 02E1          ADD     AH,CL 
1547:020E 8AC7          MOV     AL,BH 
1547:0210 02C5          ADD     AL,CH 
1547:0212 5D            POP     BP 
1547:0213 C3            RET 
突然发现,这么像我们写的汇编子程序的样子  
main: 
push .. 
... 

pop .. 
ret 

    难道.....难道main函数只是一个子程序,是一个被别的代码部分调用的子程序??如果是这样的话,那么main就相当于一个子程序的标号(子程序名),也就能解释为什么我们debug后U命令一开始看到的指令不是main函数中的指令了,还能够解释为什么能够使用用printf打印出main的偏移地址来了。到底是不是呢?接着往下看。 

    教程接下来的讲解果真提到了01faH偏移地址处的两条指令了,不过,知识简单的说理解是函数的特殊设置就行了。我想了想,其实,很像我们写子程序的那个原则,只在子程序中临时使用的寄存器应该先push,退出前再pop,为的是在使用的过程中不影响该寄存器的原有值。这里先思考到这,我们看看最后的任务给我们的提示。 

    最后,我们抱着“c语言将函数实现为汇编子程序”的猜想,去研究书中的那个代码。如果,正如我们假设的那样,那么在main函数中调用f()的地方,应该是一个call指令,这个指令的地址指向的是f的代码部分,根据前面对于c中函数对应汇编代码的格式来说,那个f的代码应该类似如下 
push bp 
mov bp,sp 
mov ... 
add ... 
popbp 
ret 
那我们就带着我们的结论,去看看吧。debug中U命令查看 偏移地址01faH处的汇编指令如下: 
1547:01FA 55            PUSH    BP 
1547:01FB 8BEC          MOV     BP,SP 
1547:01FD B80100        MOV     AX,0001 
1547:0200 BB0100        MOV     BX,0001 
1547:0203 B90200        MOV     CX,0002 
1547:0206 E80200        CALL    020B   ;调用f了。哈哈 
1547:0209 5D            POP     BP 
1547:020A C3            RET 
1547:020B 55            PUSH    BP     ;020B就是我们猜想的那样。爽!! 
1547:020C 8BEC          MOV     BP,SP 
1547:020E 8BC3          MOV     AX,BX 
1547:0210 03C1          ADD     AX,CX 
1547:0212 5D            POP     BP 
1547:0213 C3            RET 

    跟我们的结论那是相当的一致,说明什么?说明C语言中的函数就是对应的汇编语言的子程序。 

    那么我们就可以把前面这几个含糊的结论总结一下了。 
    (1)main函数在代码段中。 
    (2)main函数也是一个被调用的函数,所以,推断,C语言真正的入口不是main,main函数只是那个入口函数的一个call的函数。 
    (3)在C语言中,函数的实现其实就是对应着汇编语言中的子程序。所以,C程序的运行本质还是汇编那一套。 

    最后想说的就是:汇编,真TM牛!!(说到这突然想起了,汇编网C教程中第一个用汇编做的C启动代码好像就是在main函数之前进行内存等的分配操作,怪不得main函数不是C程序真正的开始呢。哈哈哈。这回知道了,为什么说要学好后面的C课程要把这个综合研究给整明白了的道理啦。兄弟们啊,一定要借我这前车之鉴啊,不要跟我一样再走弯路喽!) 

==================== 
    这次是体会寄存器操作数据,理解了C语言的一些本质的东西,当初没好好学习这一章真是白瞎了。兄弟们一定要好好学习这张的内容啊。 
下一节研究内容还是属于不用变量编程的范畴:使用内存空间 

    准备中...
crazyman
[第1楼]   [ 回复时间:2009-03-20 15:01 ]   [引用]   [回复]   [ top ] 
荣誉值:152
信誉值:3
注册日期:2008-01-24 21:26
是得好好研究一下啦。
kid0713
[第2楼]   [ 回复时间:2009-06-02 15:07 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-04-13 07:29
把打印main地址的那段程序运行了一下,发现打印出来的数据是1fa
使用C编译器吗
kid0713
[第3楼]   [ 回复时间:2009-06-02 15:11 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2009-04-13 07:29
知道了 学习了
ptr
[第4楼]   [ 回复时间:2009-06-30 23:21 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:4
注册日期:2009-06-01 21:42
汇编真TMD的牛
abob
[第5楼]   [ 回复时间:2009-10-30 16:53 ]   [引用]   [回复]   [ top ] 
荣誉值:169
信誉值:0
注册日期:2008-08-19 16:07
思维,跳出限制。
powerofthinking
[第6楼]   [ 回复时间:2012-01-01 19:18 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2011-12-01 13:02
好文章:
(2)main函数也是一个被调用的函数,所以,推断,C语言真正的入口不是main,main函数只是那个入口函数的一个call的函数。  
请指教:C语言真正的入口是什么?
tomato
[第7楼]   [ 回复时间:2012-01-01 22:30 ]   [引用]   [回复]   [ top ] 
荣誉值:405
信誉值:0
注册日期:2008-01-19 14:51
回复6楼:如果你看完这章节的内容应该就明白C语言真正的入口是在c0s.obj中。
idhyt
[第8楼]   [ 回复时间:2012-03-13 10:44 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2012-01-05 18:58
这么多我都想不到唉,看了之后才有恍然大悟的感觉,楼主好牛气。。。
tomato
[第9楼]   [ 回复时间:2012-03-13 23:32 ]   [引用]   [回复]   [ top ] 
荣誉值:405
信誉值:0
注册日期:2008-01-19 14:51
综合研究包含的内容其实很广很深,需要反复深入学习研究。
kubajiaoba
[第10楼]   [ 回复时间:2018-01-30 13:44 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2018-01-30 13:44
网上找不到第三版的研究实验,特来挖坟感谢!
codinv
[第11楼]   [ 回复时间:2022-07-24 10:04 ]   [引用]   [回复]   [ top ] 
荣誉值:0
信誉值:0
注册日期:2018-10-13 21:08
太有趣了
需要登录后才能回帖 -->> 请单击此处登录
    Copyright © 2006-2024   ASMEDU.NET  All Rights Reserved