《汇编语言 基于x86处理器》- 读书笔记 - 第3章-汇编语言基础 - 3.10 编程练习
* 1. 整数表达式的计算
参考 3.2 节的程序 AddTwo,编写程序,利用寄存器计算表达式: A = (A+B)-(C-D)。
整数值分配给寄存器 EAX、EBX、ECX 和 EDX。
解:
.386 ; .386伪指令,声明32位程序,能访问32位寄存器和地址。
.model flat,stdcall ; 伪指令 .MODEL 指定存内存模式为 flat 子程序调用规范 stdcall
.stack 4096 ; 声明栈空间4096字节
ExitProcess proto,dwExitCode:dword ; 声明 ExitProcess 函数原型
.code ; 代码段
main proc ; 子程序 main 开始
mov eax,5 ; A eax = 5
mov ebx,4 ; B ebx = 4
mov ecx,2 ; C ecx = 2
mov edx,3 ; D edx = 3
add eax,ebx ; eax = A + B = 9
add ecx,edx ; ecx = C + D = 5
sub eax,ecx ; eax = eax - ecx = 9 - 5 = 4
invoke ExitProcess,0 ; 调用ExitProcess返回0给操作系统
main endp ; 子程序 main 结束
end main ; 程序入口地址指向 main
EAX = 00000004 EBX = 00000004 ECX = 00000005 EDX = 00000003 ESI = 007E1005
EDI = 007E1005 EIP = 007E2042 ESP = 0069FDC4 EBP = 0069FDD0 EFL = 00000202
* 2. 符号整数常量
编写程序,为一周七天定义符号常量。创建一个数组变量,用这些符号常量作为其初始值。
解:
.data
; 定义一周七天的符号常量
MONDAY EQU 1
TUESDAY EQU 2
WEDNESDAY EQU 3
THURSDAY EQU 4
FRIDAY EQU 5
SATURDAY EQU 6
SUNDAY EQU 7
; 创建数组并初始化
daysOfWeek DB MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
** 3. 数据定义
编写程序,对 3.4 节表 3-2 中列出的每一个数据类型进行定义,并将每个变量都初始化为与其类型一致的数值。
解:
.data
byteVar BYTE 10 ; BYTE 8位无符号整数
sbyteVar SBYTE -5 ; SBYTE 8位有符号整数。S代表有符号(signed)
wordVar WORD 1000 ; WORD 16位无符号整数
swordVar SWORD -2000 ; SWORD 16位有符号整数
dwordVar DWORD 100000 ; DWORD 32位无符号整数。D代表双倍(double)
sdwordVar SDWORD -50000 ; SDWORD 32位有符号整数。SD代表有符号双倍
fwordVar FWORD 0FFFFFFFFFFFFh ; FWORD 48位整数
qwordVar QWORD 0FFFFFFFFFFFFFFFFh ; QWORD 64位整数
tbyteVar TBYTE 12345678901234567890h ; TBYTE 80位(10字节)整数
real4Var REAL4 3.14 ; REAL4 32位(4字节)IEEE短浮点数
real8Var REAL8 3.1415926535 ; REAL8 64位(8字节)IEEE长浮点数
real10Var REAL10 1.2345678901234567890 ; REAL10 80位(10字节)IEEE扩展浮点数
* 4. 符号文本常量
编写程序,定义几个字符串文本(引号之间的字符)的符号名称,并将每个符号名称都用于变量定义。
解:
.data
; 定义字符常量
str1cons EQU "hello"
str2cons EQU "jerry"
; 声明变量
str1 db str1cons,0
str2 db str2cons,0
**** 5. AddTwoSum 的列表文件
生成 AddTwoSum 程序的列表文件,为每条指令的机器代码字节编写说明。某些字节值的含义可能需要猜测。
解:
- AddTwoSum.asm
.386 ; .386伪指令,声明32位程序,能访问32位寄存器和地址。
.model flat,stdcall ; 伪指令 .MODEL 指定存内存模式为 flat 子程序调用规范 stdcall
.stack 4096 ; 声明栈空间4096字节
ExitProcess proto,dwExitCode:dword ; 声明 ExitProcess 函数原型
.data ; 伪指令 .data 定义数据段
sum DWORD 0 ; 定义名为 sum 的变量,关键字 DWORD 表示声明的是双字占32位
.code ; 伪指令 .code 定义代码段
main PROC ; 程序入口。伪指令 PROC 用于定义一个子程序
; main 是程序员自定义的子程序(函数)名称
mov eax,5 ; 将整数常量 5 送入eax 寄存器
add eax,6 ; eax = eax + 6
mov sum,eax ; sum = eax
INVOKE ExitProcess,0 ; 调用 Windows 服务(也被称为函数) ExitProcess 停止程序
main ENDP ; ENDP 与 PROC 成对出现,表示子程序结束
END main ; 程序入口地址指向 main
- AddTwoSum.lst
00000000 B8 00000005 mov eax,5 ; B8 表示将 操作数 送入eax
00000005 83 C0 06 add eax,6 ; 83 C0 表示将立即数 与 eax 相加结果放在 eax
00000008 A3 00000000 R mov sum,eax ; A3 表示将 eax 内容传给变量所指向的内存地址,00000000是地址
0000000D 6A 00 * push +000000000h ; 6A 压栈
0000000F E8 00000000 E * call ExitProcess ; E8 调用函数,00000000是地址
*** 6. AddVariables 程序
修改 AddVariables 程序使其使用64位变量。描述汇编器产生的语法错误,并说明为解决这些错误采取的措施。
解:
ExitProcess proto ; 声明 ExitProcess 函数原型
.data
firstval QWORD 0FFFFFFFFFFFFFFF0h ; 第一个变量
secondval QWORD 1h ; 第二个变量
thirdval QWORD 2h ; 第三个变量
sum QWORD 0 ; 第四个变量,用来存放前三个整数相加之和
.code
main PROC
mov rax,firstval ; rax = firstval
add rax,secondval ; rax += secondval
add rax,thirdval ; rax += thirdval
mov sum,rax ; sum = rax
mov ecx,0
call ExitProcess ; 调用ExitProcess返回0给操作系统
main endp ; 子程序 main 结束
end
关于64位项目配置见:配置项目 64位汇编