程序集怪异行为中的指针算术(nasm)

时间:2018-12-07 10:39:54

标签: pointers assembly nasm

我的数据段如下:

segment data use32 class=data
    v db 4
    v1 db 4
    v2 db 4 
    v3 db 7

为什么mov bh, v是语法错误,而mov bh, v + v1mov bh, v + v1 + v2不是语法错误? v + v1,加上2指针,实际上是无效的指针算法。此外,调试器告诉bh移入了一个小数字,例如6,但是考虑到地址是非常大的数字,看来nasm在幕后做了一些减法运算

我使用nasm 1.6

1 个答案:

答案 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 multiplierrelative 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

总而言之,当单独使用vmov ebx, v)时,NASM使用重定位地址。在进行地址代数(mov ebx, v+v1-v2)时,NASM使用相对地址。所以,是的,这有点令人困惑。