《汇编语言基础教程》 学习实录
《汇编语言基础教程》 学习实录
- 第3章 算术运算指令
- 第4章 选择结构
- 第5章 迭代结构
- 第6章 逻辑运算指令、移位指令、循环移位指令和堆栈
书目:《Guide to assembly language. A concise introduction》 by James T.Streib
时间紧迫,这里仅记录我学习过程中写的一些示例代码,每个示例代码都有对应C语言版本。长时间不用难免忘记,希望能通过一些简单示例快速拾起intel汇编语法。
IDE:VS2017
Intel x86汇编环境搭建与配置
第3章 算术运算指令
COMMENT @
#include<stdio.h>
int main(){int volts, ohms, amperes;printf("\n%s","Enter the number of volts: ");scanf("%d", &volts);printf("%s","Enter the number of ohms: ");scanf("%d", &ohms);amperes = volts / ohms;printf("\n%s%d\n\n", "The number of amperes is:", amperes);
}
@.386
.model flat, C
.stack 100hincludelib msvcrt.libprintf proto arg1:Ptr Byte, printlist:VARARG
scanf proto arg1:Ptr Byte, printlist:VARARG.data
volts SDWORD ?
ohms SDWORD ?
amperes SDWORD ?in1fmt Byte "%d",0
msg1fmt Byte 0Ah,"%s",0
msg2fmt Byte "%s",0
msg3fmt Byte 0Ah,"%s%d",0Ah,0Ah,0msg1 Byte "Enter the number of volts: ",0
msg2 Byte "Enter the number of ohms: ",0
msg3 Byte "The number of amperes is:",0
.code
start1:INVOKE printf, ADDR msg1fmt, ADDR msg1INVOKE scanf, ADDR in1fmt, ADDR voltsINVOKE printf, ADDR msg2fmt, ADDR msg2INVOKE scanf, ADDR in1fmt, ADDR ohmsmov eax, voltscdqidiv ohmsmov amperes, eaxINVOKE printf, ADDR msg3fmt,ADDR msg3, amperesret
end start1
第4章 选择结构
COMMENT @ C语言表述#include<stdio.h>int main(){int voltage;printf("%s", "Enter an AC Voltage: ");scanf("%d", &voltage);if (voltage >= 110 && voltage <= 120)printf("\n%s\n", "Voltage is Acceptable");else {printf("\n%s\n", "Warning!");if(voltage < 110)printf("%s\n", "Voltage too Low");elseprintf("%s\n", "Voltage too High");}if(voltage >=380)printf("%s", "Generator power off...");printf("\n");return 0; }
@
; 以下是上述C代码的汇编语言表述
; MASM32 intelx86 Debugger
; =============================================.listall.386.model flat, c.stack 100h
includelib msvcrt.lib
scanf PROTO :PTR Byte, :VARARG
printf PROTO :PTR Byte, :VARARG.data
in1fmt Byte "%d",0msg1fmt Byte "%s",0
msg1 Byte "Enter an AC Voltage: ",0
msg2fmt Byte 0Ah,"%s",0Ah,0
msg2 Byte "Voltage is Acceptable",0
msg3 Byte "Warning!",0
msg3fmt Byte "%s",0Ah,0
msg4 Byte "Voltage too Low",0
msg5 Byte "Voltage too High",0
msg4fmt Byte 0Ah,0
msg6 Byte "Generator power off...",0voltage SDWORD ?.code
main PROCINVOKE printf, ADDR msg1fmt, ADDR msg1INVOKE scanf, ADDR in1fmt, ADDR voltage
if01: cmp voltage, 110jl else01cmp voltage, 120jg else01
then01: INVOKE printf, ADDR msg2fmt, ADDR msg2jmp endif01
else01: nopINVOKE printf, ADDR msg2fmt, ADDR msg3
if02: cmp voltage, 110jge else02
then02: INVOKE printf, ADDR msg3fmt, ADDR msg4jmp endif02else02: INVOKE printf, ADDR msg3fmt, ADDR msg5endif02: nopendif01: nop.if voltage >= 380INVOKE printf, ADDR msg1fmt, ADDR msg6nop ;这里要有一个补位的,否则会抛出未知异常.endifINVOKE printf, ADDR msg4fmtret
main ENDPEND main
第5章 迭代结构
INVOKE指令破坏寄存器eax、ecx和edx的值,故用ecx计数时需要用到一个内存变量存储计数值
loop指令使用时ecx的值不能为0或负值
完整代码示例:实现幂函数
COMMENT @
#include<stdio.h>int main() {int x, n, i, ans;printf("%s", "Enter x: ");scanf_s("%d", &x);printf("%s", "Enter n: ");scanf_s("%d", &n);if (x < 0 || n < 0)printf("\n%s\n\n", "Error: Negative x and/or y");elseif (x == 0 && n == 0)printf("\n%s\n\n", "Error: Undefined answer");else {i = 1;ans = 1;while (i <= n) {ans = ans * x;++i;}printf("\n%s%d\n\n", "The answer is: ", ans);}return 0;
}
@.listall.386.model flat, c.stack 100hincludelib msvcrt.libprintf PROTO :Ptr Byte, :VARARG
scanf PROTO :Ptr Byte, :VARARG.data
x SDWORD ?
n SDWORD ?
i SDWORD ?
ans SDWORD ?msg1fmt Byte "%s",0
msg2fmt Byte 0Ah,"%s",0Ah,0Ah,0
msg3fmt Byte 0Ah,"%s%d",0Ah,0Ah,0in1fmt Byte "%d",0msg1 Byte "Enter x: ",0
msg2 Byte "Enter n: ",0
msg3 Byte "Error: Negative x and/or y",0
msg4 Byte "Error: Undefined answer",0
msg5 Byte "The answer is: ",0.codemain PROCINVOKE printf, ADDR msg1fmt, ADDR msg1INVOKE scanf, ADDR in1fmt, ADDR xINVOKE printf, ADDR msg1fmt, ADDR msg2INVOKE scanf, ADDR in1fmt, ADDR nif01: cmp x, 0jge else01
OR01: cmp n, 0jge else01
then01: nopINVOKE printf, ADDR msg2fmt, ADDR msg3
else01: nopif02: cmp x, 0jne else02cmp n, 0jne else02
then02: nopINVOKE printf, ADDR msg2fmt, ADDR msg4
else02: nopmov i, 1mov ans, 1mov ecx, i
w01: cmp ecx, njg endw01mov eax, ansimul xmov ans, eaxinc ecxjmp w01
endw01: nopmov i, ecxINVOKE printf, ADDR msg3fmt, ADDR msg5, ans
endif02: nopendif01:nopret
main ENDPEND main
第6章 逻辑运算指令、移位指令、循环移位指令和堆栈
逻辑运算:
and
\or
\xor A, B
逻辑移位:左
shl
\shr A, B
右测试比特位:
test A, B
A值不变 ||and A, B
,A值会变算术移位:左
sal A, B
\sar A, B
右,sal
与shl
完全一样,但sar
与shr
不一样,考虑负数的情况即可循环移位:左
rol A, B
\ror A, B
右,一般移动一整轮使得值复原堆栈:
push reg\mem\imm
;pop reg\mem
; 注意:①只能16位或32位寄存器/内存空间可使用;②pop
不能取立即数堆栈应用:排序算法中的交换值
方法一 (较慢) 方法二: 中等 方法三:较快push num1 mov eax, num1 mov eax, num1 push num2 xchg eax, num2 mov edx, num2 pop num1 mov num1, eax mov num1, edx pop num2 mov num2, eax
原因:指令执行速度 mov > xchg > push/pop,但从方法一到方法三,使用的寄存器数分别为0、1、2,所以折中考虑方法二
章节实例:模拟OCR设备,检测文档状态字节(每一位都代表一个状态)
COMMENT @bit ERROR STATE0 SHORT DOCUMENT1 LONG DOCUMENT2 CLOSE FEED3 MULTIPLE FEED4 EXCESSIVE SKEW5 DOCUMENT MISFEED6 DOCUMENT JAM7 UNSPECIFIED ERROR@.listall.386.model flat,stdcall.stack 100hincludelib msvcrt.libprintf PROTO C :PTR Byte, :VARARG scanf PROTO C :PTR Byte, :VARARG.data msg1fmt Byte "%s",0 in1fmt Byte "%x",0 msg2fmt Byte "%s%x",0Ah,0Ah,0 msg1 Byte 0Ah,"Enter a hexadecimal number: ",0 msg2 Byte "The hexadecimal number is: ",0 msgshort Byte "SHORT DOCUMENT",0Ah,0 msglong Byte "LONG DOCUMENT",0Ah,0 msgclose Byte "CLOSE FEED",0Ah,0 msgmult Byte "MULTIPLE FEED",0Ah,0 msgskew Byte "EXCESSIVE SKEW",0Ah,0 msgfeed Byte "DOCUMENT MISFEED",0Ah,0 msgjam Byte "DOCUMENT JAM",0Ah,0 msgerror Byte "UNSPECIFIED ERROR",0Ah,0dsb DWORD ?.code main PROCINVOKE printf, ADDR msg1fmt, ADDR msg1INVOKE scanf, ADDR in1fmt, ADDR dsbINVOKE printf, ADDR msg2fmt, ADDR msg2, dsb while01: cmp dsb, 0ffh ; .while dsb<=0ffhjg endwhile01 test dsb, 00000001b if01: .if !ZERO?INVOKE printf, ADDR msg1fmt, ADDR msgshort endif01: .endiftest dsb, 00000010b if02: .if !ZERO?INVOKE printf, ADDR msg1fmt, ADDR msglong endif02: .endif test dsb, 00000100b if03: .if !ZERO?INVOKE printf, ADDR msg1fmt, ADDR msgclose endif03: .endif test dsb, 00001000b if04: .if !ZERO?INVOKE printf, ADDR msg1fmt, ADDR msgmult endif04: .endif test dsb, 00010000b if05: .if !ZERO?INVOKE printf, ADDR msg1fmt, ADDR msgskew endif05: .endif test dsb, 00100000b if06: .if !ZERO?INVOKE printf, ADDR msg1fmt, ADDR msgfeed endif06: .endif test dsb, 01000000b if07: .if !ZERO?INVOKE printf, ADDR msg1fmt, ADDR msgjam endif07: .endif test dsb, 10000000b if08: .if !ZERO?INVOKE printf, ADDR msg1fmt, ADDR msgerror endif08: .endif INVOKE printf, ADDR msg1fmt, ADDR msg1INVOKE scanf, ADDR in1fmt, ADDR dsbINVOKE printf, ADDR msg2fmt, ADDR msg2, dsbendwhile01: nop ;.endwret main ENDP END main
打开VS2017, 选择VC++的“桌面安装向导”,创建项目
勾选“空项目”(有的VS版本还有安全周期检查,若有的话则把它也去掉),确定
右键项目 → \rightarrow →生成依赖项 → \rightarrow →生成自定义
勾选masm,确定
然后在源文件夹下创建如图所示的源文件,后缀名为.asm
- 右键项目 → \rightarrow →属性 → \rightarrow →弹出属性页,进行如下设置:
- 右键项目 → \rightarrow →属性 → \rightarrow →弹出属性页,进行如下设置:
设置完成,写个示例代码编译调试
.386 .model flat, c .stack 100hincludelib msvcrt.lib ;输入输出函数所在的库printf PROTO arg1:Ptr Byte, printlist:VARARG.data msg1fmt Byte "%s%d", 0 msg1 Byte "Hello World! ",0Ah, 0 num1 SDWORD ?.code main PROCmov num1, 7777INVOKE printf, ADDR msg1fmt, ADDR msg1, num1ret main ENDPEND main
运行结果如下:
设置完成!!!
《汇编语言基础教程》 学习实录相关推荐
- linux磁盘符变化autofs,Linux基础教程学习笔记之Autofs自动挂载
Linux基础教程学习笔记之Autofs自动挂载 Autofs自动挂载: yum -y install autofs vim /etc/auto.master 在文件中添加下面行 /home/gue ...
- 网络存储 linux 访问,Linux基础教程学习笔记28——使用Samba访问网络存储
Linux基础教程学习笔记28--使用Samba访问网络存储 SMB用于Windows和类Linux系统直接的文件共享 安装samba client包: [root@linuxidc~]# yum i ...
- 黑马程序员最新版JavaWeb基础教程-学习笔记
da@黑马程序员最新版JavaWeb基础教程-学习笔记 day06-HTML&CSS HTML HTML(HyperTest Markup Language):超文本标记语言 是一门语言,所有 ...
- SQL基础教程学习第六站:数据更新
仅用于记录学习,欢迎批评指正,共同交流,共同进步,大神勿喷 系列文章 SQL基础教程学习第一站:PostgreSQL下载安装以及如何创建并登录数据库: SQL基础教程学习第二站:数据库基本知识: SQ ...
- 批量加水印加logo#ps入门基础教程学习ps视频教程
批量加水印加logo#ps入门基础教程学习ps视频教程修图后期
- Python基础教程学习笔记:第一章 基础知识
Python基础教程 第二版 学习笔记 1.python的每一个语句的后面可以添加分号也可以不添加分号:在一行有多条语句的时候,必须使用分号加以区分 2.查看Python版本号,在Dos窗口中输入&q ...
- python基础教程-学习python有什么好的视频教程?
干货来袭,以下均为python好的学习视频,我们先从python的入门教程开始分享起! python入门教程(600集)https://www.bilibili.com/video/BV1ex411x ...
- 【莫烦Python】Python 基础教程——学习笔记
文章目录 本笔记基于p1-p29[莫烦Python]Python 基础教程 大家可以根据代码内容和注释进行学习. 安装 我的:python3.8+anaconda+VS code print() pr ...
- three.js基础教程学习之camera的理解
最近学习了three.js基础教程,由于WebGL中文网中对camera的解说不够详细,自己又找了几篇博文看,以下是我对camera的理解,有错误的地方希望得到大佬们的指出,同时也希望能帮到像我一样的 ...
最新文章
- GitLab 简易指引(二):GitLab Runner 安装与配置
- 理解java并发工具Phaser
- IAR J-Link下载程序出现错误提示:Failed to get CPU status after 4 retries Retry?
- kafka的消费隔离级别(持续更新中)
- linux “命令行自动补全”功能用命令
- 一个简单的Python爬虫
- C++网络编程实例(socket)
- 乾颐堂安德最新HCNP真题讲解含2017年最新变题后题库,75到90题
- weka下载后没有安装java_Weka程序原版安装文件[下载指引]
- HITB_Binary_100_writeup
- webrtc音频QOS方法四(音频接收端NACK流程实现)
- 使用EXCEL计算并绘制MACD指标
- 计算机主机的声音线是哪个好,电脑显示器连接线哪种接口好|VGA、HDMI视频接口选哪个好...
- 做自媒体,不用露脸拍视频,方法都在这篇文章
- python报错系列(9)--SyntaxError: Missing parentheses in call to ‘print‘. Did you mean print()
- GPS授时服务器(NTP授时)为银行系统提供时间服务
- Codeforces-715A-Plus and Square Root(找规律)
- 时事评论---宣誓不欠薪,好一场秀
- 微信小程序支付开发具体步骤
- 什么是高防CDN?高防CDN的用处有哪些?