【问题标题】:Moving the same byte to each address between two distinct address?将相同的字节移动到两个不同地址之间的每个地址?
【发布时间】:2019-04-05 22:40:24
【问题描述】:

是否有可能将同一个字节快速移动到一堆地址

pseudocode...
mov ax, 10
mov [memAddrStart to MemAddrEnd], ax

这会将 AX 放入每个地址,因此我可以引用序列中的任何地址并始终获取 10。

这可能吗,如果没有,我该如何解决?

【问题讨论】:

  • 查看rep stosb
  • 一般来说,这不是你通常在指令集中找到的那种东西,但是……x86 是特殊的……通常你执行一个循环来做这样的事情。查看 glibc 和 newlib 以及其他开源 C 库中各种架构的手动调整 memset。
  • 仅供参考,这种用相同值填充内存范围的操作在 C 中称为 memset。Google 以 asm 为例。

标签: assembly nasm x86-16


【解决方案1】:

是的,有专门为此设计的说明。

不过,它确实需要一些设置。

cld                                     //CLear the Direction flag (optional, see below)
mov al,10                               //we are moving bytes
mov edi,MemAddrStart                    //Destination = start
mov ecx,(MemAddrEnd - MemAddrStart)+ 1  //Count = (end-start)+1
rep stosb                               //(REP)repeat (STOS)storing (B)bytes until done

请参阅:STOSB documentation

方向标志
The direction flag 确定rep stosx 是向前还是向后移动。 您应该始终让它继续前进,因为这是默认方向。
如果您使用std 将其设置为向后,请确保之后使用cld 将其重置为正常状态。如果不这样做,可能会发生坏事,因为许多编译器和操作系统都假定方向标志始终是明确的。

'[...] 如果没有,我该怎么办?'
你当然可以使用一个简单的循环来编程:

mov al,10                               //we are moving bytes
mov edi,MemAddrStart                    //destination = start
mov ecx,(MemAddrEnd - MemAddrStart)+ 1  //length = (end-start)+1
Loop:
dec ecx                                 //This is
mov [edi+ecx],al                        //what `rep stosb` 
jnz Loop                                //does

请注意,为了提高效率和简单性,我的循环从最后开始并返回。 stos(清除方向标志)从头开始。否则,两者的工作方式相同。
因为我正在减少ecx,所以我可以使用零的隐式测试 (jnz),并且不需要添加另一个测试或另一个寄存器来查看我是否完成了。

示例代码备注

mov ax, 10
mov [memAddrStart to MemAddrEnd], ax

此代码移动一个字(16 位)。这会写入字节

Address        HEX   DEC
MemAddrStart:   0A    10
MemAddrStart+1: 00    00

如果您在循环中执行以下操作,请记住,而不是您想要的:

dec ecx 
mov [edi+ecx],ax           
jnz Loop          

您将编写以下内容:

Address        HEX   DEC
MemAddrStart:   0A    10
MemAddrStart+1: 0A    10
....
MemAddrEnd      0A    10
MemAddrEnd+1    00    00  <<-- Oops, you're writing past the buffer.

这被称为a buffer overflow,这是一个可能导致各种令人讨厌的问题的错误。

如果您想存储单词,那么您必须更改您的代码才能这样做。(mov ecx,(end-start+1)/2rep stosw)。

【讨论】:

  • 非常感谢您提供的详细信息!
  • 有趣的是,当您自己在示例循环中编写缓冲区溢出时,您应该警告缓冲区溢出!
  • 准备存储单词时ECX的计算不正确。
  • @SepRoland,请注意,不要发布未经测试的代码。
猜你喜欢
  • 2014-08-05
  • 1970-01-01
  • 2010-11-20
  • 2012-10-25
  • 1970-01-01
  • 2017-05-06
  • 2014-09-04
  • 1970-01-01
  • 2021-10-18
相关资源
最近更新 更多