《汇编语言 基于x86处理器》前五章的小程序
▶ 书中前五章的几个小程序,基本的运算操作,使用了作者的库 Irvine32 和 Irvine64(一开始以为作者网站过期了,各网站上找到的文件大小都不一样,最后发现是要搭梯子 Orz,顺利下载)。注意编译前将相关的库文件放到 “项目属性 → 链接器 → 输入 → 附加依赖项” 中。
● 代码,整数数组求和
.
.model flat,stdcall
.stack ExitProcess PROTO, dwExitCode: dword .data
array DWORD 10000h, 20000h, 30000h, 40000h, .code
main PROC
mov edi, OFFSET array ; 变址寄存器获得 array 首元素地址
mov ecx, LENGTH array ; 循环计数器获得 array 元素个数
mov eax, L1:
add eax, [edi] ; 将 array 每个元素加到 eax 中
add edi, TYPE array ; 递增变址寄存器
loop L1 ; 循环直到 ecx 减为 0 INVOKE ExitProcess,
main ENDP END main
● 代码,整数数组求和,64位版本
ExitProcess PROTO .data
array QWORD 1000000000000h, 2000000000000h, 3000000000000h, 4000000000000h, .code
main PROC
mov rdi, OFFSET array ; 用到的寄存器都改成 64 位的版本
mov rcx, LENGTH array
mov rax, L1:
add rax, [rdi]
add rdi, TYPE array
loop L1 mov ecx, ; 还是使用 ecx 作为返回值
call ExitProcess
main ENDP END
● 代码,复制字符串
.
.model flat,stdcall
.stack ExitProcess PROTO, dwExitCode: dword .data
source BYTE "Something to be copied 2333.",
target BYTE SIZEOF source DUP() .code
main PROC
mov esi, OFFSET source
mov ecx, LENGTH source L1:
mov al, source[esi]
mov target[esi], al
inc esi
loop L1 INVOKE ExitProcess,
main ENDP END main
● 涨姿势,代码中间有一个块段注释没有封口(直到代码结尾都是注释),报错信息是 END directive required at end of file。
● 代码,翻转字符串
.
.model flat,stdcall
.stack ExitProcess PROTO, dwExitCode: dword .data
source BYTE "Something to be copied 2333.",
nameSize = ($ - source) - ; 使用常量来存储字符串的长度 .code
main PROC
mov esi,
mov ecx, LENGTH source L1:
movzx eax, source[esi] ; 获取字符,压栈,递增指针,循环
push eax
inc esi
loop L1 mov esi, ; 相同的赋值
mov ecx, LENGTH source
L2:
pop eax ; 吐栈,放入字符,递增指针,循环
mov source[esi], eax
inc esi
loop L2 INVOKE ExitProcess,
main ENDP END main
● 代码,使用子过程计算数组的和
.
.model flat,stdcall
.stack
ExitProcess proto,dwExitCode:dword .data
array dword 10000h,20000h,30000h,40000h,50000h
sum dword ? .code
sumArray proc uses esi ecx ; 定义子过程,uses 在栈中备份 esi 和 ecx,并在 ret 前还原
;push esi ; 用栈备份用到的寄存器,与 uses 作用等效
;push ecx
mov eax, L1: ; 使用循环将和放入 eax 中
add eax, [esi]
add esi, type dword
loop L1 ;pop ecx ; 从栈中还原寄存器的状态
;pop esi
ret ; 从子过程中返回
sumArray endp main proc
mov esi, offset array
mov ecx, length array call sumArray
mov sum, eax invoke ExitProcess,
main endp end main
● 代码,库 Irvine32 测试 1,简单的输入输出。记得在 “属性,配置属性,链接器,输入” 中加上 Irvine32.lib,并在工作目录下添加 Irvine32.inc,Irvine32.lib,SmallWin.inc,VirtualKeys.inc。
INCLUDE Irvine32.inc ; 包含库
.data
array DWORD 1000h,2000h,3000h
message BYTE "Enter a 32-bit signed integer: ",
dwordVal DWORD ? .code
main PROC
mov eax, yellow + (blue * )
call SetTextColor
call Clrscr ; 清屏为背景色
call DumpRegs ; 显示当亲寄存器状态 mov esi, OFFSET array ; 三个寄存器分别存储数组的信息
mov ecx, LENGTHOF array
mov ebx, TYPE array
call DumpMem ; 调用库函数,输出数组所有元素
call Crlf ; 换行 mov edx, OFFSET message
call WriteString ; 输出字符串
call ReadInt ; 输入整数
mov dwordVal, eax ; 输入的整数存储到 eax 中
call Crlf
call WriteInt ; 用十进制、十六进制、二进制输出 eax
call Crlf
call WriteHex
call Crlf
call WriteBin
call Crlf
call WaitMsg ; 显示 "Press any key to cintinue" 并等待 mov eax, lightGray + (black * ) ; 恢复终端颜色
call SetTextColor
call Clrscr
call WaitMsg exit
main ENDP
END main
● 输出结果
; 清屏为蓝色 EAX=0000001E EBX= ECX= EDX=
ESI= EDI= EBP=0075FE18 ESP=0075FE08
EIP= EFL= CF= SF= ZF= OF= AF= PF= Dump of offset
------------------------------- Enter a -bit signed integer: ; 输入 + Press any key to continue... ; 清屏恢复黑色 Press any key to continue...
● 代码,库 Irvine32 测试 2,随机数
INCLUDE Irvine32.inc TAB = ; ASCII code for Tab .code
main PROC
call Randomize ; 随机数种子
call Rand1 ; 无符号随机数
call Rand2 ; 有符号随机数
call WaitMsg
exit
main ENDP Rand1 PROC
mov ecx,
L1:
call Random32 ; 生成随机整数用于输出
call WriteDec
mov al, TAB ; 给一个水平制表符用于输出
call WriteChar
loop L1 call Crlf
ret
Rand1 ENDP Rand2 PROC
mov ecx, L1:
mov eax,
call RandomRange ; 生成给定范围内的随机数
sub eax,
call WriteInt
mov al,TAB
call WriteChar
loop L1 call Crlf
ret
Rand2 ENDP END main
● 代码,库 Irvine32 测试 3,计时器
INCLUDE Irvine32.inc .data
OUTER_LOOP_COUNT =
startTime DWORD ?
msg1 BYTE "Start", 0dh, 0ah, ; 等价于 "Start\r\n\0"
msg2 BYTE "End", 0dh, 0ah, "Time(ms): ", .code
main PROC
mov edx, OFFSET msg1
call WriteString call GetMSeconds ; 计时器1
mov startTime, eax mov ecx, OUTER_LOOP_COUNT ; 外层循环
L1:
call innerLoop
loop L1 call GetMSeconds ; 计时器2
sub eax, startTime ; 直接在 eax 中计算耗时 mov edx, OFFSET msg2 ; 显示
call WriteString
call WriteDec
call Crlf call WaitMsg
exit
main ENDP innerLoop PROC uses ecx
mov ecx, 0FFFFFFFh ; 内层循环
L1:
mul eax ; 无符号乘法
mul eax
mul eax
loop L1 ret
innerLoop ENDP END main
● 代码,库 Irvine32 测试 4,对话框
INCLUDE Irvine32.inc .data
caption db "Title",
HelloMsg BYTE "This is a pop-up message box.", 0dh, 0ah, .code
main PROC
mov ebx, OFFSET caption ; 标题,可以为 0
mov edx, OFFSET HelloMsg ; 对话框内容
call MsgBox mov ebx, OFFSET caption
mov edx, OFFSET HelloMsg
call MsgBoxAsk ; 返回值在 eax 中,6(yes) 或 7(no) call WaitMsg
exit
main ENDP END main
● 代码,库 Irvine32 测试 5,用不同编码输出编号为 1~255 的字符
INCLUDE Irvine32.inc SetConsoleOutputCP PROTO, pageNum:DWORD .data
divider BYTE " - ",
codepage DWORD
; 1250 - Central Europe
; 1251 - Cyrillic
; 1252 - Latin I
; 1253 - Greek
; 1254 - Turkish
; 1255 - Hebrew
; 1256 - Arabic
; 1247 - Baltic
; 1258 - Vietnam
; 874 - Thai
; 437 - OEM United States
; 858 - OEM Multilingual Latin and European .code
main PROC
invoke SetConsoleOutputCP, codePage mov ecx,
mov eax,
mov edx, OFFSET divider
L1:
call WriteDec ; eax 作为计数器
call WriteString ; edx 指向字符串
call WriteChar ; al 为得到的字符
call Crlf
inc aL
Loop L1 call WaitMsg
exit
main ENDP END main
● 代码,库 Irvine64 测试 1,显示 20 个 64 位随机数
ExitProcess PROTO ; 手动声明需要用到的函数
WriteInt64 PROTO
Crlf PROTO
Random64 PROTO
RandomRange PROTO
Randomize PROTO .code
main proc
sub rsp, ; 栈指针对其到 16 Byte
sub rsp, 20h ; 影子空间 32 Byte call Randomize
mov rcx,
L1:
mov rax,
call RandomRange ; 返回的 64 位随机数在 eax 中
call WriteInt64
call Crlf
loop L1 add rsp, 28h ; 恢复 rsp 指针位置,main 中可以不用,子过程中需要
mov ecx,
call ExitProcess
main endp end
● 涨姿势,链接时把 irvine64.obj 加入项目中(添加现有项),然后报错 LNK2017 没有 /LARGEADDRESSAWARE:NO,“ADDR32”到“bufferLHB”的重定位无效 。改正:“属性,配置属性,连接器,系统,启用大地址” 选否(/LARGEADDRESSAWARE:NO),即可正确运行。
● 代码,库 Irvine64 测试 2,简单的输入输出
ExitProcess proto
ReadInt64 proto
ReadString proto
WriteString proto
WriteInt64 proto
WriteHex32 proto
WriteHex64 proto
Crlf proto .data
message BYTE "Test irvine64.lib",
maxval qword
minval qword -
inbuf BYTE dup(),
inbuf_size = $ - inbuf .code
main proc mov rdx,offset message
call WriteString
call Crlf call ReadInt64 ; 从键盘读取一个 64 位整数
call Crlf
call WriteInt64
call Crlf mov rdx,offset inbuf
call WriteString
call Crlf mov rax, minVal
call WriteInt64
call Crlf mov rax, maxVal
call WriteInt64
call Crlf mov ecx,
call ExitProcess
main endp end
《汇编语言 基于x86处理器》前五章的小程序的更多相关文章
- 《汇编语言 基于x86处理器》第九章字符串与数组部分的代码
▶ 书中第九章的程序,主要讲了字符串相关的输入.输出,以及冒泡排序.二分搜索 ● 代码,Irvine32 中的字符串库函数代码范例 INCLUDE Irvine32.inc .data str1 BY ...
- 《汇编语言 基于x86处理器》第十三章高级语言接口部分的代码 part 2
▶ 书中第十三章的程序,主要讲了汇编语言和 C/++ 相互调用的方法 ● 代码,汇编中调用 C++ 函数 ; subr.asm INCLUDE Irvine32.inc askForInteger P ...
- 《汇编语言 基于x86处理器》第七章整数运算部分的代码
▶ 书中第七章的程序,使用各种位移运算,加深了对内存.寄存器中整数类型变量存储的认识 ● 代码,双字数组右移 4 位 INCLUDE Irvine32.inc COUNT = ; 右移位数 .data ...
- 《汇编语言 基于x86处理器》第十一章 MS-DOS 编程部分的代码 part 2
▶ 书中第十一章的程序,主要讲了 Windows 接口,在小黑框中进行程序交互 ● 在屏幕指定位置输出带自定义属性的文字 INCLUDE Irvine32.inc .data outHandle HA ...
- 《汇编语言 基于x86处理器》第十二章浮点数部分的代码
▶ 书中第十二章的程序,主要讲了 FPU 的指令和浮点数计算的过程 ● 代码,简单的 32 为浮点数测试 INCLUDE Irvine32.inc INCLUDE macros.inc .data f ...
- 《汇编语言 基于x86处理器》第六章条件处理部分的代码
▶ 书中第六章的程序,使用了条件判断和跳转来实现一些功能 ● 代码,查找数组首个非零值 INCLUDE Irvine32.inc .data intArray SWORD , , , , , , , ...
- 《汇编语言 基于x86处理器》第十章 - 运行一个 16位实地址汇编程序
▶ 书上第 10 章,主要讲了宏,引用了一个 16 位实地址的程序,从代码开始到运行 ● 代码 ; main.asm INCLUDE Macros.inc IF IsDefined( RealMode ...
- 《汇编语言 基于x86处理器》第十章结构和宏部分的代码
▶ 书中第十章的程序,主要讲了结构与宏的使用 ● 代码,使用结构,对比是否对齐的性能差距 INCLUDE Irvine32.inc INCLUDE macros.inc structN STRUCT ...
- 《汇编语言 基于x86处理器》第八章高级过程部分的代码 - 两种规范计算数组元素的和
▶ 输入 Count 个 32 位有符号整数,计算他们的和 ● 代码,使用堆栈传参 ;// Sum_main.asm,主过程 INCLUDE Irvine32.inc EXTERN PromptFor ...
随机推荐
- rabbitmq学习(五):springboot整合rabbitmq
一.Springboot对rabbitmq的支持 springboot提供了对rabbitmq的支持,并且大大简化了rabbitmq的相关配置.在springboot中,框架帮我们将不同的交换机划分出 ...
- Visual Studio 2017 以前的旧格式的 csproj Import 进来的 targets 文件有时不能正确计算属性(PropertyGroup)和集合(ItemGroup)
我在之前的博客中有教大家如何编写 NuGet 工具包,其中就有编写 .targets 文件. 我在实际的使用中,发现 Visual Studio 2017 带来的含 Sdk 的新 csproj 格式基 ...
- CTF之MD5
MD5是一种常见的加密方式,但准确来说,它只是一种编码方式,它将任意有限长度的字符串通过哈希函数转换为特定长度的字符串. MD5编码具有单向性,即由明文变密文简单,由密文变明文困难. 破解时只能通过暴 ...
- test20180922 世界第一的猛汉王
题意 分析 由于异色点必有连边,所以一个点的covered减去两个点共有的covered就是可存在的环数,十分巧妙. 代码 #include <bits/stdc++.h> using L ...
- spark之 spark 2.2.0 Standalone安装、wordCount演示
说明:前提安装好hadoop集群,可参考 http://blog.csdn.net/zhang123456456/article/details/77621487 一. scala 安装 1.下载 s ...
- C#之设计模式之六大原则
一.单一职责原则 原文链接:http://blog.csdn.net/lovelion/article/details/7536542 单一职责原则是最简单的面向对象设计原则,它用于控制类的粒度大小. ...
- OpenWrt的web服务器
参考: http://www.szchehang.com/news/10602.html 我们登录的路由器主界面就是通过这个软件指定了80端口来访问的.我们要添加自己额外的网站服务,那只需要重新定义一 ...
- Linux系统Centos安装Python3.7
Linux下默认系统自带python2.7的版本,这个版本被系统很多程序所依赖,所以不建议删除,如果使用最新的Python3那么我们知道编译安装源码包和系统默认包之间是没有任何影响的,所以可以安装py ...
- [OI向?] ubuntu下一些常用的技巧
想起来什么就写什么吧. Ubuntu下的对拍程序 python是最为简便的. from os import system while True: system("./make > in ...
- MySQL主从同步和半同步配置
mysql主从配置: 1,安装maraidb,使用国内yum镜像站下载:[root@localhost mysql]# cat /etc/yum.repos.d/MairaDB.repo # Mari ...