我的数据段如下:
segment data use32 class=data
v db 4
v1 db 4
v2 db 4
v3 db 7
为什么mov bh, v
是语法错误,而mov bh, v + v1
或mov bh, v + v1 + v2
不是语法错误? v + v1,加上2指针,实际上是无效的指针算法。此外,调试器告诉bh移入了一个小数字,例如6,但是考虑到地址是非常大的数字,看来nasm在幕后做了一些减法运算
我使用nasm 1.6
答案 0 :(得分:1)
NASM能够在这些有效地址上进行代数运算,因此不一定看起来合法的事情就可以了。
我喜欢NASM将所有标签视为地址的方式,但是它的地址代数肯定缺乏一致性,并可能引起混乱。
以您的示例为例,
segment data use32 class=data
v db 4 ; relative address = 0
v1 db 4 ; relative address = 1
v2 db 4 ; relative address = 2
v3 db 7 ; relative address = 3
以下操作
mov bx, v
会将重定位的地址(非0)移至bx
。
mov bh, v
将导致错误:OBJ format can only handle 16- or 32-byte relocations
,因为bh
是8位的,并且重定位将不起作用。
mov bh, [v]
这是将v
中的值加载到bh
的正确方法。
Nasm还允许在地址上进行代数,例如
mov bh, [v + v1 - v2] ; 1 + 1 - 1 = 1
mov bh, [v * 2 - v1] ; 2 - 1 = 1
mov bh, [v * 3 - v1 * 2] ; 3 - 2 = 1
标签总数必须为1(或0,请参见下文)。所以它不允许这样的代码
mov bh, [v + v1] ; 1 + 1 = 2
mov bh, [v - v1 * 2] ; 1 - 2 = -1
mov bh, [v * 3 - v1] ; 3 - 1 = 2
由于invalid effective address: impossible segment base multiplier
或relative call to absolute address not supported by OBJ format
。
奇怪的是,它允许这些
mov bh, [v - v1] ; 1 - 1 = 0
mov bh, [v * 3 - v1 * 3] ; 3 - 3 = 0
生成的代码使用绝对地址。我希望NASM发出警告,但事实并非如此。对我来说,这是一个错误。
最后,NASM还允许在无[]
且无限制的地址上进行代数运算
mov bh, v - v1 ; same as mov bh, 0-1
mov bh, v + v1 ; same as mov bh, 0+1
mov bh, v + v1 * 2 + v3 ; same as mov bh, 0+1*2+3
第一个肯定是有道理的。与其他人结合使用时,其他人可能会有用:
mov eax, v2 + v3
sub eax, v + v1
总而言之,当单独使用v
(mov ebx, v
)时,NASM使用重定位地址。在进行地址代数(mov ebx, v+v1-v2
)时,NASM使用相对地址。所以,是的,这有点令人困惑。