《汇编语言:基于X86处理器》第10章 复习题和练习
本篇记录《汇编语言:基于X86处理器》第10章 复习题和练习的学习笔记.
10.7复习题和练习
10.7.1 简答题
1.STRUCT伪指令的用途是什么?
答:STRUCT伪指令用来定义结构体,与ENDS成对使用,例如:
;10.7.1_1.asm 10.7.1 简答题
;1.STRUCT伪指令的用途是什么?INCLUDE Irvine32.incCOORD STRUCTX WORD ?Y WORD ?
COORD ENDS.data
position COORD <8,9>.code
main PROCmov ax, position.Xmov bx, position.YINVOKE ExitProcess, 0
main ENDP
END main
运行调试:
2.假设定义了如下结构;
RentalInvoice STRUCTinvoiceNum BYTE 5 DUP(' ')dailyPrice WORD ?daysRented WORD ?
RentalInvoice ENDS
则下列声明是否有效:
a. rentals RentalInvoice <>
b. RentalInvoice rentals <> ;无效
c. march RentalInvoice <'12345', 10, 0>
d. RentalInvoice <, 10, 3333h>
e. current RentalInvoice <, 15, 0, 0> ;无效
答:a.有效, b.无效, c.有效, d.有效, e.无效
完整代码测试笔记
;10.7.1_2.asm 10.7.1 简答题INCLUDE Irvine32.incRentalInvoice STRUCTinvoiceNum BYTE 5 DUP(' ')dailyPrice WORD ?daysRented WORD ?
RentalInvoice ENDS.data
str1 BYTE "Please enter your name: ", 0
rentals RentalInvoice <>
;RentalInvoice rentals <> ;无效
march RentalInvoice <'12345', 10, 0>
RentalInvoice <, 10, 3333h>
;current RentalInvoice <, 15, 0, 0> ;无效.code
main PROCmov ebx, OFFSET str1mov rentals.dailyPrice, 16mov rentals.daysRented, 32mov ax, march.dailyPrice ;ax = 10mov esi, OFFSET marchmov bx,(RentalInvoice PTR[esi+9]).dailyPrice ;bx = 10mov bx,(RentalInvoice PTR[esi+9]).daysRented ;bx = 3333h call CrlfINVOKE ExitProcess, 0
main ENDP
END main
运行调试:
3.(真/假):宏不能包含数据定义。
答:假,宏可以包含数据定义,例如
; 定义一个包含数据声明的宏
MyDataMacro MACROmessage BYTE 'Hello, World!', 0
ENDM
4.LOCAL伪指令的用途是什么?
答:LABEL伪指令可以插入一个标号,并定义它的大小属性,但是不为这个标号分配存储空间,在宏扩展时找偏移地址很有用。示例如下:
;10.7.1_4.asm 10.7.1 简答题
;4.LOCAL伪指令的用途是什么?
;答:LABEL伪指令可以插入一个标号,并定义它的大小属性,但是不为这个标号分配存储空间
;在宏扩展时找偏移地址很有用。INCLUDE Irvine32.inc.data
val16 LABEL WORD
val32 DWORD 12345678h
;定义一个标签以便引用这个数组
FibonacciArray LABEL DWORD
val1 = 1
val2 = 1
DWORD val1 ;前两个值
DWORD val2
val3 = val1 + val2
WHILE val3 LT 0F0000000hDWORD val3val1 = val2val2 = val3val3 = val1+val2
ENDM
;获取数组长度:
FibonacciCount = ($ - FibonacciArray) / 4.code
main PROCmov ax, val16 ;ax = 5678hmov bx, [val16+2] ;bx = 1234hmov esi, OFFSET FibonacciArray;获取第一个斐波那契数mov eax, [esi] ;eax = 1 ;eax = 1mov ebx, [FibonacciArray] ;ebx = 1INVOKE ExitProcess, 0
main ENDP
END main
运行调试:
5.哪条伪指令能在控制台上显示汇编时消息?
答:ECHO
指令
6.哪条伪指令标志条件语句块的结束?
答:ENDIF
7.列出所有能在常量布尔表达式中使用的关系运算符。
答:汇编器允许在包含IF和其他条件伪指令的常量布尔表达式中使用下列关系运算符:
LT 小于
GT 大于
EQ 等于
NE 不等
LE 小于等于
GE 大于等于
8.宏定义中的&运算符有什么作用?
答:&是替换运算符,作用是解析对宏参数名的有歧义的引用。
9.宏定义中的!运算符有什么作用?
答:!是构造文字字符(literal-character)运算符。作用与文字文本运算符的几乎完全一样:强制预处理程序把预先定义的运算符当作普通的字符。
10.宏定义中的%运算符有什么作用?
答:%是展开运算符,作用是展开文本宏并将常表达式转换为文本形式。
10.7.2 算法基础
1.创建包含两个字段的结构 SampleStruct: field1为一个16位WORD,field2为含有20个32位DWORD 的数组。不需定义字段初始值。
;10.7.2_1.asm 10.7.2 算法基础INCLUDE Irvine32.inc
;创建包含两个字段的结构
SampleStruct STRUCTfield1 WORD ?field2 DWORD 20 DUP(?)
SampleStruct ENDS.data
temp SampleStruct <>.code
main PROCmov esi, OFFSET tempmov ecx, LENGTHOF tempmov (SampleStruct PTR[esi]).field1, 1122hINVOKE ExitProcess, 0
main ENDP
END main
运行调试:
2.编写一条语句检索结构 SYSTEMTIME 的 wHour 字段。
;10.7.2_2.asm 10.7.2 算法基础INCLUDE Irvine32.incSYSTEMTIME STRUCTwYear WORD ?wMonth WORD ?wDayOfWeek WORD ?wDay WORD ?wHour WORD ?wMinute WORD ?wSecond WORD ?wMilliseconds WORD ?
SYSTEMTIME ENDS.data
sysTime SYSTEMTIME <>.code
main PROCINVOKE GetLocalTime, ADDR sysTime;检索结构 SYSTEMTIME 的 wHour 字段movzx eax, sysTime.wHourcall WriteDecINVOKE ExitProcess, 0
main ENDP
END main
运行调试:
3.使用如下 Triangle 结构,声明一个结构变量并将其三个顶点分别初始化为(0, 0)、(5, 0)和(7, 6 ):
;10.7.2_3.asm 10.7.2 算法基础INCLUDE Irvine32.incCOORD STRUCTX WORD ?Y WORD ?
COORD ENDSTriangle STRUCTVertex1 COORD <>Vertex2 COORD <>Vertex3 COORD <>
Triangle ENDS.data
;声明一个结构变量并将其三个顶点分别初始化为(0, 0)、(5, 0)和(7, 6 ):
valTriangle Triangle <<0,0>, <5,0>, <7,6>>.code
main PROC;使用变量mov esi, OFFSET valTrianglemovzx eax, (Triangle PTR[esi]).Vertex1.Xmovzx ebx, (Triangle PTR[esi]).Vertex1.Ymovzx eax, (Triangle PTR[esi]).Vertex2.Xmovzx ebx, (Triangle PTR[esi]).Vertex2.Ymovzx eax, (Triangle PTR[esi]).Vertex3.Xmovzx ebx, (Triangle PTR[esi]).Vertex3.YINVOKE ExitProcess, 0
main ENDP
END main
运行调试:
4.声明一个 Triangle 结构的数组,并编写一个循环,用随机坐标对每个三角形的 Vertex1进行初始化,坐标范围为(0…10,0…10)。
;10.7.2_4.asm 10.7.2 算法基础INCLUDE Irvine32.incCOORD STRUCTX WORD ?Y WORD ?
COORD ENDSTriangle STRUCTVertex1 COORD <>Vertex2 COORD <>Vertex3 COORD <>
Triangle ENDS.data
;声明一个结构变量并将其三个顶点分别初始化为(0, 0)、(5, 0)和(7, 6 ):
valTriangle Triangle <<0,0>, <5,0>, <7,6>>
ARRAY_SIZE = 5
triangles Triangle ARRAY_SIZE DUP(<>).code
main PROC;使用变量mov esi, OFFSET valTrianglemovzx eax, (Triangle PTR[esi]).Vertex1.Xmovzx ebx, (Triangle PTR[esi]).Vertex1.Ymov (COORD PTR[esi]).X, 1122h ;Vertex1mov (COORD PTR[esi]).Y, 3344hmov (COORD PTR[esi+4]).X, 5566h ;Vertex2mov (COORD PTR[esi+4]).Y, 7788h;用随机坐标对每个三角形的 Vertex1进行初始化mov ecx, ARRAY_SIZEmov esi, 0
L1:mov eax, 11 ;设置随机数范围0~10call RandomRange ;产生随机数mov triangles[esi].Vertex1.X, axmov eax, 11call RandomRangemov triangles[esi].Vertex1.Y, axadd esi, TYPE Triangleloop L1INVOKE ExitProcess, 0
main ENDP
END main
运行调试:
5.编写宏 mPrintChar,在屏幕上显示一个字符。宏应有两个参数:第一个指定显示的字符,第二个指定字符重复的次数。示例调用如下:
mPrintChar ‘X', 20
;10.7.2_5.asm 10.7.2 算法基础INCLUDE Irvine32.inc.data
;定义mPrintChar宏,两个参数
mPrintChar MACRO char, countmov ecx, count
L1: mov al, charcall WriteCharloop L1
ENDM
;方法2:
mPrintChar2 MACRO char, countLOCAL temp.datatemp BYTE count DUP(&char), 0.codepush edxmov edx, OFFSET tempcall WriteStringpop edx
ENDM.code
main PROCmPrintChar 'A', 20call CrlfmPrintChar2 'A', 20INVOKE ExitProcess, 0
main ENDP
END main
运行调试:
6.编写宏mGenRandom,在0到n-1之间随机生成一个整数,n为宏的唯一参数。
;10.7.2_6.asm 10.7.2 算法基础INCLUDE Irvine32.inc.data
mGenRandom MACRO nmov eax, ncall RandomRange
ENDM.code
main PROCmGenRandom 25call WriteDeccall CrlfINVOKE ExitProcess, 0
main ENDP
END main
运行调试:
7.编写宏mPromptInteger,显示提示并接收用户输人的一个整数。向该宏传递一个字符串文本和一个双字变量名。示例调用如下:
.data
minVal DWORD ?
.code
mPromptInteger "Enter the minimum value", minVal
完整的实现如下:
;10.7.2_7.asm 10.7.2 算法基础INCLUDE Irvine32.inc.data
minVal DWORD ?
; 定义mWriteprompt宏 LOCAL对标号的自引用——324页
mWriteprompt MACRO promptLOCAL string.datastring BYTE prompt, 0 ; 定义以null结尾的字符串.codepush edx ; 保存edx寄存器mov edx, OFFSET stringcall WriteString ; 调用Irvine32库的WriteString过程pop edx ; 恢复edx寄存器
ENDMmPromptInteger MACRO prompt, valuemWriteprompt promptcall ReadInt ;输入整型数据mov value, eax
ENDM.code
main PROCmov esi, OFFSET minValmPromptInteger "Enter the minimum value", minValcall CrlfINVOKE ExitProcess, 0
main ENDP
END main
运行调试:
8.编写宏mWriteAt,定位光标并在控制台窗口显示一个字符串文本。建议:调用本书宏库中的mGotoxy和mWrite。
;10.7.2_8.asm 10.7.2 算法基础INCLUDE Irvine32.inc
INCLUDE Macros.inc.data
;宏实现
mWriteAt MACRO x, y, stringmGotoxy x, ymWrite string
ENDM.code
main PROCmWriteAt 10, 2, "定位光标显示字符串"call CrlfINVOKE ExitProcess, 0
main ENDP
END main
运行调试:
9.用如下语句调用10.2.5 节的宏mWriteString,请写出其生成的展开代码;
mWriteStr namePrompt
;10.7.2_9.asm 10.7.2 算法基础INCLUDE Irvine32.inc
INCLUDE Macros.inc.data
namePrompt BYTE "Please enter your name: ", 0.code
main PROCmov ebx, OFFSET namePromptmWriteString namePromptcall CrlfINVOKE ExitProcess, 0
main ENDP
END main;mWriteStr namePrompt ;扩展为以下:
;1 push edx
;1 mov edx, OFFSET namePrompt
;1 call WriteString
;1 pop edx
运行调试:
10.用如下语句调用10.2.5节的宏mReadString,请写出其生成的展开代码:
mReadstr customerName
;10.7.2_10.asm 10.7.2 算法基础INCLUDE Irvine32.inc
INCLUDE Macros.inc.data
customerName BYTE 30 DUP(?).code
main PROCmov esi, OFFSET customerNamemReadString customerNamecall CrlfINVOKE ExitProcess, 0
main ENDP
END main
;mReadstr customerName ;扩展为以下:
;1 push ecx
;1 push edx
;1 mov edx, OFFSET customerName
;1 mov edx, (SIZEOF customerName) - 1
;1 call ReadString
;1 pop edx
;1 pop ecx
运行调试:
11.编写宏mDumpMemx,接收一个参数和一个变量名。该宏必须调用本书链接库的宏mDumpMem,并向其传递变量的偏移量,存储对象的数量和对象的大小。演示对宏mDumpMemx的调用。
;10.7.2_11.asm 10.7.2 算法基础INCLUDE Irvine32.inc;以十六进制显示变量,使用变量的属性确定单位数和单位大小。
mDumpMemx MACRO varNamepush ebxpush ecxpush esimov esi, OFFSET varNamemov ecx, LENGTHOF varNamemov ebx, TYPE varNamecall DumpMempop esipop ecxpop ebx
ENDM.data
array1 BYTE 10h, 20h, 30h, 40h, 50h
array2 WORD 1011h, 2022h, 3033h, 4044h, 5055h
array3 DWORD 11111111h, 22222222h, 33333333h, 44444444h, 55555555h.code
main PROCmov esi, OFFSET array1mDumpMemx array1mDumpMemx array2mDumpMemx array3call CrlfINVOKE ExitProcess, 0
main ENDP
END main
运行结果:
12.举例说明有默认实参初始值的宏形参。
;10.7.2_12.asm 10.7.2 算法基础INCLUDE Irvine32.inc
INCLUDE Macros.inc;使用默认参数作初始值
mWriteInA MACRO text:=<" ">mWrite textcall Crlf
ENDM.data.code
main PROCmWriteInA "hello"mWriteInA " "mWriteInA mWriteInA "world"INVOKE ExitProcess, 0
main ENDP
END main
运行调试:
13.编写一个简短的例子来使用IF、ELSE 和ENDIF 伪指令。
;10.7.2_13.asm 10.7.2 算法基础INCLUDE Irvine32.inc.data
mCopyWord MACRO intValIF (TYPE intVal) EQ 2mov ax, intValELSEECHO Error: Invalid operand sizeENDIF
ENDM.code
main PROCmov bx, 1111hmCopyWord bxmCopyWord ebx ;调用这句会出现错误提示 "Invalid operand size"call CrlfINVOKE ExitProcess, 0
main ENDP
END main
运行调试:
14.编写一条语句,用IF 伪指令检查常量宏参数Z的值;如果Z小于 0,则在汇编时显示一条消息说明Z是无效的。
;10.7.2_14.asm 10.7.2 算法基础INCLUDE Irvine32.inc.data
mCheck MACRO ZIF Z LT 0ECHO Error: Operand Z is invalidENDIF
ENDM.code
main PROCmov bx, 1111hmCheck 1234mCheck -1 ;调用这句会出现错误提示 "Operand -1 is invalid"call CrlfINVOKE ExitProcess, 0
main ENDP
END main
编译运行:
15.编写一个简短的宏,在宏形参嵌入文本字符串时,演示运算符 &的用法。
;10.7.2_15.asm 10.7.2 算法基础INCLUDE Irvine32.inc.data
mCreateString MACRO strVal.datatemp BYTE "Var &strVal", 0temp2 BYTE "Var strVal", 0.codepush edxmov edx, OFFSET tempcall WriteStringcall Crlfmov edx, OFFSET temp2call WriteStringpop edx
ENDM.code
main PROCmov ebx, 1111hmCreateString ebxcall CrlfINVOKE ExitProcess, 0
main ENDP
END main
运行调试:
16.假设宏mLocate的定义如下:
mLocate MACRO xVal, yValIF xVal LT 0 ;;xval < 0 ?EXITM ;;若是,则退出ENDIFIF yVal LT 0 ;;yval < 0 ?EXITM ;;若是,则退出ENDIFmov bx, 0 ;;视频页面0mov ah, 2 ;;定位光标mov dh, yVal mov dl, xValint 10h ;;调用BIOS
ENDM
若用下述语句调用该宏,请写出预处理程序在进行宏展开时生成的源代码:
.data
row BYTE 15
col BYTE 60
.code
mLocate -1, 20
mLocate 10, 20
mLocate col, row
完整代码测试笔记
;10.7.2_16.asm 10.7.2 算法基础
;16.假设宏mLocate的定义如下:INCLUDE Irvine32.incmLocate MACRO xVal, yValIF xVal LT 0 ;;xval < 0 ?EXITM ;;若是,则退出ENDIFIF yVal LT 0 ;;yval < 0 ?EXITM ;;若是,则退出ENDIFmov bx, 0 ;;视频页面0mov ah, 2 ;;定位光标mov dh, yVal mov dl, xValint 10h ;;调用BIOS
ENDM.data
row BYTE 15
col BYTE 60.code
main PROCmLocate -1, 20mLocate 10, 20mLocate col, rowcall CrlfINVOKE ExitProcess, 0
main ENDP
END main
编译:
mLocate -1, 20mLocate 10, 20
1 mov bx, 0
1 mov ah, 2
1 mov dh, 20
1 mov dl, 10
1 int 10h mLocate col, row
1 IF col LT 0
chapter10\10.7.2_16.asm(29) : error A2094:operand must be relocatablemLocate(1): Macro Called Fromchapter10\10.7.2_16.asm(29): Main Line Code
1 ENDIF
chapter10\10.7.2_16.asm(29) : error A2094:operand must be relocatablemLocate(4): Macro Called Fromchapter10\10.7.2_16.asm(29): Main Line Code
1 mov bx, 0
1 mov ah, 2
1 mov dh, row
1 mov dl, col
1 int 10h