首页 > 编程语言 >汇编_将数据、代码和栈放入不同的段

汇编_将数据、代码和栈放入不同的段

时间:2023-04-25 15:57:50浏览次数:40  
标签:汇编 ends 代码 mov codesg cs ax bx 放入

数据放在哪里

之前的程序,只有一个代码段,需要运算的数据直接编码在代码里,例如:mov ax,1。如果我们想计算多个数求和,不能也傻乎乎的add多次,因为多个数可能是不一样,循环都不可以用。
我们需要一段安全的空间用来存放数据。它更像是一个数组,占据一段连续的内存空间,通过[bx++]方式,可以对内存值索引。
在操作系统的环境中,合法地通过操作系统申请的空间都是安全的。加载程序时,操作系统会分配一段内存空间,操作系统会保证这段内存的安全性。我们需要在程序中定义这段内存空间,这样加载时就会自动纳入程序的一部分。

代码段中定义数据

assume cs:codesg		;假设某一段寄存器和某一个程序段相联系
codesg segment			;定义一个段
	dw 0123h,0456h
	mov ax,cs:[0]
	mov bx,cs:[2]
	add ax,bx
  	mov ax,4c00h
  	int 21h
codesg ends
end 					;标识程序结束


在程序的开头定义了2个双字节的数据,这四个字节就放在cs代码段的开始位置。可是程序默认执行的位置cs:ip,默认指向开始的数据,翻译成指令,程序就不对了,所以我们只能手动修改ip指向执行。

虽然奇怪了一点,但是我们有了放置数据的地方。

多个段

数据直接定义在代码段中,会让cs:ip指向不正确,执行的时候还需要手动改一下代码段开始位置。一种容易想到的思路,代码和数据分开,代码段和数据段。

assume cs:codesg		;假设某一段寄存器和某一个程序段相联系
a segment
    db 1,2,3,4,5,6,7,8
a ends
b segment
    db 0,0,0,0,0,0,0,0
b ends
codesg segment			;定义一个段
start: 
	mov ax,a
	mov ds,ax
	mov ax,b
	mov es,ax
	mov bx,0
	mov cx,4
	s0:
		mov ax,[bx]
		mov es:[bx],ax
		add bx,2
		loop s0
  	mov ax,4c00h
  	int 21h
codesg ends
end start					;标识程序结束


这里定义了3个段,a b数据段和代码段,代码段这里加了start标识,标识程序从这里执行,不用我们再手动修改cs:ip指向。然后,mov ax,a,这里的a指的是数据段a的首地址,之后[bx]就可以取到数据段的值。
上一篇介绍了程序加载进内存时,存在256字节的程序段前缀(PSP),这里ds地址是075a,a的起始地址是076a。这表示a段是放在程序最开始的位置的。

有一点需要注意的是,db定义的单字节数据,但是mov ax,[bx],ax的值是0201。因为ax是一个16位寄存器,默认读取两字节数据。所以,bx设置为2,同样cx设置为4就可以读取全部数据。

实践

将a段和b段中的数据依次相加存入c段中

assume cs:codesg		;假设某一段寄存器和某一个程序段相联系
a segment
    db 1,2,3,4,5,6,7,8
a ends
b segment
    db 1,2,3,4,5,6,7,8
b ends
c segment
    db 0,0,0,0,0,0,0,0
c ends
codesg segment			;定义一个段
start: 
	mov ax,c
	mov ds,ax
	mov cx,4
	mov bx,0
	s0:
		mov ax,a
		mov es,ax
		mov ax,es:[bx]
		mov [bx],ax
		mov ax,b
		mov es,ax
		mov ax,[bx]
		add ax,es:[bx]
		mov [bx],ax
		add bx,2
		loop s0 
  	mov ax,4c00h
  	int 21h
codesg ends
end start					;标识程序结束

代码的复杂性主要体现在段寄存器之间不能在一条指令上操作,思路很简单,就是借用了es完成数值中转。

使用push指令将a段中的前八个字节,逆序保存到b段中

assume cs:codesg		;假设某一段寄存器和某一个程序段相联系
a segment
    dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
a ends
b segment
    dw 0,0,0,0,0,0,0,0
b ends
codesg segment			;定义一个段
start: 
	mov ax,a
	mov ds,ax
	mov ax,b
	mov ss,ax
	mov sp,16
	mov bx,0
	mov cx,8
	s0:
		push [bx]
		add bx,2
		loop s0
  	mov ax,4c00h
  	int 21h
codesg ends
end start					;标识程序结束

这里将b段当成一个栈段来使用,难点在合理的设置栈顶数值。因为debug时,cs:ip的值也会写入栈中,所以数据看起来有点奇怪。只关心栈顶元素,sp指向栈顶的前一位,定位查看对应的内存值。这里定义数据使用的是dw,每次push会让sp-2,需要用心体会。

写到这里的时候,ss和sp的设值有点忘记了,贴一下栈操作图示。

总结

这一章解决了一个大问题,程序可以读取数据了。这里学习下来,感觉es ds这些段寄存器之间切换,栈段的sp设值还是有点绕的,甚至dw和db之间我迷糊了一段时间,一度搞不清楚一个字节是几位数据了。折腾了几天,程序开始像模像样了。

标签:汇编,ends,代码,mov,codesg,cs,ax,bx,放入
From: https://www.cnblogs.com/snowsteps/p/17352590.html

相关文章

  • chatGPT生成的简单工厂模式代码教学
    """在这个示例代码中,我们使用了简单工厂模式来创建不同的运算对象。首先,我们定义了一个Operation类作为运算类的基类,其中包含两个操作数num1和num2,以及一个get_result方法用于获取运算结果。接下来,我们定义了四个具体的运算子类Add、Subtract、Multiply和Divide,分......
  • Java代码虾皮item_search-根据关键词获取商品列表 API 接口(title商品标题、pic_url宝
     Shopee是东南亚最大的电商平台之一。Shopee拥有商品种类,包括电子消费品、家居、美容保健、母婴、服饰及健身器材等。做好shopee店铺需要注意以下几点:1.选择优质的产品2.每日上新产品3.营销策略4.引流策略5.发货的地点Java代码操作示例importjava.io.BufferedReader;impo......
  • token认证过滤器代码实现与配置认证过滤器
    token认证过滤器代码实现认证过滤器​我们需要自定义一个过滤器,这个过滤器会去获取请求头中的token,对token进行解析取出其中的userid。​使用userid去redis中获取对应的LoginUser对象。​然后封装Authentication对象存入SecurityContextHolder......
  • 搜狗细胞词库处理代码(可用于scel转txt)
    今天先贴个简单代码,稍后再详细叙述…… 基于QT实现,主要是考虑Unicode字符处理的方便,可以稍加处理用于C或C++语言。 //取连续两字节,转换为short类型的值,字节顺序是低字节-高字节inlineunsignedshortGetUShort(QByteArray&fData,intstartPos){unsignedcharlow=fData......
  • P.10-准备工作、P.11-数据库校验用户准备工作、P.12-数据库验证用户核心代码实现
    P.10-准备工作1.添加依赖<!--redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>......
  • jenkins流水线发布前端代码
    pipeline{agent{label'hw'}environment{VERSION=sh(script:"echo`date'+%Y%m%d%H%M%S'`",returnStdout:true).trim()}stages{stage('克隆代码'){steps{......
  • C代码之GPIO
    ***@fnintgpio_is_exported(size_tgpio)*@briefTestgpioisexportedornot*@paramsize_tgpio:Thenumberofgpio*@param*@returnIsexported:(0);Isnotexported:(-1)*/intgpio_is_exported(size_tgpio){ intfd=0; charbuf[64]......
  • 登录接口实现细节分析与登录接口代码实现
    登录接口实现细节分析登陆接口接下我们需要自定义登陆接口,然后让SpringSecurity对这个接口放行,让用户访问这个接口的时候不用登录也能访问。​在接口中我们通过AuthenticationManager的authenticate方法来进行用户认证,所以需要在SecurityConfig中配置把Authe......
  • 淘宝API接口对接(商品详情,评论,按图搜图,订单列表)代码封装,可高并发
    淘宝OpenAPI(Openapplicationprogramminginterface)是一套REST方式的开放应用程序编程接口。淘宝网根据自己提供的电子商务基础服务,抽象并做成一系列的API接口。通过这些接口,可以让外部用户能够通过程序的方式访问淘宝网的数据和平台。淘宝OpenAPI是淘宝开放平台的重要组成......
  • 浏览器4行js代码自动读取IC卡号
    BS架构软件集成IC卡读卡器,在前段只需要4行js代码即可实现自动读取IC卡卡号,在web上使用IC卡读卡器其实就是这么简单.首先安装友我IC卡读卡器web插件,这个web插件安装后之后goole浏览器,火狐,IE等浏览器,然后插上IC卡读卡器YW-607HC,然后开始敲js代码了.引入相应的js后,开始寻卡......