我如何使用地址中的变量值访问变量数据,如 [var_+[second_byte]]?
How i can access a variable data using a variable value in adress like [ var_+[second_byte] ]?
我得到了这个代码:
BITS 16
data:
bytemap: db 0x0, 0x1, 0x4;
pixel_x: db 2; to return the 0x4 value
main:
; code...
mov al, [bytemap+[pixel_x]]; i need that byte in al register
; more code...
jmp main;
但是nasmreturns"expression syntax error",我试过用mov bl, [pixel_x]; mov al, [bytemap+bl]
,但是不行,正确的做法是怎样的? (如果存在)...
您需要在寻址模式下使用指针宽度寄存器。 x86 没有内存间接寻址模式,只有寄存器间接寻址模式。 。您可以在一条指令中执行的操作的限制来自机器代码可以表示的内容。汇编器不是编译器;每行都必须作为一条机器指令工作。
理想情况下,将 pixel_x
保存在寄存器中而不是内存中;这就是寄存器的用途。
假设32位代码,
movzx eax, byte [pixel_x]
movzx eax, byte [bytemap + eax] ; AL = EAX = bytemap[pixel_x]
如果您希望稍后在寄存器中使用 pixel_x
值以用于其他用途,您当然可以使用不同的寄存器,例如 EBX。
或者在这种情况下,imul eax,eax
因为数组条目只是索引平方;你不需要查找 table.
在 64 位代码中,您将使用 default rel
,因此 movzx eax, byte [pixel_x]
使用 RIP 相对寻址模式。您可能需要将 bytemap
的地址放入代码 where static addresses aren't guaranteed to fit in a 32-bit sign-extended displacement.
中的单独寄存器中
在16位代码中(可以假设386兼容),需要处理16位寻址方式的局限性:只有BX、BP、SI、DI可以作为基址寄存器或变址寄存器。 NASM x86 16-bit addressing modes
movzx bx, byte [pixel_x]
movzx ax, byte [bytemap + bx] ; AL = AX = bytemap[pixel_x]
如果(不太可能)您的代码需要 运行 在 8086 到 286 上,您需要模拟 movzx。
在 16 位模式的现代 x86 上,使用 EBX 和 EAX 作为 movzx
的目的地可能有助于提高性能,但会增加代码大小。如果您正在编写 16 位代码,您可能不关心速度,只关心代码大小。如果性能很重要,你会切换到保护模式或长模式。
movzx
是加载单个字节的最佳/最有效方式,零扩展到完整寄存器以避免部分寄存器性能问题,如 false依赖项。只有当你真正想要合并到EAX/RAX的低字节时才使用mov al, [mem]
。
字节存储,你还是像mov [mem], al
一样只读部分寄存器。
读取部分 regs 没问题,只是在可以使用 movzx
时通常避免写入它们。 add al, [mem]
之类的东西在大多数 CPU 上也很有效。
一般来说,使用部分寄存器并不是灾难,只要在可以使用 movzx
或 movsx
而不是 mov
.
的情况下轻松避免它即可
我得到了这个代码:
BITS 16
data:
bytemap: db 0x0, 0x1, 0x4;
pixel_x: db 2; to return the 0x4 value
main:
; code...
mov al, [bytemap+[pixel_x]]; i need that byte in al register
; more code...
jmp main;
但是nasmreturns"expression syntax error",我试过用mov bl, [pixel_x]; mov al, [bytemap+bl]
,但是不行,正确的做法是怎样的? (如果存在)...
您需要在寻址模式下使用指针宽度寄存器。 x86 没有内存间接寻址模式,只有寄存器间接寻址模式。
理想情况下,将 pixel_x
保存在寄存器中而不是内存中;这就是寄存器的用途。
假设32位代码,
movzx eax, byte [pixel_x]
movzx eax, byte [bytemap + eax] ; AL = EAX = bytemap[pixel_x]
如果您希望稍后在寄存器中使用 pixel_x
值以用于其他用途,您当然可以使用不同的寄存器,例如 EBX。
或者在这种情况下,imul eax,eax
因为数组条目只是索引平方;你不需要查找 table.
在 64 位代码中,您将使用 default rel
,因此 movzx eax, byte [pixel_x]
使用 RIP 相对寻址模式。您可能需要将 bytemap
的地址放入代码 where static addresses aren't guaranteed to fit in a 32-bit sign-extended displacement.
在16位代码中(可以假设386兼容),需要处理16位寻址方式的局限性:只有BX、BP、SI、DI可以作为基址寄存器或变址寄存器。 NASM x86 16-bit addressing modes
movzx bx, byte [pixel_x]
movzx ax, byte [bytemap + bx] ; AL = AX = bytemap[pixel_x]
如果(不太可能)您的代码需要 运行 在 8086 到 286 上,您需要模拟 movzx。
在 16 位模式的现代 x86 上,使用 EBX 和 EAX 作为 movzx
的目的地可能有助于提高性能,但会增加代码大小。如果您正在编写 16 位代码,您可能不关心速度,只关心代码大小。如果性能很重要,你会切换到保护模式或长模式。
movzx
是加载单个字节的最佳/最有效方式,零扩展到完整寄存器以避免部分寄存器性能问题,如 false依赖项。只有当你真正想要合并到EAX/RAX的低字节时才使用mov al, [mem]
。
字节存储,你还是像mov [mem], al
一样只读部分寄存器。
读取部分 regs 没问题,只是在可以使用 movzx
时通常避免写入它们。 add al, [mem]
之类的东西在大多数 CPU 上也很有效。
一般来说,使用部分寄存器并不是灾难,只要在可以使用 movzx
或 movsx
而不是 mov
.