8086汇编(16位汇编)学习笔记09.宏汇编

news2025/1/2 22:31:01

8086汇编(16位汇编)学习笔记09.宏汇编-C/C++基础-断点社区-专业的老牌游戏安全技术交流社区 - BpSend.net

宏汇编在文件中是当做关键字的,但是在bug中运行时并没有这些指令,这些关键词被称为伪指令,cpu并不认识他们,需要经过编译器转化成 cpu认识的代码,但是他多我们写代码帮助又很大

表达式

表达式中的求值是在程序链接时完成的,所以表达式中的各值必须是在汇编或链接期就能确定,也就是 说不能将寄存器或者变量运⽤于表达式。

算术表达式

运算符意义例⼦
+65 + 32
-size val - 54
*23h * 65h
/98 / 45
mod取模99 mod 65
mov ax, 54+65
mov ax, 65-48
mov ax, 65*78
mov ax, type byte * 78
mov ax, 78 mod 5
mov ax, 96 / 5
mov ax, size g_buf / type g_buf

;mov ax,bx+7   ;这个是错的,因为编译器无法得到结果,不知道bx的值

image.png

逻辑运算符

逻辑运算即位运算,逻辑运算符与对应的指令助记符单词是相同的,当它们出现在操作码部分时是指 令,出现在操作数时是逻辑运算符

运算符意义
and位与
or位或
not按位取反
xor异或
mov ax, 5566h and 6655h
mov ax, 7788h or 8877h
mov ax, not 5566h
mov ax, 5566h xor 7788h

image.png

关系运算符

关系运算符的结果,如果结果为真,则所有位都置为1,即FFFF;否则所有位都置为0,即 .

运算符英⽂意义
EQequal等于 ==
NEnot equal不等于 !=
GTgreater than⼤于 >
LTless than⼩于 <
GEgreater than or equal⼤于等于 >=
LEless than or equal⼩于等于 <=
mov bx,88 eq 88    ;bx= 0FFFFh   因为结果为ture
 mov bx,88 ne 88    ;bx= 0000h    因为结果为flase
 mov bx,88 ge 88    ;bx= 0FFFFh   因为结果为ture

img

标号

匿名标号 @@
  • @@是匿名标号
  • @b 向上查找最近的@@, b是back
  • @f 向下查找最近的@@ ,f是front

一般我们用 jmp 跳转你需要有标号,而且标号名必须唯一 ,但是如果 标号名是 @@ ,那么就可以重复,跳转用 @b 或 @f , @@ 的 跳转距离在段内是 没有限制的

img

调整偏移量指令 ORG

格式 ORG 偏移值

此指令后的下⼀个变量或指令从 偏移值 开始存放,即把一个变量或者指令放在指定的偏移内,可以提前,也可以延后

;这是栈段
stack segment stack
  db 512 dup(0)
stack  ends

;这是数据段
data segment
  g_buf db "hello world"

  org  20 
  g_buf1 db "hello world"  ;表示 g_buf1 会从段偏移20的地方开始存放

  org  0  
  g_buf2 db "111111"     ;表示 g_buf2 会从段偏移0的地方开始存放,回覆盖 g_buf的数据

data ends

;这里是代码
CODE segment

START:
    assume ds:data
    mov ax, data
    mov ds, ax
  
  
    org 20h
    mov ax,4C00H  ; 带参数返回的退出   ;此处代码从20H 处开始存放,后面指令依次后推
    int 21h   ;使用21号中断
   
CODE ends

end START

img

当前地址指令$
  • $伪指令代表当前指令或变量的地址
  • 常⽤于计算缓冲区⻓度和获取当前ip值
  • 可与 ORG 配合使⽤
data_seg segment
  g_buf dw 10h dup(0)
  g_len dw $ - offset g_buf  ;获取上⾯的g_buf的⻓度
  org $ + 10h                ;下⼀个变量从当前地址+10h的偏移开始存放
  g_w dw 65h
    
data_seg ends

CODE segment

START:

 org 100h
 mov ax, 5566h and 6655h ;此指令从代码段偏移100h开始存放
 mov ax, $ ;获取 本条指令的地址
 mov ax, $+4;获取 本条指令的地址+4
 mov ax, 4c00h
 int 21h
   
CODE ends

结构体 struc

格式

结构体名 struc

;这⾥定义结构体成员

结构体名 ends

结构体使⽤<>来初始化

结构体可以通过变量名和寄存器来访问成员

结构体可以在定义时候初始化,也可以在后面初始化

结构作为局部变量无法赋初值

;定义结构体
Point struc
    m_wX dw 0
    m_wY dw 0
Point ends

;关键字  struc,可以在定义时候赋初值
TagStu struc
    m_byte db 0
    m_w    dw 5656h
    m_ary  db 8 dup(0)
    m_sz   db "hello"
    m_pt   Point <>      ;结构体里面嵌套结构体
TagStu ends

;堆栈
stack_seg segment stack
    db 512 dup(0)
stack_seg ends

;数据段
data_seg segment
    g_stu TagStu <66h, 7777h, "testtest", "66", <11h, 22h>>   ;初始化结构体
    g_ary Point 12 dup(<11h, 22h>)                            ;定义结构体数组
data_seg ends

;代码
code_seg segment

;结构体传参,直接传对象,它会将结构提对象入栈,每次入栈2字节(推荐用指针)
Foo0  PROC far c stu:TagStu
    lea bx, stu

    mov stu.m_byte, 99h     ;修改结构体成员的值
    mov stu.m_w, 6666h      ;修改结构体成员的值

    ret  
Foo0  ENDP

;结构体传参,传对象指针,通过指针访问必须借助寄存器,不能直接用指针
Foo1 PROC far c pStu:ptr TagStu

    ;mov ax, [pStu]m_w   ;指针,不能直接点使用,必须通过寄存器
  
    mov bx, pStu         ;将结构体指针赋值给bx

    ;通过结构体指针访问结构体成员
    assume bx:ptr TagStu     ;将bx解释为 TagStu 结构体指针,类似强转
    mov ax, [bx].m_w         ;通过结构体指针访问成员 
    assume bx:nothing        ;将bx 的 解释方式转回默认 

    ret  
Foo1 ENDP

;结构体作为局部变量,局部变量无法赋初值
foo PROC far c 
    local @stu:TagStu   ;变量类型直接是结构体类型

    lea bx, @stu         ;获取变量的偏移地址
    mov al, @stu.m_byte  ;访问变量成员
    mov ax, @stu.m_w     ;访问变量成员

   ret 
foo ENDP

START:
    assume ds:data_seg
    mov ax, data_seg
    mov ds, ax

    mov ax, g_stu.m_pt.m_wX   ;访问结构体内 结构体的的成员

    invoke Foo1, offset g_stu  ;结构体指针作为函数参数 

    invoke Foo0, g_stu         ;结构体对象作为函数参数
 
    invoke foo                 ;结构体作为局部变量

    mov al, g_stu.m_byte      ;访问结构体成员 
    mov ax, g_stu.m_w         ;访问结构体成员
    lea bx, g_stu.m_ary       ;获取结构体成员的偏移地址
    mov byte ptr [bx], 'a'    ;修改结构体成员的值

    mov ax, 4c00h;
    int 21h
code_seg ends
end START

img

img

equ语句

作用:用来定义宏

不可以重命名

可⽤于常量和表达式

可⽤于字符串

可⽤于指令名,给指令取别名

可⽤于类型,给类型取别名

可⽤于操作数

;是无参宏,没有参数

;堆栈
stack_seg segment stack
    db 512 dup(0)
stack_seg ends

PI equ 314                  ;常量
SZNAME equ "hello world"    ;字符串
MYMOV equ mov               ;指令名
CHAR equ db                 ;类型
INT16 equ dw                ;类型

;PI equ 6677h ;不允许再次定义

;数据段
data_seg segment
    g_sz CHAR SZNAME
    g_w  INT16 PI
    g_w2 INT16 44h
data_seg ends

;代码
code_seg segment

START:
    assume ds:data_seg
    mov ax, data_seg
    mov ds, ax

    MYMOV ax, g_w

    mov ax, 4c00h;
    int 21h
code_seg ends
end START

img

=语句

可以被修改

只能⽤于常数

COUNT2 = 100h   ;后跟数值
COUNT2 = 200h   ;可以再次赋值

;szTest = "hello world"  ;错误,不能用于字符串,只能用于立即数(常量)

mov ax, COUNT2


;可以用来提高可读性

MYFUNC:
nX = 2
nY = 4
    push bp
    mov bp, sp
    sub sp, 10

    mov [bp-nX], ax
    mov [bp-nY], ax

    mov sp, bp
    pop bp
    ret
macro语句
格式

宏名 macro [参数1][,参数2]...

宏体

endm

宏会在使⽤的地⽅展开

宏可以带参数

字符串拼接使⽤&

;堆栈
stack_seg segment stack
    db 512 dup(0)
stack_seg ends


CHAR equ db 
INT16 equ dw

;内存到内存赋值宏
movm macro val1, val2
    push val1
    pop val2
endm

;字符串拼接
shift macro d, opt, count
    push cx
    mov cl, count
    sa&d opt, cl
    pop cx
endm


;数据段
data_seg segment
    g_w  INT16 55H
    g_w2 INT16 44h
data_seg ends

;代码
code_seg segment


START:
    assume ds:data_seg
    mov ax, data_seg
    mov ds, ax

  
    ;内存到内存赋值
    movm g_w, g_w2
    movm g_w2, g_w

    shift r, ax, 2
    shift r, ax, 5
    shift l, bx, 4
    shift l, dx, 2


    mov ax, 4c00h;
    int 21h
code_seg ends

end START

img

img

多文件编译

1.源文件
  • 源文件后缀名为asm
  • 每个源文件末尾需要有end
2.头文件
  • 汇编头文件后缀名为inc

  • 头文件包含 include xxx.inc

  • 头文件防重复包含

    ifndef SECOND_1
    SECOND_1 equ 1
    	Func1 proto far stdcall arg1 : word, arg2 : word
        extern g_dw : word
    endif
    
3.函数使用

函数在源文件定义,在头文件中声明即可。

4.全局变量

全局变量在定义文件中必须使用public指明此变量为全局public变量名

全局变量在使用文件中必须使用extern 指明此变量来自外部文件 extern 变量:类型

ifndef HEADER_INC    ;防止重复包含
HEADER_INC equ 1

   extern g_w:word  ;声明明 g_w 是来自外部的全局变量

endif
public g_w    ;指名 g_w 是全局变量 ,不然默认本文件内才能使用(文件作用域)

data_seg segment
    g_w dw 0
data_seg ends

end
5.编译
ml /c xx.asm yy.asm
link xx.obj yy.obj
或
ml *.asm

伪指定实现分支,循环

img

分支

格式

格式1:

.IF condition    ;以英文“句号”开头   ;条件"condition"成立时所执行的指令序列

  指令序列   

.ENDIF

格式2:

.IF condition  ;条件"condition"不成立时所执行的指令序列

  指令序列1

.ELSE

  指令序列2   

.ENDIF

格式3:

.IF condition1

  指令序列1

.ELSEIF condition2 ;条件"condition2"成立时所执行的指令序列

  指令序列2    

.ENDIF

其中:条件表达式“condition”的书写方式与C语言中条件表达式的书写方式相似,也可用括号来组成复杂的条件表达式。

条件表达式中可用的操作符有:==(等于)、!=(不等)、>(大于)、>=(大于等于)、<(小于)、<=(小于等于)、&(位操作与)、!(逻辑非)、&&(逻辑与)、||(逻辑或)等。

;堆栈
stack_seg segment stack
    db 512 dup(0)
stack_seg ends

;数据段
data_seg segment

data_seg ends

;代码
code_seg segment

START:
    assume ds:data_seg
    mov ax, data_seg
    mov ds, ax

    mov g_w, 8

    .if ax >= bx
        xor ax, ax
    .elseif ax <= bx
        xor bx, bx
    .else 
        xor cx, cx
    .endif

    mov ax, 4c00h;
    int 21h
code_seg ends

end START

1、WHILE型循环伪指令

.WHILE condition ;条件"condition”成立时所执行的指令序列
  循环体的指令序列    
.ENDW

其中:.ENDW与前面的.WHILE相匹配,它标志着其循环体到此结束。

如果条件表达式“condition”在循环开始时,就为“假”(false),那么,该循环体一次也不会被执行。

2、REPEAT型循环伪指令

.REPEAT
  循环体的指令序列
.UNTIL condition .REPEAT
  循环体的指令序列
.UNTILCXZ [condition]

REPEAT型循环在执行完循环体后,才判定逻辑表达式condition的值。若该表达式的值为真,则终止该循环,并将执行伪指令.UNTIL[CXZ]后面的指令,否则,将向上跳转到伪指令.REPEAT之后的指令,为继续执行其循环体作准备

循环终止 break 和继续 continue

(1)、终止循环伪指令
.BREAK

.BREAK .IF condition

该伪指令用来终止包含它的最内层循环。前者是无条件终止循环,后者是仅当逻辑表达式condition为真时,才终止循环。
.WHILE 1 .REPEAT

.BREAK .IF condition


.BREAK .IF condition

ENDW .UNTIL 0

对于以上二个循环,如果没有指令来终止循环的话,它们都将进入死循环状态,但如果在该层循环体内,存在伪指令“.BREAK .IF condition”的话,那么,当逻辑表达式condition为真时,该循环就会被终止了。

(2)、循环继续伪指令

.CONTINUE
.CONTINUE .IF condition

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2268084.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

leetcode 面试经典 150 题:矩阵置零

链接矩阵置零题序号73题型二维数组解题方法标记数组法难度中等熟练度✅✅✅✅ 题目 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1]…

五、CentOS7/CentOS8安装APISIX(1)

目录 &#x1f33b;&#x1f33b; 一、 Apache APISIX介绍1.1 什么是Apache APISIX1.2 APISIX架构1.3 Apache APISIX 的技术优势1.4 APISIX‌应用场景 二、APISIX快速开始2.1 centos7/centos8安装APISIX 一、 Apache APISIX介绍 1.1 什么是Apache APISIX Apache APISIX 是一个…

BUG分析 - 重启有时失败

1. 倒查版本 1.0_11 - ok1.0_12 - fail 2.对比1.0_11和1.0_12 失败时的日志 ================================== 1.0_11 ============================== 2024-12-26 09:46:51.886 INFO [26332] [ThreadPLCPool::in

Ngnix介绍、安装、实战及用法!!!

一、Nginx简介 1、Nginx概述 Nginx (“engine x”) 是一个高性能的 HTTP 和 反向代理服务器&#xff0c;特点是占有内存少&#xff0c;并发能力强&#xff0c;能经受高负载的考验,有报告表明能支持高达 50,000 个并发连接数 。 2、正向代理 正向代理&#xff1a;如果把局…

【物联网】给EoRa Pi 烧录Meshtastic

文章目录 一、Meshtastic 是什么&#xff1f;二、Meshtastic 烧录过程1. 在线烧录工具2. 刷机进度 总结 一、Meshtastic 是什么&#xff1f; Meshtastic 是一种基于 LoRa 技术的离网通信平台。它通过低成本、低功耗的无线电设备&#xff0c;实现远距离自组网通信。可在脱离现有…

Java 中的各种锁

​ Java 中我们经常听到各种锁&#xff0c;例如悲观锁&#xff0c;乐观锁&#xff0c;自旋锁等等。今天我们将 Java 中的所有锁放到一起比较一下&#xff0c;并分析各自锁的特点&#xff0c;让大家能够快捷的理解相关知识。 1、悲观锁 VS 乐观锁 从概念上来说 悲观锁: ​ 在…

【开源免费】基于SpringBoot+Vue.JS租房管理系统(JAVA毕业设计)

本文项目编号 T 102 &#xff0c;文末自助获取源码 \color{red}{T102&#xff0c;文末自助获取源码} T102&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

报考重庆大学计算机研究生有哪些要求?

想要报考重庆大学计算机研究生&#xff0c;首要你要确定考专硕还是学硕&#xff0c;考什么内容&#xff0c;需要买什么书&#xff1f;以及考研期间一些信息获取渠道等。下面C哥将对以上问题进行详细解答。 1.报考条件&#xff1a; 报考重大计算机研究生与重大其他大多数专业条…

爬虫与反爬虫实现全流程

我选取的网页爬取的是ppt nba版 需要的工具:pycharm,浏览器 爬虫需要观察它的网页信息,然后开始首先爬取它的html,可以看到有人气,标题,日期,咨询 可以看到用get方法 import requests url"https://img-home.csdnimg.cn/images/20230724024159.png?origin_urlhttps%3A%2…

Llama 3 后训练(三)

目录 4. 后训练 4.1 建模 图表解读 4.1.1 聊天对话格式 4.1.2 奖励建模 4.1.3 监督微调&#xff08;Supervised Finetuning&#xff09; 4.1.4 直接偏好优化&#xff08;Direct Preference Optimization&#xff09; 4.1.5 模型平均&#xff08;Model Averaging&#x…

小程序配置文件 —— 15 页面配置

页面配置 小程序的页面配置&#xff0c;也称为局部配置&#xff0c;每一个小程序页面也可以使用自己的 .json 文件来对页面的窗口表现进行配置&#xff1b; 需要注意的是&#xff1a;页面配置文件的属性和全局配置文件中的 window 属性几乎一致&#xff0c;只不过这里不需要额…

【设计与实现】基于Bootstrap的地方旅游管理系统的设计与实现

目录 第一章 绪论 1.1 研究现状 1.2 设计原则 1.3 研究内容 第四章 系统设计 4.1系统结构设计 4.2系统顺序图设计 4.3数据库设计 第五章 系统实现 5.1登录模块的实现 第一章 绪论 1.1 研究现状 时代的发展&#xff0c;我们迎来了数字化信息时代&#xff0c;它正在渐…

如何使用React,透传各类组件能力/属性?

在23年的时候&#xff0c;我主要使用的框架还是Vue&#xff0c;当时写了一篇“如何二次封装一个Vue3组件库&#xff1f;”的文章&#xff0c;里面涉及了一些如何使用Vue透传组件能力的方法。在我24年接触React之后&#xff0c;我发现这种扩展组件能力的方式有一个专门的术语&am…

使用Excel制作通达信自定义“序列数据“

序列数据的视频教程演示 Excel制作通达信自定义序列数据 1.序列数据的制作方法&#xff1a;删掉没有用的数据&#xff08;行与列&#xff09;和股代码格式处理&#xff0c;是和外部数据的制作方法是相同&#xff0c;自己上面看历史博文。只需要判断一下&#xff0c;股代码跟随的…

VuePress搭建个人博客

VuePress搭建个人博客 官网地址: https://v2.vuepress.vuejs.org/zh/ 相关链接: https://theme-hope.vuejs.press/zh/get-started/ 快速上手 pnpm create vuepress vuepress-starter# 选择简体中文、pnpm等, 具体如下 .../19347d7670a-1fd8 | 69 .../19…

《机器学习》从入门到实战——线性回归

目录 一、什么是线性回归 二、一元线性回归模型 三、多元线性回归模型 四、误差项分析 1、误差项是否可以忽略 2、误差项的特点 3、误差项满足高斯分布&#xff08;正太分布&#xff09; &#xff08;1&#xff09;、高斯分布公式 &#xff08;2&#xff09;、公式推导 …

Java - 日志体系_Apache Commons Logging(JCL)日志接口库_适配Log4j2 及 源码分析

文章目录 PreApache CommonsApache Commons ProperLogging &#xff08;Apache Commons Logging &#xff09; JCL 集成Log4j2添加 Maven 依赖配置 Log4j2验证集成 源码分析1. Log4j-jcl 的背景2. log4j-jcl 的工作原理2.1 替换默认的 LogFactoryImpl2.2 LogFactoryImpl 的实现…

brupsuite的基础用法常用模块(1)

proxy模块&#xff1a; Options: 设置代理端口&#xff0c;默认为8080端口&#xff0c;若8080端口被占用可在该界面更改代理端口. HTTP history: 拦截的历史请求&#xff0c;右键可做更多操作&#xff0c;很多操作与其他模块有关。&#xff08;清除历史的话右键选择clear p…

概率统计与随机过程--作业7

编程题 分别使用混合高斯聚类算法&#xff08;GMM&#xff09;和K-Means聚类算法将agricultural_economy.xlsx文件中的9个样本聚成2类&#xff08;可以使用sklearn的GaussianMixture和KMeans&#xff09;&#xff0c;用不同颜色绘图显示各类样本点&#xff0c;并与“最短距离聚…

【Unity3D】ECS入门学习(十二)IJob、IJobFor、IJobParallelFor

IJob&#xff1a;开启单个线程进行计算&#xff0c;线程内不允许对同一个数据进行操作&#xff0c;也就是如果你想用多个IJob分别计算&#xff0c;将其结果存储到同一个NativeArray<int>数组是不允许的&#xff0c;所以不要这样做&#xff0c;如下例子就是反面教材&#…