;随机游走模拟
;模拟醉汉随机游走,醉汉的起点在(25,25),并且在周围徘徊
include irvine32.inc
WalkMax =50
StartX =25
StartY =25;定义结构体
DrunkardWalk STRUCT
path COORD WalkMax DUP(<0,0>)
pathsUsed WORD 0
DrunkardWalk ENDS
DisplayPosition PROTO currX:WORD,currY:WORD
.data
aWalk DrunkardWalk <>.code
main PROC
mov esi,OFFSET aWalk
call TakeDrunkenWalk
call WaitMsg
exit
main ENDP
;------------------------------------------
TakeDrunkenWalk PROC
LOCAL currX:WORD,currY:WORD ;自定义临时变量
;向随机方向行走(东西南北)
;接收:ESI为DrunkardWalk的结构指针
;返回:结构初始化为随机数 ;这里没有传参数所以需要保存寄存器
;------------------------------------------
pushad
;用OFFSET运算符获取path-----COORD对象数组的地址,将其复制到EDI
mov edi, esi
add edi, OFFSET DrunkardWalk.path
mov ecx, WalkMax ;循环计数器
mov currX, StartX ;当前X的位置
mov currY, StartY ;当前Y的位置
Again:;把当前位置插入数组
mov ax, currX
mov(COORD PTR [edi]).X,ax
mov ax, currY
mov(COORD PTR [edi]).Y,ax
invoke DisplayPosition,currX,currY
mov eax,4;选择一个方向(0-3)
call RandomRange
.IF eax==0;北
dec currY
.ELSEIF eax==1;南
inc currY
.ELSEIF eax==2;西
dec currX
.ELSE
inc currX ;东
.ENDIF
add edi,TYPE COORD ;指向下一个COORD
loop Again
Finish:mov(DrunkardWalk PTR [esi]).pathsUsed,WalkMax
popad
ret
TakeDrunkenWalk ENDP
;----------------------------------------------
DisplayPosition PROC currX:WORD,currY:WORD
;显示当前X和Y的位置
;----------------------------------------------.data
commaStr BYTE ",",0.code
pushad
movzx eax ,currX ;当前X的位置
call WriteDec
mov edx,OFFSET commaStr
call WriteString
movzx eax ,currY
call WriteDec
call Crlf
popad
ret
DisplayPosition ENDP
END main
06.使用简单的宏
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
;在这里定义宏
printX MACRO
mov al,'X'
call WriteChar
ENDM
.data
.code
main PROC
;在这里调用宏
printX
invoke ExitProcess,0
main ENDP
END main
07.mPutChar
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
mPutChar MACRO char
push eax
mov al,char
call WriteChar
pop eax
ENDM
.data
.code
main PROC
mPutChar 'A';对于一个宏,它仅仅是一段代码并不是函数所以直接把宏的名字卸载某一个位置就等价于函数调用
invoke ExitProcess,0
main ENDP
END main
08.使用宏打印字母表
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
mPutChar MACRO char
push eax
mov al,char
call WriteChar
pop eax
ENDM
.data
.code
main PROC
mov ecx,26
mov al,'A'
L:
mPutChar al
mPutChar ' '
inc al
loop L
invoke ExitProcess,0
main ENDP
END main
09.REQ限定符规定形参
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
mPutChar MACRO char:REQ ;REQ限定符表示参数char在宏调用的时候必须被传递
push eax
mov al,char
call WriteChar
pop eax
ENDM
.data
.code
main PROC
mov ecx,26
mov al,'A'
L:
mPutChar al
mPutChar ' '
inc al
loop L
invoke ExitProcess,0
main ENDP
END main
10.ECHO伪指令
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
mPutChar MACRO char:REQ
;在使用宏汇编的时候,利用echo指令可以不外加双引号的情况下直接输出字符串
ECHO output a character:
push eax ;;提示:char必须包含8个比特
mov al,char
call WriteChar
pop eax
ENDM
.data
.code
main PROC
mPutChar 'X'
invoke ExitProcess,0
main ENDP
END main
11.使用LOCAL伪指令避免宏内部标号重复导致不可以汇编的问题
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
makeString MACRO text
LOCAL string ;使用local做限定的原因是 汇编器不允许有两个标号相同的名称
;使用了local之后string就会变成宏内部的局部变量,在汇编的
;时候,汇编器会将这个字符串转化为另外一个唯一的名字,用于
;区分
.data
string BYTE text,0;使用宏参数初始化宏内部的局部变量
.code
mov edx,offset string
call WriteString
ENDM
.data
.code
main PROC
makeString "hello world";当时用不含有结束标志的字符串作为参数的时候必须要加上双引号做字符串起止位置的标记
invoke ExitProcess,0
main ENDP
END main
12.使用包含代码和数据的宏
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
mWrite MACRO text
local string ;;使用local标号
.data
string BYTE text,0.code
push edx
mov edx,offset string
call WriteString
pop edx
ENDM
.data
.code
main PROC
;调用宏输出字符串
mWrite "Hello World"
invoke ExitProcess,0
main ENDP
END main
13.MacroTest
;测试Macro.inc库
;本程序说明Macros.inc文件中定义的不同宏的使用方式
include irvine32.inc
include macros.inc
NAME_SIZE =50.data
str1 BYTE NAME_SIZE DUP(0)
array DWORD 5DUP(12345678h).code
main PROC
call Clrscr
mGotoxy 20,0
mDumpMem offset array,lengthof array,type array
mGotoxy 10,8
mWrite "Please enter your first name:"
mReadString str1
mGotoxy 10,10
mWrite "Your name is:"
mWriteString str1
call Crlf
exit
main ENDP
END main
14.mDumpMem宏的使用
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
array DWORD 1000h,2000h,3000h,4000h
.code
main PROC
;显示数组
mDumpMem offset array,lengthof array,type array
;按照内存存储顺序显示数组
mDumpMem offset array,sizeof array,type byte
invoke ExitProcess,0
main ENDP
END main
15.使用DumpMem显示堆栈
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
.code
main PROC
mov eax,0AAAAAAAAh
push eax
mov eax,0BBBBBBBBh
push eax
mov eax,0CCCCCCCCh
push eax
mov ebx,1
mov ecx,2
mov esi,3;可以看出 mDumpMem的实现利用到了ebx ecx esi三个寄存器
mDumpMem esp,8,type dword
invoke ExitProcess,0
main ENDP
END main
16.mDump宏的使用
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
diskSize DWORD 12345h
.code
main PROC
mDump diskSize ;没有标记
mDump diskSize,Y ;含有标记 Variable name:diskSize
invoke ExitProcess,0
main ENDP
END main
17.mGotoXY宏的使用
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
buffer BYTE "Hello World!",0.code
main PROC
mGotoxy 50,50
mWriteString offset buffer
invoke ExitProcess,0
main ENDP
END main
18.mReadString宏的使用
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
firstName BYTE 30DUP(0).code
main PROC
mReadString firstName
mov edx,offset firstName
call WriteString
call Crlf
invoke ExitProcess,0
main ENDP
END main
19.mShow宏的使用
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
.code
main PROC
mov ax,4096
mShow ax ;默认选项:HIN 十六进制 又符号十进制 换行
mShow ax,DBN ;设置显示格式 无符号十进制 二进制 换行
invoke ExitProcess,0
main ENDP
END main
20.mShowRegister宏的使用
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
msg1 BYTE "ESP寄存器:",0
msg2 BYTE "EAX寄存器:",0.code
main PROC
mov eax,100h
mov edx,offset msg1
call WriteString
mShowRegister <Stack Pointer>,esp ;显示栈的基址寄存器的值
call Crlf
mov edx,offset msg2
call WriteString
mShowRegister <EAX 寄存器>,eax ;显示EAX寄存器的值
invoke ExitProcess,0
main ENDP
END main
21.mWriteSpace
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
str1 BYTE "My name is:",0
str2 BYTE "Kan Hideo",0.code
main PROC
mov edx,offset str1
call WriteString
mWriteSpace 10
mWriteString str2
call Crlf
call WaitMsg
invoke ExitProcess,0
main ENDP
END main
22.示例程序 封装器
include irvine32.inc
include macros.inc
;过程封装器宏 (Wraps.asm);本程序演示宏作为库过程封装器
;内容 mGotoxy mWrite mWriteString mReadString mDumpMem
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
array DWORD 1,2,3,4,5,6,7,8
firstname BYTE 31DUP(0)
lastname BYTE 31DUP(0).code
main PROC
mGotoxy 0,0
mWrite <"Sample Marco Program",0dh,0ah>;输入用户名
mGotoxy 0,5
mWrite "Please enter your first name:"
mReadString firstname
call Crlf
mWrite "Please enter your last name:"
mReadString lastname
call Crlf
;显示用户名
mWrite "Your name is:"
mWriteString firstname
mWriteSpace
mWriteString lastname
call Crlf
;显示整数数组
mDumpMem offset array,lengthof array,type array
exit
invoke ExitProcess,0
main ENDP
END main
23.改进版mWriteString
; Useful Macros (Macro2.ASM); This program demonstrates several useful macros:
; mGotoxy, mWrite, mWriteLn, mWriteStr, mReadStr,
; and mDumpMem.
INCLUDE Irvine32.inc
;-----------------------------------------------------
mWriteStr MACRO buffer
;; Improved version of mWriteStr that checks for; a blank argument.
;-----------------------------------------------------
IFB <buffer>
ECHO -----------------------------------------
ECHO * Error: parameter missing in mWriteStr
ECHO * (no code generated)
ECHO -----------------------------------------
EXITM
ENDIF
push edx
mov edx,OFFSET buffer
call WriteString
pop edx
ENDM
;-----------------------------------------------------
mWrite MACRO text
;; No changes to this macro.
;-----------------------------------------------------
LOCAL string
.data ;;local data
string BYTE text,0 ;; define the string
.code
push edx
mov edx,OFFSET string
call Writestring
pop edx
ENDM
;-----------------------------------------------------
; This version supplies a default argument.
mWriteLn MACRO text :=<" ">;-----------------------------------------------------
mWrite text
call Crlf
ENDM
;-----------------------------------------------------
mGotoxyConst MACRO X:REQ, Y:REQ
;; Set the cursor position
; This version checks the ranges of X and Y.
; are not used.
;------------------------------------------------------
LOCAL ERRS ;;local constant
ERRS =0
IF (X LT 0) OR (X GT 79)
ECHO Warning: First argument to mGotoxy (X) is out of range.
ECHO ********************************************************
ERRS =1
ENDIF
IF (Y LT 0) OR (Y GT 24)
ECHO Warning: Second argument to mGotoxy (Y) is out of range.
ECHO ********************************************************
ERRS = ERRS + 1
ENDIF
IF ERRS GT 0;;if errors found,
EXITM ;;exit the macro
ENDIF
push edx
mov dh,Y
mov dl,X
call Gotoxy
pop edx
ENDM
;------------------------------------------------------
mReadStr MACRO bufferPtr, maxChars
;; Read from standard input into a buffer.
; EDX cannot be the second argument.
;------------------------------------------------------
IFIDNI <maxChars> , <EDX>
ECHO Warning: EDX cannot be second argument to mReadStr.
ECHO ***************************************************
EXITM
ENDIF
push ecx
push edx
mov edx,bufferPtr
mov ecx,maxChars
call ReadString
pop edx
pop ecx
ENDM
;---------------------------------------------------
ShowRegister MACRO regName
LOCAL tempStr
;; Display a register's name and contents.
;---------------------------------------------------
.data
tempStr BYTE " ®Name=",0
.code
push eax
; Display the register name
push edx
mov edx,offset tempStr
call WriteString
pop edx
; Display the register contents
mov eax,regName
call WriteHex
pop eax
ENDM
.data
message BYTE "Hello there",0
buffer BYTE 50 DUP(?)
BadYValue TEXTEQU <Warning: Y-coordinate is !>24>
ShowWarning MACRO message
mWrite "&message"
ENDM
count =4
sumVal TEXTEQU %5 + count ; sumVal =9
.code
main PROC
mGotoxyConst %5 * 10, %3 + 4;ShowWarning %BadYValue
call Crlf
call Crlf
ShowRegister ECX
mReadStr OFFSET buffer,50 ; ok
mov edx,50
;mReadStr buffer,edx ; generates warning
mGotoxyConst 10,20
mWrite "Line one"
mWriteLn ; missing argument
mWriteLn "Line two"
mWrite <"Line three",0dh,0ah>;mWriteStr ; missing argument
exit
main ENDP
END main
24.含有默认参数的宏
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
mWriteln MACRO text:=<" ">;;设置默认参数
mWrite text
call Crlf
ENDM
.data
.code
main PROC
mWriteln
mWriteln "上面那句话是空串"
invoke ExitProcess,0
main ENDP
END main
25.IFIDN
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
;-----------------------------------------------------------------
mReadBuf MACRO bufferPtr,maxChars
;;将键盘输入读到缓冲区
;接收 缓冲区偏移量 最多可输入字符的数量 第二个参数不能使用edx EDX
;-----------------------------------------------------------------
ifidni <maxChars>,<EDX>;;如果maxChars==edx
echo Warning :Second argument to mReadBuf can't be EDX
echo ***************************************
EXITM
endif
push ecx
push edx
mov edx,offset bufferPtr
mov ecx,maxChars
call ReadString
pop edx
pop ecx
ENDM
.data
buffer BYTE 20DUP(0),0.code
main PROC
;VS不支持显示IFIDN所表示的错误信息
mov eax,15
mReadBuf offset buffer,eax
;输出刚才写入的内容
mov edx,offset buffer
call WriteString
invoke ExitProcess,0
main ENDP
END main
26.矩阵行求和 – version00
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
tableB BYTE 10h,20h,30h,40h,50h;0xF0h
BYTE 60h,70h,80h,90h,0A0h;0280h
BYTE 0B0h,0C0h,0D0h,0E0h,0F0h;0410h
RowSize =5
msg1 BYTE "Enter a row number:",0
msg2 BYTE "The sum is:",0.code
main PROC
mov edx,offset msg1 ;显示提示信息
call WriteString
call ReadInt ;读取行号
mov ebx,offset tableB
mov ecx,RowSize
call calc_row_sum ;计算结果
mov edx,offset msg2 ;显示结果提示信息
call WriteString
call WriteHex ;以十六进制的形式显示结果
invoke ExitProcess,0
main ENDP
calc_row_sum PROC uses ebx ecx esi
;-------------------------------------;接收 ebx 数组偏移量
; eax 行号
; ecx 每行元素字节数
;-------------------------------------
mul ecx ;从开始到指定行的字节数
add ebx,eax ;指定行的偏移量
mov eax,0;累加器清零
mov esi,0;偏移地址寄存器清零
L1:
movzx edx,byte ptr[ebx+esi*type byte];得到一个元素的值 从偏移量处使用间接寻址获得 将数据扩展到32bit
add eax,edx ;累加
inc esi ;指向下一个元素
loop L1
ret
calc_row_sum ENDP
END main
27.矩阵行求和 – version01
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
mCalc_row_sum MACRO ;;宏一定要写在代码段的上面不然编译的时候会出现错误
;-------------------------------------;接收 ebx 数组偏移量
; eax 行号
; ecx 每行元素字节数
;-------------------------------------
push ebx
push ecx
push esi
mul ecx ;从开始到指定行的字节数
add ebx,eax ;指定行的偏移量
mov eax,0;累加器清零
mov esi,0;偏移地址寄存器清零
L1:
movzx edx,byte ptr[ebx+esi];得到一个元素的值 从偏移量处使用间接寻址获得 将数据扩展到32bit
add eax,edx ;累加
inc esi ;指向下一个元素
loop L1
pop esi
pop ecx
pop ebx
ENDM
.data
tableB BYTE 10h,20h,30h,40h,50h;0xF0h
BYTE 60h,70h,80h,90h,0A0h;0280h
BYTE 0B0h,0C0h,0D0h,0E0h,0F0h;0410h
RowSize =5
msg1 BYTE "Enter a row number:",0
msg2 BYTE "The sum is:",0.code
main PROC
mov edx,offset msg1 ;显示提示信息
call WriteString
call ReadInt ;读取行号
mov ebx,offset tableB
mov ecx,RowSize
mov eax,0
mCalc_row_sum ;计算结果
mov edx,offset msg2 ;显示结果提示信息
call WriteString
call WriteHex ;以十六进制的形式显示结果
invoke ExitProcess,0
main ENDP
END main
28.矩阵行求和 – version02
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
mCalc_row_sum MACRO index,arrayOffset,rowSize;;宏一定要写在代码段的上面不然编译的时候会出现错误
push ebx
push ecx
push esi
mov eax,index ;设置需要的寄存器
mov ebx,arrayOffset
mov ecx,rowSize
mul ecx ;从开始到指定行的字节数
add ebx,eax ;指定行的偏移量
mov eax,0;累加器清零
mov esi,0;偏移地址寄存器清零
L1:
movzx edx,byte ptr[ebx+esi];得到一个元素的值 从偏移量处使用间接寻址获得 将数据扩展到32bit
add eax,edx ;累加
inc esi ;指向下一个元素
loop L1
pop esi ;恢复被修改的寄存器
pop ecx
pop ebx
ENDM
.data
tableB BYTE 10h,20h,30h,40h,50h;0xF0h
BYTE 60h,70h,80h,90h,0A0h;0280h
BYTE 0B0h,0C0h,0D0h,0E0h,0F0h;0410h
RowSize =5
msg1 BYTE "Enter a row number:",0
msg2 BYTE "The sum is:",0.code
main PROC
mov edx,offset msg1 ;显示提示信息
call WriteString
call ReadInt ;读取行号
mCalc_row_sum eax,offset tableB,RowSize ;计算结果
mov edx,offset msg2 ;显示结果提示信息
call WriteString
call WriteHex ;以十六进制的形式显示结果
invoke ExitProcess,0
main ENDP
END main
include irvine32.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
mShowRegister MACRO regName
.data
tempStr BYTE " ®Name=",0.code
mov edx,offset tempStr
call WriteString
mov eax,regName
call WriteHex
ENDM
.data
.code
main PROC
mov eax,10
mshowRegister eax
invoke ExitProcess,0
main ENDP
END main
31.展开运算符
include irvine32.inc
include macros.inc
.data
array DWORD 1,2,3,4,5,6,7,8
count =5
sumVal TEXTEQU %(5+ count);%表示计算
SIZEARRAY TEXTEQU %(sizeof array);计算数组所占字节数
val1 DWORD 1234h
val2 DWORD 1000h
val3 DWORD 0.code
main PROC
mGotoxy %(5*10),%(3+4);将光标重新置位
; The following donot evaluate SIZEOF:
ECHO The array contains(SIZEOF array) bytes
ECHO The array contains %(SIZEOF array) bytes
; Using the Expansion(%)operator at the beginning of a line:
TempStr TEXTEQU %(SIZEOF array)% ECHO The array contains TempStr bytes
call WaitMsg
invoke ExitProcess,0
main ENDP
END main
32.显示行号
INCLUDE Irvine32.inc
MUL32 MACRO op1, op2, product
IFIDNI <op2>,<EAX>
LINENUM TEXTEQU %(@LINE)
ECHO --------------------------------------------------% ECHO * Error on line LINENUM: EAX cannot be the second
ECHO * argument when invoking the MUL32 macro.
ECHO --------------------------------------------------
EXITM
ENDIF
push eax
mov eax,op1
mul op2
mov product,eax
pop eax
ENDM
.data
val1 DWORD 1234h
val2 DWORD 1000h
val3 DWORD ?
array DWORD 1,2,3,4,5,6,7,8.code
main PROC
; The following donot evaluate SIZEOF:
ECHO The array contains(SIZEOF array) bytes
ECHO The array contains %(SIZEOF array) bytes
; Using the Expansion(%)operator at the beginning of a line:
TempStr TEXTEQU %(SIZEOF array)% ECHO The array contains TempStr bytes
;MUL32 val1,val2,val3 ; val3 = val1 * val2
mov eax,val2
MUL32 val1,EAX,val3 ; issues a warning
exit
main ENDP
END main
33.文字文本运算符
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
.code
main PROC
mWrite <"Line Three",0dh,0ah>
mWrite "Line Three",0dh,0ah
mWrite <0dh,0ah>
mWrite "Line Three",0dh,0ah ;如果不加上<>那么0dh,0ah会在连接时被忽略
mWrite <"Line Three",0dh,0ah>
invoke ExitProcess,0
main ENDP
END main
34.文字文本运算符
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
.code
main PROC
mWrite <"Hello World!",0dh,0ah>
invoke ExitProcess,0
main ENDP
END main
35.文字字符运算符
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
BadValue TEXTEQU <"Warning :Y-coordinate is !> 24">;;!就相当于C中的转义字符
.code
main PROC
mWrite BadValue
invoke ExitProcess,0
main ENDP
END main
36.警告信息实例
include irvine32.inc
include macros.inc
;本例演示了 替换运算符& 文字文本运算符<> 文字字符运算符! 展开运算符% 的综合利用
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
mShowWarning MACRO message
mWrite " &message";;将message按照参数的值显示
ENDM
.data
BadYValue TEXTEQU <Warning :Y-coordinate is !>24,0dh,0ah>.code
main PROC
mShowWarning % BadYValue
invoke ExitProcess,0
main ENDP
END main
37.宏函数使用实例 – 判断一个常量是否被定义
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
IsDefined MACRO symbol ;;本宏函数用来判断一个变量是否被定义
IFDEF symbol
EXITM <1>;;真
ELSE
EXITM <0>;;假
ENDIF
ENDM
.data
y BYTE "YES",0
n BYTE "NO",0.code
main PROC
IF IsDefined(RealMode)
mov edx,offset y
ELSE
mov edx,offset n
ENDIF
call WriteString
invoke ExitProcess,0
main ENDP
END main
38.HelloNew
include macros.inc
IF IsDefined(RealMode)
include irvine16.inc ;实模式下的头文件
ELSE
include irvine32.inc ;保护模式下的头文件
ENDIF
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
;实模式预处理宏
Startup MACRO
IF IsDefined(RealMode)
mov ax,@data ;获取数据段的起始地址
mov ds,ax
ENDIF
ENDM
.data
.code
main PROC
Startup
mWrite <"This program can be assembled to run!",0dh,0ah>
mWrite <"in both Real mode and Protected mode",0dh,0ah>
invoke ExitProcess,0
main ENDP
END main
39.使用while伪指令生成斐波那契数列
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
val1 =1
val2 =1
DWORD val1 ;前两个值
DWORD val2
val3 = val1 + val2
while val3 LT 0f0000000h
DWORD val3
val1 = val2
val2 = val3
val3 = val1 + val2
ENDM
.code
main PROC
invoke ExitProcess,0
main ENDP
END main
40.REPEAT伪指令
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
.data
WEEKS_PER_YEAR =52
WeatherReading STRUCT
location BYTE 50DUP(0)
REPEAT WEEKS_PER_YEAR
local rainfall,humidity
rainfall DWORD ?
humidity DWORD ?
ENDM
WeatherReading ENDS
.code
main PROC
invoke ExitProcess,0
main ENDP
END main
41.FOR伪指令的使用
include irvine32.inc
include macros.inc
.686p
.model flat,stdcall
.stack 4096
ExitProcess PROTO,dwExitCode:DWORD
COURSE STRUCT
Number BYTE 9DUP(10)
Credits BYTE 100
COURSE ENDS
;semester 含有一个课程数组
SEMESTER STRUCT
Courses COURSE 6DUP(<>)
NumCourses WORD 0
SEMESTER ENDS
.data
for semName ,<Fall2013,Spring2014,Summer2014,Fall2014>
semName SEMESTER <>
endm
.code
main PROC
invoke ExitProcess,0
main ENDP
END main
; Chapter 10 Exercise 1(Ex10_ReadKey.asm)
Comment !
Description: Create a macro that waits for a keystroke and returns
the key that was pressed. The macro should include parameters for the
ASCII code and keyboard scan code.!
INCLUDE Irvine32.inc
mReadkey MACRO ascii, scan
call ReadChar
mov scan,ah
mov ascii,al
ENDM
.data
ascii BYTE ?
scan BYTE ?
str1 BYTE "ASCII code: ",0
str2 BYTE "Scan code: ",0.code
main PROC
; Wait for a key; when the macro returns, the two arguments
; contain the ASCII code and scan code of the key.
mReadkey ascii, scan
; Display the values.
mov edx,OFFSET str1
call WriteString
movzx eax,ascii
call WriteHex
call Crlf
mov edx,OFFSET str2
call WriteString
movzx eax,scan
call WriteHex
call Crlf
exit
main ENDP
END main
10.8.02
; Chapter 10 Exercise 2(Ex02_WriteString.asm)
Comment !
Description: Create a macro that writes a null-terminated
string to the console with a given text color.!
INCLUDE Irvine32.inc
mWritestringAttr MACRO aString,color
push eax
push edx
mov eax,color
call SetTextColor
mov edx,OFFSET aString
call WriteString
pop edx
pop eax
ENDM
.data
myString BYTE "This string is in color",0.code
main PROC
; Blue text on a white background:
mWritestringAttr myString,(white SHL 4)+ blue
call Crlf
; White text on a blue background:
mWritestringAttr myString,(blue SHL 4)+ white
call Crlf
mov eax,lightGray ; normal screen color
call SetTextColor
exit
main ENDP
END main
10.8.03
; Chapter 10 Exercise 3(Ex03_Move32.asm)
Comment !
Description: Write a macro named mMove32 that receives two 32-bit
memory operands. The macro should move the source operand to the
destination operand.!
INCLUDE Irvine32.inc
mMove32 MACRO destination,source
push eax
mov eax,source
mov destination,eax
pop eax
ENDM
.data
var1 DWORD 12345678h
var2 DWORD 0.code
main PROC
mMove32 var2,var1
mov eax,var2
call WriteHex ; display var2
call Crlf
exit
main ENDP
END main
10.8.04
; Chapter 10 Exercise 4(Ex04_Mult32.asm)
Comment !
Description: Create a macro named mMult32 that multiplies two
unsigned32-bit memory operands and produces a 32-bit product.!
INCLUDE Irvine32.inc
mMult32 MACRO op1,op2,product
push eax
push edx
mov eax,op1 ;; EAX = destination
mul op2 ;; EDX:EAX = product
mov product,eax ;; discard high 32 bits
pop edx
pop eax
ENDM
.data
val1 DWORD 1000h
val2 DWORD 200h
prod DWORD ?.code
main PROC
mMult32 val1,val2,prod
; Display results
mov eax,prod
call WriteHex
call Crlf
exit
main ENDP
END main
10.8.05
; Chapter 10 Exercise 5(Ex05_ReadInt.asm)
Comment !
Description: Create a macro named mReadInt that reads a 16-or32-bit
signed integer from standard input and returns the value in an argument.
Use conditional operators to allow the macro to adapt to the size of
the desired result. Write a program that calls the macro, passing it
operands of various sizes. As an extra feature, we display an error
message during assembly if the operand has an unexpected size.!
INCLUDE Irvine32.inc
mReadInt MACRO intVal
push eax
call ReadInt ;; read 32-bit integer
IF(TYPE intVal) EQ 2;; store in 16-bit operand?
mov intVal,ax
ELSEIF(TYPE intVal) EQ 4;; store in 32-bit operand?
mov intVal,eax
ELSE
%OUT ************************************************************************;(The actual value of intVal is substituted into the following message)%OUT Error: Argument intVal passed to mReadInt must be either 16or32 bits.%OUT ************************************************************************
ENDIF
pop eax
ENDM
.data
wVal SWORD ?
dVal SDWORD ?
str1 BYTE "Input a 16-bit signed integer: ",0
str2 BYTE "Input a 32-bit signed integer: ",0.code
main PROC
mReadInt EAX
; Input and display a 16-bit signed integer
mov edx,OFFSET str1
call WriteString
mReadInt wVal
movsx eax,wVal
call WriteInt
call Crlf
; Input and display a 32-bit signed integer
mov edx,OFFSET str2
call WriteString
mReadInt dVal
mov eax,dVal
call WriteInt
call Crlf
exit
main ENDP
END main
10.8.06
; Chapter 10 Exercise 6(Ex06_WriteInt.asm)
Comment !
Description: Create a macro named mWriteInt that writes a signed integer
to standard output by calling the WriteInt library procedure. The argument
passed to the macro can be a byte, word, or doubleword. Use conditional
operators in the macro so it adapts to the size of the argument. Write a
program that demonstrates the macro, passing it arguments of different sizes.
As an extra feature, we display an error message during assembly if the
operand has an unexpected size.!
include irvine32.inc
mWriteInt MACRO intVal
push eax
IF(TYPE intVal) EQ 1;;8-bit operand?
movsx eax,intVal
call WriteInt
ELSEIF(TYPE intVal) EQ 2;;16-bit operand?
movsx eax,intVal
call WriteInt
ELSEIF(TYPE intVal) EQ 4;;32-bit operand?
mov eax,intVal
call WriteInt
ELSE
%OUT ************************************************************************;(The actual value of intVal is substituted into the following message)%OUT Error: Argument intVal passed to mWriteInt must be 8,16, or 32 bits.%OUT ************************************************************************
ENDIF
pop eax
ENDM
.data
bVal BYTE 26
wVal WORD 12345
dVal DWORD 2332424
qVal QWORD 1.code
main PROC
mWriteInt bVal
call Crlf
mWriteInt wVal
call Crlf
mWriteInt dVal
call Crlf
; Test the macro's error message
;mWriteInt qVal
exit
main ENDP
END main
10.8.07
; Professor's Lost Phone(Ex07_ProfessorsLostPhone.asm)
Comment !
Drunkard's walk program. The professor starts at
coordinates 25,25and wanders around the immediate area.
When the professor took the drunkard's walk around campus in Section 10.1.6,
we discovered that he lost his cell phone somewhere along the path.
When you simulate the drunken walk, your program must drop the phone
wherever the professor is standing at some random time interval.
Each time you run the program, the cell phone will be lost at
a different time interval(and location).!
INCLUDE Irvine32.inc
WalkMax =50
StartX =25
StartY =25
DrunkardWalk STRUCT
path COORD WalkMax DUP(<0,0>)
pathsUsed WORD 0
DrunkardWalk ENDS
DisplayPosition PROTO currX:WORD, currY:WORD
.data
aWalk DrunkardWalk <>.code
main PROC
call Randomize
mov esi,OFFSET aWalk
call TakeDrunkenWalk
exit
main ENDP
;-------------------------------------------------------
TakeDrunkenWalk PROC
LOCAL currX:WORD, currY:WORD
;; Take a walk in random directions(north, south, east,; west).; Receives: ESI points to a DrunkardWalk structure
; Returns: the structure is initialized with random values
;-------------------------------------------------------
pushad
;--------------------- Prog Challenge #7------------------------------; Choose a random time interval. Choose a number between 1and WalkMax.;-----------------------------------------------------------------------.data
CellPhoneDropTime DWORD ?
DropPhoneMsg BYTE "The professor has dropped a cel phone!",0dh,0ah,0.code
mov eax,WalkMax
call RandomRange
inc eax ; must start at 1
mov CellPhoneDropTime,eax
;----------------------------------------------------------------------; Use the OFFSET operator to obtain the address of
; path, the array of COORD objects,and copy it to EDI.
mov edi,esi
add edi,OFFSET DrunkardWalk.path
mov ecx,WalkMax ; loop counter
mov currX,StartX ; current X-location
mov currY,StartY ; current Y-location
Again:; Insert current location in array.
mov ax,currX
mov(COORD PTR [edi]).X,ax
mov ax,currY
mov(COORD PTR [edi]).Y,ax
INVOKE DisplayPosition, currX, currY
;--------------------- Prog Challenge #7------------------------; Tell the user if the prof dropped the cel phone during
;this time interval, i.e. when ECX = WalkMax - CellPhoneDropTime
;----------------------------------------------------------------
mov eax,WalkMax
sub eax,CellPhoneDropTime
cmp eax,ecx
jne L2
mov edx,OFFSET DropPhoneMsg
call WriteString
;------------------------------------------------------------------
L2:
mov eax,4; choose a direction(0-3)
call RandomRange
.IF eax ==0; North
dec currY
.ELSEIF eax ==1; South
inc currY
.ELSEIF eax ==2; West
dec currX
.ELSE ;East(EAX =3)
inc currX
.ENDIF
add edi,TYPE COORD ; point to next COORD
loop Again
Finish:mov(DrunkardWalk PTR [esi]).pathsUsed, WalkMax
popad
ret
TakeDrunkenWalk ENDP
;-------------------------------------------------------
DisplayPosition PROC currX:WORD, currY:WORD
; Display the current X and Y positions.;-------------------------------------------------------.data
commaStr BYTE ",",0.code
pushad
movzx eax,currX ; current X position
call WriteDec
mov edx,OFFSET commaStr ;"," string
call WriteString
movzx eax,currY ; current Y position
call WriteDec
call Crlf
popad
ret
DisplayPosition ENDP
END main
10.8.08
; Chapter 10 Exercise 8(Ex08_DrunkardProbabilities.asm)
Comment !
When testing the Drunkard Walk program, you may have noticed
that the professor doesn抰 seem to wander very far from the starting
point. This is no doubt caused by an equal probability of the professor
moving in any direction. Modify the program so there is a 50%
probability the professor will continue to walk in the same
direction as he or she did when taking the previous step. There
should be a 10% probability that he or she will reverse direction
and a 20% probability that he or she will turn either right or
left. Assign a default starting direction before the loop begins
; revised 4/14/2011!
INCLUDE Irvine32.inc
WalkMax =100
StartX =25
StartY =25
North =1
South =3
West =2
East =0
DrunkardWalk STRUCT
path COORD WalkMax DUP(<0,0>)
pathsUsed WORD 0
DrunkardWalk ENDS
GetDirection PROTO
DisplayPosition PROTO currX:WORD, currY:WORD
.data
aWalk DrunkardWalk <>
currDirection DWORD ?.code
main PROC
call Randomize
mov esi,offset aWalk
call TakeDrunkenWalk
exit
main ENDP
;-------------------------------------------------------
TakeDrunkenWalk PROC
LOCAL currX:SWORD, currY:SWORD
;; Take a walk in random directions(north, south, east,; west).; Receives: ESI points to a DrunkardWalk structure
; Returns: the structure is initialized with random values
;-------------------------------------------------------
pushad
; Point EDI to the array of COORD objects.
mov edi,esi
add edi,OFFSET DrunkardWalk.path
mov ecx,WalkMax ; loop counter
mov currX,StartX ; current X-location
mov currY,StartY ; current Y-location
mov currDirection,North ; starting direction
Again:; Insert current location in array.
mov ax,currX
mov(COORD PTR [edi]).X,ax
mov ax,currY
mov(COORD PTR [edi]).Y,ax
INVOKE DisplayPosition, currX, currY
call GetDirection ; returns EAX
;Now that the direction has been chosen, adjust
;the professor's location in the grid..IF eax == North ; North
inc currY
.ELSEIF eax == South ; South
dec currY
.ELSEIF eax == West ; West
dec currX
.ELSE ; East
inc currX
.ENDIF
next:
mov currDirection,eax ; save current direction
add edi,TYPE COORD ; point to next COORD
loop Again
finish:
mov ax,WalkMax ; count the steps taken
sub ax,cx
mov(DrunkardWalk PTR [esi]).pathsUsed, ax
popad
ret
TakeDrunkenWalk ENDP
;----------------------------------------------------------
GetDirection PROC USES edx
; Returns: EAX =new direction
;----------------------------------------------------------
LOCAL modDivisor:DWORD
mov modDivisor,4
mov eax,10
call RandomRange
.IF eax <5; keep same direction(50%)
mov eax,currDirection
.ELSEIF eax <6; reverse direction(10%)
mov eax,currDirection ;(D+2) mod 4
add eax,2.ELSEIF eax <8; turn right(20%)
mov eax,currDirection ;(D+1) mod 4
add eax,1.ELSE ; turn left(20%)
mov eax,currDirection ;(D+4-1) mod 4
add eax,4
sub eax,1.ENDIF
; perform MOD 4 operation on eax
mov edx,0; clear upper dividend
div modDivisor
mov eax,edx ; remainder =new direction
ret ;return EAX
GetDirection ENDP
;-------------------------------------------------------
DisplayPosition PROC currX:WORD, currY:WORD
;; Display the current X and Y positions.; Optional: used for debugging.;-------------------------------------------------------.data
positionMsg BYTE "At ",0
commaStr BYTE ",",0
directionMsg BYTE ", direction = ",0.code
pushad
mov edx,OFFSET positionMsg ;"At "
call WriteString
movzx eax,currX ; current X position
call WriteDec
mov edx,OFFSET commaStr ;"," string
call WriteString
movzx eax,currY ; current Y position
call WriteDec
mov edx,OFFSET directionMsg ;"direction = "
call WriteString
mov eax,currDirection
call WriteDec
call Crlf
popad
ret
DisplayPosition ENDP
END main
10.8.09
; Chapter 10 Exercise 9(Ex09_ShiftingDoublewords.asm)
Comment !
Shifting Multiple Doublewords
Description: Create a macro that shifts an array of 32-bit integers
in either direction, a variable number of bits,usingusing the SHRD
instruction. Write a test program that tests your macro by shifting
the same array in both directions andand displaying the resulting
values. We assume that the array is in little Endian order.!
INCLUDE Irvine32.inc
mShiftDoublewords MACRO arrayName, direction, numberOfBits
; Parameters:; arrayName Name of the array
; direction Right(R)orLeft(L); numberOfBits Number of bit positions to shift
LOCAL L1
mov bl,numberOfBits ; number of bits to shift
mov ecx,(LENGTHOF arrayName)-1
mov esi,OFFSET arrayName
IFIDNI <direction>,<'L'>; Left shift?
L1: push ecx ; save loop counter
mov eax,[esi + TYPE DWORD]; get next lowest doubleword
mov cl,bl ; shift count
shld [esi],eax,cl ; shift EAX into low bits of [esi]
add esi,TYPE DWORD ; point to next doubleword pair
pop ecx ; restore loop counter
loop L1
shl DWORD PTR [esi],numberOfBits ; shift last doubleword
ELSE ; Must be a shift to the right
; point to the last array element
add esi,(SIZEOF arrayName)-(TYPE DWORD)
L1: push ecx ; save loop counter
mov eax,[esi - TYPE DWORD]; get next highest doubleword
mov cl,bl ; shift count
shrd [esi],eax,cl ; shift EAX into high bits of [esi]
sub esi,TYPE DWORD ; point to previous doubleword pair
pop ecx ; restore loop counter
loop L1
shr DWORD PTR [esi],numberOfBits ; shift last doubleword
ENDIF
ENDM
;----------------------------------------------------------------.data
array DWORD 008B2165h,8C943A29h,6DFA4B86h,91F76C04h,82AF9857h
.code
main PROC
call Display ; original values
mShiftDoublewords array,'L',4; shift left 4 bits
call Display
; Shift it back to its starting value
mShiftDoublewords array,'R',4
call Display ; same as original values
mShiftDoublewords array,'L',7; shift left 7 bits
call Display
mShiftDoublewords array,'R',7
call Display ; same as original values
exit
main ENDP
; Display the array
Display PROC
mov esi,OFFSET array
mov ecx,LENGTHOF array
mov ebx,TYPE array
call DumpMem
ret
Display ENDP
END main
10.8.10
; Chapter 10 Exercise 9(Ex10_ThreeOperandInstructions.asm)
Comment !
Three-Operand Instructions
Some computer instruction sets permit arithmetic instructions with three
operands. Such operations sometimes appear in simple virtual assemblers
used to introduce students to the conceptof assembly language orusing
intermediate language in compilers. In the following macros, EAX is reserved
for macro operations and is not preserved. Other registers modified by the
macros are preserved. All parameters are signed memory doublewords.
Operations:
a. add3 destination, source1, source2
b. sub3 destination, source1, source2 ; destination = source1 - source2
c. mul3 destination, source1, source2
d. div3 destination, source1, source2 ; destination = source1 / source2
!
INCLUDE Irvine32.inc
add3 MACRO dest, source1, source2
mov eax,source1
add eax,source2
mov dest,eax
ENDM
sub3 MACRO dest, source1, source2
mov eax,source1
sub eax,source2
mov dest,eax
ENDM
mul3 MACRO dest, source1, source2
;signed multiplication
mov eax,source1
imul source2
mov dest,eax
ENDM
div3 MACRO dest, source1, source2
;signed division
mov eax,source1
cdq
idiv source2
mov dest,eax
ENDM
.data
w SDWORD 1
x SDWORD 2
y SDWORD 3
z SDWORD -4
temp SDWORD ?
temp2 SDWORD ?.code
main PROC
; y = Z / x
div3 y, z, x
; x =(w + y)* z
add3 temp, w, y
mul3 x, temp, z
; y =(z / x)+(y * x)
mul3 temp, y, x
div3 y, z, x
add3 y, y, temp
; w =(w + x + y)*(z - x)
add3 temp, x, y
add3 temp, w, temp
sub3 temp2, z, x
mul3 w, temp, temp2
exit
main ENDP
END main