▶ 书中第十章的程序,主要讲了结构与宏的使用
● 代码,使用结构,对比是否对齐的性能差距
1 INCLUDE Irvine32.inc 2 INCLUDE macros.inc 3 4 structN STRUCT ; 非对齐的结构 5 Lastname BYTE 30 DUP(0) ; 30 6 Years WORD 0 ; 2 7 SalaryHistory DWORD 0, 0, 0, 0 ; 16 8 structN ENDS ; 48 Byte 9 10 structA STRUCT ; 对齐的结构 11 Lastname BYTE 30 DUP(0) ; 30 12 ALIGN WORD ; +2 13 Years WORD 0 ; 2 14 ALIGN DWORD ; +2 15 SalaryHistory DWORD 0, 0, 0, 0 ; 16 16 structA ENDS ; 52 Byte 17 18 .data 19 ALIGN DWORD ; 对齐到双字 20 startTime DWORD ? 21 empBad structN <> 22 emp structA <> 23 24 .code 25 main PROC 26 call GetMSeconds 27 mov startTime, eax 28 mov ecx, 0FFFFFFFFh 29 L1: 30 mov empBad.Years, 5 31 mov empBad.SalaryHistory, 35000 32 loop L1 33 34 call GetMSeconds 35 sub eax, startTime 36 mWrite "Time without align: " 37 call WriteDec 38 call Crlf 39 40 call GetMSeconds 41 mov startTime, eax 42 mov ecx, 0FFFFFFFFh 43 L2: 44 mov emp.Years, 5 45 mov emp.SalaryHistory, 35000 46 loop L2 47 48 call GetMSeconds ; get starting time 49 sub eax, startTime 50 mWrite "Time with align: " 51 call WriteDec ; display elapsed time 52 call Crlf 53 54 call WaitMsg 55 exit 56 main ENDP 57 58 END main
■ 输出结果,反复测试,时间差大概在 70 ms 左右
Time without align: 6999 Time with align: 6913
● 调用 win32 API 显示时间,并放到终端中的指定位置
1 INCLUDE Irvine32.inc 2 3 COMMENT ! 4 SmallWin.inc 中关于结构 COORD 和 SYSTEMTIME 的定义 5 COORD STRUCT 6 X WORD ? 7 Y WORD ? 8 COORD ENDS 9 10 SYSTEMTIME STRUCT 11 wYear WORD ? 12 wMonth WORD ? 13 wDayOfWeek WORD ? 14 wDay WORD ? 15 wHour WORD ? 16 wMinute WORD ? 17 wSecond WORD ? 18 wMilliseconds WORD ? 19 SYSTEMTIME ENDS 20 ! 21 22 .data 23 sysTime SYSTEMTIME <> 24 XYPos COORD <10, 5> 25 consoleHandle DWORD ? 26 colonStr BYTE ":", 0 27 TheTimeIs BYTE "The time is ", 0 28 29 .code 30 main PROC 31 INVOKE GetStdHandle, STD_OUTPUT_HANDLE ; 获取标准输出句柄,返回值在 eax,转入变量 consoleHandle 32 mov consoleHandle, eax 33 34 INVOKE SetConsoleCursorPosition, consoleHandle, XYPos ; 设置终端光标位置 35 36 INVOKE GetLocalTime, ADDR sysTime ; 获取当前时间 37 38 movzx eax, sysTime.wHour ; 小时 39 call WriteDec 40 mov edx, offset colonStr ; ":" 41 call WriteString 42 movzx eax, sysTime.wMinute ; 分钟 43 call WriteDec 44 call WriteString ; ":" 45 movzx eax, sysTime.wSecond ; 秒 46 call WriteDec 47 48 call Crlf 49 call WaitMsg 50 exit 51 main ENDP 52 53 END main
● 使用宏包装以后的汇编 Wraps.asm,主要展示了 Macros.inc 的作用
1 INCLUDE Irvine32.inc 2 INCLUDE Macros.inc 3 4 .data 5 array DWORD 1, 2, 3, 4, 5, 6, 7, 8 6 string1 BYTE 31 DUP(?) 7 string2 BYTE 31 DUP(?) 8 9 .code 10 main PROC 11 mGotoxy 0, 0 ; 调整终端光标位置,并输出指定字符串 12 mWrite <"Macro Program sample:", 0dh, 0ah> 13 14 mGotoxy 0, 5 15 mWrite <"Go to Row 5, col 0.", 0dh, 0ah> 16 call Crlf 17 18 mWrite "Input string 1: " ; 输入两个字符串,然后一并输出 19 mReadString string1 20 call Crlf 21 22 mWrite "Input string 2:" 23 mReadString string2 24 call Crlf 25 26 mWrite "Output the strings:" 27 mWriteString string1 28 mWriteSpace 29 mWriteString string2 30 call Crlf 31 32 mDumpMem OFFSET array, LENGTHOF array, TYPE array ; 输出数组 33 34 call waitmsg 35 exit 36 main ENDP 37 38 END main
● 代码,使用 WHILE 伪指令在编译阶段进行计算
1 INCLUDE Irvine32.inc 2 3 .data 4 val1 = 1 ; 先给三个常量,然后再定义成变量 5 val2 = 1 6 val3 = val1 + val2 7 DWORD val1 8 DWORD val2 9 DWORD val3 10 11 WHILE val3 LT 00010000h ; 使用 WHILE 在编辑阶段进行展开和计算 12 val1 = val2 13 val2 = val3 14 val3 = val1 + val2 15 ENDM 16 17 .code 18 main PROC 19 mov eax, val3 ; 结果放进 eax 用于输出 20 call WriteDec 21 call crlf 22 call WaitMsg 23 exit 24 main ENDP 25 26 END main
● 代码,使用 REPEAT 生成单链表
1 INCLUDE Irvine32.inc 2 3 ListNode STRUCT ; 链表节点结构 4 NodeData DWORD ? 5 NextPtr DWORD ? 6 ListNode ENDS 7 8 TotalNodeCount = 15 9 NULL = 0 10 Counter = 0 11 12 .data 13 LinkedList LABEL PTR ListNode 14 REPT TotalNodeCount 15 Counter = Counter + 1 16 ListNode <Counter, ($ + Counter * SIZEOF ListNode)> ; 设置 next 指针要计算偏移量 17 ;ListNode <Counter, ($ + SIZEOF ListNode)> ; 没有偏移量,next 指针指向自身,错误 18 ENDM 19 ListNode <0, 0> ; 尾节点 20 21 .code 22 main PROC 23 mov esi, OFFSET LinkedList 24 25 NextNode: ; 打印链表 26 mov eax, (ListNode PTR [esi]).NextPtr ; 检测是否是尾节点 27 cmp eax, NULL ; next 指针为空,说明已经到尾部了 28 je quit 29 30 mov eax, (ListNode PTR [esi]).NodeData ; 打印节点保存的值 31 call WriteDec 32 call Crlf 33 34 mov esi, (ListNode PTR [esi]).NextPtr ; 移向下一节点 35 jmp NextNode 36 37 quit: 38 call WaitMsg 39 exit 40 main ENDP 41 42 END main