首页 > 其他分享 >Aseembly(九)-[BX] Loop

Aseembly(九)-[BX] Loop

时间:2024-08-21 23:22:00浏览次数:13  
标签:code BX mov al Aseembly ax bx ds Loop

正如本篇文章的标题所示:本篇文章主要是进行 [BX] 和loop的讲解

上篇文章我们讲述了 关于 自己去dosbox里面编写汇编程序并且一步一步的编译(masm) 链接(link)
然后进行debug的过程 ,也进行了一个关于栈的实验:
详情请见我的上一篇文章
Aseembly(八)-汇编语言编写程序

让我们正式进入内容

前言

  1. 怎么说呢.bx其实有点套娃的意思
    我们看到 [] 这样的 ,一般认为是 做偏移 ,如:

    mov ax [0]
    

    将地址为ds寄存器,偏移为[0]的值,传入ax
    mov ax [1]
    这里是偏移为1的值.
    这里的偏移都是直接写出来的

    那么[bx]其实也是一样的,只不过给这个偏移取了一个变量.将所有的偏移放入到bx寄存器内.

    mov ax.[bx]
    这里就是将偏移量为bx的存入ax

  2. loop 其实就是循环
    然后我们加入进一步的描述符,()
    表示取括号内的地址的值
    如:(2000H) 代表的就是2000H处的数值
    (ax)表示ax中的内容
    (al)表示al中的内容
    ((ds)16+(bx))表示内存单元为 ds16+bx的内容
    ()中的元素可以有三种类型:
    1.寄存器 2.段寄存器名3 . 内存单元的物理地址 20位数据 如
    (20000H)

  3. 约定符号 idata 这里指的就是 :

mov ax,[idata]

表示的就是 mov ax [1] mov ax [2] ....
再补充一条:inc
inc bx
bx中的内容自增1

1. [BX]

让我们来详细的看一下 [BX]
mov ax , [bx]
回顾下我们之前讲的内容:
这里实际上就是 将bx中的偏移地址EA 与段地址SA(DS)组合成:SA:EA 后取里面的内容:
也就是
(ax)=(SA)*16+(EA)
这里用王爽老师提出的问题来进行解答:
在这里插入图片描述
写出程序执行后的 20000H-21007H中的内容
来一步一步的分析下:
首先前两句

mov ax,2000H
mov ds,ax

就是为了给段地址寄存器赋值
随后的:
mov bx,1000H mov ax,[bx]是给bx中放入偏移地址
这里在执行完毕后,ax中的值为地址: 20000H+1000H=21000H处的内容
也就是BE
随后的
inc bx inc bx
bx连续自增两次,bx变为了 1002H
随后:
mov [bx] ,ax
这里将ax中的数据 存入到[bx]处
注意 这里存放的地方是: [bx]所指的内存处,并不是bx寄存器的值!!!
所以这里[bx]所指的地址也就是 21002H 处存放的为00beh
同样的道理: 21004H处也为00beH
后面的 21005H 21006H都为BE
如图:

在这里插入图片描述
很简单吧~

2. loop

loop的语法是这样的:
loop 标号随后cpu: (cx) = (cx) -1
直到cx为01为止.
来举个例子:
简单的计算2^2
我们不使用循环可以这样写:

assume cs:codesg
codesg segment 
	mov ax,2
	add ax, ax
	
	mov ax,4c00h
	int 21h
codesg ends
end

这里使用的N+N代替了N*2

来写一下:2^3
也就是用N+N+N 代替N*3

assume cs:codesg
codesg segment 
	mov ax,2
	add ax,ax
	add ax,ax 
	
	mov ax,4c00h
	int 21h
codesg ends
end

如果计算的多了呢?如计算 2^12?
来这么写?

assume cs:codesg
codesg segment 
	mov ax,2 
	add ax,ad
	add ax,ax 
	add ax , ax
	.....
	mov ax,4c00h
	int 21h
codesg ends
end

就很麻烦了
我们可以用循环来写:

assume cs:codesg
codesg segment 
		mov ax,2
		
		mov cx,11
s: add ax,ax
	loop s 
mov ax,4c00h
int 21h
codesg ends
end

这里可以看到在add ax,ax之前加入了s:
也就是用了标号s
随后loop跳到了s处,重复执行,每执行一次 cx的值-1
正好执行11次
来练练手~
计算123*236

assume cs:codesg
codesg segment 
	mov ax,0
	mov cx,236
s: add ax,123
loops 
	mov ax,4c00h
	int 21h
codesg ends
end

这里用123相加256次
我们还可以进一步优化:让256加123次:

assume cs:codesg
codesg segment 
	mov ax,0
	mov cx,123
s: add ax,256
loop s
	mov ax,4c00h
	int 21h
codesg ends
end

也是很简单的吧
让我们来思考以下问题:
将内寸 ffff:0006单元处的数*3 结果存到dx中
该怎么写呢?
可以考虑将数存在ax中,随后用dx进行累加
但是ax寄存器是16位的,这里的数是8位的哦
因此需要将ah 变为0
看代码吧:

assume cs:code 
code segment 
	 mov ax,0fffh
	 mov ds,ax
	 mov bx.06  ds:bx-> ffff6h

	mov al,[bx]

	mov ah,0
	
	mov dx,0
	mov cx,3

s: add dx,ax
loop s 
mov ax,4c00h
int 21h
code ends 
end 

其中: mov al,[bx]是将其中的低位赋值给al 随后高位用0来填充
保证了ax中的值与 我们期望的[bx]的值相等(在位数不一致的情况下)
我们在dosbox里面debug一下
在这里插入图片描述
这里完成了赋值过程
接下来开始循环
在这里插入图片描述
第一次执行后cx未变化 随后到了 loop指令 此时cx-1
在这里插入图片描述
随后dx开始继续变化
最后执行-p
在这里插入图片描述
很清晰了吧
汇编一点也不难
别说求三倍了,求123倍也可以
修改
mov cx,123
即可
只不过循环次数在debug时过长,使用p即可让cx为0 完成循环

3. Debug和 masm对指令的处理差异

对于同一条指令:
mov ax , [0]
在debug中 编程和在汇编源程序这种是不同的
在汇编源程序中的 会当成指令:
mov ax ,0
来进行
让我们来试验一下:
首先在debug中往内存处写如下指令:

mov ax,2000
mov ds,ax
mov al,[0]
mov bl,[1]
mov cl.[2]
mov dl,[3]

在这里插入图片描述
再让我们用masm来看一下
在这里插入图片描述
可以看到,用masm进行编译的mov [] 系列的指令会变成 mov ax,0
上面我们所提到的idata就是这个意思:
在debug中
对于 mov al [idata]的没有影响,就是直接将其所在的内存地址中的数值存入到al中
但是在masm编译的汇编源程序中是会将idata本身存入到al中的
拿```mov al [1]``来讲
对于 debug来说,存入的是 ds:[1]
而对于masm来说,存入的是1
所以在我们进行汇编源程序编写的时候应该注意:
如果我们想将内容存入al这类寄存器,我们可以这样写:

assume cs:code
code segment 
	mov ax,2000h
	mov ds,ax
	mov bx,0
	mov al,[bx]
	
	mov ax,4c00h
	int 21h
code ends;
end

可以利用bx寄存器来将其写入到l内,但是这样会很麻烦,每次往l寄存器内存储都要这样写
所以提出了一种新的方法:

mov ax,2000h
mov ds,ax
mov al,ds:[0]

也就是在al类寄存器传入数值的时候写出段寄存器
所以在汇编源程序中,使用指令访问单元时,要加入段寄存器哦

4.组合一下 [bx]与loop

思考一个问题:
我们如何去计算内存地址:
ffff:0 -ffff:b单元中的数据和且放到dx中?

可以将其结果到dx中吗?可以的,因为每个内存单元为1字节,而dx为两字节
不会超出的

可以将数据直接累加到dx寄存器中吗? 不可以因为位数无法对其

那么可以直接将数据放到dl中,并且设dh=0吗?
也不可以 ,会导致溢出

因此我们有两种做法:
dx =dx +内存中的8位
dl = dl+ 内存中的8位

第一种做法运算对象的类型不匹配,第二种做法会溢出

那么我们只能:
拿一个16位的寄存器做中介,将内存中的8位数据放到16位里(ax)随后再将ax加到dx里就可以了

assume cs:code
code segment

mov ax,0ffffh
mov ds,ax

mov dx,0

mov cx,12
mov bx,0
s: mov al,ds:[bx]
    mov ah,0
    inc bx
loop s
mov ax,4c00h
int 21h

code ends

这里将bx接入循环,使其自增即可简便的完成

5.段前缀

```mov ax,[bx]`` 中默认了段是ds
其实等价于:

mov ax,ds:[bx]
除此之外还有:

mov ax,cs:[bx]
mov ax,ss:[bx]
mov ax,es:[bx]
mov ax,ss:[0]
mov ax,es:[0]

这里的ds cs ss es 都为段前缀 后面的为偏移

6 内存空间的安全问题

你们不觉得随意往内存空间写东西很危险吗


mov ax,1000h mov ds,ax mov al,0 mov ds:[0],al

假设内存空间:1000:0处存放着重要的系统代码

这里的
mov ds:[0],al
毫无疑问会将其改写 会变得十分危险
直接写结论:
写数据往 0:200-0:2ff内写没问题

7 练习:

将内存空间:ffff:0-ffff:b的内容复制到 0:200-0:20b中

assume cs:code 
code segment 
mov bx,0
mov cx,12
s: mov ax,0ffffh
	mov ds,ax
	mov dl,ds:[bx]

	mov ax,0020h
	mov ds,ax
	mov ds:[bx],dl

	inc bx 
loop s
mov ax,4c00h
int 21h
code ends

这样公用一个段寄存器效率太低了,因此改进下用两个:
代码如下:

assume cs:code 
code segment
	mov dx,0
	mov cx,12
	mov bx,0
	mov ax,0ffffh
	mov ds,ax
	mov ax,0020h
	mov es,ax
s: mov dl,[bx]
	mov es:[bx],dl
	inc bx
loop s 
	mov ax,4c00h
	int 21h
code ends
end

很简单吧~
继续来个练习
1.向内存0:200-0:23F传送数据 0-63(3FH)

 assume cs:code 
code segment 
    mov ax, 0200h      
    mov ds, ax
    
    mov bx, 0          
    mov dx, 0         
    mov cx, 03fh      

s:  mov [bx], dx      
    inc dx            
    inc bx            
    loop s           

    mov ax, 4c00h    
    int 21h

code ends
end
  1. 在第一问的前提下,只是用9条指令完成功,不包括开始的assume和 code segement
    但是包括mov ax,4c00h,int 21h
assume cs:code 
code segment 
mov ax,0200h
mov ds,ax
xor di,di 
mov cx,0040h
s: stosb
inc al 
loop s 
mov ax,4c00h
int 21h
code ends 
end

3.补全代码:

assume cs:code 
code segment 
mov ax, ?
mov ds,ax
mov ax,0020h
mov es,ax
mov bx,0
mov cx,?
s: mov al,[bx]
	mov es:[bx],al
	inc bx
	loop s
	mov ax,4c00h
	int 21h
code ends
end

答案:

assume cs:code
code segment 
	mov ax,cs
	mov ds,ax
	mov ax,0020h
	mov es,ax
	mov bx,0
	mov cx,17
s:mov al,[bx]
	mov es:[bx],al
	inc bx
loops 
mov ax,4c00h
int 21h
code ends
end

下篇文章将介绍多个段的程序
敬请期待,点赞加关注,下一篇文章马上更新!

标签:code,BX,mov,al,Aseembly,ax,bx,ds,Loop
From: https://blog.csdn.net/baidu_33751906/article/details/141359420

相关文章

  • C/C++计算一元二次方程ax²+bx+c=0的根,作业作弊神器
    //在日常计算中,我们通常要计算一元二次方程的根,当系数为整数时,硬着头皮算算就行,但如果系数位小数,有没掌握一定解题技巧,求根会变得异常困难,那么我们可以借助计算机的力量进行强行破解,只需在控制台上输入对应系数即可求根,大大提高计算效率。废话不多说上代码!!记得支持一下喔~~~//......
  • mobx模版(增删改查)
     /**@Author:Simoon.jia*@Date:2024-04-0911:06:16*@LastEditors:Simoon.jia*@LastEditTime:2024-07-2216:59:57*@Description:描述*/import{observable,action,runInAction}from'mobx';import{fetchDictionaryList,fetchd......
  • ArcPro (3.2+) Python 脚本工具中从 .atbx Toolbox 相对导入本地模块
    我设置了一个库和关联的ArcGISToolbox,以便:/root├──Toolbox.atbx├──mylib│└──my_function.py├──my_tools│└──my_gp_script.py我将代码存储库的开发克隆保存在公司共享服务器上的一个位置,并在GitHub上托管一份副本。当我进行更新时,我会......
  • SqlDbx客户端连接服务器Oracle数据库
    查了很多文章,介绍的不对,走了好多弯路,最后整理一下,供参考一、下载Oracle客户端1、SqlDbx如果是32位的,客户端也要下载32位的2、Oracle客户端版本要和服务端版本一致(本例用的是12.1.0.2.0)3、32位客户端下载地址:https://www.oracle.com/database/technologies/instant-client/mic......
  • ZigZag :nested loop 的教科书
    ZigZag在PEarray-memoryhierarchylevel上对nested-loopbased算子数据部署设计策略进行详细分析。文章作者来自鲁汶MICAS[1]实验室。软硬件建模软件上只涉及MAC-based的网络算子(Linear、Convolutional),沿用time-loop[2]方法使用nested-loop建模,从operand(Input......
  • 饿了么bxet 分析
    声明本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 大部分补环境代码//仅供学习使用window=globalself=windowtop=windowwindow.origin='###'......
  • 饿了吗bx_et 逆向
    ​声明:本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!wxa15018601872       本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲......
  • 饿了吗新版bxet
    声明(lianxia15018601872)        本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 前言(lianxia15018601872)简单分析一下bxet。逆向过程首先......
  • vulhubXXE靶机
    将下载好的靶机导入到VMware中,设置网络模式为NAT模式,然后开启靶机虚拟机使用nmap进行主机发现,获取靶机IP地址nmap192.168.47.1-254kali本机ip根据对比可知XXE的一个ip地址为192.168.134.134,并开放了80端口在浏览器访问http://192.168.134.134对网站进行目录和......
  • [米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-16 SPI LOOP环路实验
    软件版本:Anlogic-TD5.9.1-DR1_ES1.1操作系统:WIN1064bit硬件平台:适用安路(Anlogic)FPGA实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板板卡获取平台:https://milianke.tmall.com/登录"米联客"FPGA社区http://www.uisrc.com视频课程、答疑解惑! 1概述在前面完成了SPI发......