汇编实验

汇编实验

对应basis-3的内容

Irvine32链接库

配置

首先准备好一个配置好masm的项目(正常可以写汇编的),下载好Irvine32(我的在D盘Irvine目录下D:\Irvine)
然后对project右键属性:

  • 链接器附加库目录中加入你安装好的路径(D:\Irvine;)
  • 链接器输入附加依赖项中加入Irvine32.lib(用32位,别忘了分号隔开)
  • 在Microsoft Macro Assemble中的include Paths 加上你的路径(D:\Irvine;)
    配置图1
    配置图2
    配置图3

库测试1:整数IO操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
; 库测试,整数IO操作

include Irvine32.inc

.data
count = 4
BlueTextOnGray = blue + (lightGray * 16)
DefaultColor = lightGray + (black * 16)
arrayD SDWORD 12345678h,1A4B2000h, 3434h, 7AB9h
prompt BYTE "Enter a 32-bit signed integer", 0

.code
main PROC

; 选择浅灰背景蓝色文本

mov eax, BlueTextOnGray
call SetTextColor
call Clrscr ; 清屏

; 用DumpMen显示数组

mov esi, OFFSET arrayD ; 开始位置
mov ebx, TYPE arrayD ; 双字
mov ecx, LENGTHOF arrayD ; 单元数
call DumpMem ; 显示内存

; 请求用户输入一组有符号整数

call Crlf ; 显示一个新空白行
mov ecx, COUNT
L1:
mov edx, OFFSET prompt
call WriteString
call ReadInt ; 输入数据存入EAX
call Crlf

; 用十进制, 十六进制, 二进制显示

call WriteInt ; 显示为有符号十进制
call Crlf
call WriteHex ; 显示为十六进制
call Crlf
call WriteBin ; 显示为二进制数
call Crlf
call Crlf
loop L1

; 返回控制台窗口的默认颜色

call WaitMsg ; "Press any key..."
mov eax, DefaultColor
call SetTextColor
call Clrscr

exit
main ENDP

END main

  • DumpMem在控制台窗口中用16进制显示一段内存,其参数为:ESI存储内存区域首地址,ECX存放单元个数,EBX存放单个单元的大小
  • SetTextColor设置输出文本的前景色和背景色,颜色常量在Irvine32.inc中定义,要获得完整的颜色字节数值,将背景色乘16加上前景色,如下表示蓝色背景输出黄色字符:

yellow + (blue * 16)

  • WriteInt/Bin/Hex 用的都是EAX, 而WriteChar用的是AL
  • WriteString向操作台窗口输出一个以空字节结束的字符串,过程中EDX传递偏移量

库测试2:生成随机数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
include Irvine32.inc
Tab = 9 ; Tab的ASCII码

main PROC
call Randomize ; 初始化随机生成器
call Rand1
call Rand2
call WaitMsg
exit
main ENDP

Rand1 PROC
; 生成10个伪随机数
mov ecx, 10 ; 循环10次

randLoop:
call Random32

call WriteDec ; 无符号十进制形式输出
mov al, Tab ; 水平制表符
call WriteChar ; 输出制表符
loop randLoop

call Crlf
ret
Rand1 ENDP

Rand2 PROC
; 生成-50 -- +49之间的10个伪随机数
mov ecx, 10

randLoop:
mov eax, 100 ; 指定数值范围0-99
call RandomRange ; 生成随机数
sub eax, 50 ; 数值返回-50至49
call WriteInt ; 用有符号十进制的方式输出
mov al, Tab
call WriteChar
loop randLoop

call Crlf
ret
Rand2 ENDP


END main

  • 我们不需要完全记住每个的用法,需要的时候查查就行了
  • Randomize过程对Random32和RandomRange过程的第一个种子进行初始化,种子等于一天中的时间,精度为1/100秒,每当调用Random32和RandomRange的程序运行时,保证生成的序列都不相同

练习题

随机字符串

创建过程生成长度为L的随机字符串,字符全为大写。调用过程时用EAX传递长度为L的值,并传递一个指针指向用于保存该随机字符串的字节数组。编写测试程序调用10次,输出在控制台窗口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
include Irvine32.inc

.data
arrayB BYTE 50 DUP(?)
pointer DWORD OFFSET arrayB
prompt BYTE "Please Enter the length of random string( < 50 ): ", 0

.code
;----------------------------------------------------------
; 参数 EAX = 生成随机字符串长度 pointer 指向数组的指针
; 用于随机生成指定长度的大写字符串
; 无返回值
generateString PROC
mov ecx, eax ; 指定循环次数
call Randomize
mov esi, pointer
L1:
mov eax, 27 ; 范围0--26
call RandomRange
add eax, 41h
mov [esi], al ; 存入内存
inc esi
loop L1
ret
generateString ENDP

randString PROC

mov edx, OFFSET prompt ; 参数为EDX,表示偏移量
call WriteString
call ReadInt ; 读入EAX
call Crlf
push eax ; 保存有效长度
call generateString
pop ecx ; 指定输出循环次数
mov esi, pointer
L2:
mov al, BYTE PTR [esi]
call WriteChar
inc esi
loop L2
ret
randString ENDP

main PROC
call randString
call Crlf
call WaitMsg
exit
main ENDP

END main

  • RandomRange 产生的随机数结过会被保存在EAX中, 范围指定也需要EAX,所以每次loop时要重新给EAX赋值
  • WriteChar 使用al里的数写成字符, 我们使用PTR将高位数赋给低位寄存器(我寻思直接赋EAX也可以)

递归过程

编写程序调用一个递归过程,过程中对计数器自增来计数,向ECX输入一个值来控制递归次数,只使用loop,不使用后续的条件判断语句

  • 想了好久,想不出来
  • 我感觉不行

斐波那契生成器

编写一个过程生成含有N个数的斐波那契数列,并将其保存在一个双字数组中,输入参数为双字数组指针和生成个数的计数器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
include Irvine32.inc
.data
fiboArray DWORD 20 DUP(?)
p DWORD OFFSET fiboArray

.code
;-----------------------------
; 参数 ECX: 生成多少位斐波那契数, p: 存储数组指针
; 生成首两位为1的斐波那契数列
; 无返回
Fibo PROC
mov eax, 1
mov ebx, 1
mov esi, p ; 间接寻址
mov [esi], eax
add esi, TYPE p
mov [esi], ebx
add esi, TYPE p
sub ecx, 2

generateFibo:
mov edx, eax
add edx, ebx
mov eax, ebx
mov ebx, edx
mov [esi], edx
add esi, TYPE p
loop generateFibo

ret
Fibo ENDP


main PROC
mov ecx, 20
call Fibo
mov ecx, LENGTHOF fiboArray
mov ebx, TYPE fiboArray
mov esi, OFFSET fiboArray
call DumpMem
call Crlf
call WaitMsg
exit
main ENDP

END main

Author

Ctwo

Posted on

2019-07-23

Updated on

2020-10-25

Licensed under

Comments