原创:结构化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
相关资源:数据结构—成绩单生成器