当前位置: 首页 > 知识库问答 >
问题:

汇编语言数据段变量值

萧自珍
2023-03-14

我正在努力学习汇编语言。我注意到它与Java等高级编程语言完全不同。

因此,我了解到数据传输指令遵循以下语法:

mnemonic destination, source

我将其视为目的地=source换句话说,将值分配给内存

我在《数据段声明》一书中看到了一个示例。

.data 
var1 SBYTE -4,-2,3,1 
var2 WORD 1000h,2000h,3000h,4000h 
var3 SWORD -16,-42 
var4 DWORD 1,2,3,4,5

怎么会有

我会很感激任何解释。

谢谢

共有2个答案

狄英哲
2023-03-14

我甚至不会在汇编中使用“variable”这个词。

你当然可以这样想,这基本上是可行的,但从技术上讲,这是一个较低的水平。

var1 DWORD 12345678h将值12345678h编译为四个字节(在x86小端,字节将是78 56 34 12),这些将“降落”到. data段的某个地方,加载后将成为内存内容可供操作系统执行。操作系统会挑选一些空闲内存来加载它,因此它还会提供. data段的起始地址,并在二进制文件加载完成后,在执行之前调整加载的代码以反映真实地址。

这意味着在某个特定地址将有字节可用(x86上的内存可按字节寻址)。

var1将成为符号表中的“符号”,标记这四个字节中第一个字节的地址。

然后,您可以编写汇编指令,如mov cl、[var1],这意味着“从内存中加载symbol地址为var1的字节”,此指令标记为可执行指令,操作系统将使用实际symbol表值对其进行调整,因此在执行期间,它将指向正确的内存。已加载数据段。

或者,如在x86\u 64中使用相对寻址时,mov指令编译为mov cl,[rip offset\u between\u next\u instruction\u and\u var1],则操作系统根本不需要调整指令,因为它将在任何内存位置工作,偏移量是相对的。

从字节大小的地址加载内存内容将加载78h,这是非平凡变量思维中断操作的示例。并且从内存加载字将从内存加载字值(在非x86平台上,未对齐的内存访问可能会导致执行崩溃,在x86上它将工作,只有性能会受到影响)。

然后,var1 DWORD 1,2,3,4只意味着在地址后面编译更多的字节值,比如01 00 00 00 02 00 00 00 00 在这种情况下。您可以通过将它们命名为mov eax、[var1 2*4]-

请注意,var1只是内存的地址,因此如果向其添加正确的偏移量,实际上甚至可以通过它来寻址var2中的数据。因此,无意中重写汇编中的其他变量是多么容易,例如,将DWORD错误地写入字节变量就足够了,而且您已经在变量之外重写了3个字节的内存,可能被其他变量使用。

另请注意,在访问数组时,您必须始终手动执行索引的*1、*2、*4、...所以您必须始终了解数组元素的大小。

两种大小的基本能力可以直接编码到x86指令的扩展寻址模式中,如mov eax、[ebx esi*4-44]以“esi-11”索引寻址ebx地址的某些dword数组,因此类似Java的代码类似于eax=ebx[esi-11] ,避免您单独计算乘法。

这是另一个常见的bug来源,忘记了只有当数组元素为单字节大小时,“索引”才等于“内存字节偏移量”,在所有其他情况下,您必须将索引乘以元素大小才能获得内存寻址的字节偏移量。

最后,当您将这些内容写入<代码>时。数据段,它们按顺序编译,作为串联的字节流(检查汇编程序规范,了解特定指令的自动填充,如dword,根据需要在前面插入填充字节以对齐结果数据)。因此,实际上您不需要任何var1,如果您想成为核心,请自行计算所有偏移量,并通过处理这些字节。数据偏移量,这是可能的(这只是一个心理练习,告诉你在这行上写“更多值”意味着什么,而不是一个建议:)。

编辑:“欧文”。。。那么您可能正在使用as汇编程序MASM?这种方法不仅在编译过程中保留地址符号,而且还记住第一个声明的大小(如“DWORD”),因此它将尝试使用更“类似变量”的编译方法来覆盖一些用例。

我个人建议您忽略这一点,只将其视为地址,避免使用所有MASM怪癖语法,因为1)它在其他x86汇编程序中不起作用2)一旦您习惯了低级汇编,在较大的源代码中可能会非常混乱。

我的意思是,在MASM中,var1被编译成机器代码,作为mov eax,[address\u of\u var1](在var1处用内存内容加载eax,即从人的角度来看,“用变量var1加载eax”)。

但当我在没有可见代码的情况下读入源指令时,我习惯于认为它不是在访问内存,而是只使用immediate(比如在mov eax、esi和mov eax的情况下)。即使在MASM中,您也可以编写mov eax、[var1],它也可以工作。但是要提取var1本身的地址,需要额外的语法糖,比如mov eax,OFFSET var1,IIRC。

最后一点注意:这些定义通常在Java中使用数组的地方使用,比如short-wordArrayVar[]={1,2,3,4} 。这是对这些多值定义的一种可能解释。但在某些情况下,它甚至在较低级别上使用,只是在中定义特定的字节值。数据段,甚至不能用作数组,而是以某种不同的方式。

另一种常见的模式是“结构”实例的初始化,在Java中没有好的例子,因为类成员变量不能保证一个接一个地存储在内存中?但在C中,所有写在源代码中的类/结构成员变量都可以想象为逐字节的内存块,每个成员变量都有特定的偏移量和对齐方式,这取决于它在源代码中的类型和位置。此时,您可以通过在整个结构大小的块中定义每个字节的值来创建此类结构的预初始化实例。

聂昱
2023-03-14

要在汇编中定义多个WORD大小的变量,我们可以使用

var1 WORD 1000h
var2 WORD 2000h
var3 WORD 3000h
var4 WORD 4000h 

通常程序员不需要命名每个变量,只需要命名第一个,然后使用指针算术来获取其他变量。
在这种情况下,我们可以使用

var1 WORD 1000h
     WORD 2000h
     WORD 3000h
     WORD 4000h 

当一些变量可能具有不同的大小时,这尤其方便,否则关键字WORD的重复很烦人,并且可以在最终形式中简化

var1 WORD 1000h, 2000h, 3000h, 4000h

这相当于第二种形式和(名字除外)第一种形式。

 类似资料:
  • 机器语言 机器语言是指令的集合。 汇编语言 汇编语言的主体是汇编指令。 存储器 随机存储器RAM,可读可写,必须带电存储,关机后存储的内容丢失 只读存储器ROM,只读,关机后其中的内容不丢失 装有 BIOS (基本输入输出设备)的ROM 接口卡上的RAM:显存 外存(storage,磁盘)和内存(memory,主存,高速缓存) 内存地址空间 存储单元:1个字节(byte) 总线 地址总线:CPU是

  • 《汇编语言》(Assembly Language)是计算机专业中一门重要的基础课程,是一种面向机器的低级语言。它依赖于硬件,能通过巧妙的程序设计充分发挥硬件的潜力。汇编语言程序产生的代码运行效率高。因此,到目前为止,许多软件系统(例如操作系统等)的核心部分仍然用汇编语言来编写。

  • 在Go语言中,函数也是一种类型,可以和其他类型一样保存在变量中,下面的代码定义了一个函数变量 f,并将一个函数名为 fire() 的函数赋给函数变量 f,这样调用函数变量 f 时,实际调用的就是 fire() 函数,代码如下: 代码输出结果: fire 代码说明: 第 7 行,定义了一个 fire() 函数。 第 13 行,将变量 f 声明为 func() 类型,此时 f 就被俗称为“回调函数”,

  • 能跑就行,不行加机器。——rfyiamcool & 爱学习的孙老板 跟对人,做对事。——Rhichy Go语言中很多设计思想和工具都是传承自Plan9操作系统,Go汇编语言也是基于Plan9汇编演化而来。根据Rob Pike的介绍,大神Ken Thompson在1986年为Plan9系统编写的C语言编译器输出的汇编伪代码就是Plan9汇编的前身。所谓的Plan9汇编语言只是便于以手工方式书写该C语

  • 本文向大家介绍什么是汇编语言,包括了什么是汇编语言的使用技巧和注意事项,需要的朋友参考一下  汇编语言(assembly language)是一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。在汇编语言中,用助记符(Mnemonics)代替机器指令的操作码,用地址符号(Symbol)或标号(Label)代替指令或操作数的地址。在不同的设备中,汇编语言对应着不同的机器

  • 上面介绍的在Solidity中嵌入的内联汇编语言也可以单独使用。实际上,它是被计划用来作为编译器的一种中间语言。在这个目的下,它尝试达到下述的目标: 使用它编写的代码要可读,即使代码是从Solidity编译得到的。 从汇编语言转为字节码应该尽可能的少坑。 控制流应该容易检测来帮助进行形式验证与优化。 为了达到第一条和最后一条的目标,Solidity汇编语言提供了高层级的组件比如,for循环,swi