汇编程序员之代码风格指南

来源:互联网 发布:淘宝睡眠水 编辑:程序博客网 时间:2024/05/18 04:21

©CVC电脑病毒论坛 -- 中国毒客的快乐天地  4
作者:Randall HydebxLj
  http://webster.cs.ucr.edu/ 

节选1.0 和 1.1:
1.0简介
       许多人认为汇编程序难于阅读。虽然大家有这种感觉有许多原因,但最主要的还是汇编语言难以使得程序员写出易读的程序。这并不表示不可能编写出易读的程序,只是它要花费汇编程序员一部分额外的工作来写出易读代码。
   为了示范汇编程序的一些公共问题,决定使用下面的程序或程序段。这些都是在Internet上找到的真正用汇编语言编写的程序。每个例子都示范了一个单独的问题。(顺便一提:选择这些程序并不是有意让原作者难吭。这些程序都是在网上找到的汇编代码特例)。


代码:



1.1ADDHEX.ASM
%title "两个16进制数相加"
       IDEAL
       DOSSEG
       MODEL   small
       STACK   256
       DATASEG
exitCode        db      0
prompt1         db      'Enter value 1: ', 0
prompt2         db      'Enter value 2: ', 0
string          db      20 DUP (?)
       CODESEG
       EXTRN   StrLength:proc
       EXTRN   StrWrite:proc, StrRead:proc, NewLine:proc
       EXTRN   AscToBin:proc, BinToAscHex:proc
Start:
       mov     ax,@data
       mov     ds,ax
       mov     es,ax
       mov     di, offset prompt1
       call    Getvalue
       push    ax
       mov     di, offset prompt2
       call    Getvalue
       pop     bx
       add     ax,bx
       mov     cx,4
       mov     di, offset string


       call    BinToAscHex
       call    StrWrite
Exit:
       mov     ah,04Ch
       mov     al,[exitCode]
       int     21h
PROC    Getvalue
       call    StrWrite
       mov     di, offset string
       mov     cl,4
       call    StrRead
       call    NewLine
       call    StrLength
       mov     bx,cx
       mov     [word bx + di], 'h'
       call    AscToBin
       ret
ENDP    Getvalue
       END     Start


   好了,这个程序的最大问题还是相当明显的-除了标题之外完全没有其它注释(译注:国内有太多这样没注释的程序了)。另一个实际的问题则是用来提示用户的字符串出现在程序的一端但用来打印这些字符串的调用代码却出现在另外一个地方(译注:即指代码中的StrWrite等三个函数)。尽管这是个经典的汇编语言编程方法,但却导致了代码难于阅读。另外,相对次要的一个问题是该程序使用了TASM的 “less-than”IDEAL
语法(注:一些一直使用TASM的人会认为这没什么不好。但个别人就不这么认为了,由于他们不熟悉TASM的古怪语言,有时会导致被程序中的几条语句搞混淆)
   这个程序也使用了MASM/TASM的“简单化”段定义。微软声称的这个典型特性却给一个“简单”的工程增加了复杂性。如果该程序转换为标准的段定义格式将会更加易读。
(注:使用简单段定义虽然更容易编写高级语言接口的汇编程序,但无论如何,他们都只会使单一的程序问题变得复杂)
   在扔掉它之前,该程序还是有两点值得称赞的(遵循了可读性)。第一,该程序员为过程名和本程序使用的变量选择了一组合理的名称(我假定这段代码的作者同时也是该程序调用的库的作者)。程序另一个值得肯定的是助记性好和操作数之间有良好的对齐。
   OK,在抱怨这份代码如何难读后,为什么不来个更易读的版本?下面的程序便是,可证明,该版本比上面的版本更加易读。可证明,因为该版本使用了UCR标准库v2.O
并假定读者熟悉该库的细节和特性。

代码:

;**************************************************
;
; AddHex-
;
; 这个简单的程序从用户那里获取两个整数值,计算它们的和,
; 并在屏幕上打印结果。
;
; 这个例子使用了“80x86汇编程序员的UCR标准库v2.0”
;
; Randall Hyde
; 12/13/96
               title           AddHex
               .xlist
               include         ucrlib.a
               includelib      ucrlib.lib
               .list
cseg            segment para public 'code'
               assume  cs:cseg
; GetInt-
;
; 这个函数从键盘读取一个整数并将结果返回到AX寄存器中
;
; 该程序捕获无效的值(太大或无效数字)并需要用户重新输入一个数值。
;

GetInt          textequ <call GetInt_p>
GetInt_p        proc
               push    dx              ;DX 保存错误代码
GetIntLoop:     mov     dx, false       ;假定没错误
               try                     ;捕获任何可能的错误
               FlushGetc               ;清空输入来换新行
               geti                    ;读入整数值
               except  $Conversion     ;捕获错误字符
               print   "Illegal numeric conversion, please re-enter", nl
               mov     dx, true
               
               except  $Overflow       ;捕获数值太大
               print   "value out of range, please re-enter.",nl
               mov     dx, true
               endtry
               cmp     dx, true
               je      GetIntLoop
               pop     dx
               ret
GetInt_p        endp

Main            proc
               InitExcept
               print   'Enter value 1: '
               GetInt
               mov     bx, ax
               print   'Enter value 2: '
               GetInt
               print   cr, lf, 'The sum of the two values is '
               add     ax, bx
               puti
               putcr
Quit:           CleanUpEx
               ExitPgm                 ;退出程序的DOS宏
Main            endp

cseg            ends

sseg            segment para stack 'stack'
stk             db      256 dup (?)
sseg            ends


zzzzzzseg       segment para public 'zzzzzz'
LastBytes       db      16 dup (?)
zzzzzzseg       ends
               end     Main







   这里要特别指出的是这份代码比原来的那个AddHex程序要大一点。在细节上,它验证用户的输入;而在原程序上并没有这么做。如果那位想更严密地模范原程序,下面的简单代码即是:

代码:

               print   nl, 'Enter value 1: '
               Geti
               mov     bx, ax
               print   nl, 'Enter value 2: '
               Geti
               add     ax, bx
               putcr
               puti
               putcr


在这个例子中,两个简单的解决方案改良了程序的可读性:增加注释、将程序格式化得更好点,而且使用了UCR标准库的高级特性来使得编码更为简单并使得打印输出字符串的语句保持它们的字面意思。

   


 

原创粉丝点击