汇编

您所在的位置:网站首页 将数据放入数组 汇编

汇编

2023-04-28 07:40| 来源: 网络整理| 查看: 265

数据放在哪里

之前的程序,只有一个代码段,需要运算的数据直接编码在代码里,例如: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之间我迷糊了一段时间,一度搞不清楚一个字节是几位数据了。折腾了几天,程序开始像模像样了。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3