【发布时间】:2015-01-21 17:20:21
【问题描述】:
我正在使用 MASM 汇编程序。 让我们看看这个简短的代码(来自我一直在阅读的一本书):
.data
var1 BYTE 10h
.code
main proc
mov esi,OFFSET byteVal
mov al,[esi] ; AL = 10h
我并不完全理解 byteVal 是如何翻译成机器代码的——我知道它是一个标识符,一个符号名称。据我了解,在运行时 byteVal 是值 10h 的内存 address ,对吗? 但是书上说这两条指令是一样的:
mov al var1
mov al,[var1]
我不明白他们为什么这样做。
var1 = 10h的地址
[var1] = 10h
这不是真的吗? 这本书说方括号“取消引用”变量,但它说这两个是相同的。
如果 var1 是内存中的位置,那么它与使用 OFFSET var1 有什么区别? 我的意思是,偏移量是内存中的位置,不是吗? 这本书说:“OFFSET 运算符返回一个变量从其封闭的开头的距离 分割。” 为什么第一个变量的偏移量不为零,因为它是段中的第一个变量?我只是想不通。也许我应该换一本书……
【问题讨论】:
-
我很惊讶
mov al, var1真的被 MASM 接受了。按照惯例,mov esi, OFFSET var用于加载偏移量(地址),或者mov al, [var1]用于加载地址的内容。 -
@500-InternalServerError 感谢您的回答:) 我现在再次检查并使用 [] 而不是使用它们会获得相同的结果。我不明白为什么会这样,因为数据标签是数据本身的 address 。 =[还有一个问题:如果变量的名称是它的地址,为什么要使用OFFSET。我的意思是,变量是地址,所以OFFSET指令没用,不是吗?
-
传统,可能。在 32 位平面模式下,偏移量和地址是可互换的,但在分段模式(例如 16 位 DOS)中则不能。
-
@500-InternalServerError 我仍然不明白为什么这两个移动指令会做同样的事情。正如我所看到的,第一条 mov 指令甚至不应该编译,因为地址是 32 位,而 al 只有 8 位……我还读到全局变量地址是在汇编期间分配的。怎么可能,因为每台计算机都有不同的可用内存位置和其他正在使用的内存位置?
-
“我还是不明白为什么这两个移动指令会做同样的事情”。因为 MASM 和 TASM 以相同的方式解释
mov reg,[label]和mov reg,label(就好像您在两种情况下都使用了括号一样) - 就是这样。 NASM 不这样做。在 NASM 语法中,mov reg,label将使用label的地址加载reg(就像在 MASM/TASM 语法中的mov reg,offset label)。