現在寫匯編語言,就象寫結構化的高級語言一樣,非常的方便。不信?你看看下面寫的小程序就知道啦,沒有程序跳轉,完全的結構化設計。最後還附有 Glow Glove 總結的小篇文章,供大家學習參考。
;-------------------------------------------------------
;例:計算一個數據的階乘
;若結果較小,可放在 EAX 寄存器
;若結果較小,可放在 EDX:EAX 寄存器
;文件名:7.asm
.386
.model flat,stdcall
option casemap:none
include windows.inc
include masm32.inc
include kernel32.inc
include user32.inc
includelib masm32.lib
includelib kernel32.lib
includelib user32.lib
.data?
CharOut db 100 dup(?)
.code
OutEdxEax PROTO :DWORD ;將EDX:EAX中的數據轉換成十進制輸出字符串形式!
OutEdxEax proc lpString ;比如:EDX=0,EAX=01234567H,則轉換後的字符串為:
-> '19088743',0
mov edi,lpString ;指向存放結果的地址
mov esi,lpString
mov ecx,10 ;轉換成十進制
.while eax!=0 || edx!=0
push eax
mov eax,edx
xor edx,edx
div ecx
mov ebx,eax
pop eax
div ecx
add dl,'0'
mov [edi],dl ;存放結果
inc edi
mov edx,ebx
.endw
mov BYTE ptr [edi],0;字符串以0為結尾
dec edi
.while edi>esi ;結果前變後,後變前!
mov al,[esi]
xchg al,[edi]
mov [esi],al
inc esi
dec edi
.endw
ret
OutEdxEax endp
start: ;程序開始
xor eax,eax ;存放結果的寄存器EDX:EAX=1
xor edx,edx
inc eax
mov ecx,20 ;計算20的階乘。不能大於20,否則會溢出,結果將不再正確!
.while ecx>0
.if edx==0 ;結果在EAX中
mul ecx
.else ;結果在EDX:EAX中
push edx
mul ecx
pop ebx
push eax
push edx
mov eax,ecx
mul ebx
pop edx
add edx,eax
pop eax
.endif
dec ecx
.endw
.if edx==0 ;結果在EAX中
invoke dw2a,eax,addr CharOut
.else ;結果在EDX:EAX中
invoke OutEdxEax,addr CharOut ;用我們自己的程序轉換!
.endif
invoke StdOut,addr CharOut ;控制台輸出結果
invoke ExitProcess,NULL ;結束程序
end start
----------------------------------------------------------------
生成7.exe的詳細操作過程
D:\MASM7>ml /coff /I include 7.asm /link /subsystem:console /libpath:lib
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997. All rights reserved.
Assembling: 7.asm
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
/subsystem:console /libpath:lib
"7.obj"
"/OUT:7.exe"
D:\MASM7>7
2432902008176640000
D:\MASM7>_
---------------------------------------------------------------------
用W32dasm反編譯後的結果,大家可看看“匯編語言”是怎樣翻譯成“機器語言”的。
Program Entry Point = 00401042 (7.exe File Offset:00001642)
:00401000 55 push ebp
:00401001 8BEC mov ebp, esp
:00401003 8B7D08 mov edi, dword ptr [ebp+08]
:00401006 8B7508 mov esi, dword ptr [ebp+08]
:00401009 B90A000000 mov ecx, 0000000A
:0040100E EB14 jmp 00401024
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00401026(C), :0040102A(C)
|
:00401010 50 push eax
:00401011 8BC2 mov eax, edx
:00401013 33D2 xor edx, edx
:00401015 F7F1 div ecx
:00401017 8BD8 mov ebx, eax
:00401019 58 pop eax
:0040101A F7F1 div ecx
:0040101C 80C230 add dl, 30
:0040101F 8817 mov byte ptr [edi], dl
:00401021 47 inc edi
:00401022 8BD3 mov edx, ebx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040100E(U)
|
:00401024 0BC0 or eax, eax
:00401026 75E8 jne 00401010
:00401028 0BD2 or edx, edx
:0040102A 75E4 jne 00401010
:0040102C C60700 mov byte ptr [edi], 00
:0040102F 4F dec edi
:00401030 EB08 jmp 0040103A
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040103C(C)
|
:00401032 8A06 mov al, byte ptr [esi]
:00401034 8607 xchg byte ptr [edi], al
:00401036 8806 mov byte ptr [esi], al
:00401038 46 inc esi
:00401039 4F dec edi
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401030(U)
|
:0040103A 3BFE cmp edi, esi
:0040103C 77F4 ja 00401032
:0040103E C9 leave
:0040103F C20400 ret 0004
//******************** Program Entry Point ********
:00401042 33C0 xor eax, eax
:00401044 33D2 xor edx, edx
:00401046 40 inc eax
:00401047 B914000000 mov ecx, 00000014
:0040104C EB17 jmp 00401065
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401068(C)
|
:0040104E 0BD2 or edx, edx
:00401050 7504 jne 00401056
:00401052 F7E1 mul ecx
:00401054 EB0E jmp 00401064
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401050(C)
|
:00401056 52 push edx
:00401057 F7E1 mul ecx
:00401059 5B pop ebx
:0040105A 50 push eax
:0040105B 52 push edx
:0040105C 8BC1 mov eax, ecx
:0040105E F7E3 mul ebx
:00401060 5A pop edx
:00401061 03D0 add edx, eax
:00401063 58 pop eax
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401054(U)
|
:00401064 49 dec ecx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040104C(U)
|
:00401065 83F900 cmp ecx, 00000000
:00401068 77E4 ja 0040104E
:0040106A 0BD2 or edx, edx
:0040106C 750D jne 0040107B
:0040106E 6804304000 push 00403004
:00401073 50 push eax
:00401074 E81F000000 call 00401098
:00401079 EB0A jmp 00401085
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040106C(C)
|
:0040107B 6804304000 push 00403004
:00401080 E87BFFFFFF call 00401000
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401079(U)
|
:00401085 6804304000 push 00403004
:0040108A E825000000 call 004010B4
:0040108F 6A00 push 00000000
* Reference To: KERNEL32.ExitProcess, Ord:0075h
|
:00401091 E88E000000 Call 00401124
:00401096 CC int 03
:00401097 CC int 03
* Referenced by a CALL at Address:
|:00401074
|
:00401098 55 push ebp
:00401099 8BEC mov ebp, esp
:0040109B FF7508 push [ebp+08]
* Possible StringData Ref from Data Obj ->"%lu"
|
:0040109E 6800304000 push 00403000
:004010A3 FF750C push [ebp+0C]
* Reference To: USER32.wsprintfA, Ord:02A5h
|
:004010A6 E88B000000 Call 00401136
:004010AB 83C40C add esp, 0000000C
:004010AE C9 leave
:004010AF C20800 ret 0008
:004010B2 CC int 03
:004010B3 CC int 03
* Referenced by a CALL at Address:
|:0040108A
|
:004010B4 55 push ebp
:004010B5 8BEC mov ebp, esp
:004010B7 83C4F4 add esp, FFFFFFF4
:004010BA 6AF5 push FFFFFFF5
* Reference To: KERNEL32.GetStdHandle, Ord:013Dh
|
:004010BC E869000000 Call 0040112A
:004010C1 8945FC mov dword ptr [ebp-04], eax
:004010C4 FF7508 push [ebp+08]
:004010C7 E820000000 call 004010EC
:004010CC 8945F4 mov dword ptr [ebp-0C], eax
:004010CF 6A00 push 00000000
:004010D1 8D45F8 lea eax, dword ptr [ebp-08]
:004010D4 50 push eax
:004010D5 FF75F4 push [ebp-0C]
:004010D8 FF7508 push [ebp+08]
:004010DB FF75FC push [ebp-04]
* Reference To: KERNEL32.WriteFile, Ord:02B9h
|
:004010DE E84D000000 Call 00401130
:004010E3 8B45F8 mov eax, dword ptr [ebp-08]
:004010E6 C9 leave
:004010E7 C20400 ret 0004
:004010EA CC int 03
:004010EB CC int 03
* Referenced by a CALL at Address:
|:004010C7
|
:004010EC 55 push ebp
:004010ED 8BEC mov ebp, esp
:004010EF 53 push ebx
:004010F0 8B4508 mov eax, dword ptr [ebp+08]
:004010F3 8D5003 lea edx, dword ptr [eax+03]
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040110B(C)
|
:004010F6 8B18 mov ebx, dword ptr [eax]
:004010F8 83C004 add eax, 00000004
:004010FB 8D8BFFFEFEFE lea ecx, dword ptr [ebx+FEFEFEFF]
:00401101 F7D3 not ebx
:00401103 23CB and ecx, ebx
:00401105 81E180808080 and ecx, 80808080
:0040110B 74E9 je 004010F6
:0040110D F7C180800000 test ecx, 00008080
:00401113 7506 jne 0040111B
:00401115 C1E910 shr ecx, 10
:00401118 83C002 add eax, 00000002
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401113(C)
|
:0040111B D0E1 shl cl, 1
:0040111D 1BC2 sbb eax, edx
:0040111F 5B pop ebx
:00401120 C9 leave
:00401121 C20400 ret 0004
* Referenced by a CALL at Address:
|:00401091
|
* Reference To: KERNEL32.ExitProcess, Ord:0075h
|
:00401124 FF2508204000 Jmp dword ptr [00402008]
* Referenced by a CALL at Address:
|:004010BC
|
* Reference To: KERNEL32.GetStdHandle, Ord:013Dh
|
:0040112A FF2500204000 Jmp dword ptr [00402000]
* Referenced by a CALL at Address:
|:004010DE
|
* Reference To: KERNEL32.WriteFile, Ord:02B9h
|
:00401130 FF2504204000 Jmp dword ptr [00402004]
* Reference To: USER32.wsprintfA, Ord:02A5h
|
:00401136 FF2510204000 Jmp dword ptr [00402010]
:0040113C 00000000000000000000 BYTE 10 DUP(0)
------------------------------------------------------------------
MASM 6.x 新增指令列表: Glow Glove 制 (請體諒小弟辛苦,勿消去)
MASM 6.x 推出以久,但市面上有關之書籍及資料卻少得可憐,小弟當初接觸
MASM 6.x 時,辛辛苦苦才找出資料的,為了那些後進不用踏著先烈的血跡前
撲後繼,特將小弟「翻」出來的東東公布出來。
這些指令都是小弟從書上(厚顏無恥,在老板的白眼下辛苦抄下來的)
及MASM 6.0 之范例程式中翻出來的,若有遺落疏失,請包涵。
請體諒小弟之辛苦,勿將小弟的ID消去。
MASM 6.x與MASM 5.x最大不同,在於6.x 比5.x 更高階化了(或說更PASCAL化),
其內提供了判斷、回圈、模組化副程式等,各種令組合語言使用者望穿秋水之指
令,看完內容,請不要感動的痛哭流涕,或恨他為什麽不早點出來。
運算符號:
== : 等於 & : 位元測試
!= : 不等於 ! : 否 NOT
> : 大於 && : 且 AND
< : 小於 || : 或 OR
輔助運算符號:
ZERO? : ZERO ZF=1,ZR !ZERO? : NOT ZERO ZF=0,NZ
CARRY? : CARRY CF=1,CY !CARRY? : NOT CARRY CF=0,NC
OVERFLOW? : OVERFLOW,OV !OVERFLOW? : NOT OVERFLOW,NV
SIGN? : NEGATIVE,NG !SIGN? : PLUS,PL
PARITY? : PARITY EVEN,PE !PARITY? : PARITY ODD,PO
Examples:
.IF AX == 1 .REPEAT
.IF ZERO? .UNTIL ZERO?
.IF !(AX & 0Fh)
.IF AL=ESC || AL=CR
看到這些指令了嗎? 是不是似曾相識,期待以久了。
判斷式:
.IF
.
.ELSEIF
.
.ELSE
.
.ENDIF
.ELSEIF 及.ELSE 為非必要之動作,寫過高階語言的應該不難了解才對!
回圈指令:
(1) 前測式:
.WHILE
.
.
.ENDW
當條件成立,即執行回圈內,否則執行回圈後之動作
(2) 後測式:
1. .REPEAT
.
.
.UNTIL
or
2. .REPEAT
.
.
.UNTILCXZ
1. 回圈一直到條件成立即停止回圈
2. 同1 ,但加上判斷CX是否為0 (OR的關系,即條件為真或CX==0)
輔助指令:
.BREAK
.COUNTINE
配合上述回圈指令運用
.BREAK 可中止回圈
.COUNTINE 可跳至回圈開頭
可在其後加上敘述,敘述成立才動作
嗯! 愈看愈像PASCAL了
Examples:
.WHILE AX==1 || !ZERO? .REPEAT
. .
.ENDW .UNTIL (AX & 1)
.REPEAT
.
.BREAK .IF ZERO?
.
.COUNTINE
.
.UNTILCXZ (DX == 0)
引申:
上述之判斷式及回圈,其實就是CMP XX,YY
Jxx xxxx,LOOPxx xxxx
之組合。
其內動作復雜,小弟寫不出來 :~~( 請寫過MASM 5.x的人自行體會那種復雜的古老方式。
以上內容為:MASM 6.x 新增指令列表: Glow Glove 制 (請體諒小弟辛苦,勿消去)