首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

2.6  汇编语言的编程范型——在底层思考

用汇编语言编程与用一般的高级语言编程可谓天壤之别。因此,许多程序员发现学习汇编语言很艰苦。幸运的是,本书中我们只需要看懂汇编语言的知识,能分析编译器的输出就行了;不必从头编写汇编语言程序。这意味着你无需掌握汇编语言的难点部分。然而如果理解汇编程序的写法,就能理解编译器发出某些代码序列的原因。到那个时候,我们再谈汇编语言程序员以及编译器是如何“思考”的。

汇编语言编程范型[1]的最基本方面,就是将需要完成的任务分解成机器能处理的许多小块。CPU原则上在某个时刻只能执行一个微操作,这对复杂指令集的CPU同样成立。因此,像高级语言语句这样的复杂操作,只能分解成机器能执行的多条小操作。作为示例,请看下列Visual Basic赋值语句:

profits = sales - costOfGoods - overhead – commissions

哪个CPU都无法用一条机器指令执行完此VB语句,都要将其分解为机器指令序列,执行该赋值语句的各个组成部分。比如说,许多CPU提供subtract指令,用于将某机器寄存器的值减去某个值。由于该赋值语句包含三个减法运算,必须将此赋值操作分解为至少3条减法指令。

80x86家族提供了相当灵活的减法指令sub。这一指令可允许如下形式的减法运算(以HLA语法给出):

sub( constant, reg );    // reg = reg - constant

sub( constant, memory ); // memory = memory - constant

sub( reg1, reg2 );       // reg2 = reg2 - reg1

sub( memory, reg );      // reg = reg - memory

sub( reg, memory );      // memory = memory - reg

假设前面Visual Basic代码的标识符都表示变量,我们就可以使用80x86的sub和mov指令实现上述操作,其HLA代码序列如下:

// 取sales的值放入寄存器EAX

mov( sales, eax );

// 计算sales-costOfGoods (EAX := EAX - costOfGoods)

sub( costOfGoods, eax );

// 计算(sales-costOfGoods) - overhead

// (注意:此时EAX的值为sales-costOfGoods)

sub( overhead, eax );

// 计算(sales-costOfGoods-overhead)-commissions

// (注意:此时EAX的值为sales-costOfGoods-overhead)

sub( commissions, eax );

// 将EAX中的结果存入profits

mov( eax, profits );

注意这里将单条VB语句分解成了5条不同的HLA语句,每句完成整个运算的一部分。汇编语言编程范型的诀窍在于需知道如何将复杂操作分解成一串机器指令的简单序列,就像本例所做的那样。我们在第13章还会探讨这一过程。

用HLA学习汇编语言编程时,需要将复杂操作分解为较简单语句序列的另一大范畴,就是高级语言控制结构。例如,我们来看如下Pascal语言的if语句:

if( i = j ) then begin

  writeln( "i is equal to j" );

end;

CPU不支持机器指令if,但它可比较两个值,以此设置“条件码”标志位,然后通过“条件转移”指令检验这些条件码的结果。常见办法是将高级语言的if语句转换成下列汇编代码:倘若检验出相反条件(i<>j),就跳过原始条件(i=j)为True时要执行的语句。例如,这里将前面Pascal的if语句转换为“纯粹”的HLA汇编语言,而非HLA类似高级语言的结构:

   mov( i, eax );   // 取i值

   cmp( eax, j );   // 将i值与j值比较

   jne skipIfBody; // 如果(i<>j)就跳过if语句体,到标号skipIfBody处

   << 欲显示字符串的代码 >>

skipIfBody:

高级语言控制结构中的布尔表达式越复杂,对应的机器指令数目也就越多,但过程都是一样的。后面我们将会探讨编译器将高级语言控制结构转换到汇编语言的原理,请参看第14章和第15章。

向过程或函数传递参数、在过程或函数中访问这些参数,以及访问过程或函数中的其他数据,这些都是汇编语言比一般高级语言复杂得多的地方。我们不打算预演其如何实现,甚至没有例子提供感性认识。但随后当然会谈到这一重要课题,参看第16章。

总的原则是,当将某个算法从高级语言转换过来时,必须将问题分解成许多较小的块,以便能用汇编语言编码。正如前面所述,我们阅读汇编语言代码时不必猜测要用什么机器指令——生成代码的编译器或汇编语言程序员已经替我们做了这些工作,这样多好!我们只需将高级语言代码与汇编代码对应起来。至于如何对应,则是本书后面很多部分要完成的科目。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论