《汇编语言:基于X86处理器》第10章 复习题和练习

发布于:2025-07-31 ⋅ 阅读:(23) ⋅ 点赞:(0)

本篇记录《汇编语言:基于X86处理器》第10章 复习题和练习的学习笔记.

10.7复习题和练习

10.7.1 简答题

1.STRUCT伪指令的用途是什么?

答:STRUCT伪指令用来定义结构体,与ENDS成对使用,例如:

;10.7.1_1.asm    10.7.1 简答题
;1.STRUCT伪指令的用途是什么?

INCLUDE Irvine32.inc

COORD STRUCT
    X WORD ?
    Y WORD ?
COORD ENDS

.data
position COORD <8,9>

.code 
main PROC
	mov ax, position.X
	mov bx, position.Y
	INVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

2.假设定义了如下结构;

RentalInvoice STRUCT
    invoiceNum 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.inc

RentalInvoice STRUCT
    invoiceNum 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 PROC
	mov ebx, OFFSET str1
	mov rentals.dailyPrice, 16
	mov rentals.daysRented, 32
	mov ax, march.dailyPrice						;ax = 10
	mov esi, OFFSET march
	mov bx,(RentalInvoice PTR[esi+9]).dailyPrice	;bx = 10
	mov bx,(RentalInvoice PTR[esi+9]).daysRented	;bx = 3333h	
	call Crlf
	INVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

3.(真/假):宏不能包含数据定义。

答:假,宏可以包含数据定义,例如

; 定义一个包含数据声明的宏
MyDataMacro MACRO
    message 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 0F0000000h
	DWORD val3
	val1 = val2
	val2 = val3
	val3 = val1+val2
ENDM
;获取数组长度:
FibonacciCount = ($ - FibonacciArray) / 4

.code 
main PROC
	mov ax, val16				;ax = 5678h
	mov bx, [val16+2]			;bx = 1234h
	mov esi, OFFSET FibonacciArray
	;获取第一个斐波那契数
	mov eax, [esi]	;eax = 1	;eax = 1
	mov ebx, [FibonacciArray]	;ebx = 1
	INVOKE 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 STRUCT
    field1 WORD ?
    field2 DWORD 20 DUP(?)
SampleStruct ENDS

.data
temp SampleStruct <>

.code 
main PROC
	mov esi, OFFSET temp
	mov ecx, LENGTHOF temp
	mov (SampleStruct PTR[esi]).field1, 1122h
	INVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

2.编写一条语句检索结构 SYSTEMTIME 的 wHour 字段。

;10.7.2_2.asm    10.7.2 算法基础

INCLUDE Irvine32.inc

SYSTEMTIME STRUCT
    wYear WORD ?
    wMonth WORD ?
	wDayOfWeek WORD ?
	wDay WORD ?
	wHour WORD ?
	wMinute WORD ?
	wSecond WORD ?
	wMilliseconds WORD ?
SYSTEMTIME ENDS

.data
sysTime SYSTEMTIME <>

.code 
main PROC
	INVOKE GetLocalTime, ADDR sysTime
	;检索结构 SYSTEMTIME 的 wHour 字段
	movzx eax, sysTime.wHour
	call WriteDec
	
	INVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

3.使用如下 Triangle 结构,声明一个结构变量并将其三个顶点分别初始化为(0, 0)、(5, 0)和(7, 6 ):

;10.7.2_3.asm    10.7.2 算法基础

INCLUDE Irvine32.inc

COORD STRUCT
	X WORD ?
	Y WORD ?
COORD ENDS

Triangle STRUCT
    Vertex1 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 valTriangle
	movzx eax, (Triangle PTR[esi]).Vertex1.X
	movzx ebx, (Triangle PTR[esi]).Vertex1.Y
	movzx eax, (Triangle PTR[esi]).Vertex2.X
	movzx ebx, (Triangle PTR[esi]).Vertex2.Y
	movzx eax, (Triangle PTR[esi]).Vertex3.X
	movzx ebx, (Triangle PTR[esi]).Vertex3.Y
	INVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

4.声明一个 Triangle 结构的数组,并编写一个循环,用随机坐标对每个三角形的 Vertex1进行初始化,坐标范围为(0…10,0…10)。

;10.7.2_4.asm    10.7.2 算法基础

INCLUDE Irvine32.inc

COORD STRUCT
	X WORD ?
	Y WORD ?
COORD ENDS

Triangle STRUCT
    Vertex1 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 valTriangle
	movzx eax, (Triangle PTR[esi]).Vertex1.X
	movzx ebx, (Triangle PTR[esi]).Vertex1.Y
	mov (COORD PTR[esi]).X, 1122h				;Vertex1
	mov (COORD PTR[esi]).Y, 3344h
	mov (COORD PTR[esi+4]).X, 5566h				;Vertex2
	mov (COORD PTR[esi+4]).Y, 7788h
	;用随机坐标对每个三角形的 Vertex1进行初始化
	mov ecx, ARRAY_SIZE
	mov esi, 0
L1:
	mov eax, 11									;设置随机数范围0~10
	call RandomRange							;产生随机数
	mov triangles[esi].Vertex1.X, ax
	mov eax, 11
	call RandomRange
	mov triangles[esi].Vertex1.Y, ax
	add esi, TYPE Triangle
	loop L1

	INVOKE 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, count
	mov ecx, count
L1:	
	mov al, char
	call  WriteChar
	loop L1
ENDM
;方法2:
mPrintChar2 MACRO char, count
	LOCAL temp
	.data
	temp BYTE count DUP(&char), 0
	.code
	push edx
	mov edx, OFFSET temp
	call WriteString
	pop edx
ENDM

.code 
main PROC
	mPrintChar 'A', 20
	call Crlf
	mPrintChar2 'A', 20
	INVOKE 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 n
	mov eax, n
	call RandomRange
ENDM

.code 
main PROC
	mGenRandom 25
	call WriteDec
	call Crlf
	INVOKE 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 prompt
    LOCAL string
    .data
    string BYTE prompt, 0   ; 定义以null结尾的字符串
    .code
    push edx              ; 保存edx寄存器
    mov edx, OFFSET string
    call WriteString       ; 调用Irvine32库的WriteString过程
    pop edx               ; 恢复edx寄存器
ENDM

mPromptInteger MACRO prompt, value
	mWriteprompt prompt
	call ReadInt            ;输入整型数据
	mov value, eax
ENDM

.code 
main PROC
  mov esi, OFFSET minVal
	mPromptInteger "Enter the minimum value", minVal
	call Crlf
	INVOKE 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, string
	mGotoxy x, y
	mWrite string
ENDM

.code 
main PROC
	mWriteAt 10, 2, "定位光标显示字符串"
	call Crlf
	INVOKE 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 PROC
	mov ebx, OFFSET namePrompt
	mWriteString namePrompt
	call Crlf
	INVOKE 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 PROC
	mov esi, OFFSET customerName
	mReadString customerName
	call Crlf
	INVOKE 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 varName
	push ebx
	push ecx
	push esi
	mov esi, OFFSET varName
	mov ecx, LENGTHOF varName
	mov ebx, TYPE varName
	call DumpMem
	pop esi
	pop ecx
	pop 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 PROC
	mov esi, OFFSET array1
	mDumpMemx array1
	mDumpMemx array2
	mDumpMemx array3
	call Crlf
	INVOKE 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 text
	call Crlf
ENDM

.data

.code 
main PROC
	mWriteInA "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 intVal
	IF (TYPE intVal) EQ 2
		mov ax, intVal
	ELSE
		ECHO Error: Invalid operand size
	ENDIF
ENDM

.code 
main PROC
	mov bx, 1111h
	mCopyWord bx
	mCopyWord ebx		;调用这句会出现错误提示 "Invalid operand size"
	call Crlf
	INVOKE 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 Z
	IF Z LT 0
		ECHO Error: Operand Z is invalid
	ENDIF
ENDM

.code 
main PROC
	mov bx, 1111h
	mCheck 1234
	mCheck -1		;调用这句会出现错误提示 "Operand -1 is invalid"
	call Crlf
	INVOKE ExitProcess, 0
main ENDP 
END main

编译运行:

15.编写一个简短的宏,在宏形参嵌入文本字符串时,演示运算符 &的用法。

;10.7.2_15.asm    10.7.2 算法基础

INCLUDE Irvine32.inc

.data
mCreateString MACRO strVal
	.data
	temp BYTE "Var &strVal", 0
	temp2 BYTE "Var strVal", 0
	.code
	push edx
	mov edx, OFFSET temp
	call WriteString
	call Crlf
	mov edx, OFFSET temp2
	call WriteString
	pop edx
ENDM

.code 
main PROC
	mov ebx, 1111h
	mCreateString ebx
	call Crlf
	INVOKE ExitProcess, 0
main ENDP 
END main

运行调试:

16.假设宏mLocate的定义如下:

mLocate MACRO xVal, yVal
	IF xVal LT 0				;;xval < 0 ?
		EXITM					;;若是,则退出
	ENDIF
	IF yVal LT 0				;;yval < 0 ?
		EXITM					;;若是,则退出
	ENDIF
	mov bx, 0					;;视频页面0
	mov ah, 2					;;定位光标
	mov dh, yVal		
	mov dl, xVal
	int 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.inc

mLocate MACRO xVal, yVal
	IF xVal LT 0				;;xval < 0 ?
		EXITM					;;若是,则退出
	ENDIF
	IF yVal LT 0				;;yval < 0 ?
		EXITM					;;若是,则退出
	ENDIF
	mov bx, 0					;;视频页面0
	mov ah, 2					;;定位光标
	mov dh, yVal		
	mov dl, xVal
	int 10h						;;调用BIOS
ENDM

.data
row BYTE 15
col BYTE 60

.code 
main PROC
	mLocate -1, 20
	mLocate 10, 20
	mLocate col, row
	call Crlf
	INVOKE ExitProcess, 0
main ENDP 
END main

编译:

    mLocate -1, 20
		mLocate 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 relocatable
 mLocate(1): Macro Called From
  chapter10\10.7.2_16.asm(29): Main Line Code
1		ENDIF
chapter10\10.7.2_16.asm(29) : error A2094:operand must be relocatable
 mLocate(4): Macro Called From
  chapter10\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			


网站公告

今日签到

点亮在社区的每一天
去签到