灵活使用内存地址

Reverse

开始整活🏯

[bx+idata]

[bx] 可以用来指明一个内存单元,[bx+idata]也具有相同的功能且更为灵活。

[bx+idata]表示:偏移地址=(bx)+idata

例如:mov ax,[bx+200] 它的含义就是将一个内存单元的内容放入 ax 中,这个内存单元的长度为2个字节,偏移地址为 (bx)+200,段地址为 (ds)。将该命令用数学化的公式表达即为:(ax)=((ds)*16+(bx)+200)

指令mov ax,[bx+200]也可以用如下形式表示

  • mov ax,[200+bx]
  • mov ax,200[bx]
  • mov ax,[bx].200

[bx+idata]与数组的关系

问题:将 datasg 中定义的字符串转为大写,第二个字符串转为小写

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
assume cs:codesg,ds:datasg

datasg segment
db 'BaSiC'
db 'MinIX'
datasg ends

codesg segment
start:mov ax,datasg
mov ds,ax
mov bx,0

mov cx,5
s:mov al,[bx]
and al,11011111b //通过 and 将小写改为大写
mov [bx],al
inc bx
loop s

mov bx,5
mov cx,5
s0:mov al,[bx]
or al,00100000b //通过 or 将大写改为小写
mov [bx],al
inc bx
loop s0

mov ax,4c00h
int 21h
codesg ends

end start

初始时的寄存器和内存状态,我们可以观察到我们所写入的数据以及后面的指令

image-20220522163137604

结束后内存的状态

image-20220522163556577

而以上的方法并没有将 [bx+idata] 利用起来,我们依旧是通过两个循环实现我们的目的。

我们可以将这两个等长的字符串看成是2个数组,在一个循环中对2个数组同时进行处理。这两个数组的不同之处就是数组起始地址的偏移地址不一样,而每次处理时对于这两个数组的偏移地址地址都是相同的,而数组起始地址的偏移地址我们可以通过 [dx+idata] 的方式来改变。

使用 [dx+idata] 的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
assume cs:codesg,ds:datasg

datasg segment
db 'BaSiC'
db 'MinIX'
datasg ends

codesg segment
start:mov ax,datasg
mov ds,ax
mov bx,0

mov cx,5
s:mov al,0[bx] //0为第一个字符串起始地址的偏移地址
and al,11011111b
mov 0[bx],al

mov al,5[bx] //5为第二个字符串起始地址的偏移地址
or al,00100000b
mov 5[bx],al

inc bx
loop s

mov ax,4c00h
int 21h
codesg ends

end start

汇编语言和C语言相呼应的地方

  • 汇编语言:0[bx],5[bx]
  • C语言:a[i],b[i]

SI和DI

它们是寄存器中和 bx 功能相近的寄存器,它们之间的区别就是:si 和 di 不能分成两个8位寄存器来使用。

  • [bx+si] 偏移地址=(bx)+(si)
  • [bx+si+idata] 偏移地址=(bx)+(si)+idata
  • [bx+200+si]=[200+bx+si]=200[bx][si]=[bx].200[si]=[bx][si].200

暂存数据

当我们程序变得复杂庞大时,需要对一些数据进行暂存,而寄存器数量有限,我们只能通过内存来帮助我们存储这些临时数据,但是如果只是通过简单地获取内存中的一个单元地址来存储我们的数据的方法是不可取的,因为我们必须要记住我们将数据放入了哪个内存单元中,这样程序会很容易混乱。

解决办法就是利用

一般来说,在需要缓存数据的时候,我们都应该使用栈来操作。

本文作者:GhDemi

本文链接: https://ghdemi.github.io/2022/05/26/%E7%81%B5%E6%B4%BB%E4%BD%BF%E7%94%A8%E5%86%85%E5%AD%98%E5%9C%B0%E5%9D%80/

文章默认使用 CC BY-NC-SA 4.0 协议进行许可,使用时请注意遵守协议。