[原创]结构化80x86汇编语言

it2022-05-22  62

[原创]结构化80x86汇编语言

原创:结构化80x86汇编语言(walkdan(at)gmail.com)

闲来无事,把过去的一些陈年旧货翻出来,一些东西颇有感触。自从2000年后基本停止写汇编,之前差不多写了9年的x86汇编,全凭兴趣。如果硬件水平停留在386时代,写汇编非常快乐。不过一切都在改变,计算机论落成道具,编程快餐化,写程序越像写文档,而机器汇编也将尘封在永久的回忆。结构化汇编也是那个时代最有趣的编程之一。

编程的本质就是控制CPU的执行。任何现在的编程语言也托离不开这个规律。 一段汇编实现for 1 to 10循环:

  mov cx, 1 next:   cmp cx, 10   ja  exit   mov ax, cx   call print_ax   inc cx   jmp next exit:   ...

这类代码写多了,由于不是结构化代码,阅读编写尤其麻烦,也不想用C, 当年感觉C编译器复杂又慢,不如汇编对机器和CPU的控制力。94年的时候写了一套宏汇编,可以让写汇编像写结构化程序一样方便,加上编译器对类型检查也颇为有力,一段时间真没感觉到写C有什么好处。

比如上面的汇编用结构化宏可以改写为:

_For i,1,10   mov ax, i   call print_ax _Next

是不是很清晰,同C的感觉一样:for ( int i=1; i<=10; i++)   print_ax(i);

把结构化汇编语言翻译成传统汇编语言,需要用一套预定义宏,代码其实并不多,也就下面不到400行代码。或许C同汇编也许只差这400行代码。现在的编程语言经过多年的复杂演化,程序貌似越来越简单,离编程的本质却越来越远。 写这个宏的时候还知道VB, 于是借鉴了不少VB的语法:

  1 ; Struct Assemble MACRO for TASM   2 ;   3 ; Writen by Qiu Dan(walkdan) , 1994   4 ;   5 ; Compiler TASM 3.2   6   7 ; ************** _IF **************   8 ; StackName : IFstack   9 ; SP        : IFstack_sp  10 ; ******* _WHILE ***_UNTIL ********  11 ; StackName : WHILEstack  12 ; SP        : WHILEstack_sp  13 ; ************** _FOR *************  14 ; StackName : FORstack  15 ; SP        : FORstack_sp  16 ; ************** _BREAK ***********  17 ; StackName : BREAKstack  18 ; SP        : BREAKstack_sp  19 ; ************** _CASE ***********  20 ; StackName : CASEstack, SELECTStack  21 ; SP        : CASEstack_sp,SELECTStack_sp  22 ; *********************************  23  24  25 FALSE   Equ  0  26 TRUE    Equ 0ffh  27  28 ??counter= 0  29  30 ??IFstack_sp= 0  31 ??WHILEstack_sp= 0  32 ??BREAKstack_sp= 0  33 ??FORstack_sp= 0  34 ??SELECTstack_sp= 0  35 ??CASEstack_sp= 0  36  37 ??NjmpE   equ <NE>  38 ??NJmpNE  equ <E>  39 ??NjmpBE  Equ <A>  40 ??NjmpNA  equ <A>  41 ??NjmpB   equ <AE>  42 ??NjmpNAE equ <AE>  43 ??NjmpAE  equ <B>  44 ??NjmpNB  equ <B>  45 ??NjmpA   EQU <BE>  46 ??NjmpNBE equ <BE>  47 ??NjmpC   EQU <NC>  48 ??NjmpNC  EQU <C>  49 ??NjmpLE  equ <G>  50 ??NjmpNG  equ <G>  51 ??NjmpL   Equ <GE>  52 ??NjmpNGE equ <GE>  53 ??NjmpGE  equ <L>  54 ??NjmpNL  Equ <L>  55 ??NjmpG   Equ <LE>  56 ??NjmpNLE EQU <LE>  57 ??NJmpNCXZ equ <CXZ>  58  59 ??combine MACRO s1,s2,s3,s4,s5  60   ifB <s3>  61     &s1&s2 &s4&s5  62   ELSE  63     &s1&s2&s3&s4&s5  64   ENDIF  65 EndM  66  67 ??IncCounter MACRO  68   ??Counter = ??Counter +  1  69 EndM  70  71 ??MakeLabel MACRO s1  72   ??L_& s1:  73 EndM  74  75 ??GenCjmp MACRO cond,lbl  76   ??combine <J>,cond,,??L_,% lbl  77 ; ;  j&cond  ??L_&lbl  78 ENDM  79  80 ??GenNCjmp MACRO cond,lbl  81   ??combine <J>,% ??Njmp&cond,,??L_,% lbl  82 ENDM  83  84 ??GenJmp MACRO instruc,lbl  85   ??combine instruc,,,??L_,% lbl  86 ENDM  87  88 ??PushSym MACRO StackName,Symbol  89   StackName&_sp=StackName&_sp+ 1  90   ??combine StackName,% StackName&_sp ,=,Symbol  91 EndM  92  93 ??PopSym MACRO StackName  94   if StackName&_sp gt  0  95     ??combine ??sym,=,StackName,% StackName&_sp  96     StackName&_sp=StackName&_sp- 1  97   else  98     .err  99   endif 100 EndM 101 102 ??EraseSym MACRO StackName 103   if StackName&_sp gt  0 104     StackName&_sp=StackName&_sp- 1 105   else 106     .err 107   endif 108 ENDM 109 110 ??CopySym MACRO StackName,index 111   if (StackName&_sp - index) gt  0 112     ??combine ??sym,=,StackName,% StackName&_sp - index 113   else 114     .err 115   endif 116 ENDM 117 118 _IF MACRO var1,cond,var2 119   ??PushSym ??IFstack,??Counter 120   IFB <cond> 121     ??GenNCjmp var1,??Counter 122   ELSE 123      Cmp  var1,var2 124     ??GenNCjmp cond,??Counter 125   endif 126   ??IncCounter 127 ENDM 128 129 _ELSE MACRO 130   ??GenJmp < JMP >,% ??Counter 131   ??PopSym ??IFstack 132   ??MakeLabel % ??sym 133   ??PushSym ??IFstack, % ??Counter 134   ??IncCounter 135 EndM 136 137 _ENDIF MACRO 138   ??PopSym ??IFstack 139   ??MakeLabel % ??sym 140 EndM 141 142 _WHILE MACRO var1,cond,var2 143   ??MakeLabel % ??Counter +  1 144   ifb <cond> 145     ??GenNCjmp var1,??Counter 146   else 147      cmp  var1,var2 148     ??GenNCjmp cond,??Counter 149   endif 150   ??PushSym ??BREAKstack,% ??Counter 151   ??IncCounter 152   ??PushSym ??WHILEstack,% ??Counter 153   ??IncCounter 154 EndM 155 156 _WhileTrue MACRO 157   ??MakeLabel % ??Counter +  1 158   ??PushSym ??BREAKstack,% ??Counter 159   ??IncCounter 160   ??PushSym ??WHILEstack,% ??Counter 161   ??IncCounter 162 ENDM 163 164 _EndWhile MACRO 165   ??PopSym ??WHILEStack 166   ??GenJmp < JMP >,% ??Sym 167   ??PopSym ??BREAKStack 168   ??MakeLabel % ??Sym 169 EndM 170 171 _Repeat MACRO 172   ??PushSym ??BREAKStack,% ??Counter 173   ??IncCounter 174   ??MakeLabel % ??Counter 175   ??PushSym ??WHILEStack,% ??Counter 176   ??IncCounter 177 ENDM 178 179 _Until MACRO var1,cond,var2 180   ??PopSym ??WHILEStack 181   ifb <cond> 182     ??GenNCjmp var1,??Sym 183   else 184      cmp  var1,var2 185     ??GenNCjmp cond,??Sym 186   endif 187   ??PopSym ??BREAKStack 188   ??MakeLabel % ??Sym 189 ENDM 190 191 _Break MACRO level 192   ifb <level> 193     ??CopySym ??BreakStack, 0 194     ??GenJmp < JMP >,% ??Sym 195   else 196     if (.type level) eq 24h 197       ??CopySym ??BreakStack,level 198       ??GenJmp < JMP >,% ??sym 199     else 200       .err 201     endif 202   endif 203 ENDM 204 205 _BreakIf MACRO var1,cond,var2,t 206   ifB <var1> 207     ??CopySym ??BREAKStack, 0 208     ??GenJmp < JMP >,% ??Sym 209   else 210     ifB <var2> 211       ifb <cond> 212         ??copySym ??BreakStack, 0 213       else 214         ??copySym ??BreakStack,cond 215       endif 216       ??GenCJmp var1,??Sym 217     else 218        cmp  var1,var2 219       ifb <t> 220         ??copySym ??BreakStack, 0 221       else 222         ??copySym ??BreakStack,t 223       endif 224       ??GenCJmp cond,??Sym 225     endif 226   endif 227 ENDM 228 229 _BreakCXZ MACRO 230   ??CopySym ??BREAKStack, 0 231   ??GenJmp < JCXZ >,% ??Sym 232 ENDM 233 234 _Do MACRO times 235   ifNB <times> 236      mov  cx,times 237   endif 238   ??PushSym ??WHILEStack,??Counter 239   ??MakeLabel % ??Counter 240   ??IncCounter 241   ??PushSym ??BREAKStack,??Counter 242   ??IncCounter 243 ENDM 244 245 _Loop MACRO 246   ??PopSym ??WHILEStack 247   ??GenJmp <LOOP>,% ??Sym 248   ??PopSym ??BREAKStack 249   ??MakeLabel % ??Sym 250 ENDM 251 252 _ForW MACRO var,from,to,step   ; ;unsign 253    MOV  var,from 254   ??MakeLabel % ??Counter +  1 255    cmp  var,to 256   ifNB <step> 257     if .type step eq 24h 258       if step lt  0 259         ??GenNCjmp <NB>,??Counter 260       else 261         ??GenNCjmp <NA>,??Counter 262       endif 263     else 264       ??GenNCjmp <NA>,??Counter 265     endif 266   else 267     ??GenNCjmp <NA>,??Counter 268   endif 269   ??PushSym ??FORstack,??Counter 270   ??PushSym ??BREAKstack,??Counter 271   ??IncCounter 272   ??PushSym ??ForStack,??Counter 273   ??IncCounter 274   ??PushSym ??ForStack,<var> 275   ifb <step> 276     ??PushSym ??ForStack,< 1 > 277   else 278     ??PushSym ??ForStack,<step> 279   endif 280 ENDM 281 282 _ForI MACRO var,from,to,step   ; ;sign 283    MOV  var,from 284   ??MakeLabel % ??Counter +  1 285    cmp  var,to 286   ifNB <step> 287     if (.type step) eq 24h 288       if step lt  0 289         ??GenNCjmp <NL>,??Counter 290       else 291         ??GenNCjmp <NG>,??Counter 292       endif 293     else 294       ??GenNCjmp <NG>,??Counter 295     endif 296   else 297     ??GenNCjmp <NG>,??Counter 298   endif 299   ??PushSym ??FORstack,??Counter 300   ??PushSym ??BREAKstack,??Counter 301   ??IncCounter 302   ??PushSym ??ForStack,??Counter 303   ??IncCounter 304   ??PushSym ??ForStack,<var> 305   ifb <step> 306     ??PushSym ??ForStack, 1 307   else 308     ??PushSym ??ForStack,<step> 309   endif 310 ENDM 311 312 _For MACRO var,from,to,step 313   _ForI var,from,to,step 314 ENDM 315 316 _NEXT MACRO 317   local step 318   ??PopSym ??ForStack 319   step = ??sym 320   ??PopSym ??ForStack 321   ifB <step> 322      inc  ??sym 323   else 324     if (.type step) eq 24h   ; Immediate 325       if step eq  1 326          inc  ??sym 327       else 328         if step eq - 1 329            dec  ??sym 330         else 331           if step lt  0 332              sub  ??sym, 0  - step 333           else 334              add  ??sym,step 335           endif 336         endif 337       endif 338     else 339        add  ??sym,step 340     endif 341   endif 342   ??PopSym ??ForStack 343   ??GenJmp < JMP >,% ??sym 344   ??PopSym ??ForStack 345   ??MakeLabel % ??sym 346   ??EraseSym ??BreakStack 347 ENDM 348 349 _Select MACRO var 350   ??PushSym ??SELECTStack,% ??Counter 351   ??PushSym ??SELECTstack,<var> 352   ??IncCounter 353   ??PushSym ??CASEStack,FALSE 354 ENDM 355 356 _Case MACRO val,lbl 357   ??PopSym ??CASEStack 358   if ??Sym eq TRUE 359     ??CopySym ??SELECTStack, 1 360     ??GenJmp < JMP >,% ??Sym 361     ??PopSym ??CASEStack 362     ??MakeLabel % ??Sym 363   endif 364   ??CopySym ??SELECTStack, 0 365    cmp  &??sym,&val 366   ifB <lbl> 367     ??GenJmp < JNE >,% ??Counter 368     ??PushSym ??CASEStack,% ??Counter 369     ??PushSym ??CASEStack,TRUE 370     ??IncCounter 371   else 372      JE  lbl 373     ??PushSym ??CASEStack,FALSE 374   endif 375 ENDM 376 377 _CaseElse MACRO lbl 378   ??PopSym ??CASEStack 379   if ??sym eq TRUE 380     ??CopySym ??SELECTStack, 1 381     ??GenJmp < JMP >,% ??sym 382     ??PopSym ??CASEStack 383     ??MakeLabel % ??Sym 384   endif 385   ifNB <lbl> 386      JMP  lbl 387   endif 388   ??PushSym ??CASEStack,FALSE 389 ENDM 390 391 _EndSelect MACRO 392   ??PopSym ??SELECTstack 393   ??PopSym ??SELECTStack 394   ??MakeLabel % ??sym 395   ??PopSym ??CASEStack 396   IF ??sym eq TRUE 397     ??PopSym ??CASEStack 398     ??MakeLabel % ??sym 399   endif 400 ENDM 401 402 _Stop MACRO exitCode 403    mov  ah,4ch 404   ifB <exitCode> 405      mov  al, 0 406   else 407      mov  al,ExitCode 408   endif 409    int  21h 410 ENDM 比如用这段结构化宏写的命令行扫描部分代码可以是这样:  ; --------------------------------------------------------------------- ; 扫描命令行 ; int scanCmdline(void) ;; out : ;   al = TRUE    ; complet scan command line ;   al = FALSE   ; not complet scanCmdline proc near   xor  bh,bh   mov  bl,byte ptr  ds: [80h]       ;  get "command tail" count    mov  byte ptr [81h+bx], 0         ;  store null to end of the tail    mov  byte ptr [81h+bx+ 1 ], ' $ '     ;  store null to end of the tail    push  cs   pop  ds   mov  cur_posi,81h   mov  start_posi,81h   call  GetChr   call  GetSym                    ;  get the initial char and symbol   _While < cs: this_sym>,NE,symEND     mov  al,this_sym    _IF al,NE,symCOMMAND       call  scanerr       mov  al,FALSE       ret     _ENDIF     mov  al,byte ptr  cs: symValue     push  ax     call  GetSym     pop  ax    _SELECT al      _CASE  ' H '           ;  help          call  PrintHelp      _CASE  ' ? '          call  PrintHelp   ;  help       _CASE  ' K '          call  do_set_hot_key      _CASE  ' N '          mov  isSaveScreen,FALSE      _CASE  ' E '           ;  set execute program name          call  do_set_execute_prog      _CASE  ' R '           ;  Remove TSR          call  do_remove_TSR        _STOP      _CASE  ' V '          call  do_set_init_video_mode      _CASEELSE         call  scanerr    _ENDSELECT  _EndWhile   mov  al,TRUE   ret scanCmdline endp 嘿嘿, 是不是很爽! posted on 2008-06-23 18:24 Walkdan 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/walkdan/archive/2008/06/23/structure_assembler.html

相关资源:数据结构—成绩单生成器

最新回复(0)